PageSourceSearch

https://www.ahgz.de/assets/75edb39519d35e9570834e0495510e8f.js

js ahgz.de collected 2026-09-24 20:27:24 UTC 934,820 bytes, 20,648 lines download raw bytes

vendor: 39,680 bytes, lines 1-6
1/*!
2 * Bootstrap v3.4.1 (https://getbootstrap.com/)
3 * Copyright 2011-2019 Twitter, Inc.
4 * Licensed under the MIT license
5 */
6if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");!function(t){"use strict";var e=jQuery.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1||3<e[0])throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(),function(n){"use strict";n.fn.emulateTransitionEnd=function(t){var e=!1,i=this;n(this).one("bsTransitionEnd",function(){e=!0});return setTimeout(function(){e||n(i).trigger(n.support.transition.end)},t),this},n(function(){n.support.transition=function o(){var t=document.createElement("bootstrap"),e={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var i in e)if(t.style[i]!==undefined)return{end:e[i]};return!1}(),n.support.transition&&(n.event.special.bsTransitionEnd={bindType:n.support.transition.end,delegateType:n.support.transition.end,handle:function(t){if(n(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}})})}(jQuery),function(s){"use strict";var e='[data-dismiss="alert"]',a=function(t){s(t).on("click",e,this.close)};a.VERSION="3.4.1",a.TRANSITION_DURATION=150,a.prototype.close=function(t){var e=s(this),i=e.attr("data-target");i||(i=(i=e.attr("href"))&&i.replace(/.*(?=#[^\s]*$)/,"")),i="#"===i?[]:i;var o=s(document).find(i);function n(){o.detach().trigger("closed.bs.alert").remove()}t&&t.preventDefault(),o.length||(o=e.closest(".alert")),o.trigger(t=s.Event("close.bs.alert")),t.isDefaultPrevented()||(o.removeClass("in"),s.support.transition&&o.hasClass("fade")?o.one("bsTransitionEnd",n).emulateTransitionEnd(a.TRANSITION_DURATION):n())};var t=s.fn.alert;s.fn.alert=function o(i){return this.each(function(){var t=s(this),e=t.data("bs.alert");e||t.data("bs.alert",e=new a(this)),"string"==typeof i&&e[i].call(t)})},s.fn.alert.Constructor=a,s.fn.alert.noConflict=function(){return s.fn.alert=t,this},s(document).on("click.bs.alert.data-api",e,a.prototype.close)}(jQuery),function(s){"use strict";var n=function(t,e){this.$element=s(t),this.options=s.extend({},n.DEFAULTS,e),this.isLoading=!1};function i(o){return this.each(function(){var t=s(this),e=t.data("bs.button"),i="object"==typeof o&&o;e||t.data("bs.button",e=new n(this,i)),"toggle"==o?e.toggle():o&&e.setState(o)})}n.VERSION="3.4.1",n.DEFAULTS={loadingText:"loading..."},n.prototype.setState=function(t){var e="disabled",i=this.$element,o=i.is("input")?"val":"html",n=i.data();t+="Text",null==n.resetText&&i.data("resetText",i[o]()),setTimeout(s.proxy(function(){i[o](null==n[t]?this.options[t]:n[t]),"loadingText"==t?(this.isLoading=!0,i.addClass(e).attr(e,e).prop(e,!0)):this.isLoading&&(this.isLoading=!1,i.removeClass(e).removeAttr(e).prop(e,!1))},this),0)},n.prototype.toggle=function(){var t=!0,e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var i=this.$element.find("input");"radio"==i.prop("type")?(i.prop("checked")&&(t=!1),e.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==i.prop("type")&&(i.prop("checked")!==this.$element.hasClass("active")&&(t=!1),this.$element.toggleClass("active")),i.prop("checked",this.$element.hasClass("active")),t&&i.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var t=s.fn.button;s.fn.button=i,s.fn.button.Constructor=n,s.fn.button.noConflict=function(){return s.fn.button=t,this},s(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(t){var e=s(t.target).closest(".btn");i.call(e,"toggle"),s(t.target).is('input[type="radio"], input[type="checkbox"]')||(t.preventDefault(),e.is("input,button")?e.trigger("focus"):e.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(t){s(t.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(t.type))})}(jQuery),function(p){"use strict";var c=function(t,e){this.$element=p(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=e,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",p.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",p.proxy(this.pause,this)).on("mouseleave.bs.carousel",p.proxy(this.cycle,this))};function r(n){return this.each(function(){var t=p(this),e=t.data("bs.carousel"),i=p.extend({},c.DEFAULTS,t.data(),"object"==typeof n&&n),o="string"==typeof n?n:i.slide;e||t.data("bs.carousel",e=new c(this,i)),"number"==typeof n?e.to(n):o?e[o]():i.interval&&e.pause().cycle()})}c.VERSION="3.4.1",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(t){if(!/input|textarea/i.test(t.target.tagName)){switch(t.which){case 37:this.prev();break;case 39:this.next();break;default:return}t.preventDefault()}},c.prototype.cycle=function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(p.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(t){return this.$items=t.parent().children(".item"),this.$items.index(t||this.$active)},c.prototype.getItemForDirection=function(t,e){var i=this.getItemIndex(e);if(("prev"==t&&0===i||"next"==t&&i==this.$items.length-1)&&!this.options.wrap)return e;var o=(i+("prev"==t?-1:1))%this.$items.length;return this.$items.eq(o)},c.prototype.to=function(t){var e=this,i=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(t>this.$items.length-1||t<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):i==t?this.pause().cycle():this.slide(i<t?"next":"prev",this.$items.eq(t))},c.prototype.pause=function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&p.support.transition&&(this.$element.trigger(p.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(t,e){var i=this.$element.find(".item.active"),o=e||this.getItemForDirection(t,i),n=this.interval,s="next"==t?"left":"right",a=this;if(o.hasClass("active"))return this.sliding=!1;var r=o[0],l=p.Event("slide.bs.carousel",{relatedTarget:r,direction:s});if(this.$element.trigger(l),!l.isDefaultPrevented()){if(this.sliding=!0,n&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var h=p(this.$indicators.children()[this.getItemIndex(o)]);h&&h.addClass("active")}var d=p.Event("slid.bs.carousel",{relatedTarget:r,direction:s});return p.support.transition&&this.$element.hasClass("slide")?(o.addClass(t),"object"==typeof o&&o.length&&o[0].offsetWidth,i.addClass(s),o.addClass(s),i.one("bsTransitionEnd",function(){o.removeClass([t,s].join(" ")).addClass("active"),i.removeClass(["active",s].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger(d)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(i.removeClass("active"),o.addClass("active"),this.sliding=!1,this.$element.trigger(d)),n&&this.cycle(),this}};var t=p.fn.carousel;p.fn.carousel=r,p.fn.carousel.Constructor=c,p.fn.carousel.noConflict=function(){return p.fn.carousel=t,this};var e=function(t){var e=p(this),i=e.attr("href");i&&(i=i.replace(/.*(?=#[^\s]+$)/,""));var o=e.attr("data-target")||i,n=p(document).find(o);if(n.hasClass("carousel")){var s=p.extend({},n.data(),e.data()),a=e.attr("data-slide-to");a&&(s.interval=!1),r.call(n,s),a&&n.data("bs.carousel").to(a),t.preventDefault()}};p(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),p(window).on("load",function(){p('[data-ride="carousel"]').each(function(){var t=p(this);r.call(t,t.data())})})}(jQuery),function(a){"use strict";var r=function(t,e){this.$element=a(t),this.options=a.extend({},r.DEFAULTS,e),this.$trigger=a('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};function n(t){var e,i=t.attr("data-target")||(e=t.attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"");return a(document).find(i)}function l(o){return this.each(function(){var t=a(this),e=t.data("bs.collapse"),i=a.extend({},r.DEFAULTS,t.data(),"object"==typeof o&&o);!e&&i.toggle&&/show|hide/.test(o)&&(i.toggle=!1),e||t.data("bs.collapse",e=new r(this,i)),"string"==typeof o&&e[o]()})}r.VERSION="3.4.1",r.TRANSITION_DURATION=350,r.DEFAULTS={toggle:!0},r.prototype.dimension=function(){return this.$element.hasClass("width")?"width":"height"},r.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var t,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(t=e.data("bs.collapse"))&&t.transitioning)){var i=a.Event("show.bs.collapse");if(this.$element.trigger(i),!i.isDefaultPrevented()){e&&e.length&&(l.call(e,"hide"),t||e.data("bs.collapse",null));var o=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[o](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var n=function(){this.$element.removeClass("collapsing").addClass("collapse in")[o](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return n.call(this);var s=a.camelCase(["scroll",o].join("-"));this.$element.one("bsTransitionEnd",a.proxy(n,this)).emulateTransitionEnd(r.TRANSITION_DURATION)[o](this.$element[0][s])}}}},r.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var t=a.Event("hide.bs.collapse");if(this.$element.trigger(t),!t.isDefaultPrevented()){var e=this.dimension();this.$element[e](this.$element[e]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var i=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};if(!a.support.transition)return i.call(this);this.$element[e](0).one("bsTransitionEnd",a.proxy(i,this)).emulateTransitionEnd(r.TRANSITION_DURATION)}}},r.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},r.prototype.getParent=function(){return a(document).find(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(t,e){var i=a(e);this.addAriaAndCollapsedClass(n(i),i)},this)).end()},r.prototype.addAriaAndCollapsedClass=function(t,e){var i=t.hasClass("in");t.attr("aria-expanded",i),e.toggleClass("collapsed",!i).attr("aria-expanded",i)};var t=a.fn.collapse;a.fn.collapse=l,a.fn.collapse.Constructor=r,a.fn.collapse.noConflict=function(){return a.fn.collapse=t,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(t){var e=a(this);e.attr("data-target")||t.preventDefault();var i=n(e),o=i.data("bs.collapse")?"toggle":e.data();l.call(i,o)})}(jQuery),function(a){"use strict";var r='[data-toggle="dropdown"]',o=function(t){a(t).on("click.bs.dropdown",this.toggle)};function l(t){var e=t.attr("data-target");e||(e=(e=t.attr("href"))&&/#[A-Za-z]/.test(e)&&e.replace(/.*(?=#[^\s]*$)/,""));var i="#"!==e?a(document).find(e):null;return i&&i.length?i:t.parent()}function s(o){o&&3===o.which||(a(".dropdown-backdrop").remove(),a(r).each(function(){var t=a(this),e=l(t),i={relatedTarget:this};e.hasClass("open")&&(o&&"click"==o.type&&/input|textarea/i.test(o.target.tagName)&&a.contains(e[0],o.target)||(e.trigger(o=a.Event("hide.bs.dropdown",i)),o.isDefaultPrevented()||(t.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",i)))))}))}o.VERSION="3.4.1",o.prototype.toggle=function(t){var e=a(this);if(!e.is(".disabled, :disabled")){var i=l(e),o=i.hasClass("open");if(s(),!o){"ontouchstart"in document.documentElement&&!i.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",s);var n={relatedTarget:this};if(i.trigger(t=a.Event("show.bs.dropdown",n)),t.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),i.toggleClass("open").trigger(a.Event("shown.bs.dropdown",n))}return!1}},o.prototype.keydown=function(t){if(/(38|40|27|32)/.test(t.which)&&!/input|textarea/i.test(t.target.tagName)){var e=a(this);if(t.preventDefault(),t.stopPropagation(),!e.is(".disabled, :disabled")){var i=l(e),o=i.hasClass("open");if(!o&&27!=t.which||o&&27==t.which)return 27==t.which&&i.find(r).trigger("focus"),e.trigger("click");var n=i.find(".dropdown-menu li:not(.disabled):visible a");if(n.length){var s=n.index(t.target);38==t.which&&0<s&&s--,40==t.which&&s<n.length-1&&s++,~s||(s=0),n.eq(s).trigger("focus")}}}};var t=a.fn.dropdown;a.fn.dropdown=function e(i){return this.each(function(){var t=a(this),e=t.data("bs.dropdown");e||t.data("bs.dropdown",e=new o(this)),"string"==typeof i&&e[i].call(t)})},a.fn.dropdown.Constructor=o,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=t,this},a(document).on("click.bs.dropdown.data-api",s).on("click.bs.dropdown.data-api",".dropdown form",function(t){t.stopPropagation()}).on("click.bs.dropdown.data-api",r,o.prototype.toggle).on("keydown.bs.dropdown.data-api",r,o.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",o.prototype.keydown)}(jQuery),function(a){"use strict";var s=function(t,e){this.options=e,this.$body=a(document.body),this.$element=a(t),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.fixedContent=".navbar-fixed-top, .navbar-fixed-bottom",this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};function r(o,n){return this.each(function(){var t=a(this),e=t.data("bs.modal"),i=a.extend({},s.DEFAULTS,t.data(),"object"==typeof o&&o);e||t.data("bs.modal",e=new s(this,i)),"string"==typeof o?e[o](n):i.show&&e.show(n)})}s.VERSION="3.4.1",s.TRANSITION_DURATION=300,s.BACKDROP_TRANSITION_DURATION=150,s.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},s.prototype.toggle=function(t){return this.isShown?this.hide():this.show(t)},s.prototype.show=function(i){var o=this,t=a.Event("show.bs.modal",{relatedTarget:i});this.$element.trigger(t),this.isShown||t.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){o.$element.one("mouseup.dismiss.bs.modal",function(t){a(t.target).is(o.$element)&&(o.ignoreBackdropClick=!0)})}),this.backdrop(function(){var t=a.support.transition&&o.$element.hasClass("fade");o.$element.parent().length||o.$element.appendTo(o.$body),o.$element.show().scrollTop(0),o.adjustDialog(),t&&o.$element[0].offsetWidth,o.$element.addClass("in"),o.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:i});t?o.$dialog.one("bsTransitionEnd",function(){o.$element.trigger("focus").trigger(e)}).emulateTransitionEnd(s.TRANSITION_DURATION):o.$element.trigger("focus").trigger(e)}))},s.prototype.hide=function(t){t&&t.preventDefault(),t=a.Event("hide.bs.modal"),this.$element.trigger(t),this.isShown&&!t.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(s.TRANSITION_DURATION):this.hideModal())},s.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(t){document===t.target||this.$element[0]===t.target||this.$element.has(t.target).length||this.$element.trigger("focus")},this))},s.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(t){27==t.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},s.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},s.prototype.hideModal=function(){var t=this;this.$element.hide(),this.backdrop(function(){t.$body.removeClass("modal-open"),t.resetAdjustments(),t.resetScrollbar(),t.$element.trigger("hidden.bs.modal")})},s.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},s.prototype.backdrop=function(t){var e=this,i=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var o=a.support.transition&&i;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+i).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(t){this.ignoreBackdropClick?this.ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide())},this)),o&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!t)return;o?this.$backdrop.one("bsTransitionEnd",t).emulateTransitionEnd(s.BACKDROP_TRANSITION_DURATION):t()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var n=function(){e.removeBackdrop(),t&&t()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",n).emulateTransitionEnd(s.BACKDROP_TRANSITION_DURATION):n()}else t&&t()},s.prototype.handleUpdate=function(){this.adjustDialog()},s.prototype.adjustDialog=function(){var t=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},s.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},s.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth<t,this.scrollbarWidth=this.measureScrollbar()},s.prototype.setScrollbar=function(){var t=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"";var n=this.scrollbarWidth;this.bodyIsOverflowing&&(this.$body.css("padding-right",t+n),a(this.fixedContent).each(function(t,e){var i=e.style.paddingRight,o=a(e).css("padding-right");a(e).data("padding-right",i).css("padding-right",parseFloat(o)+n+"px")}))},s.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad),a(this.fixedContent).each(function(t,e){var i=a(e).data("padding-right");a(e).removeData("padding-right"),e.style.paddingRight=i||""})},s.prototype.measureScrollbar=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",this.$body.append(t);var e=t.offsetWidth-t.clientWidth;return this.$body[0].removeChild(t),e};var t=a.fn.modal;a.fn.modal=r,a.fn.modal.Constructor=s,a.fn.modal.noConflict=function(){return a.fn.modal=t,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(t){var e=a(this),i=e.attr("href"),o=e.attr("data-target")||i&&i.replace(/.*(?=#[^\s]+$)/,""),n=a(document).find(o),s=n.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(i)&&i},n.data(),e.data());e.is("a")&&t.preventDefault(),n.one("show.bs.modal",function(t){t.isDefaultPrevented()||n.one("hidden.bs.modal",function(){e.is(":visible")&&e.trigger("focus")})}),r.call(n,s,this)})}(jQuery),function(g){"use strict";var o=["sanitize","whiteList","sanitizeFn"],a=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],t={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},r=/^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi,l=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;function u(t,e){var i=t.nodeName.toLowerCase();if(-1!==g.inArray(i,e))return-1===g.inArray(i,a)||Boolean(t.nodeValue.match(r)||t.nodeValue.match(l));for(var o=g(e).filter(function(t,e){return e instanceof RegExp}),n=0,s=o.length;n<s;n++)if(i.match(o[n]))return!0;return!1}function n(t,e,i){if(0===t.length)return t;if(i&&"function"==typeof i)return i(t);if(!document.implementation||!document.implementation.createHTMLDocument)return t;var o=document.implementation.createHTMLDocument("sanitization");o.body.innerHTML=t;for(var n=g.map(e,function(t,e){return e}),s=g(o.body).find("*"),a=0,r=s.length;a<r;a++){var l=s[a],h=l.nodeName.toLowerCase();if(-1!==g.inArray(h,n))for(var d=g.map(l.attributes,function(t){return t}),p=[].concat(e["*"]||[],e[h]||[]),c=0,f=d.length;c<f;c++)u(d[c],p)||l.removeAttribute(d[c].nodeName);else l.parentNode.removeChild(l)}return o.body.innerHTML}var m=function(t,e){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",t,e)};m.VERSION="3.4.1",m.TRANSITION_DURATION=150,m.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0},sanitize:!0,sanitizeFn:null,whiteList:t},m.prototype.init=function(t,e,i){if(this.enabled=!0,this.type=t,this.$element=g(e),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&g(document).find(g.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var o=this.options.trigger.split(" "),n=o.length;n--;){var s=o[n];if("click"==s)this.$element.on("click."+this.type,this.options.selector,g.proxy(this.toggle,this));else if("manual"!=s){var a="hover"==s?"mouseenter":"focusin",r="hover"==s?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,g.proxy(this.enter,this)),this.$element.on(r+"."+this.type,this.options.selector,g.proxy(this.leave,this))}}this.options.selector?this._options=g.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},m.prototype.getDefaults=function(){return m.DEFAULTS},m.prototype.getOptions=function(t){var e=this.$element.data();for(var i in e)e.hasOwnProperty(i)&&-1!==g.inArray(i,o)&&delete e[i];return(t=g.extend({},this.getDefaults(),e,t)).delay&&"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),t.sanitize&&(t.template=n(t.template,t.whiteList,t.sanitizeFn)),t},m.prototype.getDelegateOptions=function(){var i={},o=this.getDefaults();return this._options&&g.each(this._options,function(t,e){o[t]!=e&&(i[t]=e)}),i},m.prototype.enter=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusin"==t.type?"focus":"hover"]=!0),e.tip().hasClass("in")||"in"==e.hoverState)e.hoverState="in";else{if(clearTimeout(e.timeout),e.hoverState="in",!e.options.delay||!e.options.delay.show)return e.show();e.timeout=setTimeout(function(){"in"==e.hoverState&&e.show()},e.options.delay.show)}},m.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},m.prototype.leave=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusout"==t.type?"focus":"hover"]=!1),!e.isInStateTrue()){if(clearTimeout(e.timeout),e.hoverState="out",!e.options.delay||!e.options.delay.hide)return e.hide();e.timeout=setTimeout(function(){"out"==e.hoverState&&e.hide()},e.options.delay.hide)}},m.prototype.show=function(){var t=g.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(t);var e=g.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(t.isDefaultPrevented()||!e)return;var i=this,o=this.tip(),n=this.getUID(this.type);this.setContent(),o.attr("id",n),this.$element.attr("aria-describedby",n),this.options.animation&&o.addClass("fade");var s="function"==typeof this.options.placement?this.options.placement.call(this,o[0],this.$element[0]):this.options.placement,a=/\s?auto?\s?/i,r=a.test(s);r&&(s=s.replace(a,"")||"top"),o.detach().css({top:0,left:0,display:"block"}).addClass(s).data("bs."+this.type,this),this.options.container?o.appendTo(g(document).find(this.options.container)):o.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var l=this.getPosition(),h=o[0].offsetWidth,d=o[0].offsetHeight;if(r){var p=s,c=this.getPosition(this.$viewport);s="bottom"==s&&l.bottom+d>c.bottom?"top":"top"==s&&l.top-d<c.top?"bottom":"right"==s&&l.right+h>c.width?"left":"left"==s&&l.left-h<c.left?"right":s,o.removeClass(p).addClass(s)}var f=this.getCalculatedOffset(s,l,h,d);this.applyPlacement(f,s);var u=function(){var t=i.hoverState;i.$element.trigger("shown.bs."+i.type),i.hoverState=null,"out"==t&&i.leave(i)};g.support.transition&&this.$tip.hasClass("fade")?o.one("bsTransitionEnd",u).emulateTransitionEnd(m.TRANSITION_DURATION):u()}},m.prototype.applyPlacement=function(t,e){var i=this.tip(),o=i[0].offsetWidth,n=i[0].offsetHeight,s=parseInt(i.css("margin-top"),10),a=parseInt(i.css("margin-left"),10);isNaN(s)&&(s=0),isNaN(a)&&(a=0),t.top+=s,t.left+=a,g.offset.setOffset(i[0],g.extend({using:function(t){i.css({top:Math.round(t.top),left:Math.round(t.left)})}},t),0),i.addClass("in");var r=i[0].offsetWidth,l=i[0].offsetHeight;"top"==e&&l!=n&&(t.top=t.top+n-l);var h=this.getViewportAdjustedDelta(e,t,r,l);h.left?t.left+=h.left:t.top+=h.top;var d=/top|bottom/.test(e),p=d?2*h.left-o+r:2*h.top-n+l,c=d?"offsetWidth":"offsetHeight";i.offset(t),this.replaceArrow(p,i[0][c],d)},m.prototype.replaceArrow=function(t,e,i){this.arrow().css(i?"left":"top",50*(1-t/e)+"%").css(i?"top":"left","")},m.prototype.setContent=function(){var t=this.tip(),e=this.getTitle();this.options.html?(this.options.sanitize&&(e=n(e,this.options.whiteList,this.options.sanitizeFn)),t.find(".tooltip-inner").html(e)):t.find(".tooltip-inner").text(e),t.removeClass("fade in top bottom left right")},m.prototype.hide=function(t){var e=this,i=g(this.$tip),o=g.Event("hide.bs."+this.type);function n(){"in"!=e.hoverState&&i.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),t&&t()}if(this.$element.trigger(o),!o.isDefaultPrevented())return i.removeClass("in"),g.support.transition&&i.hasClass("fade")?i.one("bsTransitionEnd",n).emulateTransitionEnd(m.TRANSITION_DURATION):n(),this.hoverState=null,this},m.prototype.fixTitle=function(){var t=this.$element;(t.attr("title")||"string"!=typeof t.attr("data-original-title"))&&t.attr("data-original-title",t.attr("title")||"").attr("title","")},m.prototype.hasContent=function(){return this.getTitle()},m.prototype.getPosition=function(t){var e=(t=t||this.$element)[0],i="BODY"==e.tagName,o=e.getBoundingClientRect();null==o.width&&(o=g.extend({},o,{width:o.right-o.left,height:o.bottom-o.top}));var n=window.SVGElement&&e instanceof window.SVGElement,s=i?{top:0,left:0}:n?null:t.offset(),a={scroll:i?document.documentElement.scrollTop||document.body.scrollTop:t.scrollTop()},r=i?{width:g(window).width(),height:g(window).height()}:null;return g.extend({},o,a,r,s)},m.prototype.getCalculatedOffset=function(t,e,i,o){return"bottom"==t?{top:e.top+e.height,left:e.left+e.width/2-i/2}:"top"==t?{top:e.top-o,left:e.left+e.width/2-i/2}:"left"==t?{top:e.top+e.height/2-o/2,left:e.left-i}:{top:e.top+e.height/2-o/2,left:e.left+e.width}},m.prototype.getViewportAdjustedDelta=function(t,e,i,o){var n={top:0,left:0};if(!this.$viewport)return n;var s=this.options.viewport&&this.options.viewport.padding||0,a=this.getPosition(this.$viewport);if(/right|left/.test(t)){var r=e.top-s-a.scroll,l=e.top+s-a.scroll+o;r<a.top?n.top=a.top-r:l>a.top+a.height&&(n.top=a.top+a.height-l)}else{var h=e.left-s,d=e.left+s+i;h<a.left?n.left=a.left-h:d>a.right&&(n.left=a.left+a.width-d)}return n},m.prototype.getTitle=function(){var t=this.$element,e=this.options;return t.attr("data-original-title")||("function"==typeof e.title?e.title.call(t[0]):e.title)},m.prototype.getUID=function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},m.prototype.tip=function(){if(!this.$tip&&(this.$tip=g(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},m.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},m.prototype.enable=function(){this.enabled=!0},m.prototype.disable=function(){this.enabled=!1},m.prototype.toggleEnabled=function(){this.enabled=!this.enabled},m.prototype.toggle=function(t){var e=this;t&&((e=g(t.currentTarget).data("bs."+this.type))||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e))),t?(e.inState.click=!e.inState.click,e.isInStateTrue()?e.enter(e):e.leave(e)):e.tip().hasClass("in")?e.leave(e):e.enter(e)},m.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})},m.prototype.sanitizeHtml=function(t){return n(t,this.options.whiteList,this.options.sanitizeFn)};var e=g.fn.tooltip;g.fn.tooltip=function i(o){return this.each(function(){var t=g(this),e=t.data("bs.tooltip"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.tooltip",e=new m(this,i)),"string"==typeof o&&e[o]())})},g.fn.tooltip.Constructor=m,g.fn.tooltip.noConflict=function(){return g.fn.tooltip=e,this}}(jQuery),function(n){"use strict";var s=function(t,e){this.init("popover",t,e)};if(!n.fn.tooltip)throw new Error("Popover requires tooltip.js");s.VERSION="3.4.1",s.DEFAULTS=n.extend({},n.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),((s.prototype=n.extend({},n.fn.tooltip.Constructor.prototype)).constructor=s).prototype.getDefaults=function(){return s.DEFAULTS},s.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();if(this.options.html){var o=typeof i;this.options.sanitize&&(e=this.sanitizeHtml(e),"string"===o&&(i=this.sanitizeHtml(i))),t.find(".popover-title").html(e),t.find(".popover-content").children().detach().end()["string"===o?"html":"append"](i)}else t.find(".popover-title").text(e),t.find(".popover-content").children().detach().end().text(i);t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},s.prototype.hasContent=function(){return this.getTitle()||this.getContent()},s.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},s.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var t=n.fn.popover;n.fn.popover=function e(o){return this.each(function(){var t=n(this),e=t.data("bs.popover"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.popover",e=new s(this,i)),"string"==typeof o&&e[o]())})},n.fn.popover.Constructor=s,n.fn.popover.noConflict=function(){return n.fn.popover=t,this}}(jQuery),function(s){"use strict";function n(t,e){this.$body=s(document.body),this.$scrollElement=s(t).is(document.body)?s(window):s(t),this.options=s.extend({},n.DEFAULTS,e),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",s.proxy(this.process,this)),this.refresh(),this.process()}function e(o){return this.each(function(){var t=s(this),e=t.data("bs.scrollspy"),i="object"==typeof o&&o;e||t.data("bs.scrollspy",e=new n(this,i)),"string"==typeof o&&e[o]()})}n.VERSION="3.4.1",n.DEFAULTS={offset:10},n.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},n.prototype.refresh=function(){var t=this,o="offset",n=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),s.isWindow(this.$scrollElement[0])||(o="position",n=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var t=s(this),e=t.data("target")||t.attr("href"),i=/^#./.test(e)&&s(e);return i&&i.length&&i.is(":visible")&&[[i[o]().top+n,e]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},n.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,i=this.getScrollHeight(),o=this.options.offset+i-this.$scrollElement.height(),n=this.offsets,s=this.targets,a=this.activeTarget;if(this.scrollHeight!=i&&this.refresh(),o<=e)return a!=(t=s[s.length-1])&&this.activate(t);if(a&&e<n[0])return this.activeTarget=null,this.clear();for(t=n.length;t--;)a!=s[t]&&e>=n[t]&&(n[t+1]===undefined||e<n[t+1])&&this.activate(s[t])},n.prototype.activate=function(t){this.activeTarget=t,this.clear();var e=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',i=s(e).parents("li").addClass("active");i.parent(".dropdown-menu").length&&(i=i.closest("li.dropdown").addClass("active")),i.trigger("activate.bs.scrollspy")},n.prototype.clear=function(){s(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var t=s.fn.scrollspy;s.fn.scrollspy=e,s.fn.scrollspy.Constructor=n,s.fn.scrollspy.noConflict=function(){return s.fn.scrollspy=t,this},s(window).on("load.bs.scrollspy.data-api",function(){s('[data-spy="scroll"]').each(function(){var t=s(this);e.call(t,t.data())})})}(jQuery),function(r){"use strict";var a=function(t){this.element=r(t)};function e(i){return this.each(function(){var t=r(this),e=t.data("bs.tab");e||t.data("bs.tab",e=new a(this)),"string"==typeof i&&e[i]()})}a.VERSION="3.4.1",a.TRANSITION_DURATION=150,a.prototype.show=function(){var t=this.element,e=t.closest("ul:not(.dropdown-menu)"),i=t.data("target");if(i||(i=(i=t.attr("href"))&&i.replace(/.*(?=#[^\s]*$)/,"")),!t.parent("li").hasClass("active")){var o=e.find(".active:last a"),n=r.Event("hide.bs.tab",{relatedTarget:t[0]}),s=r.Event("show.bs.tab",{relatedTarget:o[0]});if(o.trigger(n),t.trigger(s),!s.isDefaultPrevented()&&!n.isDefaultPrevented()){var a=r(document).find(i);this.activate(t.closest("li"),e),this.activate(a,a.parent(),function(){o.trigger({type:"hidden.bs.tab",relatedTarget:t[0]}),t.trigger({type:"shown.bs.tab",relatedTarget:o[0]})})}}},a.prototype.activate=function(t,e,i){var o=e.find("> .active"),n=i&&r.support.transition&&(o.length&&o.hasClass("fade")||!!e.find("> .fade").length);function s(){o.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),t.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),n?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu").length&&t.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),i&&i()}o.length&&n?o.one("bsTransitionEnd",s).emulateTransitionEnd(a.TRANSITION_DURATION):s(),o.removeClass("in")};var t=r.fn.tab;r.fn.tab=e,r.fn.tab.Constructor=a,r.fn.tab.noConflict=function(){return r.fn.tab=t,this};var i=function(t){t.preventDefault(),e.call(r(this),"show")};r(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',i).on("click.bs.tab.data-api",'[data-toggle="pill"]',i)}(jQuery),function(l){"use strict";var h=function(t,e){this.options=l.extend({},h.DEFAULTS,e);var i=this.options.target===h.DEFAULTS.target?l(this.options.target):l(document).find(this.options.target);this.$target=i.on("scroll.bs.affix.data-api",l.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",l.proxy(this.checkPositionWithEventLoop,this)),this.$element=l(t),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};function i(o){return this.each(function(){var t=l(this),e=t.data("bs.affix"),i="object"==typeof o&&o;e||t.data("bs.affix",e=new h(this,i)),"string"==typeof o&&e[o]()})}h.VERSION="3.4.1",h.RESET="affix affix-top affix-bottom",h.DEFAULTS={offset:0,target:window},h.prototype.getState=function(t,e,i,o){var n=this.$target.scrollTop(),s=this.$element.offset(),a=this.$target.height();if(null!=i&&"top"==this.affixed)return n<i&&"top";if("bottom"==this.affixed)return null!=i?!(n+this.unpin<=s.top)&&"bottom":!(n+a<=t-o)&&"bottom";var r=null==this.affixed,l=r?n:s.top;return null!=i&&n<=i?"top":null!=o&&t-o<=l+(r?a:e)&&"bottom"},h.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(h.RESET).addClass("affix");var t=this.$target.scrollTop(),e=this.$element.offset();return this.pinnedOffset=e.top-t},h.prototype.checkPositionWithEventLoop=function(){setTimeout(l.proxy(this.checkPosition,this),1)},h.prototype.checkPosition=function(){if(this.$element.is(":visible")){var t=this.$element.height(),e=this.options.offset,i=e.top,o=e.bottom,n=Math.max(l(document).height(),l(document.body).height());"object"!=typeof e&&(o=i=e),"function"==typeof i&&(i=e.top(this.$element)),"function"==typeof o&&(o=e.bottom(this.$element));var s=this.getState(n,t,i,o);if(this.affixed!=s){null!=this.unpin&&this.$element.css("top","");var a="affix"+(s?"-"+s:""),r=l.Event(a+".bs.affix");if(this.$element.trigger(r),r.isDefaultPrevented())return;this.affixed=s,this.unpin="bottom"==s?this.getPinnedOffset():null,this.$element.removeClass(h.RESET).addClass(a).trigger(a.replace("affix","affixed")+".bs.affix")}"bottom"==s&&this.$element.offset({top:n-t-o})}};var t=l.fn.affix;l.fn.affix=i,l.fn.affix.Constructor=h,l.fn.affix.noConflict=function(){return l.fn.affix=t,this},l(window).on("load",function(){l('[data-spy="affix"]').each(function(){var t=l(this),e=t.data();e.offset=e.offset||{},null!=e.offsetBottom&&(e.offset.bottom=e.offsetBottom),null!=e.offsetTop&&(e.offset.top=e.offsetTop),i.call(t,e)})})}(jQuery);
vendor: 4,705 bytes, lines 6-18
6
7/*
8 Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
9*/
10(function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k));
11if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("<div />"))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q,
12u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),e<F&&(m=!1,c=q,null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),
13h.detach()),b={position:"",width:"",top:""},a.css(b).removeClass(t).trigger("sticky_kit:unstick")),B&&(b=f.height(),u+q>b&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}),
14a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize",
15y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n<K;n++)d=this[n],J(b(d));return this}}).call(this);
16
17/*!@license Copyright 2013, Heinrich Goebl, License: MIT, see https://github.com/hgoebl/mobile-detect.js*/
18!function(a,b){a(function(){"use strict";function a(a,b){return null!=a&&null!=b&&a.toLowerCase()===b.toLowerCase()}function c(a,b){var c,d,e=a.length;if(!e||!b)return!1;for(c=b.toLowerCase(),d=0;d<e;++d)if(c===a[d].toLowerCase())return!0;return!1}function d(a){for(var b in a)i.call(a,b)&&(a[b]=new RegExp(a[b],"i"))}function e(a){return(a||"").substr(0,500)}function f(a,b){this.ua=e(a),this._cache={},this.maxPhoneWidth=b||600}var g={};g.mobileDetectRules={phones:{iPhone:"\\biPhone\\b|\\biPod\\b",BlackBerry:"BlackBerry|\\bBB10\\b|rim[0-9]+|\\b(BBA100|BBB100|BBD100|BBE100|BBF100|STH100)\\b-[0-9]+",HTC:"HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\\bEVO\\b|T-Mobile G1|Z520m|Android [0-9.]+; Pixel",Nexus:"Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6",Dell:"Dell[;]? (Streak|Aero|Venue|Venue Pro|Flash|Smoke|Mini 3iX)|XCD28|XCD35|\\b001DL\\b|\\b101DL\\b|\\bGS01\\b",Motorola:"Motorola|DROIDX|DROID BIONIC|\\bDroid\\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\\bMoto E\\b|XT1068|XT1092|XT1052",Samsung:
vendor: 5,421 bytes, line 18
18"\\bSamsung\\b|SM-G950F|SM-G955F|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F|SM-G920F|SM-G920V|SM-G930F|SM-N910C|SM-A310F|GT-I9190|SM-J500FN|SM-G903F|SM-J330F
18",LG:"\\bLG\\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323|M257)|LM-G710",Sony:"SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533",Asus:"Asus.*Galaxy|PadFone.*Mobile",NokiaLumia:"Lumia [0-9]{3,4}",Micromax:"Micromax.*\\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\\b",Palm:"PalmSource|Palm",Vertu:"Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature",Pantech:"PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790",Fly:"IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250",Wiko:"KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLI
18M|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM",iMobile:"i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)",SimValley:"\\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\\b",Wolfgang:"AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q",Alcatel:"Alcatel",Nintendo:"Nintendo (3DS|Switch)",Amoi:"Amoi",INQ:"INQ",OnePlus:"ONEPLUS",GenericPhone:"Tapatalk|PDA;|SAGEM|\\bmmp\\b|pocket|\\bpsp\\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\\bwap\\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser"},tablets:{iPad:"iPad|iPad.*Mobile",NexusTablet:"Android.*Nexus[\\s]+(7|9|10)",GoogleTablet:"Android.*Pixel C",SamsungTablet:"SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-T116BU|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y?|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587|SM-P350|SM-P555M|SM-P355M|SM-T113NU|SM-T815Y|SM-T585|SM-T285|SM-T825|SM-W708|SM-T835|SM-T830|SM-T837V|SM-T720|SM-T510|SM-T387V",Kindle:"Kindle|Silk.*Accelerated|Android.*\\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI|KFFOWI|KFGIWI|KFMEWI)\\b|Android.*Silk/[0-9.]+ like Chrome/[0-9.]+ (?!Mobile)",SurfaceTablet:"Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)",HPTablet:"HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10",AsusTablet:"^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\\bK00F\\b|\\bK00C\\b|\\bK00E\\b|\\bK00L\\b|TX201LA|ME176C|ME102A|\\bM80TA\\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\\bME70C\\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z|\\bP027\\b|\\bP024\\b|\\bP00C\\b",BlackBerryTablet:"PlayBook|RIM Tablet",HTCtablet:"HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410",MotorolaTablet:"xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617",NookTablet:"Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2",AcerTablet:"Android.*; \\b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\\b|W3-810|\\bA3-A10\\b|\\bA3-A11\\b|\\bA3-A20\\b|\\bA3-A30",ToshibaTablet:"Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO",LGTablet:"\\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V4
1800|LG-VK810\\b",FujitsuTablet:"Android.*\\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\\b",PrestigioTablet:"PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002",LenovoTablet:"Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-850M|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)|TB-X103F|TB-X304X|TB-X304F|TB-X304L|TB-X505F|TB-X505L|TB-X505X|TB-X605F|TB-X605L|TB-8703F|TB-8703X|TB-8703N|TB-8704N|TB-8704F|TB-8704X|TB-8704V|TB-7304F|TB-7304I|TB-7304X|Tab2A7-10F|Tab2A7-20F|TB2-X30L|YT3-X50L|YT3-X50F|YT3-X50M|YT-X705F|YT-X703F|YT-X703L|YT-X705L|YT-X705X|TB2-X30F|TB2-X30L|TB2-X30M|A2107A-F|A2107A-H|TB3-730F|TB3-730M|TB3-730X|TB-7504F|TB-7504X",DellTablet:"Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7",YarvikTablet:"Android.*\\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\\b",MedionTablet:"Android.*\\bOYO\\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB",ArnovaTablet:"97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2",IntensoTablet:"INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004",IRUTablet:"M702pro",MegafonTablet:"MegaFon V9|\\bZTE V9\\b|Android.*\\bMT7A\\b",EbodaTablet:"E-Boda (Supreme|Impresspeed|Izzycomm|Essential)",AllViewTablet:"Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)",ArchosTablet:"\\b(101G9|80G9|A101IT)\\b|Qilive 97R|Archos5|\\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|c|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\\b",AinolTablet:"NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark",NokiaLumiaTablet:"Lumia 2520",SonyTablet:"Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP641|SGP612|SOT31|SGP771|SGP611|SGP612|SGP712",PhilipsTablet:"\\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\\b",CubeTablet:"Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT",CobyTablet:"MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010",MIDTablet:"M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10",MSITablet:"MSI \\b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\\b",SMiTTablet:"Android.*(\\bMID\\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)",RockChipTablet:"Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A",FlyTablet:"IQ310|Fly Vision",bqTablet:"Android.*(bq)?.*\\b(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris ([E|M]10|M8))\\b|Maxwell.*Lite|Maxwell.*Plus",HuaweiTablet:"MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim|M2-A01L|BAH-L09|BAH-W09|AGS-L09|CMR-AL19",NecTablet:"\\bN-06D|\\bN-08D",PantechTablet:"Pantech.*P4100",Bronch
18oTablet:"Broncho.*(N701|N708|N802|a710)",VersusTablet:"TOUCHPAD.*[78910]|\\bTOUCHTAB\\b",ZyncTablet:"z1000|Z99 2G|z930|z990|z909|Z919|z900",PositivoTablet:"TB07STA|TB10STA|TB07FTA|TB10FTA",NabiTablet:"Android.*\\bNabi",KoboTablet:"Kobo Touch|\\bK080\\b|\\bVox\\b Build|\\bArc\\b Build",DanewTablet:"DSlide.*\\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\\b",TexetTablet:"NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE",PlaystationTablet:"Playstation.*(Portable|Vita)",TrekstorTablet:"ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab",PyleAudioTablet:"\\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\\b",AdvanTablet:"Android.* \\b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\\b ",DanyTechTablet:"Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1",GalapadTablet:"Android.*\\bG1\\b(?!\\))
vendor: 9,224 bytes, line 18
18",MicromaxTablet:"Funbook|Micromax.*\\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\\b",KarbonnTablet:"Android.*\\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\\b",AllFineTablet:"Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide",PROSCANTablet:"\\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\\b",YONESTablet:"BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026",ChangJiaTablet:"TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503",GUTablet:"TX-A1301|TX-M9002|Q702|kf026",PointOfViewTablet:"TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10",OvermaxTablet:"OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)|Qualcore 1027",HCLTablet:"HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync",DPSTablet:"DPS Dream 9|DPS Dual 7",VistureTablet:"V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10",CrestaTablet:"CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989",MediatekTablet:"\\bMT8125|MT8389|MT8135|MT8377\\b",ConcordeTablet:"Concorde([ ]+)?Tab|ConCorde ReadMan",GoCleverTablet:"GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042",ModecomTablet:"FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003",VoninoTablet:"\\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\\bQ8\\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\\b",ECSTablet:"V07OT2|TM105A|S10OT1|TR10CS1",StorexTablet:"eZee[_']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab",VodafoneTablet:"SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497|VFD 1400",EssentielBTablet:"Smart[ ']?TAB[ ]+?[0-9]+|Family[ ']?TAB2",RossMoorTablet:"RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711",iMobileTablet:"i-mobile i-note",TolinoTablet:"tolino tab [0-9.]+|tolino shine",AudioSonicTablet:"\\bC-22Q|T7-QC|T-17B|T-17P\\b",AMPETablet:"Android.* A78 ",SkkTablet:"Android.* (SKYPAD|PHOENIX|CYCLOPS)",TecnoTablet:"TECNO P9|TECNO DP8D",JXDTablet:"Android.* \\b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\\b",iJoyTablet:"Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)",FX2Tablet:"FX2 PAD7|FX2 PAD10",XoroTablet:"KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151",ViewsonicTablet:"ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a",VerizonTablet:"QTAQZ3|QTAIR7|QTAQTZ3|QTASUN1|QTASUN2|QTAXIA1",OdysTablet:"LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\\bXELIO\\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10",CaptivaTablet:"CAPTIVA PAD",IconbitTablet:"NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S",TeclastTablet:"T98 4G|\\bP80\\b|\\bX90HD\\b|X98 Air|X98 Air 3G|\\bX89\\b|P80 3G|\\bX80h\\b|P98 Air|\\bX89HD\\b|P98 3G|\\bP90HD\\b|P89 3G|X98 3G|\\bP70h\\b|P79HD 3G|G18d 3G|\\bP79HD\\b|\\bP89s\\b|\\bA88\\b|\\bP10HD\\b|\\bP19HD\\b|G18 3G|\\bP78HD\\b|\\bA78\\b|\\bP75\\b|G17s 3G|G17h 3G|\\bP85t\\b|\\bP90\\b|\\bP11\\b|\\bP98t\\b|\\bP98HD\\b|\\bG18d\\b|\\bP85s\\b|\\bP11HD\\b|\\bP88s\\b|\\bA80HD\\b|\\bA80se\\b|\\bA10h\\b|\\bP89\\b|\\bP78s\\b|\\bG18\\b|\\bP85\\b|\\bA70h\\b|\\bA70\\b|\\bG17\\b|\\bP18\\b|\\bA80s\\b|\\bA11s\\b|\\bP88HD\\b|\\bA80h\\b|\\bP76s\\b|\\bP76h\\b|\\bP98\\b|\\bA10HD\\b|\\bP78\\b|\\bP88\\b|\\bA11\\b|\\bA10t\\b|\\bP76a\\b|\\bP76t\\b|\\bP76e\\b|\\bP85HD\\b|\\bP85a\\b|\\bP86\\b|\\bP75HD\\b|\\bP76v\\b|\\bA12\\b|\\bP75a\\b|\\bA15\\b|\\bP76Ti\\b|\\bP81HD\\b|\\bA10\\b|\\bT760VE\\b|\\bT720HD\\b|\\bP76\\b|\\bP73\\b|\\bP71\\b|\\bP72\\b|\\bT720SE\\b|\\bC520Ti\\b|\\bT760\\b|\\bT720VE\\b|T720-3GE|T720-WiFi",OndaTablet:"\\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\\b[\\s]+|V10 \\b4G\\b",JaytechTablet:"TPC-PA762",BlaupunktTablet:"Endeavour 800NG|Endeavour 1010",DigmaTablet:"\\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\\b",EvolioTablet:"ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\\bEvotab\\b|\\bNeura\\b",LavaTablet:"QPAD E704|\\bIvoryS\\b|E-TAB IVORY|\\bE-TAB\\b",AocTablet:"MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712",MpmanTablet:"MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\\bMPG7\\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010",CelkonTablet:"CT695|CT888|CT[\\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\\bCT-1\\b",WolderTablet:"miTab \\b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\\b",MediacomTablet:"M-MPI10C3G|M-SP10EG|M-SP10EGP|M-SP10HXAH|M-SP7HXAH|M-SP10HXBH|M-SP8HXAH|M-SP8MXA",MiTablet:"\\bMI PAD\\b|\\bHM NOTE 1W\\b",NibiruTablet:"Nibiru M1|Nibiru Jupiter One",NexoTablet:"NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI",LeaderTablet:"TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100",UbislateTablet:"UbiSlate[\\s]?7C",PocketBookTablet:"Pocketbook",KocasoTablet:"\\b(TB-1207)\\b",HisenseTablet:"\\b(F5281|E2371)\\b",Hudl:"Hudl HT7S3|Hudl 2",TelstraTablet:"T-Hub2",GenericTablet:"Android.*\\b97D\\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\\bA7EB\\b|CatNova8|A1_07|CT704|CT1002|\\bM721\\b|rk30sdk|\\bEVOTAB\\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\\bM6pro\\b|CT1020W|arc 10HD|\\bTP750\\b|\\bQTAQZ3\\b|WVT101|TM1088|KT107"},oss:{AndroidOS:"Android",BlackBerryOS:"blackberry|\\bBB10\\b|rim tablet os",PalmOS:"PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino",SymbianOS:"Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\\bS60\\b",WindowsMobileOS:"Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Windows Mobile|Windows Phone [0-9.]+|WCE;",WindowsPhoneOS:"Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;",iOS:"\\biPhone.*Mobile|\\biPod|\\biPad|AppleCoreMedia",iPadOS:"CPU OS 13",
18MeeGoOS:"MeeGo",MaemoOS:"Maemo",JavaOS:"J2ME/|\\bMIDP\\b|\\bCLDC\\b",webOS:"webOS|hpwOS",badaOS:"\\bBada\\b",BREWOS:"BREW"},uas:{Chrome:"\\bCrMo\\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?",Dolfin:"\\bDolfin\\b",Opera:"Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+$|Coast/[0-9.]+",Skyfire:"Skyfire",Edge:"Mobile Safari/[.0-9]* Edge",IE:"IEMobile|MSIEMobile",Firefox:"fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS",Bolt:"bolt",TeaShark:"teashark",Blazer:"Blazer",Safari:"Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari",WeChat:"\\bMicroMessenger\\b",UCBrowser:"UC.*Browser|UCWEB",baiduboxapp:"baiduboxapp",baidubrowser:"baidubrowser",DiigoBrowser:"DiigoBrowser",Mercury:"\\bMercury\\b",ObigoBrowser:"Obigo",NetFront:"NF-Browser",GenericBrowser:"NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger",PaleMoon:"Android.*PaleMoon|Mobile.*PaleMoon"},props:{Mobile:"Mobile/[VER]",Build:"Build/[VER]",Version:"Version/[VER]",VendorID:"VendorID/[VER]",iPad:"iPad.*CPU[a-z ]+[VER]",iPhone:"iPhone.*CPU[a-z ]+[VER]",iPod:"iPod.*CPU[a-z ]+[VER]",Kindle:"Kindle/[VER]",Chrome:["Chrome/[VER]","CriOS/[VER]","CrMo/[VER]"],Coast:["Coast/[VER]"],Dolfin:"Dolfin/[VER]",Firefox:["Firefox/[VER]","FxiOS/[VER]"],Fennec:"Fennec/[VER]",Edge:"Edge/[VER]",IE:["IEMobile/[VER];","IEMobile [VER]","MSIE [VER];","Trident/[0-9.]+;.*rv:[VER]"],NetFront:"NetFront/[VER]",NokiaBrowser:"NokiaBrowser/[VER]",Opera:[" OPR/[VER]","Opera Mini/[VER]","Version/[VER]"],"Opera Mini":"Opera Mini/[VER]","Opera Mobi":"Version/[VER]",UCBrowser:["UCWEB[VER]","UC.*Browser/[VER]"],MQQBrowser:"MQQBrowser/[VER]",MicroMessenger:"MicroMessenger/[VER]",baiduboxapp:"baiduboxapp/[VER]",baidubrowser:"baidubrowser/[VER]",SamsungBrowser:"SamsungBrowser/[VER]",Iron:"Iron/[VER]",Safari:["Version/[VER]","Safari/[VER]"],Skyfire:"Skyfire/[VER]",Tizen:"Tizen/[VER]",Webkit:"webkit[ /][VER]",PaleMoon:"PaleMoon/[VER]",Gecko:"Gecko/[VER]",Trident:"Trident/[VER]",Presto:"Presto/[VER]",Goanna:"Goanna/[VER]",iOS:" \\bi?OS\\b [VER][ ;]{1}",Android:"Android [VER]",BlackBerry:["BlackBerry[\\w]+/[VER]","BlackBerry.*Version/[VER]","Version/[VER]"],BREW:"BREW [VER]",Java:"Java/[VER]","Windows Phone OS":["Windows Phone OS [VER]","Windows Phone [VER]"],"Windows Phone":"Windows Phone [VER]","Windows CE":"Windows CE/[VER]","Windows NT":"Windows NT [VER]",Symbian:["SymbianOS/[VER]","Symbian/[VER]"],webOS:["webOS/[VER]","hpwOS/[VER];"]},utils:{Bot:"Googlebot|facebookexternalhit|Google-AMPHTML|s~amp-validator|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom|contentkingapp",MobileBot:"Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2",DesktopMode:"WPDesktop",TV:"SonyDTV|HbbTV",WebKit:"(webkit)[ /]([\\w.]+)",Console:"\\b(Nintendo|Nintendo WiiU|Nintendo 3DS|Nintendo Switch|P
vendor: 7,341 bytes, lines 18-19
18LAYSTATION|Xbox)\\b",Watch:"SM-V700"}},g.detectMobileBrowsers={fullPattern:/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i,shortPattern:/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i,
19tabletPattern:/android|ipad|playbook|silk/i};var h,i=Object.prototype.hasOwnProperty;return g.FALLBACK_PHONE="UnknownPhone",g.FALLBACK_TABLET="UnknownTablet",g.FALLBACK_MOBILE="UnknownMobile",h="isArray"in Array?Array.isArray:function(a){return"[object Array]"===Object.prototype.toString.call(a)},function(){var a,b,c,e,f,j,k=g.mobileDetectRules;for(a in k.props)if(i.call(k.props,a)){for(b=k.props[a],h(b)||(b=[b]),f=b.length,e=0;e<f;++e)c=b[e],j=c.indexOf("[VER]"),j>=0&&(c=c.substring(0,j)+"([\\w._\\+]+)"+c.substring(j+5)),b[e]=new RegExp(c,"i");k.props[a]=b}d(k.oss),d(k.phones),d(k.tablets),d(k.uas),d(k.utils),k.oss0={WindowsPhoneOS:k.oss.WindowsPhoneOS,WindowsMobileOS:k.oss.WindowsMobileOS}}(),g.findMatch=function(a,b){for(var c in a)if(i.call(a,c)&&a[c].test(b))return c;return null},g.findMatches=function(a,b){var c=[];for(var d in a)i.call(a,d)&&a[d].test(b)&&c.push(d);return c},g.getVersionStr=function(a,b){var c,d,e,f,h=g.mobileDetectRules.props;if(i.call(h,a))for(c=h[a],e=c.length,d=0;d<e;++d)if(f=c[d].exec(b),null!==f)return f[1];return null},g.getVersion=function(a,b){var c=g.getVersionStr(a,b);return c?g.prepareVersionNo(c):NaN},g.prepareVersionNo=function(a){var b;return b=a.split(/[a-z._ \/\-]/i),1===b.length&&(a=b[0]),b.length>1&&(a=b[0]+".",b.shift(),a+=b.join("")),Number(a)},g.isMobileFallback=function(a){return g.detectMobileBrowsers.fullPattern.test(a)||g.detectMobileBrowsers.shortPattern.test(a.substr(0,4))},g.isTabletFallback=function(a){return g.detectMobileBrowsers.tabletPattern.test(a)},g.prepareDetectionCache=function(a,c,d){if(a.mobile===b){var e,h,i;return(h=g.findMatch(g.mobileDetectRules.tablets,c))?(a.mobile=a.tablet=h,void(a.phone=null)):(e=g.findMatch(g.mobileDetectRules.phones,c))?(a.mobile=a.phone=e,void(a.tablet=null)):void(g.isMobileFallback(c)?(i=f.isPhoneSized(d),i===b?(a.mobile=g.FALLBACK_MOBILE,a.tablet=a.phone=null):i?(a.mobile=a.phone=g.FALLBACK_PHONE,a.tablet=null):(a.mobile=a.tablet=g.FALLBACK_TABLET,a.phone=null)):g.isTabletFallback(c)?(a.mobile=a.tablet=g.FALLBACK_TABLET,a.phone=null):a.mobile=a.tablet=a.phone=null)}},g.mobileGrade=function(a){var b=null!==a.mobile();return a.os("iOS")&&a.version("iPad")>=4.3||a.os("iOS")&&a.version("iPhone")>=3.1||a.os("iOS")&&a.version("iPod")>=3.1||a.version("Android")>2.1&&a.is("Webkit")||a.version("Windows Phone OS")>=7||a.is("BlackBerry")&&a.version("BlackBerry")>=6||a.match("Playbook.*Tablet")||a.version("webOS")>=1.4&&a.match("Palm|Pre|Pixi")||a.match("hp.*TouchPad")||a.is("Firefox")&&a.version("Firefox")>=12||a.is("Chrome")&&a.is("AndroidOS")&&a.version("Android")>=4||a.is("Skyfire")&&a.version("Skyfire")>=4.1&&a.is("AndroidOS")&&a.version("Android")>=2.3||a.is("Opera")&&a.version("Opera Mobi")>11&&a.is("AndroidOS")||a.is("MeeGoOS")||a.is("Tizen")||a.is("Dolfin")&&a.version("Bada")>=2||(a.is("UC Browser")||a.is("Dolfin"))&&a.version("Android")>=2.3||a.match("Kindle Fire")||a.is("Kindle")&&a.version("Kindle")>=3||a.is("AndroidOS")&&a.is("NookTablet")||a.version("Chrome")>=11&&!b||a.version("Safari")>=5&&!b||a.version("Firefox")>=4&&!b||a.version("MSIE")>=7&&!b||a.version("Opera")>=10&&!b?"A":a.os("iOS")&&a.version("iPad")<4.3||a.os("iOS")&&a.version("iPhone")<3.1||a.os("iOS")&&a.version("iPod")<3.1||a.is("Blackberry")&&a.version("BlackBerry")>=5&&a.version("BlackBerry")<6||a.version("Opera Mini")>=5&&a.version("Opera Mini")<=6.5&&(a.version("Android")>=2.3||a.is("iOS"))||a.match("NokiaN8|NokiaC7|N97.*Series60|Symbian/3")||a.version("Opera Mobi")>=11&&a.is("SymbianOS")?"B":(a.version("BlackBerry")<5||a.match("MSIEMobile|Windows CE.*Mobile")||a.version("Windows Mobile")<=5.2,"C")},g.detectOS=function(a){return g.findMatch(g.mobileDetectRules.oss0,a)||g.findMatch(g.mobileDetectRules.oss,a)},g.getDeviceSmallerSide=function(){return window.screen.width<window.screen.height?window.screen.width:window.screen.height},f.prototype={constructor:f,mobile:function(){return g.prepareDetectionCache(this._cache,this.ua,this.maxPhoneWidth),this._cache.mobile},phone:function(){return g.prepareDetectionCache(this._cache,this.ua,this.maxPhoneWidth),this._cache.phone},tablet:function(){return g.prepareDetectionCache(this._cache,this.ua,this.maxPhoneWidth),this._cache.tablet},userAgent:function(){return this._cache.userAgent===b&&(this._cache.userAgent=g.findMatch(g.mobileDetectRules.uas,this.ua)),this._cache.userAgent},userAgents:function(){return this._cache.userAgents===b&&(this._cache.userAgents=g.findMatches(g.mobileDetectRules.uas,this.ua)),this._cache.userAgents},os:function(){return this._cache.os===b&&(this._cache.os=g.detectOS(this.ua)),this._cache.os},version:function(a){return g.getVersion(a,this.ua)},versionStr:function(a){return g.getVersionStr(a,this.ua)},is:function(b){return c(this.userAgents(),b)||a(b,this.os())||a(b,this.phone())||a(b,this.tablet())||c(g.findMatches(g.mobileDetectRules.utils,this.ua),b)},match:function(a){return a instanceof RegExp||(a=new RegExp(a,"i")),a.test(this.ua)},isPhoneSized:function(a){return f.isPhoneSized(a||this.maxPhoneWidth)},mobileGrade:function(){return this._cache.grade===b&&(this._cache.grade=g.mobileGrade(this)),this._cache.grade}},"undefined"!=typeof window&&window.screen?f.isPhoneSized=function(a){return a<0?b:g.getDeviceSmallerSide()<=a}:f.isPhoneSized=function(){},f._impl=g,f.version="1.4.4 2019-09-21",f})}
19(function(a){if("undefined"!=typeof module&&module.exports)return function(a){module.exports=a()};if("function"==typeof define&&define.amd)return define;if("undefined"!=typeof window)return function(a){window.MobileDetect=a()};throw new Error("unknown environment")}());
20/*! jQuery slabtext plugin v2.2 MIT/GPL2 @freqdec */
21(function($){$.fn.slabText=function(options){var settings={fontRatio:0.78,forceNewCharCount:true,wrapAmpersand:true,headerBreakpoint:null,viewportBreakpoint:null,noResizeEvent:false,resizeThrottleTime:300,maxFontSize:999,postTweak:true,precision:3,minCharsPerLine:0};$("body").addClass("slabtexted");return this.each(function(){if(options){$.extend(settings,options);}var $this=$(this),keepSpans=$("span.slabtext",$this).length,words=keepSpans?[]:String($.trim($this.text())).replace(/\s{2,}/g," ").split(" "),origFontSize=null,idealCharPerLine=null,fontRatio=settings.fontRatio,forceNewCharCount=settings.forceNewCharCount,headerBreakpoint=settings.headerBreakpoint,viewportBreakpoint=settings.viewportBreakpoint,postTweak=settings.postTweak,precision=settings.precision,resizeThrottleTime=settings.resizeThrottleTime,minCharsPerLine=settings.minCharsPerLine,resizeThrottle=null,viewportWidth=$(window).width(),headLink=$this.find("a:first").attr("href")||$this.attr("href"),linkTitle=headLink?$this.find("a:first").attr("title"):"";if(!keepSpans&&minCharsPerLine&&words.join(" ").length<minCharsPerLine){return;}var grabPixelFontSize=function(){var dummy=jQuery('<div style="display:none;font-size:1em;margin:0;padding:0;height:auto;line-height:1;border:0;">&nbsp;</div>').appendTo($this),emH=dummy.height();dummy.remove();return emH;};var resizeSlabs=function resizeSlabs(){var parentWidth=$this.width(),fs;$this.removeClass("slabtextdone slabtextinactive");if(viewportBreakpoint&&viewportBreakpoint>viewportWidth||headerBreakpoint&&headerBreakpoint>parentWidth){$this.addClass("slabtextinactive");return;}fs=grabPixelFontSize();if(!keepSpans&&(forceNewCharCount||fs!=origFontSize)){origFontSize=fs;var newCharPerLine=Math.min(60,Math.floor(parentWidth/(origFontSize*fontRatio))),wordIndex=0,lineText=[],counter=0,preText="",postText="",finalText="",slice,preDiff,postDiff;if(newCharPerLine!=idealCharPerLine){idealCharPerLine=newCharPerLine;while(wordIndex<words.length){postText="";while(postText.length<idealCharPerLine){preText=postText;postText+=words[wordIndex]+" ";if(++wordIndex>=words.length){break;}}if(minCharsPerLine){slice=words.slice(wordIndex).join(" ");if(slice.length<minCharsPerLine){postText+=slice;preText=postText;wordIndex=words.length+2;}}preDiff=idealCharPerLine-preText.length;postDiff=postText.length-idealCharPerLine;if((preDiff<postDiff)&&(preText.length>=(minCharsPerLine||2))){finalText=preText;wordIndex--;}else{finalText=postText;}finalText=$("<div/>").text(finalText).html();if(settings.wrapAmpersand){finalText=finalText.replace(/&amp;/g,'<span class="amp">&amp;</span>');}finalText=$.trim(finalText);lineText.push('<span class="slabtext">'+finalText+"</span>");}$this.html(lineText.join(" "));if(headLink){$this.wrapInner('<a href="'+headLink+'" '+(linkTitle?'title="'+linkTitle+'" ':"")+"/>");}}}else{origFontSize=fs;}$("span.slabtext",$this).each(function(){var $span=$(this),innerText=$span.text(),wordSpacing=innerText.split(" ").length>1,diff,ratio,fontSize;if(postTweak){$span.css({"word-spacing":0,"letter-spacing":0});}ratio=parentWidth/$span.width();fontSize=parseFloat(this.style.fontSize)||origFontSize;$span.css("font-size",Math.min((fontSize*ratio).toFixed(precision),settings.maxFontSize)+"px");diff=!!postTweak?parentWidth-$span.width():false;if(diff){$span.css((wordSpacing?"word":"letter")+"-spacing",(diff/(wordSpacing?innerText.split(" ").length-1:innerText.length)).toFixed(precision)+"px");}});$this.addClass("slabtextdone");};resizeSlabs();if(!settings.noResizeEvent){$(window).resize(function(){if($(window).width()==viewportWidth){return;}viewportWidth=$(window).width();clearTimeout(resizeThrottle);resizeThrottle=setTimeout(resizeSlabs,resizeThrottleTime);});}});};})(jQuery);
22/*! jQuery Lazy 1.6.7 - MIT & GPL-2.0 license - Copyright 2012-2016 Daniel 'Eisbehr' Kern */
23!function(e,t,a,r){"use strict";function n(a,r,n,o){function i(){p=t.devicePixelRatio>1,l(n),r("delay")>=0&&setTimeout(function(){u(!0)},r("delay")),(r("delay")<0||r("combined"))&&(o.e=m(r("throttle"),function(e){"resize"===e.type&&(b=v=-1),u(e.all)}),o.a=function(e){l(e),n.push.apply(n,e)},o.g=function(){return n=e(n).filter(function(){return!e(this).data(r("loadedName"))})},u(),e(r("appendScroll")).on("scroll."+a.name+" resize."+a.name,o.e))}function l(t){if(t=e(t).filter(function(){return!e(this).data(r("handledName"))&&(e(this).attr(r("attribute"))||e(this).attr(r("loaderAttribute")))}).data("plugin_"+a.name,a),r("defaultImage")||r("placeholder"))for(var n=0;n<t.length;n++){var o=e(t[n]),i=t[n].tagName.toLowerCase(),l="background-image";"img"==i&&r("defaultImage")&&!o.attr("src")?o.attr("src",r("defaultImage")):"img"==i||!r("placeholder")||o.css(l)&&"none"!=o.css(l)||o.css(l,"url("/js/vendor/jquery-lazy/+r("placeholder")+")")}}function u(t){if(!n.length)return void(r("autoDestroy")&&a.destroy());for(var o=!1,i=r("imageBase")?r("imageBase"):"",l=0;l<n.length;
23l++)(function(a){if(c(a)||t){var n,l=e(a),u=a.tagName.toLowerCase(),f=l.attr(r("attribute"));l.data(r("handledName"))||r("visibleOnly")&&!l.is(":visible")||!(f&&("img"==u&&i+f!=l.attr("src")||"img"!=u&&i+f!=l.css("background-image"))||(n=l.attr(r("loaderAttribute"))))||(o=!0,l.data(r("handledName"),!0),d(l,u,i,n))}})(n[l]);o&&(n=e(n).filter(function(){return!e(this).data(r("handledName"))}))}function d(t,a,n,o){++h;var i=function(){A("onError",t),g()};if(A("beforeLoad",t),o)t.off("error").one("error",i),t.one("load",function(){r("removeAttribute")&&t.removeAttr(r("loaderAttribute")),t.data(r("loadedName"),!0),A("afterLoad",t),g()}),A(o,t,function(e){e?t.load():t.error()})||t.error();else{var l=e(new Image);l.one("error",i),l.one("load",function(){t.hide(),"img"==a?t.attr("src",l.attr("src")):t.css("background-image","url('"+l.attr("src")+"')"),t[r("effect")](r("effectTime")),r("removeAttribute")&&t.removeAttr(r("attribute")+" "+r("retinaAttribute")),t.data(r("loadedName"),!0),A("afterLoad",t),l.remove(),g()}),l.attr("src",n+t.attr(r(p&&t.attr(r("retinaAttribute"))?"retinaAttribute":"attribute"))),l.complete&&l.load()}}function c(e){var t=e.getBoundingClientRect(),a=r("scrollDirection"),n=r("threshold"),o=s()+n>t.top&&-n<t.bottom,i=f()+n>t.left&&-n<t.right;return"vertical"==a?o:"horizontal"==a?i:o&&i}function f(){return b>=0?b:b=e(t).width()}function s(){return v>=0?v:v=e(t).height()}function m(e,t){var n,o=0;return function(i,l){function u(){o=+new Date,t.call(a,i)}var d=+new Date-o;n&&clearTimeout(n),d>e||!r("enableThrottle")||l?u():n=setTimeout(u,e-d)}}function g(){--h,n.length||h||A("onFinishedAll")}function A(e,t,n){return(e=r(e))?(e.apply(a,[].slice.call(arguments,1)),!0):!1}var h=0,b=-1,v=-1,p=!1;!function(){"event"==r("bind")?i():e(t).on("load."+a.name,i)}()}function o(a,o){var i=this,l=e.extend({},i.configuration,o),u={};return i.config=function(e,t){return t===r?l[e]:(l[e]=t,i)},i.addItems=function(t){return u.a&&u.a("string"===e.type(t)?e(t):t),i},i.getItems=function(){return u.g?u.g():{}},i.update=function(e){return u.e&&u.e({},!e),i},i.loadAll=function(){return u.e&&u.e({all:!0},!0),i},i.destroy=function(){return e(i.config("appendScroll")).off("."+i.name,u.e),e(t).off("."+i.name),u={},r},n(i,i.config,a,u),i.config("chainable")?a:i}e.fn.Lazy=e.fn.lazy=function(e){return new o(this,e)},e.extend(o.prototype,{name:"lazy",configuration:{chainable:!0,autoDestroy:!0,bind:"load",threshold:500,visibleOnly:!1,appendScroll:t,scrollDirection:"both",imageBase:null,defaultImage:"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",placeholder:null,delay:-1,combined:!1,attribute:"data-src",retinaAttribute:"data-retina",loaderAttribute:"data-loader",removeAttribute:!0,handledName:"handled",loadedName:"loaded",effect:"show",effectTime:0,enableThrottle:!0,throttle:250,beforeLoad:null,afterLoad:null,onError:null,onFinishedAll:null}})}(jQuery,window,document);
24$(function() {
25    if ($('div.StageVoting_groupId').length) {
26        var vid    = $('div.StageVoting_groupId').data('voting');
27        var detail = $('div.StageVoting_groupId').data('detail');
28        $.ajax({
29            url: '/_votings/arena/last.voting.php',
30            type: 'GET',
31            data: {
32                location: $(location).attr('href'),
33                select: 'id',
34                id:vid,
35                detail: detail
36            },
37            dataType: 'html',
38            success: function (data) {
39                $('div.StageVoting_groupId').html(data);
40
41            }
42        })
43    }
44    if($('div.StageVoting_groupAuto').length) {
45        $.ajax({
46            url: '/_votings/arena/last.voting.php',
47            type: 'GET',
48            data: {
49                location: $(location).attr('href'),
50                select: 'last'
51            },
52            dataType: 'html',
53            success: function (data) {
54                $('div.StageVoting_groupAuto').html(data);
55
56            }
57        })
58    }
59    var request;
60    $(document).on('submit','form.StageVoting_form',function(e){
61        e.preventDefault();
62        var hash = $("input[name='i_vhash']:checked").val();
63        if( typeof hash === "undefined"){
64            $(".StageVoting_info").text("Bitte treffen Sie eine Auswahl");
65        } else {
66            var $form = $(this);
67            var $inputs = $form.find("input, select, button, textarea");
68            var serializedData = $form.serialize();
69            $inputs.prop("disabled", true);
70
71            request = $.ajax({
72                type: "POST",
73                url: "/_votings/arena/post.php",
74                data: serializedData,
75             });
76            request.done(function (response, textStatus, jqXHR){
77                // Log a message to the console
78                if($('div.StageVoting_groupAuto').length) {
79                    $('div.StageVoting_groupAuto').html(response);
80                }
81                if($('div.StageVoting_groupId').length) {
82                    $('div.StageVoting_groupId').html(response);
83                }
84
85            });
86            request.fail(function (jqXHR, textStatus, errorThrown){
87                // Log the error to the console
88                console.error(
89                    "The following error occurred: "+
90                    textStatus, errorThrown
91                );
92            });
93            request.always(function () {
94                // Reenable the inputs
95                $inputs.prop("disabled", false);
96            });
97        }
98    })
99
100});
101/* Click auf Logo nicht scrollen */
102$(".Logo").on("click", function () {
103    localStorage.setItem('click','Logo');
104});
105
106/* ---- iPad-Events --- */
107$(window).on("orientationchange resize",function(){
108  if ( $(".Ad-superbanner .ad_superbanner").length) {
109    $(document).trigger("webskin");    
110  }
111});
112
113/* --------------- GA Event Zählung --------------- */
114
115$(".SiteHeader").on("click", ".NavigationMeta .FormLogoutPopup input[type=\"submit\"]", function(event){
116  // Trigger Event bei Logout-Link im Header
117  var fo_mr = {
118    'hitType': 'event',
119    'eventCategory': event.currentTarget.getAttribute('data-ga'),
120    'eventAction': 'Klick',
121    'eventLabel': 'Oben rechts',
122    'page': window.location.pathname,
123    'location': window.location.href
124  };
125  dfv_ga_repl(fo_mr);
126});
127
128$("body").on("click", ".ButtonMoreContent", function(event){
129    // Trigger Event bei Klick auf Alle Nachrichten
130
131    var stageTitle = 'ohne Titel';
132    var stageTitleFound = false;
133
134    // Bühnen-Titel finden
135    if ($(this).closest('section')) {
136
137        stageTitle = $(this).closest('section').find('.StageTitle').text();
138        stageTitle = stageTitle.trim();
139        if (stageTitle.length > 1) {
140            stageTitleFound = true;
141        } else {
142            stageTitleFound = true;
143            stageTitle = "ohne Titel";
144        }
145    }
146
147    var fo_pw = {
148        'hitType': 'event',
149        'eventCategory': 'Alle ' + stageTitle,
150        'eventAction': 'Klick',
151        'eventLabel': ''
152    };
153
154    dfv_ga_repl(fo_pw);
155});
156
157$(".StageGalleriesEdgewise, .StageStorechecks, .StageGalleries").on("click", "a", function(event){
158  // Trigger Event bei Click auf Galerie Fotogaleriebühnen
159  var d = event.currentTarget.getAttribute('data-te');
160  if (d !== null) {
161    var stageTitle = $(this).closest('article').parent().parent().find('.StageTitle a').text();
162    if (typeof stageTitle === 'undefined' || stageTitle === '') {
163      stageTitle = $(this).closest('article').parent().parent().parent().find('.StageTitle a').text();
164    }
165
166    var fo_pw = {
167      'hitType': 'event',
168      'eventCategory': stageTitle + ' Bühne',
169      'eventAction': 'Klick',
170      'eventLabel': event.currentTarget.getAttribute('data-te'),
171      'page': window.location.pathname,
172      'location': window.location.href
173    };
174    dfv_ga_repl(fo_pw);
175  }
176});
177
178$(".StageFewOneRow, .StageTeaserFewTwoRows").on("click", "a", function(event){
179  // Trigger Event bei Click auf News Fashionbühne
180  var d = event.currentTarget.getAttribute('data-te');
181  if (d !== null) {
182    var fo_pw = {
183      'hitType': 'event',
184      'eventCategory': $(this).closest('article').parent().parent().find('.StageTitle a').text() + ' Bühne',
185      'eventAction': 'Klick',
186      'eventLabel': event.currentTarget.getAttribute('data-te'),
187      'page': window.location.pathname,
188      'location': window.location.href
189    };
190    dfv_ga_repl(fo_pw);
191  }
192});
193
194$(".PageArticle_body").on("submit", ".StageVoting_form",function(){
195  // Trigger Event bei Umfrage
196     var fo_mr = {
197      'hitType': 'event',
198      'eventCategory': 'Umfrage',
199      'eventAction': 'Klick',
200      'eventLabel': 'Detail',
201      'page': window.location.pathname,
202      'location': window.location.href
203      };
204  dfv_ga_repl(fo_mr);
205   
206});
207
208$(".StageVoting").on("submit", ".StageVoting_form",function(){
209  // Trigger Event bei Umfrage
210     var fo_mr = {
211      'hitType': 'event',
212      'eventCategory': 'Umfrage',
213      'eventAction': 'Klick',
214      'eventLabel': 'Arena',
215      'page': window.location.pathname,
216      'location': window.location.href
217      };
218  dfv_ga_repl(fo_mr);
219   
220});
221
222/* --------------- Suche ---------- */
223
224$(function(){
225   var showSearch = function() {
226     
227    var l = $("a.navsearch").position().left;
228    console.log($("a.navsearch").position());
229     
230    $("#header-searchinput").show();
231        $("#header-searchinput").animate({
232           width: "250px",
233           right: "0"
234        }, 200 );
235  };
236
237  var hideSearch = function() {
238    $( "#header-searchinput" ).animate({
239            width: "0px",
240            right: "0"
241            }, 200, function() {
242            $("#header-searchinput").hide();
243          });
244  };
245  
246  var searchurl = $(location).attr('href');
247    
248  $(document).on("click touchstart",function(e) {
249
250    if($(e.target).attr('id') == "headersearch" && $("#header-searchinput").css("display") == "none") {
251      e.preventDefault();
252      showSearch();
253    }
254    else {
255      if ($(e.target).attr('id') == "header-searchfield" || $(e.target).attr('id') == "header-searchbutton") {
256          ;// Klick innerhalb des Suchfeldes
257      }
258      else {
259          hideSearch();
260      }
261    }
262  });
263  
264});
265
266/*---------- Aktionsseiten-Infobox ----------*/
267
268$(document).on("show-infobox", function(event, info_box_id, info_icon_position){
269  $("#"+info_box_id).css('top',info_icon_position.top + 30)
270    .css('left', info_icon_position.left - 160)
271    .css('display', 'block');
272});
273
274/*---------- Jobs auf News-Detailseite im Footer ----------*/
275
276$(".NewsJobs_item, .NewsJobs_header, .NewsJobs_footer").on("click", function(event){
277  if(event.currentTarget.getAttribute('data-te') !== undefined){
278     var fo_pw = {
279       'hitType': 'event',
280       'eventCategory': 'Jobs',
281       'eventAction': 'Klick',
282       'eventLabel': event.currentTarget.getAttribute('data-te'),
283       'page': window.location.pathname,
284       'location': window.location.href
285     };
286     dfv_ga_repl(fo_pw);
287  }
288});
289
290/*---------- Online-Specials Homepage ----------*/
291
292if($('.StageLeadOnlineSpecialHomepage_sponsorWrapper').find('div.Sponsor_item').length !== 0) {
293
294} else {
295  $('.StageLeadOnlineSpecialHomepage_rightCol-inner').hide();
296}
297
298
299/* Online-Specials Sponsoren */
300
301$(".Sponsor_item-image img").on("click", function(){
302  var val = $(this).parent().parent().attr('href');
303  console.log("val: ");
304  console.log(val);
305  if(val !== undefined){
306    var fo_mr = {
307      'hitType': 'event',
308      'eventCategory': 'Dossiers',
309      'eventAction': 'click',
310      'eventLabel': val,
311      'page': window.location.pathname,
312      'location': window.location.href
313    };
314    dfv_ga_repl(fo_mr);
315
316
317  } else {
318    return false;
319  }
320});
321
322
323var md = new MobileDetect(window.navigator.userAgent);
324var oldScrollPosition;
325
326function preventEmptySearch() {
327  $('.SiteHeader_searchform button[type="submit"]').click(function(e) {
328    e.preventDefault();
329    if ( $('.SiteHeader_searchform input[type="text"]').val() !== '' ) {
330      $('.SiteHeader_searchform form').submit();
331    }
332  });
333
334  $('.SiteHeaderSticky_formSearch button[type="submit"]').click(function(e) {
335    e.preventDefault();
336    if ( $('.SiteHeaderSticky_formSearch input[type="text"]').val() !== '' ) {
337      $('.SiteHeaderSticky_formSearch form').submit();
338    }
339  });
340
341  $('.FormSearchMobile button[type="submit"]').click(function(e) {
342    e.preventDefault();
343    if ( $('.FormSearchMobile input[type="text"]').val() !== '' ) {
344      $('.FormSearchMobile').submit();
345    }
346  });
347
348  $('.FormSearch button[type="submit"]').click(function(e) {
349    e.preventDefault();
350    if ( $('.FormSearch input[type="text"]').val() !== '' ) {
351      $('.FormSearch').submit();
352    }
353  });
354}
355
356function initAsideNav() {
357  $('.aside-menu .toggle-menu').click(function(e) {
358    e.preventDefault();
359    $(this).closest('.aside-menu').toggleClass('open');
360    $(this).closest('.aside-menu').find('.collapse-area').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) {
361      if (e.originalEvent.propertyName === 'max-height') {
362        $(document.body).trigger("sticky_kit:recalc");
363      }
364    });
365  });
366}
367
368function initSearchToggle() {
369  $('.ToggleSearch').click(function() {
370    var searchform = '.SiteHeader .SiteHeader_searchform';
371
372    if ( $(searchform+':visible').length === 0 ) {
373      $(searchform).slideDown(225);
374      $('.ToggleSearch').css('color', '#BA1818')
375      .parent().addClass('isActive');
376    } else if ( $(searchform+':visible').length > 0) {
377      $(searchform).slideUp(225);
378      $('.ToggleSearch').removeAttr('style')
379      .parent().removeClass('isActive');
380    }
381  });
382}
383
384function initMobileNav() {
385  $('.toggle-mobile-nav').click(function(e) {
386    $('body').toggleClass('mobile-nav-open');
387  });
388}
389
390function initNewsletterSelect() {
391  $('.newsletter-select').click(function(e) {
392    $(this).toggleClass('selected');
393  });
394}
395
396function initStickyColumn() {
397  var ButtonsSharing_margin_top = $('.PageArticle_content .PageArticle_sticky .ButtonsSharing, ' +
398    '.PageArticleAdvertorial_content .PageArticleAdvertorial_sticky .ButtonsSharing').css('margin-top');
399
400  $('.PageArticle_content .PageArticle_sticky, .PageArticleAdvertorial_content .PageArticleAdvertorial_sticky').stick_in_parent({
401    parent     : '.sticky-container',
402    offset_top: 97,
403    bottoming: true
404  }).on("sticky_kit:stick", function(e) {
405    $(this).addClass('is_sticky');
406    $('.PageArticle_content .PageArticle_sticky .ButtonsSharing,' +
407      '.PageArticleAdvertorial_content .PageArticleAdvertorial_sticky .ButtonsSharing ').css('margin-top',0);
408  })
409  .on("sticky_kit:bottom", function(e) {
410    $(this).parent().css('position', 'static');
411  })  
412  .on("sticky_kit:unstick", function(e) {
413    $(this).removeClass('is_sticky'); 
414    $('.PageArticle_content .PageArticle_sticky .ButtonsSharing,' +
415      '.PageArticleAdvertorial_content .PageArticleAdvertorial_sticky .ButtonsSharing').css('margin-top',ButtonsSharing_margin_top);
416  });
417  
418  $('a[href="#"]').click(function(e){
419    e.preventDefault();
420  });
421}
422
423function initCards() {
424  $('.card-collapse').on('click',(function(e) {
425    var me = $(this);
426    $('.card-collapse.open').not(this).removeClass('open');
427    me.toggleClass('open');
428  }));
429  $('.card-collapse').on('click','a',(function(e) {
430    //e.stopImmediatePropagation();
431    console.log('offa');
432    console.log($(this));
433    $(this).trigger('click');
434  }));
435}
436
437
438
439// __________________________________________________
440//
441//
442//			!Check Idle Time Mobile
443
444var timeoutID;
445
446function goInactive() {
447    if($('body').scrollTop() > 0) {
448      $('body').addClass('idle');
449    }
450    
451    $('.modal').addClass('idle');
452}
453 
454function goActive() {
455    $('body.idle').removeClass('idle');
456    $('.modal.idle').removeClass('idle');
457    startTimer();
458}
459 
460function resetTimer(e) {
461    window.clearTimeout(timeoutID);
462    goActive();
463}
464 
465function startTimer() {
466    // wait 2 seconds before calling goInactive
467    timeoutID = window.setTimeout(goInactive, 2000);
468}
469
470
471function make_square(element) {
472//   var cw = $(element).width();
473//   $(element).css({'height':cw+'px'});
474}
475
476
477
478
479
480 
481function setupIdle() {
482    this.addEventListener("mousemove", resetTimer);
483    this.addEventListener("mousedown", resetTimer);
484    this.addEventListener("keypress", resetTimer);
485    this.addEventListener("DOMMouseScroll", resetTimer);
486    this.addEventListener('mousewheel', resetTimer, {passive: true});
487    this.addEventListener("touchmove", resetTimer);
488    this.addEventListener("touchstart", resetTimer);
489    this.addEventListener("MSPointerMove", resetTimer);
490 
491    startTimer();
492}
493
494function createYoutubeApi() {
495  var tag = document.createElement('script');
496  tag.src = "https://www.youtube.com/iframe_api";
497  var firstScriptTag = document.getElementsByTagName('script')[0];
498  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
499}
500
501function initToggleList() {
502  $('.toggleList li').click(function () {
503    $(this).toggleClass('isActive');
504    $('div', this).toggle();
505  });
506}
507
508$(document).ready(function(){
509//  $("a[href=#]").click(function(e) {
510//    e.preventDefault();
511//  });
512//  if (md.mobile() != null) {
513//    $('body').addClass('is-mobile');   
514//  }; 
515//  if (md.phone() != null) {
516//     $('.stage-fashion > .row > .col-sm-4').slice(-2).remove();
517//  }
518  initSearchToggle();
519  setupIdle();
520  initStickyColumn();  
521  initAsideNav();
522  initMobileNav();
523  preventEmptySearch();
524  initCards();
525  initNewsletterSelect();
526  createYoutubeApi();
527  initToggleList();
528  
529  $('.ImageModal').colorbox({iframe:false, opacity: 0.8, maxWidth:'95%', maxHeight:'95%'});
530  
531  // mobile Navigation Flyout
532  $(".NavigationFlyout_toggleButton").on('click',function(e){
533    e.preventDefault();$('.NavigationFlyout').toggleClass('isActive');
534  });
535  
536  // mobile Navigation Flyout
537  $(".NavigationMobile_toggle").on('click',function(e){
538    e.preventDefault();$('.NavigationMobile').toggleClass('isActive');
539    $('body').toggleClass('isFixed');
540  });
541  
542  $('.paneltop').click( function() {
543    $(this).css({"background-position":"0px -21px"})
544    .siblings().animate({"height":"100px"}, 200)
545  }, function() {
546    $(this).css({"background-position":"0px 0px"})
547    .siblings().animate({"height":"0px"}, 200);
548  })
549
550   // Bilder quadratisieren
551   $( '.to-be-squared .teaser-image' ).each(function( index ) {
552      make_square($(this));
553   });
554   
555  // Login-Popup/Logout-Popup
556  var accountBtn = $(".NavigationMeta_item-account");
557  var accountBtnLink = $(".NavigationMeta_item-account .NavigationMeta_itemLink");
558  var loginPanel = $(".NavigationMeta .FormLoginPopup");
559  var logoutPanel = $(".NavigationMeta .FormLogoutPopup");
560  var panel = accountBtn.hasClass('isSignedOut') ? loginPanel : logoutPanel;
561  var panel_input = $(".NavigationMeta .FormLoginPopup input");
562
563  function showPanel(selector, a) {
564    selector.css('visibility', 'visible');
565    a.addClass('isActive');
566  }
567  function hidePanel(selector, a) {
568    selector.removeAttr('style');
569    a.removeClass('isActive');
570  }
571
572  $(".NavigationMeta .FormLoginPopup .FormField_icon").click(function() {
573    $('.NavigationMeta .FormLoginPopup .FormField_control').trigger('click');
574  });
575
576  accountBtn.click(function(e) {
577    e.preventDefault();
578  });
579
580  accountBtn.mouseover( function() { showPanel(panel, accountBtn); } );
581  accountBtn.mouseout( function() { hidePanel(panel, accountBtn); } );
582  panel.mouseover( function() { showPanel(panel, accountBtn); } );
583  panel.mouseout( function() {
584    if ( !panel_input.is(":focus") ) {
585      hidePanel(panel, accountBtn);
586    }
587  });
588
589});
590
591// quadratische Bildergrößen beim Fenster-Verkleinern neu berechnen
592$( window ).resize(function() {
593   $( '.to-be-squared .teaser-image' ).each(function( index ) {
594      make_square($(this));
595   });
596});
597
598function manage_input_active_state(selector) {
599  $(selector).each(function() {
600    if ( $(this).val() ) {
601      $(this).addClass('FormField_control-filled');
602    }
603    $(this).change(function() {
604      if ( $(this).val() ) {
605        $(this).addClass('FormField_control-filled');
606      }
607      if ( $(this).val() === '' ) {
608        $(this).removeClass('FormField_control-filled');
609      }
610    });
611  });
612}
613
614manage_input_active_state(".FormField_control:not([type='submit'])");
615manage_input_active_state(".FormField_controlGroupField:not([type='submit'])");
616
617$(document).ready(function() {
618    /**
619     * ersetzt das Carousel
620     * durch ein swipen beim neu Laden der Seite
621     * in data-ride wird onPageLoad getsetzt
622     * die Ids des Elements muessen eindeutig sein !!!
623     */
624    $.each($("[data-ride]"), function (k, v) {
625        if ($(this).data('ride') == 'onPageLoad') {
626            var id = $(this).attr('id');
627            var store_name = 'onPageLoad' + id;
628            var stack = [];
629            var count_elm = $(this).children(".carousel-inner").children(".item").length;            
630            var random_stack_index = Math.floor(Math.random() * ((count_elm -1) + 1));                
631            
632            if (sessionStorage.getItem(store_name)) {
633                stack = JSON.parse(sessionStorage.getItem(store_name));
634            }
635            if (stack.length !== count_elm) {
636                stack = [];
637                for (var i = 0; i < count_elm; i++) {
638                    stack[i] = 0;
639                }
640                stack[random_stack_index] = 1;
641            } else {
642                stack.unshift('0');
643                if (stack.pop() == 1) {
644                    stack[0] = 1;
645                }
646            }
647            $.each($(this).children(".carousel-inner").children(".item"), function (i, x) {
648                if (stack[i] == 0) {
649                    $(this).removeClass('active');
650                } else {
651                    $(this).addClass('active');
652                }
653            })
654            sessionStorage.setItem(store_name, JSON.stringify(stack));
655        }
656    });
657});
658(()=>{var __webpack_modules__={768:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";__webpack_require__.d(__webpack_exports__,{Z:()=>Embed});var _module__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(631),_utils_sendRequest__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(58),_utils_adBlockCheck__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(173),_tracking_module__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(558);function _await(e,t,n){return n?t?t(e):e:(e&&e.then||(e=Promise.resolve(e)),t?e.then(t):e)}function _empty(){}function _invokeIgnored(e){var t=e();if(t&&t.then)return t.then(_empty)}function _async(e){return function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];try{return Promise.resolve(e.apply(this,t))}catch(e){return Promise.reject(e)}}}function _awaitIgnored(e,t){if(!t)return e&&e.then?e.then(_empty):Promise.resolve()}function _invoke(e,t){var n=e();return n&&n.then?n.then(t):t(n)}function ownKeys(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function _objectSpread(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?ownKeys(Object(n),!0).forEach((function(t){_defineProperty(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ownKeys(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var loadAutoplayList=_async((function(e,t,n,i){var o;return _invoke((function(){if(e.fallbackElementsPromise)return _awaitIgnored(e.fallbackElementsPromise)}),(function(){var a,r=null===(a=e.fallbackElements)||void 0===a?void 0:a.length;return _await(r?e.fallbackElements.map((function(e){return _objectSpread(_objectSpread({},e),{},{fallback_id:e.id})})):new Promise((function(n){(0,_utils_sendRequest__WEBPACK_IMPORTED_MODULE_1__.w)("https://api.embed.pinpoll.com/autoplay/nextEmbeds",{elementId:t,url:e.url,topic:e.topic},window.Pinpoll.storage).then((function(e){return e.json()})).then((function(t){var o;return n(null===(o=window.Pinpoll.embed)||void 0===o?void 0:o.sortPreferredAutoEmbeddedElements(t.elements,e,i))})).catch((function(e){console.log("Pinpoll: error during fetching autoplay polls",e),n([])}))})),(function(e){var t;return o=e,n&&(o=null===(t=o)||void 0===t?void 0:t.slice(0,n)),o}),r)}))})),Embed=function(){function Embed(e,t,n){var i=this;if(_classCallCheck(this,Embed),_defineProperty(this,"targetWindow",void 0),_defineProperty(this,"lazyLoading",void 0),_defineProperty(this,"type",void 0),_defineProperty(this,"id",void 0),_defineProperty(this,"iframe",void 0),_defineProperty(this,"element",void 0),_defineProperty(this,"mode",void 0),_defineProperty(this,"data",void 0),_defineProperty(this,"loaded",!1),_defineProperty(this,"instance",void 0),_defineProperty(this,"questionViewTriggered",!1),_defineProperty(this,"url",void 0),_defineProperty(this,"autoplay",null),_defineProperty(this,"nativeAd",null),_defineProperty(this,"pendings",{}),_defineProperty(this,"pendingPostMessages",[]),_defineProperty(this,"loadDataSet",!1),_defineProperty(this,"widgetIndex",void 0),_defineProperty(this,"stats",void 0),this.element=t,this.targetWindow=e.location,this.type=e.type,this.mode=e.mode,this.data=e,this.stats=n,this.id=generateId(e),this.widgetIndex=window.Pinpoll.embed.initedEmbeds,window.Pinpoll.embed.initedEmbeds+=1,this.lazyLoading="eager"!==e.loading&&"preload"!==e.loading,this.data.native)return this.loadNative(t,e).then((function(t){if(t){t.targetId=i.id,i.instance=t,i.instance.promises.preload?i.instance.promises.preload.then((function(){return i.stats.markLoad()})):i.stats.markLoad();var n=!1;i.instance.on("poll:initialized","global.js - statTracker",(function(){var e;n||(n=!0,i.stats.markRender(),i.stats.observeImpression((null===(e=i.instance)||void 0===e?void 0:e.container)||i.element))})),i.instance.on("poll:initialized","global.js",(function(){var n,o;t.elementId&&(e.id=+t.elementId,(0,_tracking_module__WEBPACK_IMPORTED_MODULE_2__.Z)(t.visitorStorage,{widgetIndex:"e"+(null!==(n=null===(o=window.Pinpoll.embed)||void 0===o?void 0:o.embeds.findIndex((function(e){return e===i})))&&void 0!==n?n:0),originPage:e.url,widgetLocation:buildUrl(e,t.targetId||"")}).start())}))}})).catch((function(e){console.error("Pinpoll: error during loading native embed",e)})),void this.registerEventListener();this.iframe=buildIframe(e,this.id),this.lazyLoading?(this.iframe.setAttribute("class","lazyload"),document.addEventListener("lazybeforeunveil",(function e(t){t.target===i.iframe&&((0,_module__WEBPACK_IMPORTED_MODULE_0__.oW)(i.data,i.element),i.url=buildUrl(i.data,i.id),i.iframe.setAttribute("data-src",
658i.url),i.stats.markLoad(),document.removeEventListener("lazybeforeunveil",e))})),document.addEventListener("lazyloaded",(function e(t){t.target===i.iframe&&(i.loaded=!0,i.stats.markRender(),i.stats.observeImpression(i.iframe),document.removeEventListener("lazyloaded",e))}))):(this.loaded=!0,this.stats.markLoad(),this.url=buildUrl(e,this.id),this.iframe.src=this.url),this.registerEventListener(),t.parentNode===document.getElementsByTagName("head")[0]?document.body.appendChild(this.iframe):t.parentElement?t.parentElement.insertBefore(this.iframe,t):document.body.appendChild(this.iframe),this.lazyLoading||(this.stats.markRender(),this.stats.observeImpression(this.iframe))}return _createClass(Embed,[{key:"loadNative",value:function(e,t){if(!window.Pinpoll.nativeLoader){var n=document.createElement("script");n.async=!0,n.type="module",n.innerHTML="window.Pinpoll.nativeLoader = async (embedElement, options) => {\n                const { createEmbed } = await import('".concat("https://tools.pinpoll.com/embed-v2/main.js?v=1790061720894","');\n                return createEmbed(embedElement, options);\n            }"),document.head.appendChild(n)}return new Promise((function(n){!function i(){if("function"==typeof window.Pinpoll.nativeLoader)return n(window.Pinpoll.nativeLoader(e,t));setTimeout(i,100)}()}))}},{key:"loadNextEmbed",value:function(){if(this.autoplay){var e;this.autoplay.currentIndex=this.autoplay.currentIndex||0;var t=null===(e=this.autoplay.nextAutoplayedElements)||void 0===e?void 0:e[this.autoplay.currentIndex++];t&&this.loadEmbedItem(t)}}},{key:"registerEventListener",value:function(){var e=this;window.addEventListener("message",(function(t){var n,i,o=t.data;try{if("string"==typeof o){if(!o.startsWith("{"))return!1;o=JSON.parse(o)}}catch(e){console.warn(e)}if(o&&"object"===_typeof(o)&&o.action)if("vote"===o.action||"unvote"===o.action)-1!==navigator.appName.indexOf("Internet Explorer")&&-1===navigator.appVersion.indexOf("MSIE 1")&&(o=JSON.stringify(o)),null!==(n=e.iframe)&&void 0!==n&&n.contentWindow||(e.iframe=document.getElementById(e.id)),null===(i=e.iframe.contentWindow)||void 0===i||i.postMessage(o,e.targetWindow);else if(o.target===e.id)switch(o.action){case"get:loaddata":e.setLoadData();break;case"set:height":e.data.height||e.setEmbedHeight(o.value);break;case"get:recaptcha":e.activateRecaptcha(o.top,o.sitekey);break;case"poll-view:finished":e.questionViewTriggered=!0;break;case"autoplay:check":var a;e.initAutoplay(),e.autoplay&&(null===(a=e.autoplay.loadPromise)||void 0===a||a.then((function(){var t,n,i,o;null!==(t=e.autoplay)&&void 0!==t&&null!==(n=t.nextAutoplayedElements)&&void 0!==n&&n.length&&e.autoplay.nextAutoplayedElements[e.autoplay.currentIndex||0]&&(null===(i=e.iframe)||void 0===i||null===(o=i.contentWindow)||void 0===o||o.postMessage({action:"autoplay:ready"},"*"))})));break;case"autoplay:fire":e.loadNextEmbed();break;case"update:visitor":window.Pinpoll.storage.visitor=o.visitor;break;case"native-ad:set":(0,_utils_adBlockCheck__WEBPACK_IMPORTED_MODULE_3__.I)().finally((function(){var t;if(window.Pinpoll.userHasAdblock&&1===(null===(t=o.adConfig)||void 0===t?void 0:t.type))return console.warn("Pinpoll Native Ad: AdBlock detected, no native ad will be shown");e.setNativeAd(o.adTag,o.adConfig),e.nativeAd&&e.pendings.nativeinterstitial&&(e.nativeAd.onInterstitialStart(""+e.pendings.nativeinterstitial),e.pendings.nativeinterstitial=null)}));break;case"interstitial-start":e.nativeAd?e.nativeAd.onInterstitialStart(o.ad.duration):e.pendings.nativeinterstitial=o.ad.duration}}))}}
658,{key:"setLoadData",value:function(){var e,t=this;if(null!==(e=this.iframe)&&void 0!==e&&e.contentWindow){var n,i,o={embed_url:this.url,visitor:window.Pinpoll.storage.visitor,trackingDone:null===(n=window.Pinpoll.tracking)||void 0===n?void 0:n.requestDone,cookieEnabled:navigator.cookieEnabled,originPage:this.data.url,path:window.location.pathname,fallback_id:this.data.fallback_id,autoplayedElementId:this.data.autoplayedElementId,cssClass:this.data.cssClass,parent_id:this.id,autoplayDelay:this.data.autoplayDelay};for(["consent","targetAds","customURL","ppId"].forEach((function(e){t.data[e]&&(o[e]=t.data[e])})),window.Pinpoll.appName&&(o.app=window.Pinpoll.appName),this.loadDataSet||void 0===this.widgetIndex||(o.widgetIndex="e"+this.widgetIndex),null===(i=this.iframe)||void 0===i||i.contentWindow.postMessage({action:"set:loaddata",data:o},"*"),this.loadDataSet=!0;this.pendingPostMessages.length;){var a=this.pendingPostMessages.shift();a&&this.postMessage(a)}}}},{key:"setNativeAd",value:function setNativeAd(adTag,adConfig){var _this4=this;if(adTag)if(this.nativeAd)this.nativeAd.handle("reinitialized",{adTag,adConfig})||this.nativeAd.show();else{var _ref,_this$instance2,container=document.createElement("div");container.setAttribute("style","position:relative;"),null===(_ref=this.iframe||(null===(_this$instance2=this.instance)||void 0===_this$instance2?void 0:_this$instance2.container))||void 0===_ref||_ref.after(container);var script=document.createElement("script");script.adData={config:adConfig,embed:this},script.innerText=adTag,container.append(script),this.nativeAd={script,container,handle:function handle(handlerName,params){return!!_this4.nativeAd&&!!_this4.nativeAd.script.adData.config[handlerName]&&(eval(String(_this4.nativeAd.script.adData.config[handlerName]))(params),!0)},hide:function(){_this4.nativeAd&&(_this4.nativeAd.handle("hide")||(_this4.nativeAd.container.style.visibility="hidden"),_this4.nativeAd.handle("hidden"))},show:function(){_this4.nativeAd&&(_this4.nativeAd.handle("show")||(_this4.nativeAd.container.style.visibility="visible"),_this4.nativeAd.handle("shown"))},onInterstitialStart:function(e){var t,n,i;null!==(t=_this4.nativeAd)&&void 0!==t&&t.handle("interstitialStart",{duration:e})||(null===(i=_this4.nativeAd)||void 0===i||i.hide(),setTimeout((function(){var e,t,n;(null===(e=_this4.nativeAd)||void 0===e?void 0:e.handle("interstitialStop"))||null===(t=_this4.nativeAd)||void 0===t||t.show(),null===(n=_this4.nativeAd)||void 0===n||n.handle("interstitialStopped")}),1e3*+e)),null===(n=_this4.nativeAd)||void 0===n||n.handle("interstitialStarted")}},this.nativeAd.handle("initialized",{adConfig})}}},{key:"loadEmbedItem",value:function(e){var t,n;this.iframe&&e&&(this.data.id=e.element_id,e.id&&(this.data.fallback_id=e.id),e.element_id&&(this.data.autoplayedElementId=e.element_id),e.custom_design_id&&(this.data.design=e.custom_design_id),null===(t=this.nativeAd)||void 0===t||t.hide(),this.id=generateId(this.data),this.url=buildUrl(this.data,this.id),null===(n=this.iframe)||void 0===n||n.setAttribute("id",this.id),this.iframe.src=this.url)}},{key:"setEmbedHeight",value:function(e){if(e&&parseFloat(e)){var t=document.getElementById(this.id);t&&(t.setAttribute("height",e),t.setAttribute("style","display:block;height:".concat(parseFloat(e),"px!important;")))}}},{key:"activateRecaptcha",value:function(e,t){var n=this,i=function(e){var i,o,a,r,l,s=document.createElement("div"),d=document.createElement("div");window.grecaptcha.render(d,{sitekey:t,callback:function(e){var t,i;null===(t=n.iframe)||void 0===t||null===(i=t.contentWindow)||void 0===i||i.postMessage({action:"recaptcha:success",response:e},n.targetWindow),s.style.opacity="0",s.style.transform="translateY(20px)",window.setTimeout((function(){var e;null==s||null===(e=s.parentNode)||void 0===e||e.removeChild(s)}),400)}}),s.appendChild(d),s.setAttribute("style","-webkit-transition:opacity .4s,-webkit-transform .4s;transition:opacity .4s,-webkit-transform .4s;transition:opacity .4s,transform .4s;transition:opacity .4s,transform .4s,-webkit-transform .4s;-webkit-transform:translateY(20px);transform:translateY(20px)"),s.style.position="absolute",s.style.width="".concat(null===(i=n.iframe)||void 0===i?void 0:i.offsetWidth,"px"),s.style.left="".concat(null===(o=n.iframe)||void 0===o?void 0:o.offsetLeft,"px"),s.style.top="".concat((null===(a=n.iframe)||void 0===a?void 0:a.offsetTop)||0+e,"px"),s.style["text-align"]="answer"!=n.type?"center":"left",d.style.display="inline-block",d.style.margin="answer"!=n.type?"0 0 0 12%":"0 0 0 8em",s.style.opacity="0",window.setTimeout((function(){s.style.opacity="1",s.setAttribute("style",s.getAttribute("style").replace("translateY(20px)","translateY(0)"))}),1),null===(r=n.iframe)||void 0===r||null===(l=r.parentNode)||void 0===l||l.insertBefore(s,n.iframe.nextSibling)};if(window.grecaptcha)i(e);
658else{var o="recaptcha_".concat(this.id),a=document.createElement("script");a.src="https://www.google.com/recaptcha/api.js?onload=".concat(o,"&render=explicit"),a.async=!0,a.defer=!0,window[o]=function(){i(e)},document.head.appendChild(a)}}},{key:"postMessage",value:function(e){var t,n;this.loadDataSet?null===(t=this.iframe)||void 0===t||null===(n=t.contentWindow)||void 0===n||n.postMessage(e,this.targetWindow):this.pendingPostMessages.push(e)}},{key:"initPreload",value:function(){(0,_module__WEBPACK_IMPORTED_MODULE_0__.oW)(this.data,this.element);var e=this.instance;if(e)e.dispatch("poll:initPreload",e);else{var t=_objectSpread(_objectSpread({},this.data),{},{fallbackElementsPromise:void 0});this.postMessage({action:"preload:init",data:t})}"preload"===this.data.loading&&(this.data.loading="eager")}},{key:"reload",value:function(){this.iframe&&(this.iframe.src=buildUrl(this.data,this.id))}},{key:"loadAutoplayedElements",value:function(e){var t=this;this.autoplay&&(this.autoplay.loadPromise=_async((function(){return _invokeIgnored((function(){if(t.autoplay)return _await(loadAutoplayList(t.data,t.autoplay.elementId,e||t.autoplay.limit,t.iframe),(function(e){t.autoplay.nextAutoplayedElements=e,t.data.id||t.loadNextEmbed()}))}))}))())}},{key:"initAutoplay",value:function(){this.autoplay||void 0===this.data.autoplay||(this.autoplay={nextAutoplayedElements:void 0,limit:this.data.autoplay,elementId:this.data.id},this.loadAutoplayedElements())}}]),Embed}();function generateId(e){return"pinpoll_".concat(e.type,"_").concat(e.id,"_").concat(e.mode)}function buildIframe(e,t){var n;switch(e.type){case"quiz":n=500;break;case"answer":n=50;break;default:n=0}var i=document.createElement("iframe");i.setAttribute("title","Pinpoll Widget"),i.setAttribute("frameborder","0"),i.setAttribute("scrolling","no"),i.setAttribute("width","100%"),i.setAttribute("id",t),i.setAttribute("name",window.location.toString()),i.setAttribute("style","display:block; height:"+e.height||0);var o=e.height||n;return o&&i.setAttribute("height",o.toString()),i}function buildUrl(e,t){var n,i=!1,o="";e.styles&&(o+=e.styles),e.height&&(o+="".concat(o.length>0?"&":"","height=").concat(e.height)),e.trackmode&&"preview"===e.trackmode&&(o+="".concat(o.length>0?"&":"","previewMode=1")),e.simulate&&"on"===e.simulate&&(o+="".concat(o.length>0?"&":"","simulate=1")),e.editmode&&"on"===e.editmode&&(o+="".concat(o.length>0?"&":"","editMode=1"),i=!0),e.randomQuestions&&(o+="".concat(o.length>0?"&":"","randomQuestions=1")),e.randomAnswers&&(o+="".concat(o.length>0?"&":"","randomAnswers=1")),"preload"===e.loading&&(o+="".concat(o.length>0?"&":"","preloadMode=1")),e.blockAds&&(o+="".concat(o.length>0?"&":"","blockAds=1")),e.info&&Object.keys(e.info).length&&(o+="".concat(o.length>0?"&":"","info=").concat(encodeURIComponent(JSON.stringify(e.info)))),t&&(o+="".concat(o.length>0?"&":"","parentID=").concat(encodeURIComponent(t)));var a="";if(e.version)return"".concat(e.location,"/embed/").concat(e.version,"?id=").concat(e.id).concat(o?"&".concat(o):"");switch(e.type){case"answer":n="".concat(e.location,"/embed/answer/").concat(e.id).concat(o?"?".concat(o):"");break;default:"result"===e.mode&&(a+="/result"),n="".concat(e.location||"","/").concat(i?"direct/":"","embed/").concat("aipoll"===e.mode?"inspire/":"").concat(e.id).concat(a),e.design&&(n+="/cd/"+e.design),n+=o?"?".concat(o):""}return n}},631:(e,t,n)=>{"use strict";n.d(t,{ZP:()=>g,oW:()=>v});var i=n(768);function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var l=["served","loads","renders","impressions"],s=new Set(["url","ppid","class","consent","style","opointdata","rect_data","bis_style"]),d=["target-ads-","_","font-"],c=function(){function e(t,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:500;o(this,e),r(this,"endpoint",void 0),r(this,"flushDelayMs",void 0),r(this,"url",void 0),r(this,"embedcode",void 0),r(this,"stage",-1),r(this,"sentStage",-1),r(this,"flushTimer",null),r(this,"flushing",!1),r(this,"impressionObserver",void 0),this.endpoint=this.resolveEndpoint(),this.flushDelayMs=i,this.url=n,this.embedcode=this.buildEmbedcode(t),this.registerLifecycleFlush()}var t,n;return t=e,(n=[{key:"markServed",value:function(){this.mark("served")}},{key:"markLoad",value:function(){this.mark("loads")}},{key:"markRender",value:function(){this.mark("renders")}},{key:"markImpression",value:function(){var e=this.stage;this.mark("impressions",!1),this.stage>e&&(null!==this.flushTimer&&(window.clearTimeout(this.flushTimer),this.flushTimer=null),this.flush(!1))}},{key:"observeImpression",value:function(e){var t=this;this.stage>=l.indexOf("impressions")||("IntersectionObserver"in window?(this.impressionObserver||(this.impressionObserver=new IntersectionObserver((function(e){e.forEach((function(e){var n;e.isIntersecting&&e.intersectionRatio>=.5&&(t.markImpression(),null===(n=t.impressionObserver)||void 0===n||n.disconnect())}
658))}),{threshold:[.5]})),this.impressionObserver.observe(e)):this.markImpression())}},{key:"resolveEndpoint",value:function(){var e="https://api.embed.pinpoll.com";return"".concat(e.replace(/\/+$/,""),"/v3/widget")}},{key:"buildEmbedcode",value:function(e){var t=this,n={};Array.from(e.attributes).sort((function(e,t){return e.name.localeCompare(t.name)})).forEach((function(e){var i=t.normalizeAttrName(e.name);!i||s.has(i)||d.some((function(e){return i.startsWith(e)}))||void 0!==n[i]||(n[i]=e.value)}));var i={};return Object.keys(n).sort().forEach((function(e){i[e]=n[e]})),JSON.stringify(i)}},{key:"normalizeAttrName",value:function(e){return e.startsWith("data-pinpoll-")?e.substring(13):e.startsWith("data-")?e.substring(5):e}},{key:"advance",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=l.indexOf(e);if(!(n<=this.stage)){if(n>this.stage+1)for(var i=this.stage+1;i<n;i++){var o=l[i];console.warn('Pinpoll: automatically marked skipped stage "'.concat(o,'" for embed ').concat(this.embedcode))}this.stage=n,t&&this.scheduleFlush()}}},{key:"scheduleFlush",value:function(){var e=this;this.endpoint&&(null!==this.flushTimer&&window.clearTimeout(this.flushTimer),this.flushTimer=window.setTimeout((function(){e.flushTimer=null,e.flush(!1)}),this.flushDelayMs))}},{key:"hasPending",value:function(){return this.stage>this.sentStage}},{key:"buildPayloadRow",value:function(e,t){var n=function(n){var i=l.indexOf(n);return i>e&&i<=t?1:0};return{url:this.url,embedcode:this.embedcode,served:n("served"),loads:n("loads"),renders:n("renders"),impressions:n("impressions")}}},{key:"flush",value:function(e){var t=this;if(this.endpoint&&this.hasPending()&&!this.flushing){var n=this.stage,i=this.buildPayloadRow(this.sentStage,n);if(i.served+i.loads+i.renders+i.impressions!==0){var o=i;e&&navigator.sendBeacon?navigator.sendBeacon(this.endpoint,new Blob([JSON.stringify(o)],{type:"application/json"}))&&(this.sentStage=Math.max(this.sentStage,n)):(this.flushing=!0,fetch(this.endpoint,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},credentials:"include",keepalive:e,body:JSON.stringify(o)}).then((function(){t.sentStage=Math.max(t.sentStage,n)})).catch((function(){})).finally((function(){t.flushing=!1,t.hasPending()&&t.scheduleFlush()})))}}}},{key:"mark",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.advance(e,t)}},{key:"registerLifecycleFlush",value:function(){var e=this;window.addEventListener("pagehide",(function(){return e.flush(!0)})),document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&e.flush(!0)}))}}])&&a(t.prototype,n),e}();function u(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=p(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var i=0,o=function(){};return{s:o,n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,r=!0,l=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return r=e.done,e},e:function(e){l=!0,a=e},f:function(){try{r||null==n.return||n.return()}finally{if(l)throw a}}}}function p(e,t){if(e){if("string"==typeof e)return f(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?f(e,t):void 0}}function f(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n<t;n++)i[n]=e[n];return i}var m={1:"poll",2:"quiz",6:"personality_test"};function h(e){var t,n,i=e.getAttribute("data-pinpoll-location")||e.getAttribute("data-location")||"https://embed.pinpoll.com",o=e.getAttribute("data-design");return{type:e.getAttribute("data-pinpoll-type")||e.getAttribute("data-type")||"poll",aiPollMode:"aipoll"===e.getAttribute("data-mode"),version:e.getAttribute("data-version"),native:null!==e.getAttribute("data-native")||"v2"===e.getAttribute("data-version"),mode:e.getAttribute("data-pinpoll-mode")||e.getAttribute("data-mode")||"poll",location:i,trackmode:e.getAttribute("data-pinpoll-trackmode")||e.getAttribute("data-trackmode")||"default",editmode:e.getAttribute("data-pinpoll-editmode")||e.getAttribute("data-editmode")||"default",simulate:e.getAttribute("data-pinpoll-simulate")||e.getAttribute("data-simulate")||"default",id:parseInt(e.getAttribute("data-pinpoll-id")||e.getAttribute("data-id"),10)||0,height:parseInt(e.getAttribute("data-pinpoll-height")||e.getAttribute("data-height"),10)||0,label:e.getAttribute("data-pinpoll-label")||e.getAttribute("data-label")||"",bgcolor:e.getAttribute("data-pinpoll-bgcolor")||e.getAttribute("data-bgcolor")||"#2395a6",styles:function(){var t,n=/data(?:-pinpoll)?-style-(.+)/,i=[],o=u(e.attributes);try{for(o.s();!(t=o.n()).done;){var a=t.value,r=a.name.match(n);r&&i.push("".concat(encodeURIComponent(r[1]),"=").concat(encodeURIComponent(a.value)))}}catch(e){o.e(e)}finally{o.f()}return!!i.length&&i.join("&")}(),loading:e.getAttribute("data-loading")||!1,design:o?+o:null,randomQuestions:null!==e.getAttribute("random-questions"),randomAnswers:null!==e.getAttribute("random-answers"),forceLoad:null!==e.getAttribute("force-load"),cssClass:null===(t=e.getAttribute("data-css-class"))||void 0===t?void 0:t.trim(),customURL:null===(n=e.getAttribute("data-url"))||void 0===n?void 0:n.trim(),url:e.getAttribute("data-url")||(window.location.origin||"unknown_origin")+window.location.pathname,info:e.getAttributeNames().reduce((function(t,n){return n.startsWith("data-info-")&&(t[n.substring(10)]=e.getAttribute(n)),t}),{}),targetAds:e.getAttributeNames().reduce((function(t,n){return n.startsWith("data-target-a
658ds-")&&(t[n.substring(16)]=e.getAttribute(n)),t}),{}),autoplay:[null,"false"].includes(e.getAttribute("data-autoplay"))?void 0:+(e.getAttribute("data-autoplay")||0),autoplayDelay:[null,""].includes(e.getAttribute("data-autoplay-delay"))?void 0:+(e.getAttribute("data-autoplay-delay")||0),mqeDelay:[null,""].includes(e.getAttribute("data-mqe-delay"))?void 0:+(e.getAttribute("data-mqe-delay")||0),blockAds:![null,"false","0"].includes(e.getAttribute("data-block-ads")),topic:e.getAttribute("data-topic"),ppId:e.getAttribute("data-ppid"),consent:e.getAttribute("data-consent"),muteVoted:![null,"false","0"].includes(e.getAttribute("data-mute-voted"))}}function v(e,t){var n,i=h(t);Object.assign(e,i,{id:i.id||e.id,design:null!==(n=i.design)&&void 0!==n?n:e.design})}const g=function(){return{embeds:[],initedEmbeds:0,fallbackElementsPromise:{},isElementAlreadyEmbedded:function(e,t,n){var i=t?m[t]:null;try{var o=['[data-pinpoll-id="'.concat(e,'"]'),'script[data-location*="'.concat(n||"pinpoll.com",'"][data-id="').concat(e,'"]')],a=i?o.map((function(e){return"".concat(e,":not([data-type]), ").concat(e,'[data-type="').concat(i,'"]')})).join(", "):o.join(", ");return!!document.body.querySelector(a)||!!this.embeds.find((function(t){var n,i,o;return(null===(n=t.data)||void 0===n?void 0:n.id)===e&&("poll"===(null===(i=t.data)||void 0===i?void 0:i.type)||"aipoll"===(null===(o=t.data)||void 0===o?void 0:o.type))}))}catch(e){return!1}},isAnyElementEmbedded:function(){return!!this.embeds.find((function(e){return"aipoll"!==e.mode}))||!!document.body.querySelector('[data-pinpoll-id]:not([data-mode="aipoll"]), script[data-location*="'.concat("pinpoll.com",'"][data-id]'))},getElementVotedStatus:function(e){var t,n,i=e.questions,o=e.multiple_vote_interval,a=null===(t=window.Pinpoll)||void 0===t||null===(n=t.storage)||void 0===n?void 0:n.votes;if(i&&a){var r=a.filter((function(e){return i.includes(e.question_id)}));if(null!=r&&r.length)return!o||r.find((function(e){return e.voted_at+o>(new Date).getTime()}))?2:1}return 0},sortPreferredAutoEmbeddedElements:function(e,t,n){var i=this,o=t.location,a=t.muteVoted,r=t.height,l=[];if(e){var s,d;if(l=e.filter((function(e){return!i.isElementAlreadyEmbedded(e.element_id,e.type_id,o)})),null!==(s=window.Pinpoll)&&void 0!==s&&s.appName&&(l=l.filter((function(e){return 1===e.type_id&&2===e.max_answers}))),null!==(d=window.Pinpoll)&&void 0!==d&&d.heightFilterActive&&r){var c=n&&n.parentNode!==document.getElementsByTagName("head")[0]&&n.parentElement?n.clientWidth:document.body.clientWidth;l=l.filter((function(e){try{var t=JSON.parse(e.height),n=Math.max.apply(Math,function(e){if(Array.isArray(e))return f(e)}(i=Object.keys(t).map(Number).filter((function(e){return e<=c})))||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(i)||p(i)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}());if(t[n])return parseInt(t[n])<=r}catch(e){return!1}var i}))}a?l=l.filter((function(e){return 2!==i.getElementVotedStatus(e)})):l.length&&void 0===l[0].sort&&(l=l.sort((function(e,t){var n=i.getElementVotedStatus(e),o=i.getElementVotedStatus(t);return n===o?0:n<o?-1:1})))}return l},getFallbackElements:function(e,t){var n=t+e;if(!this.fallbackElementsPromise[n]){var i={url:e};t&&(i.topic=t),this.fallbackElementsPromise[n]=fetch("https://api.embed.pinpoll.com/aipolls/search?"+new URLSearchParams(i),{method:"GET"}).then((function(e){return e.json()})).then((function(e){return e})).catch((function(e){console.log("Pinpoll: error during fetching aipolls",e)}))}return this.fallbackElementsPromise[n]},initEmbed:function(e){var t=this;if(!this.embeds.find((function(t){return t.element===e}))){var n=h(e),o=new c(e,n.url);e.classList.add("loaded"),o.markServed(),n.id&&!n.native?this.embeds.push(new i.Z(n,e,o)):new Promise((function(t){"eager"!==n.loading&&"preload"!==n.loading?(e.classList.add("lazyload"),new Promise((function(t){document.addEventListener("lazybeforeunveil",(function(n){n.target===e&&t()}))})).finally((function(){t()}))):t()})).then((function(){v(n,e),n.native?t.embeds.push(new i.Z(n,e,o)):n.aiPollMode||n.topic?n.forceLoad||!t.isAnyElementEmbedded()?new Promise((function(e){n.aiPollMode?(o.markLoad(),fetch("https://api.embed.pinpoll.com/aipolls/first?"+new URLSearchParams({url:n.url}),{method:"GET"}).then((function(e){return e.json()})).then((function(t){n.id=t.id,e()})).catch((function(t){console.log("Pinpoll: error during fetching aipoll",t),e()}))):e()})).finally((function(){n.id?t.embeds.push(new i.Z(n,e,o)):(n.aiPollMode&&!n.topic||!n.aiPollMode&&n.topic)&&(o.markLoad(),n.fallbackElementsPromise=t.getFallbackElements(n.url,n.topic).then((function(a){var r,l=a.elements;n.fallbackElements=t.sortPreferredAutoEmbeddedElements(l,n,e);var s=null===(r=n.fallbackElements)||void 0===r?void 0:r.shift();s?(n.id=s.element_id,!n.design&&s.custom_design_id&&(n.design=s.custom_design_id),n.fallback_id=s.id,t.embeds.push(new i.Z(n,e,o))):console.log("Pinpoll: no suitable element found for",e)})))})):console.log("Pinpoll: not embedding as another element is already embedded",e):console.log("Pinpoll: no id or data specified for element",e)}))}},start:function(){var e=this;window.MutationObserver=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;var t=function(){var t,n=u(document.querySelectorAll("div[data-pinpoll-id]:not(.loaded), div.pinpoll:not(.loaded)"));try{for(n.s();!(t=n.n()).done;){var i=t.value;e.initEmbed(i)}}catch(e){n.e(e)}finally{n.f()}};t();var n=window.setInterval((function(){t()}),500);window.MutationObserver&&(window.setTimeout((function(){window.clearInterval(n)}),1e4),new window.MutationObserver((function(t){t.forEach((function(t){var n,i=u(t.addedNodes);try{for(i.s();!(n=i.n()).done;){var o=n.value;o.matches&&o.matches("div[data-pinpoll-id]:not(.loaded), div.pinpoll:not(.loaded)")&&e.initEmbed(o)}}catch(e){i.e(e)}finally{i.f()}}))})).observe(document,{childList:!0,subtree:!0}))},broadcast:function(e){var t,n=u(this.embeds);try{for(n.s();!(t=n.n()).done;)t.value.postMessage(e)}catch(e){n.e(e)}finally{n.f()}}}}},726:()=>{function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function t(t){for(var i=1;i<arguments.length;i++){var o=null!=arguments[i]?arguments[i]:{};
658i%2?e(Object(o),!0).forEach((function(e){n(t,e,o[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(o)):e(Object(o)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(o,e))}))}return t}function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(e){var t=window.Pinpoll.storage.votes;t||(t=[]),-1===t.findIndex((function(t){return t.answer_id===e.answer_id&&t.voted_at===e.voted_at}))&&t.push(e),window.Pinpoll.storage.votes=t}window.addEventListener("message",(function(e){var n=e.data;try{if("string"==typeof n){if(!n.startsWith("{"))return!1;n=JSON.parse(n)}}catch(e){console.warn(e)}var a=function(t){e.source&&e.source.postMessage(t,e.origin)};if(n&&"object"===i(n)&&n.action)switch(n.action){case"get:visitor-votes":a({action:"return:visitor-votes",data:window.Pinpoll.storage.votes.map((function(e){return t(t({},e),{},{justVoted:!!window.Pinpoll.votelinkVotes.find((function(t){return t.answer_id===e.answer_id&&t.voted_at===e.voted_at}))})}))});break;case"add:visitor-vote":o(n.data);break;case"remove:visitor-vote":var r=window.Pinpoll.storage.votes,l=n.data,s=l.questionId,d=l.answerId;if(r){var c=r.filter((function(e){return(e.question_id||e.poll_id)!==s||e.answer_id!==d}));window.Pinpoll.storage.votes=c}break;case"remove:visitor-vote-element":var u=window.Pinpoll.storage.votes,p=n.data.questionIds;if(u){var f=u.filter((function(e){return!p.some((function(t){return t===e.question_id}))}));window.Pinpoll.storage.votes=f}break;case"add":var m=n.key;if(!m)break;var h=window.Pinpoll.storage[m];if(!h)break;if(!(h instanceof Array))break;h.push(n.value),window.Pinpoll.storage[m]=h;break;case"get":var v=n.key;if(!v)break;a({action:"return:"+v,data:{key:v,value:window.Pinpoll.storage[v]}})}return null})),function(){var e=new URL(window.location.href),t=e.searchParams.get("pinpoll_votes");if(t){var n;try{n=JSON.parse(t)}catch(e){console.warn("Pinpoll: Failed parsing pinpoll_votes GET parameter")}n&&n instanceof Array&&n.forEach((function(e){o(e),window.Pinpoll.votelinkVotes.push(e)}));try{e.searchParams.delete("pinpoll_votes"),window.history.pushState({},document.title,e.toString())}catch(e){}}}()},558:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var i=n(38),o=n(58),a=n(173);function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n<t;n++)i[n]=e[n];return i}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}const d=function(e,t){var n=t||{},d=n.widgetIndex,c=n.originPage,u=n.widgetLocation,p={},f=(0,i.G)({BASE_DOMAIN:"pinpoll.com",CDN_ENDPOINT:"https://static.pinpoll.com",API_ENDPOINT:"https://pa.pinpoll.com/v1",cookiesEnabled:function(){if(navigator.cookieEnabled)return!0;document.cookie="cookietest=1";var e=-1!==document.cookie.indexOf("cookietest=");return document.cookie="cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT",e}(),thirdPartyCookiesEnabled:!1,tcfApi:{},requestSent:!1,requestDone:!1,start:function(e){"loading"===document.readyState?document.addEventListener("DOMContentLoaded",m):m(),e&&(p=e)}});function m(){window.setTimeout((function(){Promise.all([(0,a.I)(),window.location.hostname.match(f.BASE_DOMAIN)?Promise.resolve():new Promise((function(e){try{var t=document.createElement("iframe");t.style.display="none",t.title="Pinpoll Third Party Cookie Test",t.src="".concat(f.CDN_ENDPOINT,"/static/start.html"),window.addEventListener("message",(function(t){"MM:3PCunsupported"===t.data?f.thirdPartyCookiesEnabled=!1:"MM:3PCsupported"===t.data&&(f.thirdPartyCookiesEnabled=!0),e()}),!1),document.body.appendChild(t),window.setTimeout((function(){t.remove(),e()}),5e3)}catch(t){f.log("Could not check ThirdPartyCookiesEnabled",t),e()}})),window.ppTcString?(f.tcfApi.tcString=window.ppTcString,f.tcfApi.available=!!window.__tcfapi,Promise.resolve()):window.__tcfapi?(f.tcfApi.available=!0,new Promise((function(e){var t=(new Date).getTime();window.__tcfapi("addEventListener",2,(function(n,i){f.tcfApi.responseTime=(new Date).getTime()-t,i?f.tcfApi.tcString=n.tcString:f.log("tcf api responded with error",n),f.tcfApi.timeout||(f.tcfApi.timeout=!1),f.tcfApi.checkFinished=!0,e()})),window.setTimeout((function(){f.tcfApi.checkFinished||(f.tcfApi.timeout=!0,e())}),1e3)}))):(f.tcfApi.available=!1,Promise.resolve())]).then((function(){var t,n;t=u?function(){try{return new URL(u)}catch(e){return f.log("Could not parse widget location",e),document.location}}():document.location,n=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};
658t%2?l(Object(n),!0).forEach((function(t){s(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}({timezone:(new Date).getTimezoneOffset(),adblock:window.Pinpoll.userHasAdblock?1:0,dnt:window.navigator.doNotTrack,cookiesEnabled:f.cookiesEnabled?1:0,localStorageEnabled:v(),thirdPartyCookiesEnabled:f.thirdPartyCookiesEnabled?1:0,referrer:c||document.referrer,title:document.title,tcString:f.tcfApi.tcString,tcfApiAvailable:f.tcfApi.available,location:{hash:t.hash,hostname:t.hostname,pathname:t.pathname,protocol:t.protocol,search:t.search},screen:{width:window.screen.width,height:window.screen.height,colorDepth:window.screen.colorDepth,orientation:window.screen.orientation?window.screen.orientation.type:null},metaTags:h(),widgetIndex:d||""},p),(0,o.w)(f.API_ENDPOINT,n,e).then((function(t){var n,i,o=t.headers.get("PP-Visitor");o&&(e.visitor=o,null===(n=window.Pinpoll)||void 0===n||null===(i=n.embed)||void 0===i||i.broadcast({action:"global:trackingDone",visitor:o}))})).catch((function(e){var t,n;f.log("fetch request failed",e),null===(t=window.Pinpoll)||void 0===t||null===(n=t.embed)||void 0===n||n.broadcast({action:"global:trackingDone"})})).finally((function(){f.requestDone=!0}))}))}))}function h(){var e,t={},n=function(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=function(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?r(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var i=0,o=function(){};return{s:o,n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,l=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return l=e.done,e},e:function(e){s=!0,a=e},f:function(){try{l||null==n.return||n.return()}finally{if(s)throw a}}}}(document.getElementsByTagName("meta"));try{for(n.s();!(e=n.n()).done;){var i=e.value,o=i.getAttribute("name")||i.getAttribute("property"),a=i.getAttribute("content");if(o&&a&&o.replace(/\s/g,"").length>0){var l=o.trim().toLowerCase(),s=t[l];s?s instanceof Array?t[l].push(a):t[l]=[s,a]:t[l]=a}}}catch(e){n.e(e)}finally{n.f()}return t}function v(){var e="test";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(e){return!1}}return f}},38:(e,t,n)=>{"use strict";function i(e){var t=e;return t.logs=[],t.log=function(){for(var e=arguments.length,n=new Array(e),i=0;i<e;i++)n[i]=arguments[i];t.logs.push([new Date,n])},t}n.d(t,{G:()=>i})},173:(e,t,n)=>{"use strict";function i(){var e;return void 0!==(null===(e=window.Pinpoll)||void 0===e?void 0:e.userHasAdblock)?Promise.resolve(window.Pinpoll.userHasAdblock):new Promise((function(e){var t=window.setTimeout((function(){var e;null!==(e=window.Pinpoll)&&void 0!==e&&e.userHasAdblock||n(!1)}),1e3),n=function(n){clearTimeout(t),window.Pinpoll=window.Pinpoll||{},window.Pinpoll.userHasAdblock=n,e(n)},i=document.createElement("div");i.innerHTML="&nbsp;",i.style.position="absolute",i.className="native-ad-container mobile-ad js-ad_iframe";try{document.body.appendChild(i)}catch(e){console.log("Could not check Adblock",e),n(!1)}window.setTimeout((function(){n(0===i.offsetHeight),i.remove()}),100)}))}n.d(t,{I:()=>i})},58:(e,t,n)=>{"use strict";function i(e,t,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"post",o={Accept:"application/json","Content-Type":"application/json"},a=n.visitor;return a&&(o["PP-Visitor"]=a),fetch(e,{method:i,headers:o,credentials:"include",body:JSON.stringify(t)})}n.d(t,{w:()=>i})},90:e=>{!function(t,n){var i=function(e,t,n){"use strict";var i,o;if(function(){var t,n={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",fastLoadedClass:"ls-is-cached",iframeLoadMode:0,srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};for(t in o=e.lazySizesConfig||e.lazysizesConfig||{},n)t in o||(o[t]=n[t])}(),!t||!t.getElementsByClassName)return{init:function(){},cfg:o,noSupport:!0};var a,r,l,s,d,c,u,p,f,m,h,v,g,b,w,y,_,k,P,A,E,O,S,I,C,T,x,M,N,D,j,z,L,q,R,W,B,U,G,F,V,J,H,K,$=t.documentElement,Z=e.HTMLPictureElement,Y="addEventListener",X=e.addEventListener.bind(e),Q=e.setTimeout,ee=e.requestAnimationFrame||Q,te=e.requestIdleCallback,ne=/^picture$/i,ie=["load","error","lazyincluded","_lazyloaded"],oe={},ae=Array.prototype.forEach,re=function(e,t){return oe[t]||(oe[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),oe[t].test(e.getAttribute("class")||"")&&oe[t]},le=function(e,t){re(e,t)||e.setAttribute("class",(e.getAttribute("class")||"").trim()+" "+t)},se=function(e,t){var n;(n=re(e,t))&&e.setAttribute("class",(e.getAttribute("class")||"").replace(n," "))},de=function(e,t,n){var i=n?Y:"removeEventListener";n&&de(e,t),ie.forEach((function(n){e[i](n,t)}))},ce=function(e,n,o,a,r){var l=t.createEvent("Event");return o||(o={}),o.instance=i,l.initEvent(n,!a,!r),l.detail=o,e.dispatchEvent(l),l},ue=function(t,n){var i;!Z&&(i=e.picturefill||o.pf)?(n&&n.src&&!t.getAttribute("srcset")&&t.setAttribute("srcset",n.src),i({reevaluate:!0,elements:[t]})):n&&n.src&&(t.src=n.src)},pe=function(e,t){return(getComputedStyle(e,null)||{})[t]},fe=function(e,t,n){for(n=n||e.offsetWidth;n<o.minSize&&t&&!e._lazysizesWidth;)n=t.offsetWidth,t=t.parentNode;return n},me=(V=[],J=F=[],(K=function(e,n){U&&!n?e.apply(this,arguments):(J.push(e),G||(G=!0,(t.hidden?Q:ee)(H)))})._lsFlush=H=function(){var e=J;for(J=F.length?V:F,U=!0,G=!1;e.length;)e.shift()();U=!1},K),he=function(e,t){return t?function(){me(e)}:function(){var t=this,n=arguments;me((function(){e.apply(t,n)}))}},ve=function(e){var t,i,o=function(){t=null,e()},a=function(){var e=n.now()-i;e<99?Q(a,99-e):(te||o)(o)};return function(){i=n.now(),t||(t=Q(a,99))}},ge=(_=/^img$/i,k=/^iframe$/i,P="onscroll"in e&&!/(gle|ing)bot/.test(navigator.userAgent),0,A=0,E=0,O=-1,S=function(e){E--,(!e||E<0||!e.target)&&(E=0)},I=function(e){return null==y&&(y="hidden"==pe(t.body,"visibility")),y||!("hidden"==pe(e.parentNode,"visibility")&&"hidden"==pe(e,"visibility"))},C=function(e,n){var i,o=e,a=I(e);for(v-=n,w+=n,g-=n,b+=n;a&&(o=o.offsetParent)&&o!=t.body&&o!=$;)(a=(pe(o,"opacity")||1)>0)&&"visible"!=pe(o,"overflow")&&(i=o.getBoundingClientRect(),a=b>i.left&&g<i.right&&w>i.top-1&&v<i.bottom+1);return a},x=function(e){var t,i=0,a=o.throttleDelay,r=o.ricTimeout,l=function(){t=!1,i=n.now(),e()},s=te&&r>49?function(){te(l,{timeout:r}),r!==o.ricTimeout&&(r=o.ricTimeout)}:he((function(){Q(l)}),!0);return function(e){var o;(e=!0===e)&&(r=33),t||(t=!0,(o=a-(n.now()-i))<0&&(o=0),e||o<9?s():Q(s,o))}}(T=function(){var e,n,a,r,l,s,u,f,_,k,S,T,x=i.elements;if((p=o.loadMode)&&E<8&&(e=x.length)){for(n=0,O++;n<e;n++)if(x[n]&&!x[n]._lazyRace)if(!P||i.prematureUnveil&&i.prematureUnveil(x[n]))q(x[n]);else if((f=x[n].getAttribute("data-expand"))&&(s=1*f)||(s=A),k||(k=!o.expand||o.expand<1?$.clientHeight>500&&$.clientWidth>500?500:370:o.expand,i._defEx=k,S=k*o.expFactor,T=o.hFac,y=null,A<S&&E<1&&O>2&&p>2&&!t.hidden?(A=S,O=0):A=p>1&&O>1&&E<6?k:0),_!==s&&(m=innerWidth+s*T,h=innerHeight+s,u=-1*s,_=s),a=x[n].getBoundingClientRect(),(w=a.bottom)>=u&&(v=a.top)<=h&&(b=a.right)>=u*T&&(g=a.left)<=m&&(w||b||g||v)&&(o.loadHidden||I(x[n]))&&(c&&E<3&&!f&&(p<3||O<4)||C(x[n],s))){if(q(x[n]),l=!0,E>9)break}else!l&&c&&!r&&E<4&&O<4&&p>
6582&&(d[0]||o.preloadAfterLoad)&&(d[0]||!f&&(w||b||g||v||"auto"!=x[n].getAttribute(o.sizesAttr)))&&(r=d[0]||x[n]);r&&!l&&q(r)}}),N=he(M=function(e){var t=e.target;t._lazyCache?delete t._lazyCache:(S(e),le(t,o.loadedClass),se(t,o.loadingClass),de(t,D),ce(t,"lazyloaded"))}),D=function(e){N({target:e.target})},j=function(e,t){var n=e.getAttribute("data-load-mode")||o.iframeLoadMode;0==n?e.contentWindow.location.replace(t):1==n&&(e.src=t)},z=function(e){var t,n=e.getAttribute(o.srcsetAttr);(t=o.customMedia[e.getAttribute("data-media")||e.getAttribute("media")])&&e.setAttribute("media",t),n&&e.setAttribute("srcset",n)},L=he((function(e,t,n,i,a){var r,l,s,d,c,p;(c=ce(e,"lazybeforeunveil",t)).defaultPrevented||(i&&(n?le(e,o.autosizesClass):e.setAttribute("sizes",i)),l=e.getAttribute(o.srcsetAttr),r=e.getAttribute(o.srcAttr),a&&(d=(s=e.parentNode)&&ne.test(s.nodeName||"")),p=t.firesLoad||"src"in e&&(l||r||d),c={target:e},le(e,o.loadingClass),p&&(clearTimeout(u),u=Q(S,2500),de(e,D,!0)),d&&ae.call(s.getElementsByTagName("source"),z),l?e.setAttribute("srcset",l):r&&!d&&(k.test(e.nodeName)?j(e,r):e.src=r),a&&(l||d)&&ue(e,{src:r})),e._lazyRace&&delete e._lazyRace,se(e,o.lazyClass),me((function(){var t=e.complete&&e.naturalWidth>1;p&&!t||(t&&le(e,o.fastLoadedClass),M(c),e._lazyCache=!0,Q((function(){"_lazyCache"in e&&delete e._lazyCache}),9)),"lazy"==e.loading&&E--}),!0)})),q=function(e){if(!e._lazyRace){var t,n=_.test(e.nodeName),i=n&&(e.getAttribute(o.sizesAttr)||e.getAttribute("sizes")),a="auto"==i;(!a&&c||!n||!e.getAttribute("src")&&!e.srcset||e.complete||re(e,o.errorClass)||!re(e,o.lazyClass))&&(t=ce(e,"lazyunveilread").detail,a&&be.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,E++,L(e,t,a,i,n))}},R=ve((function(){o.loadMode=3,x()})),B=function(){c||(n.now()-f<999?Q(B,999):(c=!0,o.loadMode=3,x(),X("scroll",W,!0)))},{_:function(){f=n.now(),i.elements=t.getElementsByClassName(o.lazyClass),d=t.getElementsByClassName(o.lazyClass+" "+o.preloadClass),X("scroll",x,!0),X("resize",x,!0),X("pageshow",(function(e){if(e.persisted){var n=t.querySelectorAll("."+o.loadingClass);n.length&&n.forEach&&ee((function(){n.forEach((function(e){e.complete&&q(e)}))}))}})),e.MutationObserver?new MutationObserver(x).observe($,{childList:!0,subtree:!0,attributes:!0}):($.addEventListener("DOMNodeInserted",x,!0),$.addEventListener("DOMAttrModified",x,!0),setInterval(x,999)),X("hashchange",x,!0),["focus","mouseover","click","load","transitionend","animationend"].forEach((function(e){t.addEventListener(e,x,!0)})),/d$|^c/.test(t.readyState)?B():(X("load",B),t.addEventListener("DOMContentLoaded",x),Q(B,2e4)),i.elements.length?(T(),me._lsFlush()):x()},checkElems:x,unveil:q,_aLSL:W=function(){3==o.loadMode&&(o.loadMode=2),R()}}),be=(r=he((function(e,t,n,i){var o,a,r;if(e._lazysizesWidth=i,i+="px",e.setAttribute("sizes",i),ne.test(t.nodeName||""))for(a=0,r=(o=t.getElementsByTagName("source")).length;a<r;a++)o[a].setAttribute("sizes",i);n.detail.dataAttr||ue(e,n.detail)})),l=function(e,t,n){var i,o=e.parentNode;o&&(n=fe(e,o,n),(i=ce(e,"lazybeforesizes",{width:n,dataAttr:!!t})).defaultPrevented||(n=i.detail.width)&&n!==e._lazysizesWidth&&r(e,o,i,n))},{_:function(){a=t.getElementsByClassName(o.autosizesClass),X("resize",s)},checkElems:s=ve((function(){var e,t=a.length;if(t)for(e=0;e<t;e++)l(a[e])})),updateElem:l}),we=function(){!we.i&&t.getElementsByClassName&&(we.i=!0,be._(),ge._())};return Q((function(){o.init&&we()})),i={cfg:o,autoSizer:be,loader:ge,init:we,uP:ue,aC:le,rC:se,hC:re,fire:ce,gW:fe,rAF:me}}(t,t.document,Date);t.lazySizes=i,e.exports&&(e.exports=i)}("undefined"!=typeof window?window:{})}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{"use strict";const e={embed:null,tracking:null,retargeting:null,remarketing:null,storage:function(){var e={};Object.defineProperty(e,"visitor",{set:function(e){if(window.Pinpoll.embed){var t;try{t=JSON.parse(localStorage.PP_visitor).value}catch(e){t=null}t!==e&&setTimeout((function(){window.Pinpoll.embed.broadcast({action:"set:visitor",visitor:e})}))}try{localStorage.PP_visitor=e&&"null"!==e?JSON.stringify({value:e,expires:(new Date).setDate((new Date).getDate()+30)}):JSON.stringify({value:e,expires:0})}catch(e){console.warn(e)}},get:function(){try{if(!localStorage.PP_visitor)return null;var e=JSON.parse(localStorage.PP_visitor);return e.expires&&e.expires<Date.now()?(delete localStorage.PP_visitor,null):(e.expires=(new Date).setDate((new Date).getDate()+30),localStorage.PP_visitor=JSON.stringify(e),e.value)}catch(e){return console.warn(e),null}}});for(var t=function(){var t=i[n];Object.defineProperty(e,t.id,{set:function(e){try{localStorage[t.key]=JSON.stringify(e)}catch(e){console.warn(e)}},get:function(){try{var e=localStorage[t.key];return e?JSON.parse(e):t.d}catch(e){return console.warn(e),t.d}}})},n=0,i=[{id:"votes",key:"PP_votes",d:[]},{id:"leadForms",key:"PP_forms",d:[]},{id:"lastTriggered",key:"PP_marketing",d:null}];n<i.length;n++)t();try{localStorage.pinpoll_allVisitorVotes&&(localStorage.PP_votes=localStorage.pinpoll_allVisitorVotes,delete localStorage.pinpoll_allVisitorVotes)}catch(e){}return e}(),heightFilterActive:!1,nativeLoader:void 0,votelinkVotes:[],init:function(){var e=document.querySelector("script[src*='pinpoll.com/global.js'][data-app]");e&&(this.appName=e.getAttribute("data-app"))}};window.Pinpoll&&Object.keys(window.Pinpoll).length>0||(window.Pinpoll=e,e.init())})(),(()=>{"use strict";var e=__webpack_require__(558);window.Pinpoll.tracking||(window.Pinpoll.tracking=(0,e.Z)(window.Pinpoll.storage,{widgetIndex:"global"}),window.Pinpoll.tracking.start(window.Pinpoll.appName?{app:window.Pinpoll.appName}:void 0))})(),(()=>{"use strict";var e=__webpack_require__(38),t=__webpack_require__(58);function n(){var e;if(null!==(e=window.Pinpoll)&&void 0!==e&&e.appName)return!0;var t=window.navigator,n=t.userAgent.toLowerCase();return/iphone|ipod|ipad/.test(n)&&!window.MSStream?!t.standalone&&!/safari/.test(n):n.includes("wv")}var i=eval;window.Pinpoll.retargeting||(window.Pinpoll.retargeting=function(o,a){var r,l,s=(0,e.G)({RETARGETING_ENDPOINT:"https://api2.dmp.pinpoll.com",pixelsLoaded:!1,pixels:[],isMobileDevice:(l=!1,r=navigator.userAgent||navigator.vendor||window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(r)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|
658sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(r.substr(0,4)))&&(l=!0),l),isApp:n(),googleLoaded:!1,trackEmbedEvent:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;if(s.pixelsLoaded)d(e,n);else{var o=window.location!==window.parent.location?document.referrer:document.location.href;p({referrer:o,questionId:t,leadFormId:i}).then((function(t){s.pixelsLoaded=!0,t&&"success"===t.status&&t.data.length>0&&(s.pixels=t.data),d(e,n)})).catch((function(e){s.log("Retargeting Endpoint not reachable:",e)}))}},triggerPixels:function(e){c(e,!1)}});function d(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=s.pixels.filter((function(n){if(("vote"===e||"vote_click"===e)&&n.answer_id&&(!t.length||!t.includes(n.answer_id)))return!1;if("all"!==n.device_type){if(a&&n.device_type!==a)return!1;if(s.isApp&&"app"!==n.device_type)return!1;if(s.isMobileDevice&&"desktop"===n.device_type)return!1;if(!s.isMobileDevice&&"mobile"===n.device_type)return!1}return n.event===e}));(n=n.filter((function(e,t,n){return t===n.findIndex((function(t){return t.id===e.id}))}))).length&&c(n,!0)}function c(e,n){var a;e&&e.length>0&&(e.forEach((function(e){!function(e){switch(e.type){case"javascript":!function(e,t){e.externalcode?u({src:e.externalcode,async:!0},(function(){e.staticcode&&u({text:e.staticcode}),e.loaded=!0,t()})):e.staticcode?(u({text:e.staticcode}),e.loaded=!0,t()):t()}(e,(function(){e.trigger_code&&i(e.trigger_code)}));break;case"google":!function(e,t,n){if(window.google_trackConversion)window.google_trackConversion&&window.google_trackConversion({google_conversion_id:e,google_conversion_label:t,google_custom_value:n,google_custom_params:window.google_tag_params,google_remarketing_only:!0});else{var i=document.createElement("script");i.src="https://www.googleadservices.com/pagead/conversion_async.js",i.async=!0,i.addEventListener("load",(function(){s.googleLoaded=!0,window.google_trackConversion&&window.google_trackConversion({google_conversion_id:e,google_conversion_label:t,google_custom_value:n,google_custom_params:window.google_tag_params,google_remarketing_only:!0})}),!1),document.body.appendChild(i)}}(e.conversion_id,e.conversion_label,e.custom_value);break;case"facebook":e.event&&(e.group_title=e.event),function(e,t,n){if(function(e,t,n,i,o,a,r){e.fbq||(o=e.fbq=function(){o.callMethod?o.callMethod.apply(o,arguments):o.queue.push(arguments)},e._fbq||(e._fbq=o),o.push=o,o.loaded=!0,o.version="2.0",o.queue=[],(a=t.createElement(n)).async=!0,a.src="https://connect.facebook.net/en_US/fbevents.js",(r=t.getElementsByTagName(n)[0]).parentNode.insertBefore(a,r))}(window,document,"script"),window.fbq){window.fbq("init",e),window.fbq("track","PageView");var i="string"==typeof n&&n.length>0?{customValue:n}:{};window.fbq("trackCustom",t,i)}}(e.facebook_id,e.group_title,e.custom_value);break;case"image":t=e.source,(n=new Image).onload=function(){n.naturalHeight+n.naturalWidth!==0?document.body.appendChild(n):s.log("Error on loadImage: natural height and width === 0")},n.onerror=function(e){s.log(e)},t&&(n.src=t);break;default:s.log("Pixel execution error: no type specified!")}var t,n}(e)})),n&&(a={triggeredPixels:e.map((function(e){return{pixel_id:e.id,campaign_id:e.campaign_id}}))},(0,t.w)(s.RETARGETING_ENDPOINT+"/public/triggered",a,o).then((function(e){return e.json()})).then((function(e){"success"!==e.status&&s.log("Return type of triggered data did not success!",e.data)})).catch((function(e){s.log("Failed to send triggered data!",e)}))))}function u(e,t){var n=document.createElement("script");Object.keys(e).forEach((function(t){n[t]=e[t]})),t&&"function"==typeof t&&n.addEventListener("load",(function(e){t(null,e)}),!1),document.body.appendChild(n)}function p(e){return(0,t.w)(s.RETARGETING_ENDPOINT+"/public/tr",e,o).then((function(e){return e.json()}))}return s}(window.Pinpoll.storage),window.Pinpoll.remarketing=function(n,i){var o=(0,e.G)({RETARGETING_ENDPOINT:"https://api2.dmp.pinpoll.com",REMARKETING_MAX_TRIGGER_TIME:parseInt("MISSING_ENV_VAR".MIX_REMARKETING_MAX_TRIGGER_TIME||"",10)||36e5,start:function(){window.requestIdleCallback?window.requestIdleCallback((function(){a()}),{timeout:3e3}):window.setTimeout((function(){a()}),3e3)}});function a(){var e,a;!(a=i.lastTriggered)||Date.now()-a>o.REMARKETING_MAX_TRIGGER_TIME?(e={referrer:window.location.origin||window.location.hostname},(0,t.w)(o.RETARGETING_ENDPOINT+"/public/remarketing",e,i).then((function(e){return e.json()}))).then((function(e){i.lastTriggered=Date.now(),e.data.length&&n.triggerPixels(e.data)})).catch((function(e){o.log("Failed to send getRemarketingPixels",e)})):o.log("Checked Remarketing; last triggered happened within max trigger time, last triggered at:",i.lastTriggered)}return o.start(),o}(window.Pinpoll.retargeting,window.Pinpoll.storage))})(),(()=>{"use strict";var e=__webpack_require__(631);__webpack_require__(90),__webpack_require__(726),window.Pinpoll.embed||(window.Pinpoll.embed=(0,e.ZP)(),window.Pinpoll.embed.start())})()})();
659/*!
660	Colorbox 1.6.3
661	license: MIT
662	http://www.jacklmoore.com/colorbox
663*/
vendor: 4,671 bytes, line 664
664(function(t,e,i){function n(i,n,o){var r=e.createElement(i);return n&&(r.id=Z+n),o&&(r.style.cssText=o),t(r)}function o(){return i.innerHeight?i.innerHeight:t(i).height()}function r(e,i){i!==Object(i)&&(i={}),this.cache={},this.el=e,this.value=function(e){var n;return void 0===this.cache[e]&&(n=t(this.el).attr("data-cbox-"+e),void 0!==n?this.cache[e]=n:void 0!==i[e]?this.cache[e]=i[e]:void 0!==X[e]&&(this.cache[e]=X[e])),this.cache[e]},this.get=function(e){var i=this.value(e);return t.isFunction(i)?i.call(this.el,this):i}}function h(t){var e=W.length,i=(A+t)%e;return 0>i?e+i:i}function a(t,e){return Math.round((/%/.test(t)?("x"===e?E.width():o())/100:1)*parseInt(t,10))}function s(t,e){return t.get("photo")||t.get("photoRegex").test(e)}function l(t,e){return t.get("retinaUrl")&&i.devicePixelRatio>1?e.replace(t.get("photoRegex"),t.get("retinaSuffix")):e}function d(t){"contains"in x[0]&&!x[0].contains(t.target)&&t.target!==v[0]&&(t.stopPropagation(),x.focus())}function c(t){c.str!==t&&(x.add(v).removeClass(c.str).addClass(t),c.str=t)}function g(e){A=0,e&&e!==!1&&"nofollow"!==e?(W=t("."+te).filter(function(){var i=t.data(this,Y),n=new r(this,i);return n.get("rel")===e}),A=W.index(_.el),-1===A&&(W=W.add(_.el),A=W.length-1)):W=t(_.el)}function u(i){t(e).trigger(i),ae.triggerHandler(i)}function f(i){var o;if(!G){if(o=t(i).data(Y),_=new r(i,o),g(_.get("rel")),!$){$=q=!0,c(_.get("className")),x.css({visibility:"hidden",display:"block",opacity:""}),I=n(se,"LoadedContent","width:0; height:0; overflow:hidden; visibility:hidden"),b.css({width:"",height:""}).append(I),j=T.height()+k.height()+b.outerHeight(!0)-b.height(),D=C.width()+H.width()+b.outerWidth(!0)-b.width(),N=I.outerHeight(!0),z=I.outerWidth(!0);var h=a(_.get("initialWidth"),"x"),s=a(_.get("initialHeight"),"y"),l=_.get("maxWidth"),f=_.get("maxHeight");_.w=Math.max((l!==!1?Math.min(h,a(l,"x")):h)-z-D,0),_.h=Math.max((f!==!1?Math.min(s,a(f,"y")):s)-N-j,0),I.css({width:"",height:_.h}),J.position(),u(ee),_.get("onOpen"),O.add(F).hide(),x.focus(),_.get("trapFocus")&&e.addEventListener&&(e.addEventListener("focus",d,!0),ae.one(re,function(){e.removeEventListener("focus",d,!0)})),_.get("returnFocus")&&ae.one(re,function(){t(_.el).focus()})}var p=parseFloat(_.get("opacity"));v.css({opacity:p===p?p:"",cursor:_.get("overlayClose")?"pointer":"",visibility:"visible"}).show(),_.get("closeButton")?B.html(_.get("close")).appendTo(b):B.appendTo("<div/>"),w()}}function p(){x||(V=!1,E=t(i),x=n(se).attr({id:Y,"class":t.support.opacity===!1?Z+"IE":"",role:"dialog",tabindex:"-1"}).hide(),v=n(se,"Overlay").hide(),L=t([n(se,"LoadingOverlay")[0],n(se,"LoadingGraphic")[0]]),y=n(se,"Wrapper"),b=n(se,"Content").append(F=n(se,"Title"),R=n(se,"Current"),P=t('<button type="button"/>').attr({id:Z+"Previous"}),K=t('<button type="button"/>').attr({id:Z+"Next"}),S=n("button","Slideshow"),L),B=t('<button type="button"/>').attr({id:Z+"Close"}),y.append(n(se).append(n(se,"TopLeft"),T=n(se,"TopCenter"),n(se,"TopRight")),n(se,!1,"clear:left").append(C=n(se,"MiddleLeft"),b,H=n(se,"MiddleRight")),n(se,!1,"clear:left").append(n(se,"BottomLeft"),k=n(se,"BottomCenter"),n(se,"BottomRight"))).find("div div").css({"float":"left"}),M=n(se,!1,"position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;"),O=K.add(P).add(R).add(S)),e.body&&!x.parent().length&&t(e.body).append(v,x.append(y,M))}function m(){function i(t){t.which>1||t.shiftKey||t.altKey||t.metaKey||t.ctrlKey||(t.preventDefault(),f(this))}return x?(V||(V=!0,K.click(function(){J.next()}),P.click(function(){J.prev()}),B.click(function(){J.close()}),v.click(function(){_.get("overlayClose")&&J.close()}),t(e).bind("keydown."+Z,function(t){var e=t.keyCode;$&&_.get("escKey")&&27===e&&(t.preventDefault(),J.close()),$&&_.get("arrowKey")&&W[1]&&!t.altKey&&(37===e?(t.preventDefault(),P.click()):39===e&&(t.preventDefault(),K.click()))}),t.isFunction(t.fn.on)?t(e).on("click."+Z,"."+te,i):t("."+te).live("click."+Z,i)),!0):!1}function w(){var e,o,r,h=J.prep,d=++le;if(q=!0,U=!1,u(he),u(ie),_.get("onLoad"),_.h=_.get("height")?a(_.get("height"),"y")-N-j:_.get("innerHeight")&&a(_.get("innerHeight"),"y"),_.w=_.get("width")?a(_.get("width"),"x")-z-D:_.get("innerWidth")&&a(_.get("innerWidth"),"x"),_.mw=_.w,_.mh=_.h,_.get("maxWidth")&&(_.mw=a(_.get("maxWidth"),"x")-z-D,_.mw=_.w&&_.w<_.mw?_.w:_.mw),_.get("maxHeight")&&(_.mh=a(_.get("maxHeight"),"y")-N-j,_.mh=_.h&&_.h<_.mh?_.h:_.mh),e=_.get("href"),Q=setTimeout(function(){L.show()},100),_.get("inline")){var c=t(e);r=t("<div>").hide().insertBefore(c),ae.one(he,function(){r.replaceWith(c)}),h(c)}else _.get("iframe")?h(" "):_.get("html")?h(_.get("html")):s(_,e)?(e=l(_,e),U=_.get("
664createImg"),t(U).addClass(Z+"Photo").bind("error."+Z,function(){h(n(se,"Error").html(_.get("imgError")))}).one("load",function(){d===le&&setTimeout(function(){var e;_.get("retinaImage")&&i.devicePixelRatio>1&&(U.height=U.height/i.devicePixelRatio,U.width=U.width/i.devicePixelRatio),_.get("scalePhotos")&&(o=function(){U.height-=U.height*e,U.width-=U.width*e},_.mw&&U.width>_.mw&&(e=(U.width-_.mw)/U.width,o()),_.mh&&U.height>_.mh&&(e=(U.height-_.mh)/U.height,o())),_.h&&(U.style.marginTop=Math.max(_.mh-U.height,0)/2+"px"),W[1]&&(_.get("loop")||W[A+1])&&(U.style.cursor="pointer",t(U).bind("click."+Z,function(){J.next()})),U.style.width=U.width+"px",U.style.height=U.height+"px",h(U)},1)}),U.src=e):e&&M.load(e,_.get("data"),function(e,i){d===le&&h("error"===i?n(se,"Error").html(_.get("xhrError")):t(this).contents())})}var v,x,y,b,T,C,H,k,W,E,I,M,L,F,R,S,K,P,B,O,_,j,D,N,z,A,U,$,q,G,Q,J,V,X={html:!1,photo:!1,iframe:!1,inline:!1,transition:"elastic",speed:300,fadeOut:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,opacity:.9,preloading:!0,className:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:void 0,closeButton:!0,fastIframe:!0,open:!1,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",returnFocus:!0,trapFocus:!0,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1,rel:function(){return this.rel},href:function(){return t(this).attr("href")},title:function(){return this.title},createImg:function(){var e=new Image,i=t(this).data("cbox-img-attrs");return"object"==typeof i&&t.each(i,function(t,i){e[t]=i}),e},createIframe:function(){var i=e.createElement("iframe"),n=t(this).data("cbox-iframe-attrs");return"object"==typeof n&&t.each(n,function(t,e){i[t]=e}),"frameBorder"in i&&(i.frameBorder=0),"allowTransparency"in i&&(i.allowTransparency="true"),i.name=(new Date).getTime(),i.allowFullscreen=!0,i}},Y="colorbox",Z="cbox",te=Z+"Element",ee=Z+"_open",ie=Z+"_load",ne=Z+"_complete",oe=Z+"_cleanup",re=Z+"_closed",he=Z+"_purge",ae=t("<a/>"),se="div",le=0,de={},ce=function(){function t(){clearTimeout(h)}function e(){(_.get("loop")||W[A+1])&&(t(),h=setTimeout(J.next,_.get("slideshowSpeed")))}function i(){S.html(_.get("slideshowStop")).unbind(s).one(s,n),ae.bind(ne,e).bind(ie,t),x.removeClass(a+"off").addClass(a+"on")}function n(){t(),ae.unbind(ne,e).unbind(ie,t),S.html(_.get("slideshowStart")).unbind(s).one(s,function(){J.next(),i()}),x.removeClass(a+"on").addClass(a+"off")}function o(){r=!1,S.hide(),t(),ae.unbind(ne,e).unbind(ie,t),x.removeClass(a+"off "+a+"on")}var r,h,a=Z+"Slideshow_",s="click."+Z;return function(){r?_.get("slideshow")||(ae.unbind(oe,o),o()):_.get("slideshow")&&W[1]&&(r=!0,ae.one(oe,o),_.get("slideshowAuto")?i():n(),S.show())}}();t[Y]||(t(p),J=t.fn[Y]=t[Y]=function(e,i){var n,o=this;return e=e||{},t.isFunction(o)&&(o=t("<a/>"),e.open=!0),o[0]?(p(),m()&&(i&&(e.onComplete=i),o.each(function(){var i=t.data(this,Y)||{};t.data(this,Y,t.extend(i,e))}).addClass(te),n=new r(o[0],e),n.get("open")&&f(o[0])),o):o},J.position=function(e,i){function n(){T[0].style.width=k[0].style.width=b[0].style.width=parseInt(x[0].style.width,10)-D+"px",b[0].style.height=C[0].style.height=H[0].style.height=parseInt(x[0].style.height,10)-j+"px"}var r,h,s,l=0,d=0,c=x.offset();if(E.unbind("resize."+Z),x.css({top:-9e4,left:-9e4}),h=E.scrollTop(),s=E.scrollLeft(),_.get("fixed")?(c.top-=h,c.left-=s,x.css({position:"fixed"})):(l=h,d=s,x.css({position:"absolute"})),d+=_.get("right")!==!1?Math.max(E.width()-_.w-z-D-a(_.get("right"),"x"),0):_.get("left")!==!1?a(_.get("left"),"x"):Math.round(Math.max(E.width()-_.w-z-D,0)/2),l+=_.get("bottom")!==!1?Math.max(o()-_.h-N-j-a(_.get("bottom"),"y"),0):_.get("top")!==!1?a(_.get("top"),"y"):Math.round(Math.max(o()-_.h-N-j,0)/2),x.css({top:c.top,left
664:c.left,visibility:"visible"}),y[0].style.width=y[0].style.height="9999px",r={width:_.w+z+D,height:_.h+N+j,top:l,left:d},e){var g=0;t.each(r,function(t){return r[t]!==de[t]?(g=e,void 0):void 0}),e=g}de=r,e||x.css(r),x.dequeue().animate(r,{duration:e||0,complete:function(){n(),q=!1,y[0].style.width=_.w+z+D+"px",y[0].style.height=_.h+N+j+"px",_.get("reposition")&&setTimeout(function(){E.bind("resize."+Z,J.position)},1),t.isFunction(i)&&i()},step:n})},J.resize=function(t){var e;$&&(t=t||{},t.width&&(_.w=a(t.width,"x")-z-D),t.innerWidth&&(_.w=a(t.innerWidth,"x")),I.css({width:_.w}),t.height&&(_.h=a(t.height,"y")-N-j),t.innerHeight&&(_.h=a(t.innerHeight,"y")),t.innerHeight||t.height||(e=I.scrollTop(),I.css({height:"auto"}),_.h=I.height()),I.css({height:_.h}),e&&I.scrollTop(e),J.position("none"===_.get("transition")?0:_.get("speed")))},J.prep=function(i){function o(){return _.w=_.w||I.width(),_.w=_.mw&&_.mw<_.w?_.mw:_.w,_.w}function a(){return _.h=_.h||I.height(),_.h=_.mh&&_.mh<_.h?_.mh:_.h,_.h}if($){var d,g="none"===_.get("transition")?0:_.get("speed");I.remove(),I=n(se,"LoadedContent").append(i),I.hide().appendTo(M.show()).css({width:o(),overflow:_.get("scrolling")?"auto":"hidden"}).css({height:a()}).prependTo(b),M.hide(),t(U).css({"float":"none"}),c(_.get("className")),d=function(){function i(){t.support.opacity===!1&&x[0].style.removeAttribute("filter")}var n,o,a=W.length;$&&(o=function(){clearTimeout(Q),L.hide(),u(ne),_.get("onComplete")},F.html(_.get("title")).show(),I.show(),a>1?("string"==typeof _.get("current")&&R.html(_.get("current").replace("{current}",A+1).replace("{total}",a)).show(),K[_.get("loop")||a-1>A?"show":"hide"]().html(_.get("next")),P[_.get("loop")||A?"show":"hide"]().html(_.get("previous")),ce(),_.get("preloading")&&t.each([h(-1),h(1)],function(){var i,n=W[this],o=new r(n,t.data(n,Y)),h=o.get("href");h&&s(o,h)&&(h=l(o,h),i=e.createElement("img"),i.src=h)})):O.hide(),_.get("iframe")?(n=_.get("createIframe"),_.get("scrolling")||(n.scrolling="no"),t(n).attr({src:_.get("href"),"class":Z+"Iframe"}).one("load",o).appendTo(I),ae.one(he,function(){n.src="//about:blank"}),_.get("fastIframe")&&t(n).trigger("load")):o(),"fade"===_.get("transition")?x.fadeTo(g,1,i):i())},"fade"===_.get("transition")?x.fadeTo(g,0,function(){J.position(0,d)}):J.position(g,d)}},J.next=function(){!q&&W[1]&&(_.get("loop")||W[A+1])&&(A=h(1),f(W[A]))},J.prev=function(){!q&&W[1]&&(_.get("loop")||A)&&(A=h(-1),f(W[A]))},J.close=function(){$&&!G&&(G=!0,$=!1,u(oe),_.get("onCleanup"),E.unbind("."+Z),v.fadeTo(_.get("fadeOut")||0,0),x.stop().fadeTo(_.get("fadeOut")||0,0,function(){x.hide(),v.hide(),u(he),I.remove(),setTimeout(function(){G=!1,u(re),_.get("onClosed")},1)}))},J.remove=function(){x&&(x.stop(),t[Y].close(),x.stop(!1,!0).remove(),v.remove(),G=!1,x=null,t("."+te).removeData(Y).removeClass(te),t(e).unbind("click."+Z).unbind("keydown."+Z))},J.element=function(){return t(_.el)},J.settings=X)})(jQuery,document,window);
665/* Javascript plotting library for jQuery, version 0.8.3.
666
667Copyright (c) 2007-2014 IOLA and Ole Laursen.
668Licensed under the MIT license.
669
670*/
671
672// first an inline dependency, jquery.colorhelpers.js, we inline it here
673// for convenience
674
675/* Plugin for jQuery for working with colors.
676 *
677 * Version 1.1.
678 *
679 * Inspiration from jQuery color animation plugin by John Resig.
680 *
681 * Released under the MIT license by Ole Laursen, October 2009.
682 *
683 * Examples:
684 *
685 *   $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
686 *   var c = $.color.extract($("#mydiv"), 'background-color');
687 *   console.log(c.r, c.g, c.b, c.a);
688 *   $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
689 *
690 * Note that .scale() and .add() return the same modified object
691 * instead of making a new one.
692 *
693 * V. 1.1: Fix error handling so e.g. parsing an empty string does
694 * produce a color rather than just crashing.
695 */
696(function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3}
vendor: 124,626 bytes, lines 696-3847
696)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);
697
698// the actual Flot code
699(function($) {
700
701	// Cache the prototype hasOwnProperty for faster access
702
703	var hasOwnProperty = Object.prototype.hasOwnProperty;
704
705    // A shim to provide 'detach' to jQuery versions prior to 1.4.  Using a DOM
706    // operation produces the same effect as detach, i.e. removing the element
707    // without touching its jQuery data.
708
709    // Do not merge this into Flot 0.9, since it requires jQuery 1.4.4+.
710
711    if (!$.fn.detach) {
712        $.fn.detach = function() {
713            return this.each(function() {
714                if (this.parentNode) {
715                    this.parentNode.removeChild( this );
716                }
717            });
718        };
719    }
720
721	///////////////////////////////////////////////////////////////////////////
722	// The Canvas object is a wrapper around an HTML5 <canvas> tag.
723	//
724	// @constructor
725	// @param {string} cls List of classes to apply to the canvas.
726	// @param {element} container Element onto which to append the canvas.
727	//
728	// Requiring a container is a little iffy, but unfortunately canvas
729	// operations don't work unless the canvas is attached to the DOM.
730
731	function Canvas(cls, container) {
732
733		var element = container.children("." + cls)[0];
734
735		if (element == null) {
736
737			element = document.createElement("canvas");
738			element.className = cls;
739
740			$(element).css({ direction: "ltr", position: "absolute", left: 0, top: 0 })
741				.appendTo(container);
742
743			// If HTML5 Canvas isn't available, fall back to [Ex|Flash]canvas
744
745			if (!element.getContext) {
746				if (window.G_vmlCanvasManager) {
747					element = window.G_vmlCanvasManager.initElement(element);
748				} else {
749					throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.");
750				}
751			}
752		}
753
754		this.element = element;
755
756		var context = this.context = element.getContext("2d");
757
758		// Determine the screen's ratio of physical to device-independent
759		// pixels.  This is the ratio between the canvas width that the browser
760		// advertises and the number of pixels actually present in that space.
761
762		// The iPhone 4, for example, has a device-independent width of 320px,
763		// but its screen is actually 640px wide.  It therefore has a pixel
764		// ratio of 2, while most normal devices have a ratio of 1.
765
766		var devicePixelRatio = window.devicePixelRatio || 1,
767			backingStoreRatio =
768				context.webkitBackingStorePixelRatio ||
769				context.mozBackingStorePixelRatio ||
770				context.msBackingStorePixelRatio ||
771				context.oBackingStorePixelRatio ||
772				context.backingStorePixelRatio || 1;
773
774		this.pixelRatio = devicePixelRatio / backingStoreRatio;
775
776		// Size the canvas to match the internal dimensions of its container
777
778		this.resize(container.width(), container.height());
779
780		// Collection of HTML div layers for text overlaid onto the canvas
781
782		this.textContainer = null;
783		this.text = {};
784
785		// Cache of text fragments and metrics, so we can avoid expensively
786		// re-calculating them when the plot is re-rendered in a loop.
787
788		this._textCache = {};
789	}
790
791	// Resizes the canvas to the given dimensions.
792	//
793	// @param {number} width New width of the canvas, in pixels.
794	// @param {number} width New height of the canvas, in pixels.
795
796	Canvas.prototype.resize = function(width, height) {
797
798		if (width <= 0 || height <= 0) {
799			throw new Error("Invalid dimensions for plot, width = " + width + ", height = " + height);
800		}
801
802		var element = this.element,
803			context = this.context,
804			pixelRatio = this.pixelRatio;
805
806		// Resize the canvas, increasing its density based on the display's
807		// pixel ratio; basically giving it more pixels without increasing the
808		// size of its element, to take advantage of the fact that retina
809		// displays have that many more pixels in the same advertised space.
810
811		// Resizing should reset the state (excanvas seems to be buggy though)
812
813		if (this.width != width) {
814			element.width = width * pixelRatio;
815			element.style.width = width + "px";
816			this.width = width;
817		}
818
819		if (this.height != height) {
820			element.height = height * pixelRatio;
821			element.style.height = height + "px";
822			this.height = height;
823		}
824
825		// Save the context, so we can reset in case we get replotted.  The
826		// restore ensure that we're really back at the initial state, and
827		// should be safe even if we haven't saved the initial state yet.
828
829		context.restore();
830		context.save();
831
832		// Scale the coordinate space to match the display density; so even though we
833		// may have twice as many pixels, we still want lines and other drawing to
834		// appear at the same size; the extra pixels will just make them crisper.
835
836		context.scale(pixelRatio, pixelRatio);
837	};
838
839	// Clears the entire canvas area, not including any overlaid HTML text
840
841	Canvas.prototype.clear = function() {
842		this.context.clearRect(0, 0, this.width, this.height);
843	};
844
845	// Finishes rendering the canvas, including managing the text overlay.
846
847	Canvas.prototype.render = function() {
848
849		var cache = this._textCache;
850
851		// For each text layer, add elements marked as active that haven't
852		// already been rendered, and remove those that are no longer active.
853
854		for (var layerKey in cache) {
855			if (hasOwnProperty.call(cache, layerKey)) {
856
857				var layer = this.getTextLayer(layerKey),
858					layerCache = cache[layerKey];
859
860				layer.hide();
861
862				for (var styleKey in layerCache) {
863					if (hasOwnProperty.call(layerCache, styleKey)) {
864						var styleCache = layerCache[styleKey];
865						for (var key in styleCache) {
866							if (hasOwnProperty.call(styleCache, key)) {
867
868								var positions = styleCache[key].positions;
869
870								for (var i = 0, position; position = positions[i]; i++) {
871									if (position.active) {
872										if (!position.rendered) {
873											layer.append(position.element);
874											position.rendered = true;
875										}
876									} else {
877										positions.splice(i--, 1);
878										if (position.rendered) {
879											position.element.detach();
880										}
881									}
882								}
883
884								if (positions.length == 0) {
885									delete styleCache[key];
886								}
887							}
888						}
889					}
890				}
891
892				layer.show();
893			}
894		}
895	};
896
897	// Creates (if necessary) and returns the text overlay container.
898	//
899	// @param {string} classes String of space-separated CSS classes used to
900	//     uniquely identify the text layer.
901	// @return {object} The jQuery-wrapped text-layer div.
902
903	Canvas.prototype.getTextLayer = function(classes) {
904
905		var layer = this.text[classes];
906
907		// Create the text layer if it doesn't exist
908
909		if (layer == null) {
910
911			// Create the text layer container, if it doesn't exist
912
913			if (this.textContainer == null) {
914				this.textContainer = $("<div class='flot-text'></div>")
915					.css({
916						position: "absolute",
917						top: 0,
918						left: 0,
919						bottom: 0,
920						right: 0,
921						'font-size': "smaller",
922						color: "#545454"
923					})
924					.insertAfter(this.element);
925			}
926
927			layer = this.text[classes] = $("<div></div>")
928				.addClass(classes)
929				.css({
930					position: "absolute",
931					top: 0,
932					left: 0,
933					bottom: 0,
934					right: 0
935				})
936				.appendTo(this.textContainer);
937		}
938
939		return layer;
940	};
941
942	// Creates (if necessary) and returns a text info object.
943	//
944	// The object looks like this:
945	//
946	// {
947	//     width: Width of the text's wrapper div.
948	//     height: Height of the text's wrapper div.
949	//     element: The jQuery-wrapped HTML div containing the text.
950	//     positions: Array of positions at which this text is drawn.
951	// }
952	//
953	// The positions array contains objects that look like this:
954	//
955	// {
956	//     active: Flag indicating whether the text should be visible.
957	//     rendered: Flag indicating whether the text is currently visible.
958	//     element: The jQuery-wrapped HTML div containing the text.
959	//     x: X coordinate at which to draw the text.
960	//     y: Y coordinate at which to draw the text.
961	// }
962	//
963	// Each position after the first receives a clone of the original element.
964	//
965	// The idea is that that the width, height, and general 'identity' of the
966	// text is constant no matter where it is placed; the placements are a
967	// secondary property.
968	//
969	// Canvas maintains a cache of recently-used text info objects; getTextInfo
970	// either returns the cached element or creates a new entry.
971	//
972	// @param {string} layer A string of space-separated CSS classes uniquely
973	//     identifying the layer containing this text.
974	// @param {string} text Text string to retrieve info for.
975	// @param {(string|object)=} font Either a string of space-separated CSS
976	//     classes or a font-spec object, defining the text's font and style.
977	// @param {number=} angle Angle at which to rotate the text, in degrees.
978	//     Angle is currently unused, it will be implemented in the future.
979	// @param {number=} width Maximum width of the text before it wraps.
980	// @return {object} a text info object.
981
982	Canvas.prototype.getTextInfo = function(layer, text, font, angle, width) {
983
984		var textStyle, layerCache, styleCache, info;
985
986		// Cast the value to a string, in case we were given a number or such
987
988		text = "" + text;
989
990		// If the font is a font-spec object, generate a CSS font definition
991
992		if (typeof font === "object") {
993			textStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px/" + font.lineHeight + "px " + font.family;
994		} else {
995			textStyle = font;
996		}
997
998		// Retrieve (or create) the cache for the text's layer and styles
999
1000		layerCache = this._textCache[layer];
1001
1002		if (layerCache == null) {
1003			layerCache = this._textCache[layer] = {};
1004		}
1005
1006		styleCache = layerCache[textStyle];
1007
1008		if (styleCache == null) {
1009			styleCache = layerCache[textStyle] = {};
1010		}
1011
1012		info = styleCache[text];
1013
1014		// If we can't find a matching element in our cache, create a new one
1015
1016		if (info == null) {
1017
1018			var element = $("<div></div>").html(text)
1019				.css({
1020					position: "absolute",
1021					'max-width': width,
1022					top: -9999
1023				})
1024				.appendTo(this.getTextLayer(layer));
1025
1026			if (typeof font === "object") {
1027				element.css({
1028					font: textStyle,
1029					color: font.color
1030				});
1031			} else if (typeof font === "string") {
1032				element.addClass(font);
1033			}
1034
1035			info = styleCache[text] = {
1036				width: element.outerWidth(true),
1037				height: element.outerHeight(true),
1038				element: element,
1039				positions: []
1040			};
1041
1042			element.detach();
1043		}
1044
1045		return info;
1046	};
1047
1048	// Adds a text string to the canvas text overlay.
1049	//
1050	// The text isn't drawn immediately; it is marked as rendering, which will
1051	// result in its addition to the canvas on the next render pass.
1052	//
1053	// @param {string} layer A string of space-separated CSS classes uniquely
1054	//     identifying the layer containing this text.
1055	// @param {number} x X coordinate at which to draw the text.
1056	// @param {number} y Y coordinate at which to draw the text.
1057	// @param {string} text Text string to draw.
1058	// @param {(string|object)=} font Either a string of space-separated CSS
1059	//     classes or a font-spec object, defining the text's font and style.
1060	// @param {number=} angle Angle at which to rotate the text, in degrees.
1061	//     Angle is currently unused, it will be implemented in the future.
1062	// @param {number=} width Maximum width of the text before it wraps.
1063	// @param {string=} halign Horizontal alignment of the text; either "left",
1064	//     "center" or "right".
1065	// @param {string=} valign Vertical alignment of the text; either "top",
1066	//     "middle" or "bottom".
1067
1068	Canvas.prototype.addText = function(layer, x, y, text, font, angle, width, halign, valign) {
1069
1070		var info = this.getTextInfo(layer, text, font, angle, width),
1071			positions = info.positions;
1072
1073		// Tweak the div's position to match the text's alignment
1074
1075		if (halign == "center") {
1076			x -= info.width / 2;
1077		} else if (halign == "right") {
1078			x -= info.width;
1079		}
1080
1081		if (valign == "middle") {
1082			y -= info.height / 2;
1083		} else if (valign == "bottom") {
1084			y -= info.height;
1085		}
1086
1087		// Determine whether this text already exists at this position.
1088		// If so, mark it for inclusion in the next render pass.
1089
1090		for (var i = 0, position; position = positions[i]; i++) {
1091			if (position.x == x && position.y == y) {
1092				position.active = true;
1093				return;
1094			}
1095		}
1096
1097		// If the text doesn't exist at this position, create a new entry
1098
1099		// For the very first position we'll re-use the original element,
1100		// while for subsequent ones we'll clone it.
1101
1102		position = {
1103			active: true,
1104			rendered: false,
1105			element: positions.length ? info.element.clone() : info.element,
1106			x: x,
1107			y: y
1108		};
1109
1110		positions.push(position);
1111
1112		// Move the element to its final position within the container
1113
1114		position.element.css({
1115			top: Math.round(y),
1116			left: Math.round(x),
1117			'text-align': halign	// In case the text wraps
1118		});
1119	};
1120
1121	// Removes one or more text strings from the canvas text overlay.
1122	//
1123	// If no parameters are given, all text within the layer is removed.
1124	//
1125	// Note that the text is not immediately removed; it is simply marked as
1126	// inactive, which will result in its removal on the next render pass.
1127	// This avoids the performance penalty for 'clear and redraw' behavior,
1128	// where we potentially get rid of all text on a layer, but will likely
1129	// add back most or all of it later, as when redrawing axes, for example.
1130	//
1131	// @param {string} layer A string of space-separated CSS classes uniquely
1132	//     identifying the layer containing this text.
1133	// @param {number=} x X coordinate of the text.
1134	// @param {number=} y Y coordinate of the text.
1135	// @param {string=} text Text string to remove.
1136	// @param {(string|object)=} font Either a string of space-separated CSS
1137	//     classes or a font-spec object, defining the text's font and style.
1138	// @param {number=} angle Angle at which the text is rotated, in degrees.
1139	//     Angle is currently unused, it will be implemented in the future.
1140
1141	Canvas.prototype.removeText = function(layer, x, y, text, font, angle) {
1142		if (text == null) {
1143			var layerCache = this._textCache[layer];
1144			if (layerCache != null) {
1145				for (var styleKey in layerCache) {
1146					if (hasOwnProperty.call(layerCache, styleKey)) {
1147						var styleCache = layerCache[styleKey];
1148						for (var key in styleCache) {
1149							if (hasOwnProperty.call(styleCache, key)) {
1150								var positions = styleCache[key].positions;
1151								for (var i = 0, position; position = positions[i]; i++) {
1152									position.active = false;
1153								}
1154							}
1155						}
1156					}
1157				}
1158			}
1159		} else {
1160			var positions = this.getTextInfo(layer, text, font, angle).positions;
1161			for (var i = 0, position; position = positions[i]; i++) {
1162				if (position.x == x && position.y == y) {
1163					position.active = false;
1164				}
1165			}
1166		}
1167	};
1168
1169	///////////////////////////////////////////////////////////////////////////
1170	// The top-level container for the entire plot.
1171
1172    function Plot(placeholder, data_, options_, plugins) {
1173        // data is on the form:
1174        //   [ series1, series2 ... ]
1175        // where series is either just the data as [ [x1, y1], [x2, y2], ... ]
1176        // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... }
1177
1178        var series = [],
1179            options = {
1180                // the color theme used for graphs
1181                colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"],
1182                legend: {
1183                    show: true,
1184                    noColumns: 1, // number of colums in legend table
1185                    labelFormatter: null, // fn: string -> string
1186                    labelBoxBorderColor: "#ccc", // border color for the little label boxes
1187                    container: null, // container (as jQuery object) to put legend in, null means default on top of graph
1188                    position: "ne", // position of default legend container within plot
1189                    margin: 5, // distance from grid edge to default legend container within plot
1190                    backgroundColor: null, // null means auto-detect
1191                    backgroundOpacity: 0.85, // set to 0 to avoid background
1192                    sorted: null    // default to no legend sorting
1193                },
1194                xaxis: {
1195                    show: null, // null = auto-detect, true = always, false = never
1196                    position: "bottom", // or "top"
1197                    mode: null, // null or "time"
1198                    font: null, // null (derived from CSS in placeholder) or object like { size: 11, lineHeight: 13, style: "italic", weight: "bold", family: "sans-serif", variant: "small-caps" }
1199                    color: null, // base color, labels, ticks
1200                    tickColor: null, // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)"
1201                    transform: null, // null or f: number -> number to transform axis
1202                    inverseTransform: null, // if transform is set, this should be the inverse function
1203                    min: null, // min. value to show, null means set automatically
1204                    max: null, // max. value to show, null means set automatically
1205                    autoscaleMargin: null, // margin in % to add if auto-setting min/max
1206                    ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
1207                    tickFormatter: null, // fn: number -> string
1208                    labelWidth: null, // size of tick labels in pixels
1209                    labelHeight: null,
1210                    reserveSpace: null, // whether to reserve space even if axis isn't shown
1211                    tickLength: null, // size in pixels of ticks, or "full" for whole line
1212                    alignTicksWithAxis: null, // axis number or null for no sync
1213                    tickDecimals: null, // no. of decimals, null means auto
1214                    tickSize: null, // number or [number, "unit"]
1215                    minTickSize: null // number or [number, "unit"]
1216                },
1217                yaxis: {
1218                    autoscaleMargin: 0.02,
1219                    position: "left" // or "right"
1220                },
1221                xaxes: [],
1222                yaxes: [],
1223                series: {
1224                    points: {
1225                        show: false,
1226                        radius: 3,
1227                        lineWidth: 2, // in pixels
1228                        fill: true,
1229                        fillColor: "#ffffff",
1230                        symbol: "circle" // or callback
1231                    },
1232                    lines: {
1233                        // we don't put in show: false so we can see
1234                        // whether lines were actively disabled
1235                        lineWidth: 2, // in pixels
1236                        fill: false,
1237                        fillColor: null,
1238                        steps: false
1239                        // Omit 'zero', so we can later default its value to
1240                        // match that of the 'fill' option.
1241                    },
1242                    bars: {
1243                        show: false,
1244                        lineWidth: 2, // in pixels
1245                        barWidth: 1, // in units of the x axis
1246                        fill: true,
1247                        fillColor: null,
1248                        align: "left", // "left", "right", or "center"
1249                        horizontal: false,
1250                        zero: true
1251                    },
1252                    shadowSize: 3,
1253                    highlightColor: null
1254                },
1255                grid: {
1256                    show: true,
1257                    aboveData: false,
1258                    color: "#545454", // primary color used for outline and labels
1259                    backgroundColor: null, // null for transparent, else color
1260                    borderColor: null, // set if different from the grid color
1261                    tickColor: null, // color for the ticks, e.g. "rgba(0,0,0,0.15)"
1262                    margin: 0, // distance from the canvas edge to the grid
1263                    labelMargin: 5, // in pixels
1264                    axisMargin: 8, // in pixels
1265                    borderWidth: 2, // in pixels
1266                    minBorderMargin: null, // in pixels, null means taken from points radius
1267                    markings: null, // array of ranges or fn: axes -> array of ranges
1268                    markingsColor: "#f4f4f4",
1269                    markingsLineWidth: 2,
1270                    // interactive stuff
1271                    clickable: false,
1272                    hoverable: false,
1273                    autoHighlight: true, // highlight in case mouse is near
1274                    mouseActiveRadius: 10 // how far the mouse can be away to activate an item
1275                },
1276                interaction: {
1277                    redrawOverlayInterval: 1000/60 // time between updates, -1 means in same flow
1278                },
1279                hooks: {}
1280            },
1281        surface = null,     // the canvas for the plot itself
1282        overlay = null,     // canvas for interactive stuff on top of plot
1283        eventHolder = null, // jQuery object that events should be bound to
1284        ctx = null, octx = null,
1285        xaxes = [], yaxes = [],
1286        plotOffset = { left: 0, right: 0, top: 0, bottom: 0},
1287        plotWidth = 0, plotHeight = 0,
1288        hooks = {
1289            processOptions: [],
1290            processRawData: [],
1291            processDatapoints: [],
1292            processOffset: [],
1293            drawBackground: [],
1294            drawSeries: [],
1295            draw: [],
1296            bindEvents: [],
1297            drawOverlay: [],
1298            shutdown: []
1299        },
1300        plot = this;
1301
1302        // public functions
1303        plot.setData = setData;
1304        plot.setupGrid = setupGrid;
1305        plot.draw = draw;
1306        plot.getPlaceholder = function() { return placeholder; };
1307        plot.getCanvas = function() { return surface.element; };
1308        plot.getPlotOffset = function() { return plotOffset; };
1309        plot.width = function () { return plotWidth; };
1310        plot.height = function () { return plotHeight; };
1311        plot.offset = function () {
1312            var o = eventHolder.offset();
1313            o.left += plotOffset.left;
1314            o.top += plotOffset.top;
1315            return o;
1316        };
1317        plot.getData = function () { return series; };
1318        plot.getAxes = function () {
1319            var res = {}, i;
1320            $.each(xaxes.concat(yaxes), function (_, axis) {
1321                if (axis)
1322                    res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis;
1323            });
1324            return res;
1325        };
1326        plot.getXAxes = function () { return xaxes; };
1327        plot.getYAxes = function () { return yaxes; };
1328        plot.c2p = canvasToAxisCoords;
1329        plot.p2c = axisToCanvasCoords;
1330        plot.getOptions = function () { return options; };
1331        plot.highlight = highlight;
1332        plot.unhighlight = unhighlight;
1333        plot.triggerRedrawOverlay = triggerRedrawOverlay;
1334        plot.pointOffset = function(point) {
1335            return {
1336                left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left, 10),
1337                top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top, 10)
1338            };
1339        };
1340        plot.shutdown = shutdown;
1341        plot.destroy = function () {
1342            shutdown();
1343            placeholder.removeData("plot").empty();
1344
1345            series = [];
1346            options = null;
1347            surface = null;
1348            overlay = null;
1349            eventHolder = null;
1350            ctx = null;
1351            octx = null;
1352            xaxes = [];
1353            yaxes = [];
1354            hooks = null;
1355            highlights = [];
1356            plot = null;
1357        };
1358        plot.resize = function () {
1359        	var width = placeholder.width(),
1360        		height = placeholder.height();
1361            surface.resize(width, height);
1362            overlay.resize(width, height);
1363        };
1364
1365        // public attributes
1366        plot.hooks = hooks;
1367
1368        // initialize
1369        initPlugins(plot);
1370        parseOptions(options_);
1371        setupCanvases();
1372        setData(data_);
1373        setupGrid();
1374        draw();
1375        bindEvents();
1376
1377
1378        function executeHooks(hook, args) {
1379            args = [plot].concat(args);
1380            for (var i = 0; i < hook.length; ++i)
1381                hook[i].apply(this, args);
1382        }
1383
1384        function initPlugins() {
1385
1386            // References to key classes, allowing plugins to modify them
1387
1388            var classes = {
1389                Canvas: Canvas
1390            };
1391
1392            for (var i = 0; i < plugins.length; ++i) {
1393                var p = plugins[i];
1394                p.init(plot, classes);
1395                if (p.options)
1396                    $.extend(true, options, p.options);
1397            }
1398        }
1399
1400        function parseOptions(opts) {
1401
1402            $.extend(true, options, opts);
1403
1404            // $.extend merges arrays, rather than replacing them.  When less
1405            // colors are provided than the size of the default palette, we
1406            // end up with those colors plus the remaining defaults, which is
1407            // not expected behavior; avoid it by replacing them here.
1408
1409            if (opts && opts.colors) {
1410            	options.colors = opts.colors;
1411            }
1412
1413            if (options.xaxis.color == null)
1414                options.xaxis.color = $.color.parse(options.grid.color).scale('a', 0.22).toString();
1415            if (options.yaxis.color == null)
1416                options.yaxis.color = $.color.parse(options.grid.color).scale('a', 0.22).toString();
1417
1418            if (options.xaxis.tickColor == null) // grid.tickColor for back-compatibility
1419                options.xaxis.tickColor = options.grid.tickColor || options.xaxis.color;
1420            if (options.yaxis.tickColor == null) // grid.tickColor for back-compatibility
1421                options.yaxis.tickColor = options.grid.tickColor || options.yaxis.color;
1422
1423            if (options.grid.borderColor == null)
1424                options.grid.borderColor = options.grid.color;
1425            if (options.grid.tickColor == null)
1426                options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString();
1427
1428            // Fill in defaults for axis options, including any unspecified
1429            // font-spec fields, if a font-spec was provided.
1430
1431            // If no x/y axis options were provided, create one of each anyway,
1432            // since the rest of the code assumes that they exist.
1433
1434            var i, axisOptions, axisCount,
1435                fontSize = placeholder.css("font-size"),
1436                fontSizeDefault = fontSize ? +fontSize.replace("px", "") : 13,
1437                fontDefaults = {
1438                    style: placeholder.css("font-style"),
1439                    size: Math.round(0.8 * fontSizeDefault),
1440                    variant: placeholder.css("font-variant"),
1441                    weight: placeholder.css("font-weight"),
1442                    family: placeholder.css("font-family")
1443                };
1444
1445            axisCount = options.xaxes.length || 1;
1446            for (i = 0; i < axisCount; ++i) {
1447
1448                axisOptions = options.xaxes[i];
1449                if (axisOptions && !axisOptions.tickColor) {
1450                    axisOptions.tickColor = axisOptions.color;
1451                }
1452
1453                axisOptions = $.extend(true, {}, options.xaxis, axisOptions);
1454                options.xaxes[i] = axisOptions;
1455
1456                if (axisOptions.font) {
1457                    axisOptions.font = $.extend({}, fontDefaults, axisOptions.font);
1458                    if (!axisOptions.font.color) {
1459                        axisOptions.font.color = axisOptions.color;
1460                    }
1461                    if (!axisOptions.font.lineHeight) {
1462                        axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15);
1463                    }
1464                }
1465            }
1466
1467            axisCount = options.yaxes.length || 1;
1468            for (i = 0; i < axisCount; ++i) {
1469
1470                axisOptions = options.yaxes[i];
1471                if (axisOptions && !axisOptions.tickColor) {
1472                    axisOptions.tickColor = axisOptions.color;
1473                }
1474
1475                axisOptions = $.extend(true, {}, options.yaxis, axisOptions);
1476                options.yaxes[i] = axisOptions;
1477
1478                if (axisOptions.font) {
1479                    axisOptions.font = $.extend({}, fontDefaults, axisOptions.font);
1480                    if (!axisOptions.font.color) {
1481                        axisOptions.font.color = axisOptions.color;
1482                    }
1483                    if (!axisOptions.font.lineHeight) {
1484                        axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15);
1485                    }
1486                }
1487            }
1488
1489            // backwards compatibility, to be removed in future
1490            if (options.xaxis.noTicks && options.xaxis.ticks == null)
1491                options.xaxis.ticks = options.xaxis.noTicks;
1492            if (options.yaxis.noTicks && options.yaxis.ticks == null)
1493                options.yaxis.ticks = options.yaxis.noTicks;
1494            if (options.x2axis) {
1495                options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis);
1496                options.xaxes[1].position = "top";
1497                // Override the inherit to allow the axis to auto-scale
1498                if (options.x2axis.min == null) {
1499                    options.xaxes[1].min = null;
1500                }
1501                if (options.x2axis.max == null) {
1502                    options.xaxes[1].max = null;
1503                }
1504            }
1505            if (options.y2axis) {
1506                options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis);
1507                options.yaxes[1].position = "right";
1508                // Override the inherit to allow the axis to auto-scale
1509                if (options.y2axis.min == null) {
1510                    options.yaxes[1].min = null;
1511                }
1512                if (options.y2axis.max == null) {
1513                    options.yaxes[1].max = null;
1514                }
1515            }
1516            if (options.grid.coloredAreas)
1517                options.grid.markings = options.grid.coloredAreas;
1518            if (options.grid.coloredAreasColor)
1519                options.grid.markingsColor = options.grid.coloredAreasColor;
1520            if (options.lines)
1521                $.extend(true, options.series.lines, options.lines);
1522            if (options.points)
1523                $.extend(true, options.series.points, options.points);
1524            if (options.bars)
1525                $.extend(true, options.series.bars, options.bars);
1526            if (options.shadowSize != null)
1527                options.series.shadowSize = options.shadowSize;
1528            if (options.highlightColor != null)
1529                options.series.highlightColor = options.highlightColor;
1530
1531            // save options on axes for future reference
1532            for (i = 0; i < options.xaxes.length; ++i)
1533                getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i];
1534            for (i = 0; i < options.yaxes.length; ++i)
1535                getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i];
1536
1537            // add hooks from options
1538            for (var n in hooks)
1539                if (options.hooks[n] && options.hooks[n].length)
1540                    hooks[n] = hooks[n].concat(options.hooks[n]);
1541
1542            executeHooks(hooks.processOptions, [options]);
1543        }
1544
1545        function setData(d) {
1546            series = parseData(d);
1547            fillInSeriesOptions();
1548            processData();
1549        }
1550
1551        function parseData(d) {
1552            var res = [];
1553            for (var i = 0; i < d.length; ++i) {
1554                var s = $.extend(true, {}, options.series);
1555
1556                if (d[i].data != null) {
1557                    s.data = d[i].data; // move the data instead of deep-copy
1558                    delete d[i].data;
1559
1560                    $.extend(true, s, d[i]);
1561
1562                    d[i].data = s.data;
1563                }
1564                else
1565                    s.data = d[i];
1566                res.push(s);
1567            }
1568
1569            return res;
1570        }
1571
1572        function axisNumber(obj, coord) {
1573            var a = obj[coord + "axis"];
1574            if (typeof a == "object") // if we got a real axis, extract number
1575                a = a.n;
1576            if (typeof a != "number")
1577                a = 1; // default to first axis
1578            return a;
1579        }
1580
1581        function allAxes() {
1582            // return flat array without annoying null entries
1583            return $.grep(xaxes.concat(yaxes), function (a) { return a; });
1584        }
1585
1586        function canvasToAxisCoords(pos) {
1587            // return an object with x/y corresponding to all used axes
1588            var res = {}, i, axis;
1589            for (i = 0; i < xaxes.length; ++i) {
1590                axis = xaxes[i];
1591                if (axis && axis.used)
1592                    res["x" + axis.n] = axis.c2p(pos.left);
1593            }
1594
1595            for (i = 0; i < yaxes.length; ++i) {
1596                axis = yaxes[i];
1597                if (axis && axis.used)
1598                    res["y" + axis.n] = axis.c2p(pos.top);
1599            }
1600
1601            if (res.x1 !== undefined)
1602                res.x = res.x1;
1603            if (res.y1 !== undefined)
1604                res.y = res.y1;
1605
1606            return res;
1607        }
1608
1609        function axisToCanvasCoords(pos) {
1610            // get canvas coords from the first pair of x/y found in pos
1611            var res = {}, i, axis, key;
1612
1613            for (i = 0; i < xaxes.length; ++i) {
1614                axis = xaxes[i];
1615                if (axis && axis.used) {
1616                    key = "x" + axis.n;
1617                    if (pos[key] == null && axis.n == 1)
1618                        key = "x";
1619
1620                    if (pos[key] != null) {
1621                        res.left = axis.p2c(pos[key]);
1622                        break;
1623                    }
1624                }
1625            }
1626
1627            for (i = 0; i < yaxes.length; ++i) {
1628                axis = yaxes[i];
1629                if (axis && axis.used) {
1630                    key = "y" + axis.n;
1631                    if (pos[key] == null && axis.n == 1)
1632                        key = "y";
1633
1634                    if (pos[key] != null) {
1635                        res.top = axis.p2c(pos[key]);
1636                        break;
1637                    }
1638                }
1639            }
1640
1641            return res;
1642        }
1643
1644        function getOrCreateAxis(axes, number) {
1645            if (!axes[number - 1])
1646                axes[number - 1] = {
1647                    n: number, // save the number for future reference
1648                    direction: axes == xaxes ? "x" : "y",
1649                    options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis)
1650                };
1651
1652            return axes[number - 1];
1653        }
1654
1655        function fillInSeriesOptions() {
1656
1657            var neededColors = series.length, maxIndex = -1, i;
1658
1659            // Subtract the number of series that already have fixed colors or
1660            // color indexes from the number that we still need to generate.
1661
1662            for (i = 0; i < series.length; ++i) {
1663                var sc = series[i].color;
1664                if (sc != null) {
1665                    neededColors--;
1666                    if (typeof sc == "number" && sc > maxIndex) {
1667                        maxIndex = sc;
1668                    }
1669                }
1670            }
1671
1672            // If any of the series have fixed color indexes, then we need to
1673            // generate at least as many colors as the highest index.
1674
1675            if (neededColors <= maxIndex) {
1676                neededColors = maxIndex + 1;
1677            }
1678
1679            // Generate all the colors, using first the option colors and then
1680            // variations on those colors once they're exhausted.
1681
1682            var c, colors = [], colorPool = options.colors,
1683                colorPoolSize = colorPool.length, variation = 0;
1684
1685            for (i = 0; i < neededColors; i++) {
1686
1687                c = $.color.parse(colorPool[i % colorPoolSize] || "#666");
1688
1689                // Each time we exhaust the colors in the pool we adjust
1690                // a scaling factor used to produce more variations on
1691                // those colors. The factor alternates negative/positive
1692                // to produce lighter/darker colors.
1693
1694                // Reset the variation after every few cycles, or else
1695                // it will end up producing only white or black colors.
1696
1697                if (i % colorPoolSize == 0 && i) {
1698                    if (variation >= 0) {
1699                        if (variation < 0.5) {
1700                            variation = -variation - 0.2;
1701                        } else variation = 0;
1702                    } else variation = -variation;
1703                }
1704
1705                colors[i] = c.scale('rgb', 1 + variation);
1706            }
1707
1708            // Finalize the series options, filling in their colors
1709
1710            var colori = 0, s;
1711            for (i = 0; i < series.length; ++i) {
1712                s = series[i];
1713
1714                // assign colors
1715                if (s.color == null) {
1716                    s.color = colors[colori].toString();
1717                    ++colori;
1718                }
1719                else if (typeof s.color == "number")
1720                    s.color = colors[s.color].toString();
1721
1722                // turn on lines automatically in case nothing is set
1723                if (s.lines.show == null) {
1724                    var v, show = true;
1725                    for (v in s)
1726                        if (s[v] && s[v].show) {
1727                            show = false;
1728                            break;
1729                        }
1730                    if (show)
1731                        s.lines.show = true;
1732                }
1733
1734                // If nothing was provided for lines.zero, default it to match
1735                // lines.fill, since areas by default should extend to zero.
1736
1737                if (s.lines.zero == null) {
1738                    s.lines.zero = !!s.lines.fill;
1739                }
1740
1741                // setup axes
1742                s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x"));
1743                s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y"));
1744            }
1745        }
1746
1747        function processData() {
1748            var topSentry = Number.POSITIVE_INFINITY,
1749                bottomSentry = Number.NEGATIVE_INFINITY,
1750                fakeInfinity = Number.MAX_VALUE,
1751                i, j, k, m, length,
1752                s, points, ps, x, y, axis, val, f, p,
1753                data, format;
1754
1755            function updateAxis(axis, min, max) {
1756                if (min < axis.datamin && min != -fakeInfinity)
1757                    axis.datamin = min;
1758                if (max > axis.datamax && max != fakeInfinity)
1759                    axis.datamax = max;
1760            }
1761
1762            $.each(allAxes(), function (_, axis) {
1763                // init axis
1764                axis.datamin = topSentry;
1765                axis.datamax = bottomSentry;
1766                axis.used = false;
1767            });
1768
1769            for (i = 0; i < series.length; ++i) {
1770                s = series[i];
1771                s.datapoints = { points: [] };
1772
1773                executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]);
1774            }
1775
1776            // first pass: clean and copy data
1777            for (i = 0; i < series.length; ++i) {
1778                s = series[i];
1779
1780                data = s.data;
1781                format = s.datapoints.format;
1782
1783                if (!format) {
1784                    format = [];
1785                    // find out how to copy
1786                    format.push({ x: true, number: true, required: true });
1787                    format.push({ y: true, number: true, required: true });
1788
1789                    if (s.bars.show || (s.lines.show && s.lines.fill)) {
1790                        var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero));
1791                        format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale });
1792                        if (s.bars.horizontal) {
1793                            delete format[format.length - 1].y;
1794                            format[format.length - 1].x = true;
1795                        }
1796                    }
1797
1798                    s.datapoints.format = format;
1799                }
1800
1801                if (s.datapoints.pointsize != null)
1802                    continue; // already filled in
1803
1804                s.datapoints.pointsize = format.length;
1805
1806                ps = s.datapoints.pointsize;
1807                points = s.datapoints.points;
1808
1809                var insertSteps = s.lines.show && s.lines.steps;
1810                s.xaxis.used = s.yaxis.used = true;
1811
1812                for (j = k = 0; j < data.length; ++j, k += ps) {
1813                    p = data[j];
1814
1815                    var nullify = p == null;
1816                    if (!nullify) {
1817                        for (m = 0; m < ps; ++m) {
1818                            val = p[m];
1819                            f = format[m];
1820
1821                            if (f) {
1822                                if (f.number && val != null) {
1823                                    val = +val; // convert to number
1824                                    if (isNaN(val))
1825                                        val = null;
1826                                    else if (val == Infinity)
1827                                        val = fakeInfinity;
1828                                    else if (val == -Infinity)
1829                                        val = -fakeInfinity;
1830                                }
1831
1832                                if (val == null) {
1833                                    if (f.required)
1834                                        nullify = true;
1835
1836                                    if (f.defaultValue != null)
1837                                        val = f.defaultValue;
1838                                }
1839                            }
1840
1841                            points[k + m] = val;
1842                        }
1843                    }
1844
1845                    if (nullify) {
1846                        for (m = 0; m < ps; ++m) {
1847                            val = points[k + m];
1848                            if (val != null) {
1849                                f = format[m];
1850                                // extract min/max info
1851                                if (f.autoscale !== false) {
1852                                    if (f.x) {
1853                                        updateAxis(s.xaxis, val, val);
1854                                    }
1855                                    if (f.y) {
1856                                        updateAxis(s.yaxis, val, val);
1857                                    }
1858                                }
1859                            }
1860                            points[k + m] = null;
1861                        }
1862                    }
1863                    else {
1864                        // a little bit of line specific stuff that
1865                        // perhaps shouldn't be here, but lacking
1866                        // better means...
1867                        if (insertSteps && k > 0
1868                            && points[k - ps] != null
1869                            && points[k - ps] != points[k]
1870                            && points[k - ps + 1] != points[k + 1]) {
1871                            // copy the point to make room for a middle point
1872                            for (m = 0; m < ps; ++m)
1873                                points[k + ps + m] = points[k + m];
1874
1875                            // middle point has same y
1876                            points[k + 1] = points[k - ps + 1];
1877
1878                            // we've added a point, better reflect that
1879                            k += ps;
1880                        }
1881                    }
1882                }
1883            }
1884
1885            // give the hooks a chance to run
1886            for (i = 0; i < series.length; ++i) {
1887                s = series[i];
1888
1889                executeHooks(hooks.processDatapoints, [ s, s.datapoints]);
1890            }
1891
1892            // second pass: find datamax/datamin for auto-scaling
1893            for (i = 0; i < series.length; ++i) {
1894                s = series[i];
1895                points = s.datapoints.points;
1896                ps = s.datapoints.pointsize;
1897                format = s.datapoints.format;
1898
1899                var xmin = topSentry, ymin = topSentry,
1900                    xmax = bottomSentry, ymax = bottomSentry;
1901
1902                for (j = 0; j < points.length; j += ps) {
1903                    if (points[j] == null)
1904                        continue;
1905
1906                    for (m = 0; m < ps; ++m) {
1907                        val = points[j + m];
1908                        f = format[m];
1909                        if (!f || f.autoscale === false || val == fakeInfinity || val == -fakeInfinity)
1910                            continue;
1911
1912                        if (f.x) {
1913                            if (val < xmin)
1914                                xmin = val;
1915                            if (val > xmax)
1916                                xmax = val;
1917                        }
1918                        if (f.y) {
1919                            if (val < ymin)
1920                                ymin = val;
1921                            if (val > ymax)
1922                                ymax = val;
1923                        }
1924                    }
1925                }
1926
1927                if (s.bars.show) {
1928                    // make sure we got room for the bar on the dancing floor
1929                    var delta;
1930
1931                    switch (s.bars.align) {
1932                        case "left":
1933                            delta = 0;
1934                            break;
1935                        case "right":
1936                            delta = -s.bars.barWidth;
1937                            break;
1938                        default:
1939                            delta = -s.bars.barWidth / 2;
1940                    }
1941
1942                    if (s.bars.horizontal) {
1943                        ymin += delta;
1944                        ymax += delta + s.bars.barWidth;
1945                    }
1946                    else {
1947                        xmin += delta;
1948                        xmax += delta + s.bars.barWidth;
1949                    }
1950                }
1951
1952                updateAxis(s.xaxis, xmin, xmax);
1953                updateAxis(s.yaxis, ymin, ymax);
1954            }
1955
1956            $.each(allAxes(), function (_, axis) {
1957                if (axis.datamin == topSentry)
1958                    axis.datamin = null;
1959                if (axis.datamax == bottomSentry)
1960                    axis.datamax = null;
1961            });
1962        }
1963
1964        function setupCanvases() {
1965
1966            // Make sure the placeholder is clear of everything except canvases
1967            // from a previous plot in this container that we'll try to re-use.
1968
1969            placeholder.css("padding", 0) // padding messes up the positioning
1970                .children().filter(function(){
1971                    return !$(this).hasClass("flot-overlay") && !$(this).hasClass('flot-base');
1972                }).remove();
1973
1974            if (placeholder.css("position") == 'static')
1975                placeholder.css("position", "relative"); // for positioning labels and overlay
1976
1977            surface = new Canvas("flot-base", placeholder);
1978            overlay = new Canvas("flot-overlay", placeholder); // overlay canvas for interactive features
1979
1980            ctx = surface.context;
1981            octx = overlay.context;
1982
1983            // define which element we're listening for events on
1984            eventHolder = $(overlay.element).unbind();
1985
1986            // If we're re-using a plot object, shut down the old one
1987
1988            var existing = placeholder.data("plot");
1989
1990            if (existing) {
1991                existing.shutdown();
1992                overlay.clear();
1993            }
1994
1995            // save in case we get replotted
1996            placeholder.data("plot", plot);
1997        }
1998
1999        function bindEvents() {
2000            // bind events
2001            if (options.grid.hoverable) {
2002                eventHolder.mousemove(onMouseMove);
2003
2004                // Use bind, rather than .mouseleave, because we officially
2005                // still support jQuery 1.2.6, which doesn't define a shortcut
2006                // for mouseenter or mouseleave.  This was a bug/oversight that
2007                // was fixed somewhere around 1.3.x.  We can return to using
2008                // .mouseleave when we drop support for 1.2.6.
2009
2010                eventHolder.bind("mouseleave", onMouseLeave);
2011            }
2012
2013            if (options.grid.clickable)
2014                eventHolder.click(onClick);
2015
2016            executeHooks(hooks.bindEvents, [eventHolder]);
2017        }
2018
2019        function shutdown() {
2020            if (redrawTimeout)
2021                clearTimeout(redrawTimeout);
2022
2023            eventHolder.unbind("mousemove", onMouseMove);
2024            eventHolder.unbind("mouseleave", onMouseLeave);
2025            eventHolder.unbind("click", onClick);
2026
2027            executeHooks(hooks.shutdown, [eventHolder]);
2028        }
2029
2030        function setTransformationHelpers(axis) {
2031            // set helper functions on the axis, assumes plot area
2032            // has been computed already
2033
2034            function identity(x) { return x; }
2035
2036            var s, m, t = axis.options.transform || identity,
2037                it = axis.options.inverseTransform;
2038
2039            // precompute how much the axis is scaling a point
2040            // in canvas space
2041            if (axis.direction == "x") {
2042                s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min));
2043                m = Math.min(t(axis.max), t(axis.min));
2044            }
2045            else {
2046                s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min));
2047                s = -s;
2048                m = Math.max(t(axis.max), t(axis.min));
2049            }
2050
2051            // data point to canvas coordinate
2052            if (t == identity) // slight optimization
2053                axis.p2c = function (p) { return (p - m) * s; };
2054            else
2055                axis.p2c = function (p) { return (t(p) - m) * s; };
2056            // canvas coordinate to data point
2057            if (!it)
2058                axis.c2p = function (c) { return m + c / s; };
2059            else
2060                axis.c2p = function (c) { return it(m + c / s); };
2061        }
2062
2063        function measureTickLabels(axis) {
2064
2065            var opts = axis.options,
2066                ticks = axis.ticks || [],
2067                labelWidth = opts.labelWidth || 0,
2068                labelHeight = opts.labelHeight || 0,
2069                maxWidth = labelWidth || (axis.direction == "x" ? Math.floor(surface.width / (ticks.length || 1)) : null),
2070                legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis",
2071                layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles,
2072                font = opts.font || "flot-tick-label tickLabel";
2073
2074            for (var i = 0; i < ticks.length; ++i) {
2075
2076                var t = ticks[i];
2077
2078                if (!t.label)
2079                    continue;
2080
2081                var info = surface.getTextInfo(layer, t.label, font, null, maxWidth);
2082
2083                labelWidth = Math.max(labelWidth, info.width);
2084                labelHeight = Math.max(labelHeight, info.height);
2085            }
2086
2087            axis.labelWidth = opts.labelWidth || labelWidth;
2088            axis.labelHeight = opts.labelHeight || labelHeight;
2089        }
2090
2091        function allocateAxisBoxFirstPhase(axis) {
2092            // find the bounding box of the axis by looking at label
2093            // widths/heights and ticks, make room by diminishing the
2094            // plotOffset; this first phase only looks at one
2095            // dimension per axis, the other dimension depends on the
2096            // other axes so will have to wait
2097
2098            var lw = axis.labelWidth,
2099                lh = axis.labelHeight,
2100                pos = axis.options.position,
2101                isXAxis = axis.direction === "x",
2102                tickLength = axis.options.tickLength,
2103                axisMargin = options.grid.axisMargin,
2104                padding = options.grid.labelMargin,
2105                innermost = true,
2106                outermost = true,
2107                first = true,
2108                found = false;
2109
2110            // Determine the axis's position in its direction and on its side
2111
2112            $.each(isXAxis ? xaxes : yaxes, function(i, a) {
2113                if (a && (a.show || a.reserveSpace)) {
2114                    if (a === axis) {
2115                        found = true;
2116                    } else if (a.options.position === pos) {
2117                        if (found) {
2118                            outermost = false;
2119                        } else {
2120                            innermost = false;
2121                        }
2122                    }
2123                    if (!found) {
2124                        first = false;
2125                    }
2126                }
2127            });
2128
2129            // The outermost axis on each side has no margin
2130
2131            if (outermost) {
2132                axisMargin = 0;
2133            }
2134
2135            // The ticks for the first axis in each direction stretch across
2136
2137            if (tickLength == null) {
2138                tickLength = first ? "full" : 5;
2139            }
2140
2141            if (!isNaN(+tickLength))
2142                padding += +tickLength;
2143
2144            if (isXAxis) {
2145                lh += padding;
2146
2147                if (pos == "bottom") {
2148                    plotOffset.bottom += lh + axisMargin;
2149                    axis.box = { top: surface.height - plotOffset.bottom, height: lh };
2150                }
2151                else {
2152                    axis.box = { top: plotOffset.top + axisMargin, height: lh };
2153                    plotOffset.top += lh + axisMargin;
2154                }
2155            }
2156            else {
2157                lw += padding;
2158
2159                if (pos == "left") {
2160                    axis.box = { left: plotOffset.left + axisMargin, width: lw };
2161                    plotOffset.left += lw + axisMargin;
2162                }
2163                else {
2164                    plotOffset.right += lw + axisMargin;
2165                    axis.box = { left: surface.width - plotOffset.right, width: lw };
2166                }
2167            }
2168
2169             // save for future reference
2170            axis.position = pos;
2171            axis.tickLength = tickLength;
2172            axis.box.padding = padding;
2173            axis.innermost = innermost;
2174        }
2175
2176        function allocateAxisBoxSecondPhase(axis) {
2177            // now that all axis boxes have been placed in one
2178            // dimension, we can set the remaining dimension coordinates
2179            if (axis.direction == "x") {
2180                axis.box.left = plotOffset.left - axis.labelWidth / 2;
2181                axis.box.width = surface.width - plotOffset.left - plotOffset.right + axis.labelWidth;
2182            }
2183            else {
2184                axis.box.top = plotOffset.top - axis.labelHeight / 2;
2185                axis.box.height = surface.height - plotOffset.bottom - plotOffset.top + axis.labelHeight;
2186            }
2187        }
2188
2189        function adjustLayoutForThingsStickingOut() {
2190            // possibly adjust plot offset to ensure everything stays
2191            // inside the canvas and isn't clipped off
2192
2193            var minMargin = options.grid.minBorderMargin,
2194                axis, i;
2195
2196            // check stuff from the plot (FIXME: this should just read
2197            // a value from the series, otherwise it's impossible to
2198            // customize)
2199            if (minMargin == null) {
2200                minMargin = 0;
2201                for (i = 0; i < series.length; ++i)
2202                    minMargin = Math.max(minMargin, 2 * (series[i].points.radius + series[i].points.lineWidth/2));
2203            }
2204
2205            var margins = {
2206                left: minMargin,
2207                right: minMargin,
2208                top: minMargin,
2209                bottom: minMargin
2210            };
2211
2212            // check axis labels, note we don't check the actual
2213            // labels but instead use the overall width/height to not
2214            // jump as much around with replots
2215            $.each(allAxes(), function (_, axis) {
2216                if (axis.reserveSpace && axis.ticks && axis.ticks.length) {
2217                    if (axis.direction === "x") {
2218                        margins.left = Math.max(margins.left, axis.labelWidth / 2);
2219                        margins.right = Math.max(margins.right, axis.labelWidth / 2);
2220                    } else {
2221                        margins.bottom = Math.max(margins.bottom, axis.labelHeight / 2);
2222                        margins.top = Math.max(margins.top, axis.labelHeight / 2);
2223                    }
2224                }
2225            });
2226
2227            plotOffset.left = Math.ceil(Math.max(margins.left, plotOffset.left));
2228            plotOffset.right = Math.ceil(Math.max(margins.right, plotOffset.right));
2229            plotOffset.top = Math.ceil(Math.max(margins.top, plotOffset.top));
2230            plotOffset.bottom = Math.ceil(Math.max(margins.bottom, plotOffset.bottom));
2231        }
2232
2233        function setupGrid() {
2234            var i, axes = allAxes(), showGrid = options.grid.show;
2235
2236            // Initialize the plot's offset from the edge of the canvas
2237
2238            for (var a in plotOffset) {
2239                var margin = options.grid.margin || 0;
2240                plotOffset[a] = typeof margin == "number" ? margin : margin[a] || 0;
2241            }
2242
2243            executeHooks(hooks.processOffset, [plotOffset]);
2244
2245            // If the grid is visible, add its border width to the offset
2246
2247            for (var a in plotOffset) {
2248                if(typeof(options.grid.borderWidth) == "object") {
2249                    plotOffset[a] += showGrid ? options.grid.borderWidth[a] : 0;
2250                }
2251                else {
2252                    plotOffset[a] += showGrid ? options.grid.borderWidth : 0;
2253                }
2254            }
2255
2256            $.each(axes, function (_, axis) {
2257                var axisOpts = axis.options;
2258                axis.show = axisOpts.show == null ? axis.used : axisOpts.show;
2259                axis.reserveSpace = axisOpts.reserveSpace == null ? axis.show : axisOpts.reserveSpace;
2260                setRange(axis);
2261            });
2262
2263            if (showGrid) {
2264
2265                var allocatedAxes = $.grep(axes, function (axis) {
2266                    return axis.show || axis.reserveSpace;
2267                });
2268
2269                $.each(allocatedAxes, function (_, axis) {
2270                    // make the ticks
2271                    setupTickGeneration(axis);
2272                    setTicks(axis);
2273                    snapRangeToTicks(axis, axis.ticks);
2274                    // find labelWidth/Height for axis
2275                    measureTickLabels(axis);
2276                });
2277
2278                // with all dimensions calculated, we can compute the
2279                // axis bounding boxes, start from the outside
2280                // (reverse order)
2281                for (i = allocatedAxes.length - 1; i >= 0; --i)
2282                    allocateAxisBoxFirstPhase(allocatedAxes[i]);
2283
2284                // make sure we've got enough space for things that
2285                // might stick out
2286                adjustLayoutForThingsStickingOut();
2287
2288                $.each(allocatedAxes, function (_, axis) {
2289                    allocateAxisBoxSecondPhase(axis);
2290                });
2291            }
2292
2293            plotWidth = surface.width - plotOffset.left - plotOffset.right;
2294            plotHeight = surface.height - plotOffset.bottom - plotOffset.top;
2295
2296            // now we got the proper plot dimensions, we can compute the scaling
2297            $.each(axes, function (_, axis) {
2298                setTransformationHelpers(axis);
2299            });
2300
2301            if (showGrid) {
2302                drawAxisLabels();
2303            }
2304
2305            insertLegend();
2306        }
2307
2308        function setRange(axis) {
2309            var opts = axis.options,
2310                min = +(opts.min != null ? opts.min : axis.datamin),
2311                max = +(opts.max != null ? opts.max : axis.datamax),
2312                delta = max - min;
2313
2314            if (delta == 0.0) {
2315                // degenerate case
2316                var widen = max == 0 ? 1 : 0.01;
2317
2318                if (opts.min == null)
2319                    min -= widen;
2320                // always widen max if we couldn't widen min to ensure we
2321                // don't fall into min == max which doesn't work
2322                if (opts.max == null || opts.min != null)
2323                    max += widen;
2324            }
2325            else {
2326                // consider autoscaling
2327                var margin = opts.autoscaleMargin;
2328                if (margin != null) {
2329                    if (opts.min == null) {
2330                        min -= delta * margin;
2331                        // make sure we don't go below zero if all values
2332                        // are positive
2333                        if (min < 0 && axis.datamin != null && axis.datamin >= 0)
2334                            min = 0;
2335                    }
2336                    if (opts.max == null) {
2337                        max += delta * margin;
2338                        if (max > 0 && axis.datamax != null && axis.datamax <= 0)
2339                            max = 0;
2340                    }
2341                }
2342            }
2343            axis.min = min;
2344            axis.max = max;
2345        }
2346
2347        function setupTickGeneration(axis) {
2348            var opts = axis.options;
2349
2350            // estimate number of ticks
2351            var noTicks;
2352            if (typeof opts.ticks == "number" && opts.ticks > 0)
2353                noTicks = opts.ticks;
2354            else
2355                // heuristic based on the model a*sqrt(x) fitted to
2356                // some data points that seemed reasonable
2357                noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? surface.width : surface.height);
2358
2359            var delta = (axis.max - axis.min) / noTicks,
2360                dec = -Math.floor(Math.log(delta) / Math.LN10),
2361                maxDec = opts.tickDecimals;
2362
2363            if (maxDec != null && dec > maxDec) {
2364                dec = maxDec;
2365            }
2366
2367            var magn = Math.pow(10, -dec),
2368                norm = delta / magn, // norm is between 1.0 and 10.0
2369                size;
2370
2371            if (norm < 1.5) {
2372                size = 1;
2373            } else if (norm < 3) {
2374                size = 2;
2375                // special case for 2.5, requires an extra decimal
2376                if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
2377                    size = 2.5;
2378                    ++dec;
2379                }
2380            } else if (norm < 7.5) {
2381                size = 5;
2382            } else {
2383                size = 10;
2384            }
2385
2386            size *= magn;
2387
2388            if (opts.minTickSize != null && size < opts.minTickSize) {
2389                size = opts.minTickSize;
2390            }
2391
2392            axis.delta = delta;
2393            axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
2394            axis.tickSize = opts.tickSize || size;
2395
2396            // Time mode was moved to a plug-in in 0.8, and since so many people use it
2397            // we'll add an especially friendly reminder to make sure they included it.
2398
2399            if (opts.mode == "time" && !axis.tickGenerator) {
2400                throw new Error("Time mode requires the flot.time plugin.");
2401            }
2402
2403            // Flot supports base-10 axes; any other mode else is handled by a plug-in,
2404            // like flot.time.js.
2405
2406            if (!axis.tickGenerator) {
2407
2408                axis.tickGenerator = function (axis) {
2409
2410                    var ticks = [],
2411                        start = floorInBase(axis.min, axis.tickSize),
2412                        i = 0,
2413                        v = Number.NaN,
2414                        prev;
2415
2416                    do {
2417                        prev = v;
2418                        v = start + i * axis.tickSize;
2419                        ticks.push(v);
2420                        ++i;
2421                    } while (v < axis.max && v != prev);
2422                    return ticks;
2423                };
2424
2425				axis.tickFormatter = function (value, axis) {
2426
2427					var factor = axis.tickDecimals ? Math.pow(10, axis.tickDecimals) : 1;
2428					var formatted = "" + Math.round(value * factor) / factor;
2429
2430					// If tickDecimals was specified, ensure that we have exactly that
2431					// much precision; otherwise default to the value's own precision.
2432
2433					if (axis.tickDecimals != null) {
2434						var decimal = formatted.indexOf(".");
2435						var precision = decimal == -1 ? 0 : formatted.length - decimal - 1;
2436						if (precision < axis.tickDecimals) {
2437							return (precision ? formatted : formatted + ".") + ("" + factor).substr(1, axis.tickDecimals - precision);
2438						}
2439					}
2440
2441                    return formatted;
2442                };
2443            }
2444
2445            if ($.isFunction(opts.tickFormatter))
2446                axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); };
2447
2448            if (opts.alignTicksWithAxis != null) {
2449                var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1];
2450                if (otherAxis && otherAxis.used && otherAxis != axis) {
2451                    // consider snapping min/max to outermost nice ticks
2452                    var niceTicks = axis.tickGenerator(axis);
2453                    if (niceTicks.length > 0) {
2454                        if (opts.min == null)
2455                            axis.min = Math.min(axis.min, niceTicks[0]);
2456                        if (opts.max == null && niceTicks.length > 1)
2457                            axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]);
2458                    }
2459
2460                    axis.tickGenerator = function (axis) {
2461                        // copy ticks, scaled to this axis
2462                        var ticks = [], v, i;
2463                        for (i = 0; i < otherAxis.ticks.length; ++i) {
2464                            v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min);
2465                            v = axis.min + v * (axis.max - axis.min);
2466                            ticks.push(v);
2467                        }
2468                        return ticks;
2469                    };
2470
2471                    // we might need an extra decimal since forced
2472                    // ticks don't necessarily fit naturally
2473                    if (!axis.mode && opts.tickDecimals == null) {
2474                        var extraDec = Math.max(0, -Math.floor(Math.log(axis.delta) / Math.LN10) + 1),
2475                            ts = axis.tickGenerator(axis);
2476
2477                        // only proceed if the tick interval rounded
2478                        // with an extra decimal doesn't give us a
2479                        // zero at end
2480                        if (!(ts.length > 1 && /\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec))))
2481                            axis.tickDecimals = extraDec;
2482                    }
2483                }
2484            }
2485        }
2486
2487        function setTicks(axis) {
2488            var oticks = axis.options.ticks, ticks = [];
2489            if (oticks == null || (typeof oticks == "number" && oticks > 0))
2490                ticks = axis.tickGenerator(axis);
2491            else if (oticks) {
2492                if ($.isFunction(oticks))
2493                    // generate the ticks
2494                    ticks = oticks(axis);
2495                else
2496                    ticks = oticks;
2497            }
2498
2499            // clean up/labelify the supplied ticks, copy them over
2500            var i, v;
2501            axis.ticks = [];
2502            for (i = 0; i < ticks.length; ++i) {
2503                var label = null;
2504                var t = ticks[i];
2505                if (typeof t == "object") {
2506                    v = +t[0];
2507                    if (t.length > 1)
2508                        label = t[1];
2509                }
2510                else
2511                    v = +t;
2512                if (label == null)
2513                    label = axis.tickFormatter(v, axis);
2514                if (!isNaN(v))
2515                    axis.ticks.push({ v: v, label: label });
2516            }
2517        }
2518
2519        function snapRangeToTicks(axis, ticks) {
2520            if (axis.options.autoscaleMargin && ticks.length > 0) {
2521                // snap to ticks
2522                if (axis.options.min == null)
2523                    axis.min = Math.min(axis.min, ticks[0].v);
2524                if (axis.options.max == null && ticks.length > 1)
2525                    axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);
2526            }
2527        }
2528
2529        function draw() {
2530
2531            surface.clear();
2532
2533            executeHooks(hooks.drawBackground, [ctx]);
2534
2535            var grid = options.grid;
2536
2537            // draw background, if any
2538            if (grid.show && grid.backgroundColor)
2539                drawBackground();
2540
2541            if (grid.show && !grid.aboveData) {
2542                drawGrid();
2543            }
2544
2545            for (var i = 0; i < series.length; ++i) {
2546                executeHooks(hooks.drawSeries, [ctx, series[i]]);
2547                drawSeries(series[i]);
2548            }
2549
2550            executeHooks(hooks.draw, [ctx]);
2551
2552            if (grid.show && grid.aboveData) {
2553                drawGrid();
2554            }
2555
2556            surface.render();
2557
2558            // A draw implies that either the axes or data have changed, so we
2559            // should probably update the overlay highlights as well.
2560
2561            triggerRedrawOverlay();
2562        }
2563
2564        function extractRange(ranges, coord) {
2565            var axis, from, to, key, axes = allAxes();
2566
2567            for (var i = 0; i < axes.length; ++i) {
2568                axis = axes[i];
2569                if (axis.direction == coord) {
2570                    key = coord + axis.n + "axis";
2571                    if (!ranges[key] && axis.n == 1)
2572                        key = coord + "axis"; // support x1axis as xaxis
2573                    if (ranges[key]) {
2574                        from = ranges[key].from;
2575                        to = ranges[key].to;
2576                        break;
2577                    }
2578                }
2579            }
2580
2581            // backwards-compat stuff - to be removed in future
2582            if (!ranges[key]) {
2583                axis = coord == "x" ? xaxes[0] : yaxes[0];
2584                from = ranges[coord + "1"];
2585                to = ranges[coord + "2"];
2586            }
2587
2588            // auto-reverse as an added bonus
2589            if (from != null && to != null && from > to) {
2590                var tmp = from;
2591                from = to;
2592                to = tmp;
2593            }
2594
2595            return { from: from, to: to, axis: axis };
2596        }
2597
2598        function drawBackground() {
2599            ctx.save();
2600            ctx.translate(plotOffset.left, plotOffset.top);
2601
2602            ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)");
2603            ctx.fillRect(0, 0, plotWidth, plotHeight);
2604            ctx.restore();
2605        }
2606
2607        function drawGrid() {
2608            var i, axes, bw, bc;
2609
2610            ctx.save();
2611            ctx.translate(plotOffset.left, plotOffset.top);
2612
2613            // draw markings
2614            var markings = options.grid.markings;
2615            if (markings) {
2616                if ($.isFunction(markings)) {
2617                    axes = plot.getAxes();
2618                    // xmin etc. is backwards compatibility, to be
2619                    // removed in the future
2620                    axes.xmin = axes.xaxis.min;
2621                    axes.xmax = axes.xaxis.max;
2622                    axes.ymin = axes.yaxis.min;
2623                    axes.ymax = axes.yaxis.max;
2624
2625                    markings = markings(axes);
2626                }
2627
2628                for (i = 0; i < markings.length; ++i) {
2629                    var m = markings[i],
2630                        xrange = extractRange(m, "x"),
2631                        yrange = extractRange(m, "y");
2632
2633                    // fill in missing
2634                    if (xrange.from == null)
2635                        xrange.from = xrange.axis.min;
2636                    if (xrange.to == null)
2637                        xrange.to = xrange.axis.max;
2638                    if (yrange.from == null)
2639                        yrange.from = yrange.axis.min;
2640                    if (yrange.to == null)
2641                        yrange.to = yrange.axis.max;
2642
2643                    // clip
2644                    if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max ||
2645                        yrange.to < yrange.axis.min || yrange.from > yrange.axis.max)
2646                        continue;
2647
2648                    xrange.from = Math.max(xrange.from, xrange.axis.min);
2649                    xrange.to = Math.min(xrange.to, xrange.axis.max);
2650                    yrange.from = Math.max(yrange.from, yrange.axis.min);
2651                    yrange.to = Math.min(yrange.to, yrange.axis.max);
2652
2653                    var xequal = xrange.from === xrange.to,
2654                        yequal = yrange.from === yrange.to;
2655
2656                    if (xequal && yequal) {
2657                        continue;
2658                    }
2659
2660                    // then draw
2661                    xrange.from = Math.floor(xrange.axis.p2c(xrange.from));
2662                    xrange.to = Math.floor(xrange.axis.p2c(xrange.to));
2663                    yrange.from = Math.floor(yrange.axis.p2c(yrange.from));
2664                    yrange.to = Math.floor(yrange.axis.p2c(yrange.to));
2665
2666                    if (xequal || yequal) {
2667                        var lineWidth = m.lineWidth || options.grid.markingsLineWidth,
2668                            subPixel = lineWidth % 2 ? 0.5 : 0;
2669                        ctx.beginPath();
2670                        ctx.strokeStyle = m.color || options.grid.markingsColor;
2671                        ctx.lineWidth = lineWidth;
2672                        if (xequal) {
2673                            ctx.moveTo(xrange.to + subPixel, yrange.from);
2674                            ctx.lineTo(xrange.to + subPixel, yrange.to);
2675                        } else {
2676                            ctx.moveTo(xrange.from, yrange.to + subPixel);
2677                            ctx.lineTo(xrange.to, yrange.to + subPixel);                            
2678                        }
2679                        ctx.stroke();
2680                    } else {
2681                        ctx.fillStyle = m.color || options.grid.markingsColor;
2682                        ctx.fillRect(xrange.from, yrange.to,
2683                                     xrange.to - xrange.from,
2684                                     yrange.from - yrange.to);
2685                    }
2686                }
2687            }
2688
2689            // draw the ticks
2690            axes = allAxes();
2691            bw = options.grid.borderWidth;
2692
2693            for (var j = 0; j < axes.length; ++j) {
2694                var axis = axes[j], box = axis.box,
2695                    t = axis.tickLength, x, y, xoff, yoff;
2696                if (!axis.show || axis.ticks.length == 0)
2697                    continue;
2698
2699                ctx.lineWidth = 1;
2700
2701                // find the edges
2702                if (axis.direction == "x") {
2703                    x = 0;
2704                    if (t == "full")
2705                        y = (axis.position == "top" ? 0 : plotHeight);
2706                    else
2707                        y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0);
2708                }
2709                else {
2710                    y = 0;
2711                    if (t == "full")
2712                        x = (axis.position == "left" ? 0 : plotWidth);
2713                    else
2714                        x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0);
2715                }
2716
2717                // draw tick bar
2718                if (!axis.innermost) {
2719                    ctx.strokeStyle = axis.options.color;
2720                    ctx.beginPath();
2721                    xoff = yoff = 0;
2722                    if (axis.direction == "x")
2723                        xoff = plotWidth + 1;
2724                    else
2725                        yoff = plotHeight + 1;
2726
2727                    if (ctx.lineWidth == 1) {
2728                        if (axis.direction == "x") {
2729                            y = Math.floor(y) + 0.5;
2730                        } else {
2731                            x = Math.floor(x) + 0.5;
2732                        }
2733                    }
2734
2735                    ctx.moveTo(x, y);
2736                    ctx.lineTo(x + xoff, y + yoff);
2737                    ctx.stroke();
2738                }
2739
2740                // draw ticks
2741
2742                ctx.strokeStyle = axis.options.tickColor;
2743
2744                ctx.beginPath();
2745                for (i = 0; i < axis.ticks.length; ++i) {
2746                    var v = axis.ticks[i].v;
2747
2748                    xoff = yoff = 0;
2749
2750                    if (isNaN(v) || v < axis.min || v > axis.max
2751                        // skip those lying on the axes if we got a border
2752                        || (t == "full"
2753                            && ((typeof bw == "object" && bw[axis.position] > 0) || bw > 0)
2754                            && (v == axis.min || v == axis.max)))
2755                        continue;
2756
2757                    if (axis.direction == "x") {
2758                        x = axis.p2c(v);
2759                        yoff = t == "full" ? -plotHeight : t;
2760
2761                        if (axis.position == "top")
2762                            yoff = -yoff;
2763                    }
2764                    else {
2765                        y = axis.p2c(v);
2766                        xoff = t == "full" ? -plotWidth : t;
2767
2768                        if (axis.position == "left")
2769                            xoff = -xoff;
2770                    }
2771
2772                    if (ctx.lineWidth == 1) {
2773                        if (axis.direction == "x")
2774                            x = Math.floor(x) + 0.5;
2775                        else
2776                            y = Math.floor(y) + 0.5;
2777                    }
2778
2779                    ctx.moveTo(x, y);
2780                    ctx.lineTo(x + xoff, y + yoff);
2781                }
2782
2783                ctx.stroke();
2784            }
2785
2786
2787            // draw border
2788            if (bw) {
2789                // If either borderWidth or borderColor is an object, then draw the border
2790                // line by line instead of as one rectangle
2791                bc = options.grid.borderColor;
2792                if(typeof bw == "object" || typeof bc == "object") {
2793                    if (typeof bw !== "object") {
2794                        bw = {top: bw, right: bw, bottom: bw, left: bw};
2795                    }
2796                    if (typeof bc !== "object") {
2797                        bc = {top: bc, right: bc, bottom: bc, left: bc};
2798                    }
2799
2800                    if (bw.top > 0) {
2801                        ctx.strokeStyle = bc.top;
2802                        ctx.lineWidth = bw.top;
2803                        ctx.beginPath();
2804                        ctx.moveTo(0 - bw.left, 0 - bw.top/2);
2805                        ctx.lineTo(plotWidth, 0 - bw.top/2);
2806                        ctx.stroke();
2807                    }
2808
2809                    if (bw.right > 0) {
2810                        ctx.strokeStyle = bc.right;
2811                        ctx.lineWidth = bw.right;
2812                        ctx.beginPath();
2813                        ctx.moveTo(plotWidth + bw.right / 2, 0 - bw.top);
2814                        ctx.lineTo(plotWidth + bw.right / 2, plotHeight);
2815                        ctx.stroke();
2816                    }
2817
2818                    if (bw.bottom > 0) {
2819                        ctx.strokeStyle = bc.bottom;
2820                        ctx.lineWidth = bw.bottom;
2821                        ctx.beginPath();
2822                        ctx.moveTo(plotWidth + bw.right, plotHeight + bw.bottom / 2);
2823                        ctx.lineTo(0, plotHeight + bw.bottom / 2);
2824                        ctx.stroke();
2825                    }
2826
2827                    if (bw.left > 0) {
2828                        ctx.strokeStyle = bc.left;
2829                        ctx.lineWidth = bw.left;
2830                        ctx.beginPath();
2831                        ctx.moveTo(0 - bw.left/2, plotHeight + bw.bottom);
2832                        ctx.lineTo(0- bw.left/2, 0);
2833                        ctx.stroke();
2834                    }
2835                }
2836                else {
2837                    ctx.lineWidth = bw;
2838                    ctx.strokeStyle = options.grid.borderColor;
2839                    ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);
2840                }
2841            }
2842
2843            ctx.restore();
2844        }
2845
2846        function drawAxisLabels() {
2847
2848            $.each(allAxes(), function (_, axis) {
2849                var box = axis.box,
2850                    legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis",
2851                    layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles,
2852                    font = axis.options.font || "flot-tick-label tickLabel",
2853                    tick, x, y, halign, valign;
2854
2855                // Remove text before checking for axis.show and ticks.length;
2856                // otherwise plugins, like flot-tickrotor, that draw their own
2857                // tick labels will end up with both theirs and the defaults.
2858
2859                surface.removeText(layer);
2860
2861                if (!axis.show || axis.ticks.length == 0)
2862                    return;
2863
2864                for (var i = 0; i < axis.ticks.length; ++i) {
2865
2866                    tick = axis.ticks[i];
2867                    if (!tick.label || tick.v < axis.min || tick.v > axis.max)
2868                        continue;
2869
2870                    if (axis.direction == "x") {
2871                        halign = "center";
2872                        x = plotOffset.left + axis.p2c(tick.v);
2873                        if (axis.position == "bottom") {
2874                            y = box.top + box.padding;
2875                        } else {
2876                            y = box.top + box.height - box.padding;
2877                            valign = "bottom";
2878                        }
2879                    } else {
2880                        valign = "middle";
2881                        y = plotOffset.top + axis.p2c(tick.v);
2882                        if (axis.position == "left") {
2883                            x = box.left + box.width - box.padding;
2884                            halign = "right";
2885                        } else {
2886                            x = box.left + box.padding;
2887                        }
2888                    }
2889
2890                    surface.addText(layer, x, y, tick.label, font, null, null, halign, valign);
2891                }
2892            });
2893        }
2894
2895        function drawSeries(series) {
2896            if (series.lines.show)
2897                drawSeriesLines(series);
2898            if (series.bars.show)
2899                drawSeriesBars(series);
2900            if (series.points.show)
2901                drawSeriesPoints(series);
2902        }
2903
2904        function drawSeriesLines(series) {
2905            function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {
2906                var points = datapoints.points,
2907                    ps = datapoints.pointsize,
2908                    prevx = null, prevy = null;
2909
2910                ctx.beginPath();
2911                for (var i = ps; i < points.length; i += ps) {
2912                    var x1 = points[i - ps], y1 = points[i - ps + 1],
2913                        x2 = points[i], y2 = points[i + 1];
2914
2915                    if (x1 == null || x2 == null)
2916                        continue;
2917
2918                    // clip with ymin
2919                    if (y1 <= y2 && y1 < axisy.min) {
2920                        if (y2 < axisy.min)
2921                            continue;   // line segment is outside
2922                        // compute new intersection point
2923                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
2924                        y1 = axisy.min;
2925                    }
2926                    else if (y2 <= y1 && y2 < axisy.min) {
2927                        if (y1 < axisy.min)
2928                            continue;
2929                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
2930                        y2 = axisy.min;
2931                    }
2932
2933                    // clip with ymax
2934                    if (y1 >= y2 && y1 > axisy.max) {
2935                        if (y2 > axisy.max)
2936                            continue;
2937                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
2938                        y1 = axisy.max;
2939                    }
2940                    else if (y2 >= y1 && y2 > axisy.max) {
2941                        if (y1 > axisy.max)
2942                            continue;
2943                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
2944                        y2 = axisy.max;
2945                    }
2946
2947                    // clip with xmin
2948                    if (x1 <= x2 && x1 < axisx.min) {
2949                        if (x2 < axisx.min)
2950                            continue;
2951                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
2952                        x1 = axisx.min;
2953                    }
2954                    else if (x2 <= x1 && x2 < axisx.min) {
2955                        if (x1 < axisx.min)
2956                            continue;
2957                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
2958                        x2 = axisx.min;
2959                    }
2960
2961                    // clip with xmax
2962                    if (x1 >= x2 && x1 > axisx.max) {
2963                        if (x2 > axisx.max)
2964                            continue;
2965                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
2966                        x1 = axisx.max;
2967                    }
2968                    else if (x2 >= x1 && x2 > axisx.max) {
2969                        if (x1 > axisx.max)
2970                            continue;
2971                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
2972                        x2 = axisx.max;
2973                    }
2974
2975                    if (x1 != prevx || y1 != prevy)
2976                        ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
2977
2978                    prevx = x2;
2979                    prevy = y2;
2980                    ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);
2981                }
2982                ctx.stroke();
2983            }
2984
2985            function plotLineArea(datapoints, axisx, axisy) {
2986                var points = datapoints.points,
2987                    ps = datapoints.pointsize,
2988                    bottom = Math.min(Math.max(0, axisy.min), axisy.max),
2989                    i = 0, top, areaOpen = false,
2990                    ypos = 1, segmentStart = 0, segmentEnd = 0;
2991
2992                // we process each segment in two turns, first forward
2993                // direction to sketch out top, then once we hit the
2994                // end we go backwards to sketch the bottom
2995                while (true) {
2996                    if (ps > 0 && i > points.length + ps)
2997                        break;
2998
2999                    i += ps; // ps is negative if going backwards
3000
3001                    var x1 = points[i - ps],
3002                        y1 = points[i - ps + ypos],
3003                        x2 = points[i], y2 = points[i + ypos];
3004
3005                    if (areaOpen) {
3006                        if (ps > 0 && x1 != null && x2 == null) {
3007                            // at turning point
3008                            segmentEnd = i;
3009                            ps = -ps;
3010                            ypos = 2;
3011                            continue;
3012                        }
3013
3014                        if (ps < 0 && i == segmentStart + ps) {
3015                            // done with the reverse sweep
3016                            ctx.fill();
3017                            areaOpen = false;
3018                            ps = -ps;
3019                            ypos = 1;
3020                            i = segmentStart = segmentEnd + ps;
3021                            continue;
3022                        }
3023                    }
3024
3025                    if (x1 == null || x2 == null)
3026                        continue;
3027
3028                    // clip x values
3029
3030                    // clip with xmin
3031                    if (x1 <= x2 && x1 < axisx.min) {
3032                        if (x2 < axisx.min)
3033                            continue;
3034                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
3035                        x1 = axisx.min;
3036                    }
3037                    else if (x2 <= x1 && x2 < axisx.min) {
3038                        if (x1 < axisx.min)
3039                            continue;
3040                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
3041                        x2 = axisx.min;
3042                    }
3043
3044                    // clip with xmax
3045                    if (x1 >= x2 && x1 > axisx.max) {
3046                        if (x2 > axisx.max)
3047                            continue;
3048                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
3049                        x1 = axisx.max;
3050                    }
3051                    else if (x2 >= x1 && x2 > axisx.max) {
3052                        if (x1 > axisx.max)
3053                            continue;
3054                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
3055                        x2 = axisx.max;
3056                    }
3057
3058                    if (!areaOpen) {
3059                        // open area
3060                        ctx.beginPath();
3061                        ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
3062                        areaOpen = true;
3063                    }
3064
3065                    // now first check the case where both is outside
3066                    if (y1 >= axisy.max && y2 >= axisy.max) {
3067                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
3068                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
3069                        continue;
3070                    }
3071                    else if (y1 <= axisy.min && y2 <= axisy.min) {
3072                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
3073                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
3074                        continue;
3075                    }
3076
3077                    // else it's a bit more complicated, there might
3078                    // be a flat maxed out rectangle first, then a
3079                    // triangular cutout or reverse; to find these
3080                    // keep track of the current x values
3081                    var x1old = x1, x2old = x2;
3082
3083                    // clip the y values, without shortcutting, we
3084                    // go through all cases in turn
3085
3086                    // clip with ymin
3087                    if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
3088                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
3089                        y1 = axisy.min;
3090                    }
3091                    else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {
3092                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
3093                        y2 = axisy.min;
3094                    }
3095
3096                    // clip with ymax
3097                    if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {
3098                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
3099                        y1 = axisy.max;
3100                    }
3101                    else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {
3102                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
3103                        y2 = axisy.max;
3104                    }
3105
3106                    // if the x value was changed we got a rectangle
3107                    // to fill
3108                    if (x1 != x1old) {
3109                        ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1));
3110                        // it goes to (x1, y1), but we fill that below
3111                    }
3112
3113                    // fill triangular section, this sometimes result
3114                    // in redundant points if (x1, y1) hasn't changed
3115                    // from previous line to, but we just ignore that
3116                    ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
3117                    ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
3118
3119                    // fill the other rectangle if it's there
3120                    if (x2 != x2old) {
3121                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
3122                        ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2));
3123                    }
3124                }
3125            }
3126
3127            ctx.save();
3128            ctx.translate(plotOffset.left, plotOffset.top);
3129            ctx.lineJoin = "round";
3130
3131            var lw = series.lines.lineWidth,
3132                sw = series.shadowSize;
3133            // FIXME: consider another form of shadow when filling is turned on
3134            if (lw > 0 && sw > 0) {
3135                // draw shadow as a thick and thin line with transparency
3136                ctx.lineWidth = sw;
3137                ctx.strokeStyle = "rgba(0,0,0,0.1)";
3138                // position shadow at angle from the mid of line
3139                var angle = Math.PI/18;
3140                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis);
3141                ctx.lineWidth = sw/2;
3142                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis);
3143            }
3144
3145            ctx.lineWidth = lw;
3146            ctx.strokeStyle = series.color;
3147            var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight);
3148            if (fillStyle) {
3149                ctx.fillStyle = fillStyle;
3150                plotLineArea(series.datapoints, series.xaxis, series.yaxis);
3151            }
3152
3153            if (lw > 0)
3154                plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis);
3155            ctx.restore();
3156        }
3157
3158        function drawSeriesPoints(series) {
3159            function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) {
3160                var points = datapoints.points, ps = datapoints.pointsize;
3161
3162                for (var i = 0; i < points.length; i += ps) {
3163                    var x = points[i], y = points[i + 1];
3164                    if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
3165                        continue;
3166
3167                    ctx.beginPath();
3168                    x = axisx.p2c(x);
3169                    y = axisy.p2c(y) + offset;
3170                    if (symbol == "circle")
3171                        ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);
3172                    else
3173                        symbol(ctx, x, y, radius, shadow);
3174                    ctx.closePath();
3175
3176                    if (fillStyle) {
3177                        ctx.fillStyle = fillStyle;
3178                        ctx.fill();
3179                    }
3180                    ctx.stroke();
3181                }
3182            }
3183
3184            ctx.save();
3185            ctx.translate(plotOffset.left, plotOffset.top);
3186
3187            var lw = series.points.lineWidth,
3188                sw = series.shadowSize,
3189                radius = series.points.radius,
3190                symbol = series.points.symbol;
3191
3192            // If the user sets the line width to 0, we change it to a very 
3193            // small value. A line width of 0 seems to force the default of 1.
3194            // Doing the conditional here allows the shadow setting to still be 
3195            // optional even with a lineWidth of 0.
3196
3197            if( lw == 0 )
3198                lw = 0.0001;
3199
3200            if (lw > 0 && sw > 0) {
3201                // draw shadow in two steps
3202                var w = sw / 2;
3203                ctx.lineWidth = w;
3204                ctx.strokeStyle = "rgba(0,0,0,0.1)";
3205                plotPoints(series.datapoints, radius, null, w + w/2, true,
3206                           series.xaxis, series.yaxis, symbol);
3207
3208                ctx.strokeStyle = "rgba(0,0,0,0.2)";
3209                plotPoints(series.datapoints, radius, null, w/2, true,
3210                           series.xaxis, series.yaxis, symbol);
3211            }
3212
3213            ctx.lineWidth = lw;
3214            ctx.strokeStyle = series.color;
3215            plotPoints(series.datapoints, radius,
3216                       getFillStyle(series.points, series.color), 0, false,
3217                       series.xaxis, series.yaxis, symbol);
3218            ctx.restore();
3219        }
3220
3221        function drawBar(x, y, b, barLeft, barRight, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) {
3222            var left, right, bottom, top,
3223                drawLeft, drawRight, drawTop, drawBottom,
3224                tmp;
3225
3226            // in horizontal mode, we start the bar from the left
3227            // instead of from the bottom so it appears to be
3228            // horizontal rather than vertical
3229            if (horizontal) {
3230                drawBottom = drawRight = drawTop = true;
3231                drawLeft = false;
3232                left = b;
3233                right = x;
3234                top = y + barLeft;
3235                bottom = y + barRight;
3236
3237                // account for negative bars
3238                if (right < left) {
3239                    tmp = right;
3240                    right = left;
3241                    left = tmp;
3242                    drawLeft = true;
3243                    drawRight = false;
3244                }
3245            }
3246            else {
3247                drawLeft = drawRight = drawTop = true;
3248                drawBottom = false;
3249                left = x + barLeft;
3250                right = x + barRight;
3251                bottom = b;
3252                top = y;
3253
3254                // account for negative bars
3255                if (top < bottom) {
3256                    tmp = top;
3257                    top = bottom;
3258                    bottom = tmp;
3259                    drawBottom = true;
3260                    drawTop = false;
3261                }
3262            }
3263
3264            // clip
3265            if (right < axisx.min || left > axisx.max ||
3266                top < axisy.min || bottom > axisy.max)
3267                return;
3268
3269            if (left < axisx.min) {
3270                left = axisx.min;
3271                drawLeft = false;
3272            }
3273
3274            if (right > axisx.max) {
3275                right = axisx.max;
3276                drawRight = false;
3277            }
3278
3279            if (bottom < axisy.min) {
3280                bottom = axisy.min;
3281                drawBottom = false;
3282            }
3283
3284            if (top > axisy.max) {
3285                top = axisy.max;
3286                drawTop = false;
3287            }
3288
3289            left = axisx.p2c(left);
3290            bottom = axisy.p2c(bottom);
3291            right = axisx.p2c(right);
3292            top = axisy.p2c(top);
3293
3294            // fill the bar
3295            if (fillStyleCallback) {
3296                c.fillStyle = fillStyleCallback(bottom, top);
3297                c.fillRect(left, top, right - left, bottom - top)
3298            }
3299
3300            // draw outline
3301            if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) {
3302                c.beginPath();
3303
3304                // FIXME: inline moveTo is buggy with excanvas
3305                c.moveTo(left, bottom);
3306                if (drawLeft)
3307                    c.lineTo(left, top);
3308                else
3309                    c.moveTo(left, top);
3310                if (drawTop)
3311                    c.lineTo(right, top);
3312                else
3313                    c.moveTo(right, top);
3314                if (drawRight)
3315                    c.lineTo(right, bottom);
3316                else
3317                    c.moveTo(right, bottom);
3318                if (drawBottom)
3319                    c.lineTo(left, bottom);
3320                else
3321                    c.moveTo(left, bottom);
3322                c.stroke();
3323            }
3324        }
3325
3326        function drawSeriesBars(series) {
3327            function plotBars(datapoints, barLeft, barRight, fillStyleCallback, axisx, axisy) {
3328                var points = datapoints.points, ps = datapoints.pointsize;
3329
3330                for (var i = 0; i < points.length; i += ps) {
3331                    if (points[i] == null)
3332                        continue;
3333                    drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);
3334                }
3335            }
3336
3337            ctx.save();
3338            ctx.translate(plotOffset.left, plotOffset.top);
3339
3340            // FIXME: figure out a way to add shadows (for instance along the right edge)
3341            ctx.lineWidth = series.bars.lineWidth;
3342            ctx.strokeStyle = series.color;
3343
3344            var barLeft;
3345
3346            switch (series.bars.align) {
3347                case "left":
3348                    barLeft = 0;
3349                    break;
3350                case "right":
3351                    barLeft = -series.bars.barWidth;
3352                    break;
3353                default:
3354                    barLeft = -series.bars.barWidth / 2;
3355            }
3356
3357            var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;
3358            plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, fillStyleCallback, series.xaxis, series.yaxis);
3359            ctx.restore();
3360        }
3361
3362        function getFillStyle(filloptions, seriesColor, bottom, top) {
3363            var fill = filloptions.fill;
3364            if (!fill)
3365                return null;
3366
3367            if (filloptions.fillColor)
3368                return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
3369
3370            var c = $.color.parse(seriesColor);
3371            c.a = typeof fill == "number" ? fill : 0.4;
3372            c.normalize();
3373            return c.toString();
3374        }
3375
3376        function insertLegend() {
3377
3378            if (options.legend.container != null) {
3379                $(options.legend.container).html("");
3380            } else {
3381                placeholder.find(".legend").remove();
3382            }
3383
3384            if (!options.legend.show) {
3385                return;
3386            }
3387
3388            var fragments = [], entries = [], rowStarted = false,
3389                lf = options.legend.labelFormatter, s, label;
3390
3391            // Build a list of legend entries, with each having a label and a color
3392
3393            for (var i = 0; i < series.length; ++i) {
3394                s = series[i];
3395                if (s.label) {
3396                    label = lf ? lf(s.label, s) : s.label;
3397                    if (label) {
3398                        entries.push({
3399                            label: label,
3400                            color: s.color
3401                        });
3402                    }
3403                }
3404            }
3405
3406            // Sort the legend using either the default or a custom comparator
3407
3408            if (options.legend.sorted) {
3409                if ($.isFunction(options.legend.sorted)) {
3410                    entries.sort(options.legend.sorted);
3411                } else if (options.legend.sorted == "reverse") {
3412                	entries.reverse();
3413                } else {
3414                    var ascending = options.legend.sorted != "descending";
3415                    entries.sort(function(a, b) {
3416                        return a.label == b.label ? 0 : (
3417                            (a.label < b.label) != ascending ? 1 : -1   // Logical XOR
3418                        );
3419                    });
3420                }
3421            }
3422
3423            // Generate markup for the list of entries, in their final order
3424
3425            for (var i = 0; i < entries.length; ++i) {
3426
3427                var entry = entries[i];
3428
3429                if (i % options.legend.noColumns == 0) {
3430                    if (rowStarted)
3431                        fragments.push('</tr>');
3432                    fragments.push('<tr>');
3433                    rowStarted = true;
3434                }
3435
3436                fragments.push(
3437                    '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + entry.color + ';overflow:hidden"></div></div></td>' +
3438                    '<td class="legendLabel">' + entry.label + '</td>'
3439                );
3440            }
3441
3442            if (rowStarted)
3443                fragments.push('</tr>');
3444
3445            if (fragments.length == 0)
3446                return;
3447
3448            var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>';
3449            if (options.legend.container != null)
3450                $(options.legend.container).html(table);
3451            else {
3452                var pos = "",
3453                    p = options.legend.position,
3454                    m = options.legend.margin;
3455                if (m[0] == null)
3456                    m = [m, m];
3457                if (p.charAt(0) == "n")
3458                    pos += 'top:' + (m[1] + plotOffset.top) + 'px;';
3459                else if (p.charAt(0) == "s")
3460                    pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;';
3461                if (p.charAt(1) == "e")
3462                    pos += 'right:' + (m[0] + plotOffset.right) + 'px;';
3463                else if (p.charAt(1) == "w")
3464                    pos += 'left:' + (m[0] + plotOffset.left) + 'px;';
3465                var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(placeholder);
3466                if (options.legend.backgroundOpacity != 0.0) {
3467                    // put in the transparent background
3468                    // separately to avoid blended labels and
3469                    // label boxes
3470                    var c = options.legend.backgroundColor;
3471                    if (c == null) {
3472                        c = options.grid.backgroundColor;
3473                        if (c && typeof c == "string")
3474                            c = $.color.parse(c);
3475                        else
3476                            c = $.color.extract(legend, 'background-color');
3477                        c.a = 1;
3478                        c = c.toString();
3479                    }
3480                    var div = legend.children();
3481                    $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
3482                }
3483            }
3484        }
3485
3486
3487        // interactive features
3488
3489        var highlights = [],
3490            redrawTimeout = null;
3491
3492        // returns the data item the mouse is over, or null if none is found
3493        function findNearbyItem(mouseX, mouseY, seriesFilter) {
3494            var maxDistance = options.grid.mouseActiveRadius,
3495                smallestDistance = maxDistance * maxDistance + 1,
3496                item = null, foundPoint = false, i, j, ps;
3497
3498            for (i = series.length - 1; i >= 0; --i) {
3499                if (!seriesFilter(series[i]))
3500                    continue;
3501
3502                var s = series[i],
3503                    axisx = s.xaxis,
3504                    axisy = s.yaxis,
3505                    points = s.datapoints.points,
3506                    mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster
3507                    my = axisy.c2p(mouseY),
3508                    maxx = maxDistance / axisx.scale,
3509                    maxy = maxDistance / axisy.scale;
3510
3511                ps = s.datapoints.pointsize;
3512                // with inverse transforms, we can't use the maxx/maxy
3513                // optimization, sadly
3514                if (axisx.options.inverseTransform)
3515                    maxx = Number.MAX_VALUE;
3516                if (axisy.options.inverseTransform)
3517                    maxy = Number.MAX_VALUE;
3518
3519                if (s.lines.show || s.points.show) {
3520                    for (j = 0; j < points.length; j += ps) {
3521                        var x = points[j], y = points[j + 1];
3522                        if (x == null)
3523                            continue;
3524
3525                        // For points and lines, the cursor must be within a
3526                        // certain distance to the data point
3527                        if (x - mx > maxx || x - mx < -maxx ||
3528                            y - my > maxy || y - my < -maxy)
3529                            continue;
3530
3531                        // We have to calculate distances in pixels, not in
3532                        // data units, because the scales of the axes may be different
3533                        var dx = Math.abs(axisx.p2c(x) - mouseX),
3534                            dy = Math.abs(axisy.p2c(y) - mouseY),
3535                            dist = dx * dx + dy * dy; // we save the sqrt
3536
3537                        // use <= to ensure last point takes precedence
3538                        // (last generally means on top of)
3539                        if (dist < smallestDistance) {
3540                            smallestDistance = dist;
3541                            item = [i, j / ps];
3542                        }
3543                    }
3544                }
3545
3546                if (s.bars.show && !item) { // no other point can be nearby
3547
3548                    var barLeft, barRight;
3549
3550                    switch (s.bars.align) {
3551                        case "left":
3552                            barLeft = 0;
3553                            break;
3554                        case "right":
3555                            barLeft = -s.bars.barWidth;
3556                            break;
3557                        default:
3558                            barLeft = -s.bars.barWidth / 2;
3559                    }
3560
3561                    barRight = barLeft + s.bars.barWidth;
3562
3563                    for (j = 0; j < points.length; j += ps) {
3564                        var x = points[j], y = points[j + 1], b = points[j + 2];
3565                        if (x == null)
3566                            continue;
3567
3568                        // for a bar graph, the cursor must be inside the bar
3569                        if (series[i].bars.horizontal ?
3570                            (mx <= Math.max(b, x) && mx >= Math.min(b, x) &&
3571                             my >= y + barLeft && my <= y + barRight) :
3572                            (mx >= x + barLeft && mx <= x + barRight &&
3573                             my >= Math.min(b, y) && my <= Math.max(b, y)))
3574                                item = [i, j / ps];
3575                    }
3576                }
3577            }
3578
3579            if (item) {
3580                i = item[0];
3581                j = item[1];
3582                ps = series[i].datapoints.pointsize;
3583
3584                return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
3585                         dataIndex: j,
3586                         series: series[i],
3587                         seriesIndex: i };
3588            }
3589
3590            return null;
3591        }
3592
3593        function onMouseMove(e) {
3594            if (options.grid.hoverable)
3595                triggerClickHoverEvent("plothover", e,
3596                                       function (s) { return s["hoverable"] != false; });
3597        }
3598
3599        function onMouseLeave(e) {
3600            if (options.grid.hoverable)
3601                triggerClickHoverEvent("plothover", e,
3602                                       function (s) { return false; });
3603        }
3604
3605        function onClick(e) {
3606            triggerClickHoverEvent("plotclick", e,
3607                                   function (s) { return s["clickable"] != false; });
3608        }
3609
3610        // trigger click or hover event (they send the same parameters
3611        // so we share their code)
3612        function triggerClickHoverEvent(eventname, event, seriesFilter) {
3613            var offset = eventHolder.offset(),
3614                canvasX = event.pageX - offset.left - plotOffset.left,
3615                canvasY = event.pageY - offset.top - plotOffset.top,
3616            pos = canvasToAxisCoords({ left: canvasX, top: canvasY });
3617
3618            pos.pageX = event.pageX;
3619            pos.pageY = event.pageY;
3620
3621            var item = findNearbyItem(canvasX, canvasY, seriesFilter);
3622
3623            if (item) {
3624                // fill in mouse pos for any listeners out there
3625                item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left, 10);
3626                item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top, 10);
3627            }
3628
3629            if (options.grid.autoHighlight) {
3630                // clear auto-highlights
3631                for (var i = 0; i < highlights.length; ++i) {
3632                    var h = highlights[i];
3633                    if (h.auto == eventname &&
3634                        !(item && h.series == item.series &&
3635                          h.point[0] == item.datapoint[0] &&
3636                          h.point[1] == item.datapoint[1]))
3637                        unhighlight(h.series, h.point);
3638                }
3639
3640                if (item)
3641                    highlight(item.series, item.datapoint, eventname);
3642            }
3643
3644            placeholder.trigger(eventname, [ pos, item ]);
3645        }
3646
3647        function triggerRedrawOverlay() {
3648            var t = options.interaction.redrawOverlayInterval;
3649            if (t == -1) {      // skip event queue
3650                drawOverlay();
3651                return;
3652            }
3653
3654            if (!redrawTimeout)
3655                redrawTimeout = setTimeout(drawOverlay, t);
3656        }
3657
3658        function drawOverlay() {
3659            redrawTimeout = null;
3660
3661            // draw highlights
3662            octx.save();
3663            overlay.clear();
3664            octx.translate(plotOffset.left, plotOffset.top);
3665
3666            var i, hi;
3667            for (i = 0; i < highlights.length; ++i) {
3668                hi = highlights[i];
3669
3670                if (hi.series.bars.show)
3671                    drawBarHighlight(hi.series, hi.point);
3672                else
3673                    drawPointHighlight(hi.series, hi.point);
3674            }
3675            octx.restore();
3676
3677            executeHooks(hooks.drawOverlay, [octx]);
3678        }
3679
3680        function highlight(s, point, auto) {
3681            if (typeof s == "number")
3682                s = series[s];
3683
3684            if (typeof point == "number") {
3685                var ps = s.datapoints.pointsize;
3686                point = s.datapoints.points.slice(ps * point, ps * (point + 1));
3687            }
3688
3689            var i = indexOfHighlight(s, point);
3690            if (i == -1) {
3691                highlights.push({ series: s, point: point, auto: auto });
3692
3693                triggerRedrawOverlay();
3694            }
3695            else if (!auto)
3696                highlights[i].auto = false;
3697        }
3698
3699        function unhighlight(s, point) {
3700            if (s == null && point == null) {
3701                highlights = [];
3702                triggerRedrawOverlay();
3703                return;
3704            }
3705
3706            if (typeof s == "number")
3707                s = series[s];
3708
3709            if (typeof point == "number") {
3710                var ps = s.datapoints.pointsize;
3711                point = s.datapoints.points.slice(ps * point, ps * (point + 1));
3712            }
3713
3714            var i = indexOfHighlight(s, point);
3715            if (i != -1) {
3716                highlights.splice(i, 1);
3717
3718                triggerRedrawOverlay();
3719            }
3720        }
3721
3722        function indexOfHighlight(s, p) {
3723            for (var i = 0; i < highlights.length; ++i) {
3724                var h = highlights[i];
3725                if (h.series == s && h.point[0] == p[0]
3726                    && h.point[1] == p[1])
3727                    return i;
3728            }
3729            return -1;
3730        }
3731
3732        function drawPointHighlight(series, point) {
3733            var x = point[0], y = point[1],
3734                axisx = series.xaxis, axisy = series.yaxis,
3735                highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString();
3736
3737            if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
3738                return;
3739
3740            var pointRadius = series.points.radius + series.points.lineWidth / 2;
3741            octx.lineWidth = pointRadius;
3742            octx.strokeStyle = highlightColor;
3743            var radius = 1.5 * pointRadius;
3744            x = axisx.p2c(x);
3745            y = axisy.p2c(y);
3746
3747            octx.beginPath();
3748            if (series.points.symbol == "circle")
3749                octx.arc(x, y, radius, 0, 2 * Math.PI, false);
3750            else
3751                series.points.symbol(octx, x, y, radius, false);
3752            octx.closePath();
3753            octx.stroke();
3754        }
3755
3756        function drawBarHighlight(series, point) {
3757            var highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString(),
3758                fillStyle = highlightColor,
3759                barLeft;
3760
3761            switch (series.bars.align) {
3762                case "left":
3763                    barLeft = 0;
3764                    break;
3765                case "right":
3766                    barLeft = -series.bars.barWidth;
3767                    break;
3768                default:
3769                    barLeft = -series.bars.barWidth / 2;
3770            }
3771
3772            octx.lineWidth = series.bars.lineWidth;
3773            octx.strokeStyle = highlightColor;
3774
3775            drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,
3776                    function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth);
3777        }
3778
3779        function getColorOrGradient(spec, bottom, top, defaultColor) {
3780            if (typeof spec == "string")
3781                return spec;
3782            else {
3783                // assume this is a gradient spec; IE currently only
3784                // supports a simple vertical gradient properly, so that's
3785                // what we support too
3786                var gradient = ctx.createLinearGradient(0, top, 0, bottom);
3787
3788                for (var i = 0, l = spec.colors.length; i < l; ++i) {
3789                    var c = spec.colors[i];
3790                    if (typeof c != "string") {
3791                        var co = $.color.parse(defaultColor);
3792                        if (c.brightness != null)
3793                            co = co.scale('rgb', c.brightness);
3794                        if (c.opacity != null)
3795                            co.a *= c.opacity;
3796                        c = co.toString();
3797                    }
3798                    gradient.addColorStop(i / (l - 1), c);
3799                }
3800
3801                return gradient;
3802            }
3803        }
3804    }
3805
3806    // Add the plot function to the top level of the jQuery object
3807
3808    $.plot = function(placeholder, data, options) {
3809        //var t0 = new Date();
3810        var plot = new Plot($(placeholder), data, options, $.plot.plugins);
3811        //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime()));
3812        return plot;
3813    };
3814
3815    $.plot.version = "0.8.3";
3816
3817    $.plot.plugins = [];
3818
3819    // Also add the plot function as a chainable property
3820
3821    $.fn.plot = function(data, options) {
3822        return this.each(function() {
3823            $.plot(this, data, options);
3824        });
3825    };
3826
3827    // round to nearby lower multiple of base
3828    function floorInBase(n, base) {
3829        return base * Math.floor(n / base);
3830    }
3831
3832})(jQuery);
3833
3834/* Flot plugin for plotting textual data or categories.
3835
3836Copyright (c) 2007-2014 IOLA and Ole Laursen.
3837Licensed under the MIT license.
3838
3839Consider a dataset like [["February", 34], ["March", 20], ...]. This plugin
3840allows you to plot such a dataset directly.
3841
3842To enable it, you must specify mode: "categories" on the axis with the textual
3843labels, e.g.
3844
3845	$.plot("#placeholder", data, { xaxis: { mode: "categories" } });
3846
3847By default, the labels are ordered as they are met in the data series. If you
3848need a different ordering, you can specify "categories" on the axis options
3849and list the categories there:
3850
3851	xaxis: {
3852		mode: "categories",
3853		categories: ["February", "March", "April"]
3854	}
3855
3856If you need to customize the distances between the categories, you can specify
3857"categories" as an object mapping labels to values
3858
3859	xaxis: {
3860		mode: "categories",
3861		categories: { "February": 1, "March": 3, "April": 4 }
3862	}
3863
3864If you don't specify all categories, the remaining categories will be numbered
3865from the max value plus 1 (with a spacing of 1 between each).
3866
3867Internally, the plugin works by transforming the input data through an auto-
3868generated mapping where the first category becomes 0, the second 1, etc.
3869Hence, a point like ["February", 34] becomes [0, 34] internally in Flot (this
3870is visible in hover and click events that return numbers rather than the
3871category labels). The plugin also overrides the tick generator to spit out the
3872categories as ticks instead of the values.
3873
3874If you need to map a value back to its label, the mapping is always accessible
3875as "categories" on the axis object, e.g. plot.getAxes().xaxis.categories.
3876
3877*/
3878
3879(function ($) {
3880    var options = {
3881        xaxis: {
3882            categories: null
3883        },
3884        yaxis: {
3885            categories: null
3886        }
3887    };
3888    
3889    function processRawData(plot, series, data, datapoints) {
3890        // if categories are enabled, we need to disable
3891        // auto-transformation to numbers so the strings are intact
3892        // for later processing
3893
3894        var xCategories = series.xaxis.options.mode == "categories",
3895            yCategories = series.yaxis.options.mode == "categories";
3896        
3897        if (!(xCategories || yCategories))
3898            return;
3899
3900        var format = datapoints.format;
3901
3902        if (!format) {
3903            // FIXME: auto-detection should really not be defined here
3904            var s = series;
3905            format = [];
3906            format.push({ x: true, number: true, required: true });
3907            format.push({ y: true, number: true, required: true });
3908
3909            if (s.bars.show || (s.lines.show && s.lines.fill)) {
3910                var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero));
3911                format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale });
3912                if (s.bars.horizontal) {
3913                    delete format[format.length - 1].y;
3914                    format[format.length - 1].x = true;
3915                }
3916            }
3917            
3918            datapoints.format = format;
3919        }
3920
3921        for (var m = 0; m < format.length; ++m) {
3922            if (format[m].x && xCategories)
3923                format[m].number = false;
3924            
3925            if (format[m].y && yCategories)
3926                format[m].number = false;
3927        }
3928    }
3929
3930    function getNextIndex(categories) {
3931        var index = -1;
3932        
3933        for (var v in categories)
3934            if (categories[v] > index)
3935                index = categories[v];
3936
3937        return index + 1;
3938    }
3939
3940    function categoriesTickGenerator(axis) {
3941        var res = [];
3942        for (var label in axis.categories) {
3943            var v = axis.categories[label];
3944            if (v >= axis.min && v <= axis.max)
3945                res.push([v, label]);
3946        }
3947
3948        res.sort(function (a, b) { return a[0] - b[0]; });
3949
3950        return res;
3951    }
3952    
3953    function setupCategoriesForAxis(series, axis, datapoints) {
3954        if (series[axis].options.mode != "categories")
3955            return;
3956        
3957        if (!series[axis].categories) {
3958            // parse options
3959            var c = {}, o = series[axis].options.categories || {};
3960            if ($.isArray(o)) {
3961                for (var i = 0; i < o.length; ++i)
3962                    c[o[i]] = i;
3963            }
3964            else {
3965                for (var v in o)
3966                    c[v] = o[v];
3967            }
3968            
3969            series[axis].categories = c;
3970        }
3971
3972        // fix ticks
3973        if (!series[axis].options.ticks)
3974            series[axis].options.ticks = categoriesTickGenerator;
3975
3976        transformPointsOnAxis(datapoints, axis, series[axis].categories);
3977    }
3978    
3979    function transformPointsOnAxis(datapoints, axis, categories) {
3980        // go through the points, transforming them
3981        var points = datapoints.points,
3982            ps = datapoints.pointsize,
3983            format = datapoints.format,
3984            formatColumn = axis.charAt(0),
3985            index = getNextIndex(categories);
3986
3987        for (var i = 0; i < points.length; i += ps) {
3988            if (points[i] == null)
3989                continue;
3990            
3991            for (var m = 0; m < ps; ++m) {
3992                var val = points[i + m];
3993
3994                if (val == null || !format[m][formatColumn])
3995                    continue;
3996
3997                if (!(val in categories)) {
3998                    categories[val] = index;
3999                    ++index;
4000                }
4001                
4002                points[i + m] = categories[val];
4003            }
4004        }
4005    }
4006
4007    function processDatapoints(plot, series, datapoints) {
4008        setupCategoriesForAxis(series, "xaxis", datapoints);
4009        setupCategoriesForAxis(series, "yaxis", datapoints);
4010    }
4011
4012    function init(plot) {
4013        plot.hooks.processRawData.push(processRawData);
4014        plot.hooks.processDatapoints.push(processDatapoints);
4015    }
4016    
4017    $.plot.plugins.push({
4018        init: init,
4019        options: options,
4020        name: 'categories',
4021        version: '1.0'
4022    });
vendor: 7,382 bytes, lines 4023-4269
4023})(jQuery);
4024
4025/* Flot plugin for rendering pie charts.
4026
4027Copyright (c) 2007-2014 IOLA and Ole Laursen.
4028Licensed under the MIT license.
4029
4030The plugin assumes that each series has a single data value, and that each
4031value is a positive integer or zero.  Negative numbers don't make sense for a
4032pie chart, and have unpredictable results.  The values do NOT need to be
4033passed in as percentages; the plugin will calculate the total and per-slice
4034percentages internally.
4035
4036* Created by Brian Medendorp
4037
4038* Updated with contributions from btburnett3, Anthony Aragues and Xavi Ivars
4039
4040The plugin supports these options:
4041
4042	series: {
4043		pie: {
4044			show: true/false
4045			radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto'
4046			innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect
4047			startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result
4048			tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show)
4049			offset: {
4050				top: integer value to move the pie up or down
4051				left: integer value to move the pie left or right, or 'auto'
4052			},
4053			stroke: {
4054				color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF')
4055				width: integer pixel width of the stroke
4056			},
4057			label: {
4058				show: true/false, or 'auto'
4059				formatter:  a user-defined function that modifies the text/style of the label text
4060				radius: 0-1 for percentage of fullsize, or a specified pixel length
4061				background: {
4062					color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000')
4063					opacity: 0-1
4064				},
4065				threshold: 0-1 for the percentage value at which to hide labels (if they're too small)
4066			},
4067			combine: {
4068				threshold: 0-1 for the percentage value at which to combine slices (if they're too small)
4069				color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined
4070				label: any text value of what the combined slice should be labeled
4071			}
4072			highlight: {
4073				opacity: 0-1
4074			}
4075		}
4076	}
4077
4078More detail and specific examples can be found in the included HTML file.
4079
4080*/
4081
4082(function($) {
4083
4084	// Maximum redraw attempts when fitting labels within the plot
4085
4086	var REDRAW_ATTEMPTS = 10;
4087
4088	// Factor by which to shrink the pie when fitting labels within the plot
4089
4090	var REDRAW_SHRINK = 0.95;
4091
4092	function init(plot) {
4093
4094		var canvas = null,
4095			target = null,
4096			options = null,
4097			maxRadius = null,
4098			centerLeft = null,
4099			centerTop = null,
4100			processed = false,
4101			ctx = null;
4102
4103		// interactive variables
4104
4105		var highlights = [];
4106
4107		// add hook to determine if pie plugin in enabled, and then perform necessary operations
4108
4109		plot.hooks.processOptions.push(function(plot, options) {
4110			if (options.series.pie.show) {
4111
4112				options.grid.show = false;
4113
4114				// set labels.show
4115
4116				if (options.series.pie.label.show == "auto") {
4117					if (options.legend.show) {
4118						options.series.pie.label.show = false;
4119					} else {
4120						options.series.pie.label.show = true;
4121					}
4122				}
4123
4124				// set radius
4125
4126				if (options.series.pie.radius == "auto") {
4127					if (options.series.pie.label.show) {
4128						options.series.pie.radius = 3/4;
4129					} else {
4130						options.series.pie.radius = 1;
4131					}
4132				}
4133
4134				// ensure sane tilt
4135
4136				if (options.series.pie.tilt > 1) {
4137					options.series.pie.tilt = 1;
4138				} else if (options.series.pie.tilt < 0) {
4139					options.series.pie.tilt = 0;
4140				}
4141			}
4142		});
4143
4144		plot.hooks.bindEvents.push(function(plot, eventHolder) {
4145			var options = plot.getOptions();
4146			if (options.series.pie.show) {
4147				if (options.grid.hoverable) {
4148					eventHolder.unbind("mousemove").mousemove(onMouseMove);
4149				}
4150				if (options.grid.clickable) {
4151					eventHolder.unbind("click").click(onClick);
4152				}
4153			}
4154		});
4155
4156		plot.hooks.processDatapoints.push(function(plot, series, data, datapoints) {
4157			var options = plot.getOptions();
4158			if (options.series.pie.show) {
4159				processDatapoints(plot, series, data, datapoints);
4160			}
4161		});
4162
4163		plot.hooks.drawOverlay.push(function(plot, octx) {
4164			var options = plot.getOptions();
4165			if (options.series.pie.show) {
4166				drawOverlay(plot, octx);
4167			}
4168		});
4169
4170		plot.hooks.draw.push(function(plot, newCtx) {
4171			var options = plot.getOptions();
4172			if (options.series.pie.show) {
4173				draw(plot, newCtx);
4174			}
4175		});
4176
4177		function processDatapoints(plot, series, datapoints) {
4178			if (!processed)	{
4179				processed = true;
4180				canvas = plot.getCanvas();
4181				target = $(canvas).parent();
4182				options = plot.getOptions();
4183				plot.setData(combine(plot.getData()));
4184			}
4185		}
4186
4187		function combine(data) {
4188
4189			var total = 0,
4190				combined = 0,
4191				numCombined = 0,
4192				color = options.series.pie.combine.color,
4193				newdata = [];
4194
4195			// Fix up the raw data from Flot, ensuring the data is numeric
4196
4197			for (var i = 0; i < data.length; ++i) {
4198
4199				var value = data[i].data;
4200
4201				// If the data is an array, we'll assume that it's a standard
4202				// Flot x-y pair, and are concerned only with the second value.
4203
4204				// Note how we use the original array, rather than creating a
4205				// new one; this is more efficient and preserves any extra data
4206				// that the user may have stored in higher indexes.
4207
4208				if ($.isArray(value) && value.length == 1) {
4209    				value = value[0];
4210				}
4211
4212				if ($.isArray(value)) {
4213					// Equivalent to $.isNumeric() but compatible with jQuery < 1.7
4214					if (!isNaN(parseFloat(value[1])) && isFinite(value[1])) {
4215						value[1] = +value[1];
4216					} else {
4217						value[1] = 0;
4218					}
4219				} else if (!isNaN(parseFloat(value)) && isFinite(value)) {
4220					value = [1, +value];
4221				} else {
4222					value = [1, 0];
4223				}
4224
4225				data[i].data = [value];
4226			}
4227
4228			// Sum up all the slices, so we can calculate percentages for each
4229
4230			for (var i = 0; i < data.length; ++i) {
4231				total += data[i].data[0][1];
4232			}
4233
4234			// Count the number of slices with percentages below the combine
4235			// threshold; if it turns out to be just one, we won't combine.
4236
4237			for (var i = 0; i < data.length; ++i) {
4238				var value = data[i].data[0][1];
4239				if (value / total <= options.series.pie.combine.threshold) {
4240					combined += value;
4241					numCombined++;
4242					if (!color) {
4243						color = data[i].color;
4244					}
4245				}
4246			}
4247
4248			for (var i = 0; i < data.length; ++i) {
4249				var value = data[i].data[0][1];
4250				if (numCombined < 2 || value / total > options.series.pie.combine.threshold) {
4251					newdata.push(
4252						$.extend(data[i], {     /* extend to allow keeping all other original data values
4253						                           and using them e.g. in labelFormatter. */
4254							data: [[1, value]],
4255							color: data[i].color,
4256							label: data[i].label,
4257							angle: value * Math.PI * 2 / total,
4258							percent: value / (total / 100)
4259						})
4260					);
4261				}
4262			}
4263
4264			if (numCombined > 1) {
4265				newdata.push({
4266					data: [[1, combined]],
4267					color: color,
4268					label: options.series.pie.combine.label,
4269					angle: combined * Math.PI * 2 / total,
4270					percent: combined / (total / 100)
4271				});
4272			}
4273
4274			return newdata;
4275		}
4276
4277		function draw(plot, newCtx) {
4278
4279			if (!target) {
4280				return; // if no series were passed
4281			}
4282
4283			var canvasWidth = plot.getPlaceholder().width(),
4284				canvasHeight = plot.getPlaceholder().height(),
4285				legendWidth = target.children().filter(".legend").children().width() || 0;
4286
4287			ctx = newCtx;
4288
4289			// WARNING: HACK! REWRITE THIS CODE AS SOON AS POSSIBLE!
4290
4291			// When combining smaller slices into an 'other' slice, we need to
4292			// add a new series.  Since Flot gives plugins no way to modify the
4293			// list of series, the pie plugin uses a hack where the first call
4294			// to processDatapoints results in a call to setData with the new
4295			// list of series, then subsequent processDatapoints do nothing.
4296
4297			// The plugin-global 'processed' flag is used to control this hack;
4298			// it starts out false, and is set to true after the first call to
4299			// processDatapoints.
4300
4301			// Unfortunately this turns future setData calls into no-ops; they
4302			// call processDatapoints, the flag is true, and nothing happens.
4303
vendor: 14,920 bytes, lines 4304-4801
4304			// To fix this we'll set the flag back to false here in draw, when
4305			// all series have been processed, so the next sequence of calls to
4306			// processDatapoints once again starts out with a slice-combine.
4307			// This is really a hack; in 0.9 we need to give plugins a proper
4308			// way to modify series before any processing begins.
4309
4310			processed = false;
4311
4312			// calculate maximum radius and center point
4313
4314			maxRadius =  Math.min(canvasWidth, canvasHeight / options.series.pie.tilt) / 2;
4315			centerTop = canvasHeight / 2 + options.series.pie.offset.top;
4316			centerLeft = canvasWidth / 2;
4317
4318			if (options.series.pie.offset.left == "auto") {
4319				if (options.legend.position.match("w")) {
4320					centerLeft += legendWidth / 2;
4321				} else {
4322					centerLeft -= legendWidth / 2;
4323				}
4324				if (centerLeft < maxRadius) {
4325					centerLeft = maxRadius;
4326				} else if (centerLeft > canvasWidth - maxRadius) {
4327					centerLeft = canvasWidth - maxRadius;
4328				}
4329			} else {
4330				centerLeft += options.series.pie.offset.left;
4331			}
4332
4333			var slices = plot.getData(),
4334				attempts = 0;
4335
4336			// Keep shrinking the pie's radius until drawPie returns true,
4337			// indicating that all the labels fit, or we try too many times.
4338
4339			do {
4340				if (attempts > 0) {
4341					maxRadius *= REDRAW_SHRINK;
4342				}
4343				attempts += 1;
4344				clear();
4345				if (options.series.pie.tilt <= 0.8) {
4346					drawShadow();
4347				}
4348			} while (!drawPie() && attempts < REDRAW_ATTEMPTS)
4349
4350			if (attempts >= REDRAW_ATTEMPTS) {
4351				clear();
4352				target.prepend("<div class='error'>Could not draw pie with labels contained inside canvas</div>");
4353			}
4354
4355			if (plot.setSeries && plot.insertLegend) {
4356				plot.setSeries(slices);
4357				plot.insertLegend();
4358			}
4359
4360			// we're actually done at this point, just defining internal functions at this point
4361
4362			function clear() {
4363				ctx.clearRect(0, 0, canvasWidth, canvasHeight);
4364				target.children().filter(".pieLabel, .pieLabelBackground").remove();
4365			}
4366
4367			function drawShadow() {
4368
4369				var shadowLeft = options.series.pie.shadow.left;
4370				var shadowTop = options.series.pie.shadow.top;
4371				var edge = 10;
4372				var alpha = options.series.pie.shadow.alpha;
4373				var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
4374
4375				if (radius >= canvasWidth / 2 - shadowLeft || radius * options.series.pie.tilt >= canvasHeight / 2 - shadowTop || radius <= edge) {
4376					return;	// shadow would be outside canvas, so don't draw it
4377				}
4378
4379				ctx.save();
4380				ctx.translate(shadowLeft,shadowTop);
4381				ctx.globalAlpha = alpha;
4382				ctx.fillStyle = "#000";
4383
4384				// center and rotate to starting position
4385
4386				ctx.translate(centerLeft,centerTop);
4387				ctx.scale(1, options.series.pie.tilt);
4388
4389				//radius -= edge;
4390
4391				for (var i = 1; i <= edge; i++) {
4392					ctx.beginPath();
4393					ctx.arc(0, 0, radius, 0, Math.PI * 2, false);
4394					ctx.fill();
4395					radius -= i;
4396				}
4397
4398				ctx.restore();
4399			}
4400
4401			function drawPie() {
4402
4403				var startAngle = Math.PI * options.series.pie.startAngle;
4404				var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
4405
4406				// center and rotate to starting position
4407
4408				ctx.save();
4409				ctx.translate(centerLeft,centerTop);
4410				ctx.scale(1, options.series.pie.tilt);
4411				//ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera
4412
4413				// draw slices
4414
4415				ctx.save();
4416				var currentAngle = startAngle;
4417				for (var i = 0; i < slices.length; ++i) {
4418					slices[i].startAngle = currentAngle;
4419					drawSlice(slices[i].angle, slices[i].color, true);
4420				}
4421				ctx.restore();
4422
4423				// draw slice outlines
4424
4425				if (options.series.pie.stroke.width > 0) {
4426					ctx.save();
4427					ctx.lineWidth = options.series.pie.stroke.width;
4428					currentAngle = startAngle;
4429					for (var i = 0; i < slices.length; ++i) {
4430						drawSlice(slices[i].angle, options.series.pie.stroke.color, false);
4431					}
4432					ctx.restore();
4433				}
4434
4435				// draw donut hole
4436
4437				drawDonutHole(ctx);
4438
4439				ctx.restore();
4440
4441				// Draw the labels, returning true if they fit within the plot
4442
4443				if (options.series.pie.label.show) {
4444					return drawLabels();
4445				} else return true;
4446
4447				function drawSlice(angle, color, fill) {
4448
4449					if (angle <= 0 || isNaN(angle)) {
4450						return;
4451					}
4452
4453					if (fill) {
4454						ctx.fillStyle = color;
4455					} else {
4456						ctx.strokeStyle = color;
4457						ctx.lineJoin = "round";
4458					}
4459
4460					ctx.beginPath();
4461					if (Math.abs(angle - Math.PI * 2) > 0.000000001) {
4462						ctx.moveTo(0, 0); // Center of the pie
4463					}
4464
4465					//ctx.arc(0, 0, radius, 0, angle, false); // This doesn't work properly in Opera
4466					ctx.arc(0, 0, radius,currentAngle, currentAngle + angle / 2, false);
4467					ctx.arc(0, 0, radius,currentAngle + angle / 2, currentAngle + angle, false);
4468					ctx.closePath();
4469					//ctx.rotate(angle); // This doesn't work properly in Opera
4470					currentAngle += angle;
4471
4472					if (fill) {
4473						ctx.fill();
4474					} else {
4475						ctx.stroke();
4476					}
4477				}
4478
4479				function drawLabels() {
4480
4481					var currentAngle = startAngle;
4482					var radius = options.series.pie.label.radius > 1 ? options.series.pie.label.radius : maxRadius * options.series.pie.label.radius;
4483
4484					for (var i = 0; i < slices.length; ++i) {
4485						if (slices[i].percent >= options.series.pie.label.threshold * 100) {
4486							if (!drawLabel(slices[i], currentAngle, i)) {
4487								return false;
4488							}
4489						}
4490						currentAngle += slices[i].angle;
4491					}
4492
4493					return true;
4494
4495					function drawLabel(slice, startAngle, index) {
4496
4497						if (slice.data[0][1] == 0) {
4498							return true;
4499						}
4500
4501						// format label text
4502
4503						var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter;
4504
4505						if (lf) {
4506							text = lf(slice.label, slice);
4507						} else {
4508							text = slice.label;
4509						}
4510
4511						if (plf) {
4512							text = plf(text, slice);
4513						}
4514
4515						var halfAngle = ((startAngle + slice.angle) + startAngle) / 2;
4516						var x = centerLeft + Math.round(Math.cos(halfAngle) * radius);
4517						var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt;
4518
4519						var html = "<span class='pieLabel' id='pieLabel" + index + "' style='position:absolute;top:" + y + "px;left:" + x + "px;'>" + text + "</span>";
4520						target.append(html);
4521
4522						var label = target.children("#pieLabel" + index);
4523						var labelTop = (y - label.height() / 2);
4524						var labelLeft = (x - label.width() / 2);
4525
4526						label.css("top", labelTop);
4527						label.css("left", labelLeft);
4528
4529						// check to make sure that the label is not outside the canvas
4530
4531						if (0 - labelTop > 0 || 0 - labelLeft > 0 || canvasHeight - (labelTop + label.height()) < 0 || canvasWidth - (labelLeft + label.width()) < 0) {
4532							return false;
4533						}
4534
4535						if (options.series.pie.label.background.opacity != 0) {
4536
4537							// put in the transparent background separately to avoid blended labels and label boxes
4538
4539							var c = options.series.pie.label.background.color;
4540
4541							if (c == null) {
4542								c = slice.color;
4543							}
4544
4545							var pos = "top:" + labelTop + "px;left:" + labelLeft + "px;";
4546							$("<div class='pieLabelBackground' style='position:absolute;width:" + label.width() + "px;height:" + label.height() + "px;" + pos + "background-color:" + c + ";'></div>")
4547								.css("opacity", options.series.pie.label.background.opacity)
4548								.insertBefore(label);
4549						}
4550
4551						return true;
4552					} // end individual label function
4553				} // end drawLabels function
4554			} // end drawPie function
4555		} // end draw function
4556
4557		// Placed here because it needs to be accessed from multiple locations
4558
4559		function drawDonutHole(layer) {
4560			if (options.series.pie.innerRadius > 0) {
4561
4562				// subtract the center
4563
4564				layer.save();
4565				var innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius;
4566				layer.globalCompositeOperation = "destination-out"; // this does not work with excanvas, but it will fall back to using the stroke color
4567				layer.beginPath();
4568				layer.fillStyle = options.series.pie.stroke.color;
4569				layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false);
4570				layer.fill();
4571				layer.closePath();
4572				layer.restore();
4573
4574				// add inner stroke
4575
4576				layer.save();
4577				layer.beginPath();
4578				layer.strokeStyle = options.series.pie.stroke.color;
4579				layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false);
4580				layer.stroke();
4581				layer.closePath();
4582				layer.restore();
4583
4584				// TODO: add extra shadow inside hole (with a mask) if the pie is tilted.
4585			}
4586		}
4587
4588		//-- Additional Interactive related functions --
4589
4590		function isPointInPoly(poly, pt) {
4591			for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
4592				((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1]))
4593				&& (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
4594				&& (c = !c);
4595			return c;
4596		}
4597
4598		function findNearbySlice(mouseX, mouseY) {
4599
4600			var slices = plot.getData(),
4601				options = plot.getOptions(),
4602				radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius,
4603				x, y;
4604
4605			for (var i = 0; i < slices.length; ++i) {
4606
4607				var s = slices[i];
4608
4609				if (s.pie.show) {
4610
4611					ctx.save();
4612					ctx.beginPath();
4613					ctx.moveTo(0, 0); // Center of the pie
4614					//ctx.scale(1, options.series.pie.tilt);	// this actually seems to break everything when here.
4615					ctx.arc(0, 0, radius, s.startAngle, s.startAngle + s.angle / 2, false);
4616					ctx.arc(0, 0, radius, s.startAngle + s.angle / 2, s.startAngle + s.angle, false);
4617					ctx.closePath();
4618					x = mouseX - centerLeft;
4619					y = mouseY - centerTop;
4620
4621					if (ctx.isPointInPath) {
4622						if (ctx.isPointInPath(mouseX - centerLeft, mouseY - centerTop)) {
4623							ctx.restore();
4624							return {
4625								datapoint: [s.percent, s.data],
4626								dataIndex: 0,
4627								series: s,
4628								seriesIndex: i
4629							};
4630						}
4631					} else {
4632
4633						// excanvas for IE doesn;t support isPointInPath, this is a workaround.
4634
4635						var p1X = radius * Math.cos(s.startAngle),
4636							p1Y = radius * Math.sin(s.startAngle),
4637							p2X = radius * Math.cos(s.startAngle + s.angle / 4),
4638							p2Y = radius * Math.sin(s.startAngle + s.angle / 4),
4639							p3X = radius * Math.cos(s.startAngle + s.angle / 2),
4640							p3Y = radius * Math.sin(s.startAngle + s.angle / 2),
4641							p4X = radius * Math.cos(s.startAngle + s.angle / 1.5),
4642							p4Y = radius * Math.sin(s.startAngle + s.angle / 1.5),
4643							p5X = radius * Math.cos(s.startAngle + s.angle),
4644							p5Y = radius * Math.sin(s.startAngle + s.angle),
4645							arrPoly = [[0, 0], [p1X, p1Y], [p2X, p2Y], [p3X, p3Y], [p4X, p4Y], [p5X, p5Y]],
4646							arrPoint = [x, y];
4647
4648						// TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt?
4649
4650						if (isPointInPoly(arrPoly, arrPoint)) {
4651							ctx.restore();
4652							return {
4653								datapoint: [s.percent, s.data],
4654								dataIndex: 0,
4655								series: s,
4656								seriesIndex: i
4657							};
4658						}
4659					}
4660
4661					ctx.restore();
4662				}
4663			}
4664
4665			return null;
4666		}
4667
4668		function onMouseMove(e) {
4669			triggerClickHoverEvent("plothover", e);
4670		}
4671
4672		function onClick(e) {
4673			triggerClickHoverEvent("plotclick", e);
4674		}
4675
4676		// trigger click or hover event (they send the same parameters so we share their code)
4677
4678		function triggerClickHoverEvent(eventname, e) {
4679
4680			var offset = plot.offset();
4681			var canvasX = parseInt(e.pageX - offset.left);
4682			var canvasY =  parseInt(e.pageY - offset.top);
4683			var item = findNearbySlice(canvasX, canvasY);
4684
4685			if (options.grid.autoHighlight) {
4686
4687				// clear auto-highlights
4688
4689				for (var i = 0; i < highlights.length; ++i) {
4690					var h = highlights[i];
4691					if (h.auto == eventname && !(item && h.series == item.series)) {
4692						unhighlight(h.series);
4693					}
4694				}
4695			}
4696
4697			// highlight the slice
4698
4699			if (item) {
4700				highlight(item.series, eventname);
4701			}
4702
4703			// trigger any hover bind events
4704
4705			var pos = { pageX: e.pageX, pageY: e.pageY };
4706			target.trigger(eventname, [pos, item]);
4707		}
4708
4709		function highlight(s, auto) {
4710			//if (typeof s == "number") {
4711			//	s = series[s];
4712			//}
4713
4714			var i = indexOfHighlight(s);
4715
4716			if (i == -1) {
4717				highlights.push({ series: s, auto: auto });
4718				plot.triggerRedrawOverlay();
4719			} else if (!auto) {
4720				highlights[i].auto = false;
4721			}
4722		}
4723
4724		function unhighlight(s) {
4725			if (s == null) {
4726				highlights = [];
4727				plot.triggerRedrawOverlay();
4728			}
4729
4730			//if (typeof s == "number") {
4731			//	s = series[s];
4732			//}
4733
4734			var i = indexOfHighlight(s);
4735
4736			if (i != -1) {
4737				highlights.splice(i, 1);
4738				plot.triggerRedrawOverlay();
4739			}
4740		}
4741
4742		function indexOfHighlight(s) {
4743			for (var i = 0; i < highlights.length; ++i) {
4744				var h = highlights[i];
4745				if (h.series == s)
4746					return i;
4747			}
4748			return -1;
4749		}
4750
4751		function drawOverlay(plot, octx) {
4752
4753			var options = plot.getOptions();
4754
4755			var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
4756
4757			octx.save();
4758			octx.translate(centerLeft, centerTop);
4759			octx.scale(1, options.series.pie.tilt);
4760
4761			for (var i = 0; i < highlights.length; ++i) {
4762				drawHighlight(highlights[i].series);
4763			}
4764
4765			drawDonutHole(octx);
4766
4767			octx.restore();
4768
4769			function drawHighlight(series) {
4770
4771				if (series.angle <= 0 || isNaN(series.angle)) {
4772					return;
4773				}
4774
4775				//octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString();
4776				octx.fillStyle = "rgba(255, 255, 255, " + options.series.pie.highlight.opacity + ")"; // this is temporary until we have access to parseColor
4777				octx.beginPath();
4778				if (Math.abs(series.angle - Math.PI * 2) > 0.000000001) {
4779					octx.moveTo(0, 0); // Center of the pie
4780				}
4781				octx.arc(0, 0, radius, series.startAngle, series.startAngle + series.angle / 2, false);
4782				octx.arc(0, 0, radius, series.startAngle + series.angle / 2, series.startAngle + series.angle, false);
4783				octx.closePath();
4784				octx.fill();
4785			}
4786		}
4787	} // end init (plugin body)
4788
4789	// define pie specific options and their default values
4790
4791	var options = {
4792		series: {
4793			pie: {
4794				show: false,
4795				radius: "auto",	// actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)
4796				innerRadius: 0, /* for donut */
4797				startAngle: 3/2,
4798				tilt: 1,
4799				shadow: {
4800					left: 5,	// shadow left offset
4801					top: 15,	// shadow top offset
4802					alpha: 0.02	// shadow alpha
4803				},
4804				offset: {
4805					top: 0,
4806					left: "auto"
4807				},
4808				stroke: {
4809					color: "#fff",
4810					width: 1
4811				},
4812				label: {
4813					show: "auto",
4814					formatter: function(label, slice) {
4815						return "<div style='font-size:x-small;text-align:center;padding:2px;color:" + slice.color + ";'>" + label + "<br/>" + Math.round(slice.percent) + "%</div>";
4816					},	// formatter function
4817					radius: 1,	// radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)
4818					background: {
4819						color: null,
4820						opacity: 0
4821					},
4822					threshold: 0	// percentage at which to hide the label (i.e. the slice is too narrow)
4823				},
4824				combine: {
4825					threshold: -1,	// percentage at which to combine little slices into one larger slice
4826					color: null,	// color to give the new slice (auto-generated if null)
4827					label: "Other"	// label to give the new slice
4828				},
4829				highlight: {
4830					//color: "#fff",		// will add this functionality once parseColor is available
4831					opacity: 0.5
4832				}
4833			}
4834		}
4835	};
4836
4837	$.plot.plugins.push({
4838		init: init,
4839		options: options,
4840		name: "pie",
4841		version: "1.1"
4842	});
4843
4844})(jQuery);
4845
4846$(document).ready(function() {
4847
4848  $('.Form_newsletterSubscribe,' +
4849    '.PageArticle .FormRegisterNG,' +
4850    '.StageNewsletterSimple,' +
4851    '.PageRegister,' +
4852    '.StagePremiumPaywall'
4853  ).on('click', '.FormNLOptinPopup_open', function(e) {
4854    var parent = e.delegateTarget;
4855    $('.FormNLOptinPopup, .FormNLOptinPopup_overlay', parent).fadeIn();
4856
4857    $('input', parent).each(function() {
4858      if ($(this).attr('name') === 'i_email') {
4859        var user_email = $(this).val();
4860        if (user_email !== '' && user_email !== undefined) {
4861          var icon = "<i class=\"fas fa-envelope\"></i>";
4862          $('.FormNLOptinPopup_email', parent).html(icon + user_email);
4863        }
4864      }
4865    });
4866
4867    $('.FormNLOptinPopup_close-icon,' +
4868      '.FormNLOptinPopup_cancel,' +
4869      '.FormNLOptinPopup_overlay', parent).on('click', function(e) {
4870      $('.FormNLOptinPopup, .FormNLOptinPopup_overlay', parent).fadeOut();
4871    });
4872
4873  });
4874
4875});
4876
4877$(document).ready( function() {
4878
4879  function gA_on_Action(action, data) {
4880    if (data.indexOf('GoogleAnalytics_action') !== -1) {
4881      var url = window.location.href
4882        .split("?")[0]
4883        .split("#")[0];
4884      url += '/user/registration/completed';
4885      switch (action) {
4886        case '/user/registerng/register/':
4887          window.dfv_ga_vpageview(url);
4888          if (typeof window.sp_track_virtual_page_view === 'function') {
4889            window.sp_track_virtual_page_view(null, url);
4890          }
4891          break;
4892        default:
4893      }
4894    }
4895  }
4896
4897  function getLocationURL(url) {
4898
4899    const searchParams = new URLSearchParams(window.location.href);
4900    if (searchParams.has('redirect')) {
4901      return searchParams.get('redirect').split("#")[0];
4902    }
4903
4904    return url.replace('?password=1&', '?')
4905      .replace('?password-en=1&', '?')
4906      .replace('?password=1', '')
4907      .replace('?password-en=1', '')
4908      .replace('&password=1', '')
4909      .replace('&password-en=1', '')
4910      .replace('?password', '?')
4911      .replace('?password-en', '?')
4912      .replace('&password', '')
4913      .replace('&password-en', '')
4914      .replace('?login=1', '?')
4915      .replace('?login-en=1', '?')
4916      .replace('&login=1', '')
4917      .replace('&login-en=1', '')
4918      .split("#")[0];
4919  }
4920
4921  function sendCCSconversionToCMS(path, verifyhash, cceconversionid, info) {
4922    console.log('sendCCSconversionToCMS', path, verifyhash, cceconversionid, info);
4923    const xhr = new XMLHttpRequest();
4924    xhr.open('POST', path);
4925    xhr.setRequestHeader('Content-Type', 'application/json');
4926    xhr.onreadystatechange = () => {
4927      if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
4928        console.log('cceconversion CMS OK');
4929      } else if (xhr.readyState === XMLHttpRequest.DONE) {
4930        console.log('cceconversion CMS failed');
4931      }
4932    };
4933    const json = JSON.stringify({'i_verifyhash': verifyhash, 'i_cceconversionid':cceconversionid, 'i_info': info});
4934    xhr.send(json);
4935  }
4936
4937  function pianoSendConversionEventAndGotoURL(data, url) {
4938    var cceconversionid = '';
4939    document.querySelectorAll('#PianoConversionObject[data-piano-cceconversion-id]').forEach(function(element) {cceconversionid = element.getAttribute('data-piano-cceconversion-id');});
4940    /* console.log('pianoSendConversionEvent "', cceconversionid, '" cX: ', typeof cX, 'cX.CCE', typeof cX.CCE); */
4941    let verifyhash = '';
4942    document.querySelectorAll('input[name=i_verifyhash]').forEach(function(element) {verifyhash = element.getAttribute('value');});
4943    if (cceconversionid === ''|| verifyhash === '') {
4944      if (verifyhash === '') {
4945        verifyhash = 'no verifyhash';
4946      }
4947      sendCCSconversionToCMS('/_piano/api/cceconversion/store/', verifyhash, 'NO', 'no-cceconversionid');
4948      window.location = url;
4949    }
4950    console.log('sendCCSconversionToCMS');
4951    sendCCSconversionToCMS('/_piano/api/cceconversion/store/', verifyhash, cceconversionid, 'start-sen
4951d-conversion-event');
4952    if (typeof cX === 'undefined' || typeof cX.CCE === 'undefined') {
4953      sendCCSconversionToCMS('/_piano/api/cceconversion/store/', verifyhash, cceconversionid, 'error-no-cX-or-cXCCE');
4954      window.location = url;
4955    }
4956    else {
4957      console.log('sendConversionEvent');
4958      cX.CCE.callQueue.push(['sendConversionEvent', {
4959        'productId': cceconversionid,
4960        'funnelStep': 'convertProduct'
4961      }, {
4962        'callback': function (result) {
4963          console.log(result.httpStatus); // 200
4964          console.log(result.response); // {}
4965          let info =  (result.httpStatus !== 200) ? 'error-api-response' : 'OK';
4966          sendCCSconversionToCMS('/_piano/api/cceconversion/store/', verifyhash, cceconversionid, info);
4967          window.location = url;
4968        }
4969      }]);
4970    }
4971  }
4972  $('.FormRegisterNG').on('submit', '.FormRegisterNG_form',  function(event) {
4973    const formRegisterNg = $(this).closest('.FormRegisterNG');
4974    event.preventDefault();
4975    var action = event.currentTarget.getAttribute('action');
4976    var data = $( this ).serialize();
4977    $.post(
4978      action,
4979      data,
4980      function(data) {
4981        gA_on_Action(action, data);
4982        var url = '';
4983        let obj = null;
4984        try {
4985          obj = JSON.parse(data);
4986          switch (obj.step) {
4987            case 'thankyou':
4988              window.dataLayer.push({event: 'registration'});
4989              formRegisterNg.html( obj.html );
4990              window.location.href = '#formRegisterNG';
4991              break;
4992            case 'auto_login':
4993              const searchParams = new URLSearchParams(window.location.href);
4994              console.log( searchParams.has('community') , searchParams.has('community', 1));
4995              if ( searchParams.has('community') ) {
4996                window.location.href = '/community/';
4997                break;
4998              }
4999              url = getLocationURL(obj.url);
5000              window.location.href = url;
5001              break;
5002            case 'auto_login_conversion':
5003              url = getLocationURL(obj.url);
5004              pianoSendConversionEventAndGotoURL(data, url);
5005              break;
5006            default:
5007              formRegisterNg.html( obj.html );
5008              window.location.href = '#formRegisterNG';
5009          }
5010          return true;
5011        }
5012        catch(e) {
5013          console.log('JSON.parse(data) failed, use html replace', data);
5014        }
5015
5016        if (data === 'auto_login') {
5017          url = getLocationURL(window.location.href);
5018          window.location.href = url;
5019        } else if (data === 'auto_login_conversion' ) {
5020          url = getLocationURL(window.location.href);
5021          pianoSendConversionEventAndGotoURL(data, url);
5022        } else {
5023          let innerHtml = $(data).hasClass('FormRegisterNG_wrapper') ? $(data) : $(data).find('.FormRegisterNG_wrapper');
5024          if (innerHtml.length > 0) {
5025            formRegisterNg.html(innerHtml);
5026          } else {
5027            formRegisterNg.html(data);
5028          }
5029          window.location.href = '#formRegisterNG';
5030        }
5031      }
5032    );
5033  });
5034
5035  $('.FormRegisterNG').on('click', function(event) {
5036    const formRegisterNg = $(this);
5037    if ($(event.target).hasClass('FormRegisterNG_control-showPassword')) {
5038      event.preventDefault();
5039      var wdt = $('.FormRegisterNG_control-passwordField').css('width');
5040      if ($('.FormRegisterNG_control-passwordField').attr('type') === 'password') {
5041        $('.FormRegisterNG_control-passwordField').attr('type', 'text');
5042        if ($('a.FormRegisterNG_control-showPassword').text() === 'Show password') {
5043          $('a.FormRegisterNG_control-showPassword').text('Hide password');
5044        } else if ($('a.FormRegisterNG_control-showPassword').text() === 'Mostra password') {
5045          $('a.FormRegisterNG_control-showPassword').text('Inserire password');
5046        } else if ($('a.FormRegisterNG_control-showPassword').text() === 'Pokaż hasło') {
5047          $('a.FormRegisterNG_control-showPassword').text('Ukryj hasło');
5048        } else {
5049          $('a.FormRegisterNG_control-showPassword').text('Passwort ausblenden');
5050        }
5051      } else {
5052        $('.FormRegisterNG_control-passwordField').attr('type', 'password');
5053        if ($('a.FormRegisterNG_control-showPassword').text() === 'Hide password') {
5054          $('a.FormRegisterNG_control-showPassword').text('Show password');
5055        } else if ($('a.FormRegisterNG_control-showPassword').text() === 'Inserire password') {
5056          $('a.FormRegisterNG_control-showPassword').text('Mostra password');
5057        } else if ($('a.FormRegisterNG_control-showPassword').text() === 'Ukryj hasło') {
5058          $('a.FormRegisterNG_control-showPassword').text('Pokaż hasło');
5059        } else {
5060          $('a.FormRegisterNG_control-showPassword').text('Passwort einblenden');
5061        }
5062      }
5063      $('.FormRegisterNG_control-passwordField').css('width', wdt);
5064    } else if (event.target.getAttribute('data-action')) {
5065      event.preventDefault();
5066      var action = event.target.getAttribute('data-action');
5067      var url = event.target.getAttribute('data-url');
5068      data = 'url='+url;
5069      $.post(
5070        action,
5071        data,
5072        function(data) {
5073          gA_on_Action(action, data);
5074          formRegisterNg.html( data );
5075        }
5076      );
5077    }
5078  });
5079
5080});
5081
5082(function() {
5083
5084  if (typeof window.googletag === 'undefined') {
5085    window.googletag = { cmd: [] };
5086  }
5087
5088  /* Event-Listener Adition iframe */
5089  window.addEventListener('message',function(event) {
5090    const origin = window.location.origin;
5091    if(event.origin !== origin) return;
5092
5093    switch(event.data) {
5094      case 'bta':
5095        $(document).trigger('btaTeasering');
5096        break;
5097
5098      default:
5099        return;
5100    }
5101
5102  },false);
5103
5104
5105
5106  'use strict';
5107
5108  function insertAdvTag2(AdvTxt) {
5109    const taglines = document.querySelectorAll('.bta1Tagline, .bta2Tagline, .BTA-Artikeldetail-aSide-1 .Tagline, .BTA-Artikeldetail-aSide-2 .Tagline, .BTA-Artikeldetail-Stage-1 .Tagline, .BTA-Artikeldetail-Stage-2 .Tagline, .BTA-Artikeldetail-Stage-3 .Tagline');
5110
5111    taglines.forEach(tagline => {
5112      const btaAdvTag = document.createElement('div');
5113      btaAdvTag.className = 'AdvertNote';
5114      btaAdvTag.textContent = AdvTxt;
5115
5116      /* btaAdvTag als erstes Kind des aktuellen Tagline-Elements einfügen */
5117      tagline.insertBefore(btaAdvTag, tagline.firstChild);
5118    });
5119  }
5120
5121  function insertAdvTag(AdvTxt, tagline) {
5122
5123      const btaAdvTag = document.createElement('div');
5124      btaAdvTag.className = 'AdvertNote';
5125      btaAdvTag.textContent = AdvTxt;
5126
5127      /* btaAdvTag als erstes Kind des aktuellen Tagline-Elements einfügen */
5128      tagline.insertBefore(btaAdvTag, tagline.firstChild);
5129
5130  }
5131
5132  let btaAsideExists = false;
5133  let btaStageExists = false;
5134
5135  function setBtaStageMargin() {
5136
5137
5138    if (btaAsideExists) {
5139      const pageArticleContent = document.querySelector('.PageArticle_content');
5140      if (!pageArticleContent) return;
5141
5142      const elAfterContent = pageArticleContent.nextElementSibling;
5143      if (elAfterContent) {
5144        const btaAsideDiv = document.querySelector('.btaAsideContainer');
5145
5146        if (btaAsideDiv) {
5147          const computedStyle = getComputedStyle(btaAsideDiv);
5148          const btaAsideHeight = btaAsideDiv.offsetHeight + parseFloat(computedStyle.marginTop) + parseFloat(computedStyle.marginBottom);
5149          elAfterContent.style.marginTop = `${btaAsideHeight + 20}px`;
5150        }
5151      }
5152    }
5153
5154  }
5155
5156/* BTA-Aside */
5157
5158  let isAsideListenerActive = false;
5159
5160  function positionAsideBta() {
5161    const leadEl = document.querySelector('.PageArticle_sticky');
5162    const targetEl = document.querySelector('.btaAsideContainer');
5163
5164    if (leadEl && targetEl) {
5165      /* hat leadEl "position: fixed" */
5166      const leadComputedStyle = window.getComputedStyle(leadEl);
5167      const isLeadFixed = leadComputedStyle.position === 'fixed';
5168
5169      let newTop;
5170
5171      if (isLeadFixed) {
5172        // wenn leadEl "fixed", dann positioniere targetEl relativ zum Viewport
5173        const leadRect = leadEl.getBoundingClientRect();
5174        targetEl.style.position = 'fixed';
5175        newTop = leadRect.bottom + 5;
5176      } else {
5177        // wenn leadEl nicht "fixed", dann positioniere targetEl relativ zum Dokument
5178        const leadOffsetTop = leadEl.offsetTop + leadEl.offsetHeight;
5179        targetEl.style.position = 'absolute';
5180        newTop = leadOffsetTop + 5;
5181      }
5182
5183      targetEl.style.top = `${newTop}px`;
5184
5185      /* debugging */
5186      /*
5187      console.log({
5188                    leadPosition: leadComputedStyle.position,
5189                    leadBottom: leadEl.getBoundingClientRect().bottom,
5190                    leadOffsetTop: leadEl.offsetTop,
5191                    targetTop: targetEl.style.top,
5192                  });
5193      */
5194    }
5195  }
5196
5197  function addAsideEventListeners() {
5198    if (!isAsideListenerActive) {
5199      window.addEventListener('resize', positionAsideBta);
5200      window.addEventListener('scroll', positionAsideBta);
5201      isAsideListenerActive = true;
5202    }
5203  }
5204
5205  $(document).on("btaTeasering", function(event){
5206    // alle Elementen mit der Klasse "btaFrame" und dem Data-Attribut "ad_position" gleich "0"
5207    const bta1Els = document.querySelectorAll('.btaFrame[data-ad_position="bta1"]');
5208    const bta2Els = document.querySelectorAll('.btaFrame[data-ad_position="bta2"]');
5209    const bta3Els = document.querySelectorAll('.btaFrame[data-ad_position="bta3"]');
5210    const bta4Els = document.querySelectorAll('.btaFrame[data-ad_position="bta4"]');
5211    const bta5Els = document.querySelectorAll('.btaFrame[data-ad_position="bta5"]');
5212    const bta6Els = document.querySelectorAll('.btaFrame[data-ad_position="bta6"]');
5213    const bta7Els = document.querySelectorAll('.btaFrame[data-ad_position="bta7"]');
5214
5215    if (bta1Els.length > 0) {
5216      const bta1Tagline = document.querySelector('.bta1Tagline');
5217      const bta1Headline = document.querySelector('.bta1Headline');
5218      const bta1href = document.querySelector('.bta1Url');
5219      const bta1Text = document.querySelector('.BTA-Homepage-Aufmacher .ArticleTeaser_abstract');
5220
5221      bta1Els.forEach(bta1El => {
5222        const bta_kicker = bta1El.getAttribute('data-kicker');
5223        if (bta1Tagline && bta_kicker) {
5224          bta1Tagline.textContent = bta_kicker;
5225        }
5226        const bta_titel = bta1El.getAttribute('data-titel');
5227        if (bta1Headline && bta_titel) {
5228          bta1Headline.textContent = bta_titel;
5229        }
5230        const bta_url = bta1El.getAttribute('data-targeturl');
5231        if (bta1href && bta_url) {
5232          bta1href.href = bta_url;
5233          bta1href.setAttribute('target', '_blank');
5234        }
5235        const bta_text = bta1El.getAttribute('data-text_content');
5236        if (bta1Text) {
5237          bta1Text.textContent = bta_text;
5238        }
5239        insertAdvTag('Anzeige', bta1Tagline);
5240      });
5241
5242    }
5243
5244    if (bta2Els.length > 0) {
5245      const bta2Tagline = document.querySelector('.bta2Tagline');
5246      const bta2Headline = document.querySelector('.bta2Headline');
5247      const bta2href = document.querySelector('.bta2Url');
5248
5249      bta2Els.forEach(bta2El => {
5250        const bta_kicker = bta2El.getAttribute('data-kicker');
5251        if (bta2Tagline && bta_kicker) {
5252          bta2Tagline.textContent = bta_kicker;
5253        }
5254        const bta_titel = bta2El.getAttribute('data-titel');
5255        if (bta2Headline && bta_titel) {
5256          bta2Headline.textContent = bta_titel;
5257        }
5258        const bta_url = bta2El.getAttribute('data-targeturl');
5259        if (bta2href && bta_url) {
5260          bta2href.href = bta_url;
5261        }
5262      });
5263      insertAdvTag('Anzeige', bta2Tagline);
5264    }
5265
5266
5267    if (bta3Els.length > 0) {
5268      const bta3Tagline = document.querySelector('.BTA-Artikeldetail-aSide-1 .Tagline');
5269      const bta3Headline = document.querySelector('.BTA-Artikeldetail-aSide-1 .Headline');
5270      const bta3href = document.querySelector('.BTA-Artikeldetail-aSide-1 .btaAside1Link');
5271
5272      bta3Els.forEach(bta3El => {
5273        const bta_kicker = bta3El.getAttribute('data-kicker');
5274        if (bta3Tagline && bta_kicker) {
5275          bta3Tagline.textContent = bta_kicker;
5276        }
5277        const bta_titel = bta3El.getAttribute('data-titel');
5278        if (bta3Headline && bta_titel) {
5279          bta3Headline.textContent = bta_titel;
5280        }
5281        const bta_url = bta3El.getAttribute('data-targeturl');
5282        if (bta3href && bta_url) {
5283          bta3href.href = bta_url;
5284        }
5285
5286        /* Position bei Änderungen aktualisieren */
5287        addAsideEventListeners();
5288
5289        /* Initiale Positionierung */
5290        document.addEventListener('DOMContentLoaded', positionAsideBta);
5291        btaAsideExists = true;
5292        insertAdvTag('Anzeige', bta3Tagline);
5293
5294      });
5295    } else {
5296      const btaAsideContainer = document.querySelector('.btaAsideContainer');
5297      if (btaAsideContainer && (bta4Els.length < 1) ) {
5298        btaAsideContainer.style.display = 'none';
5299      }
5300    }
5301
5302    if (bta4Els.length > 0) {
5303      const bta4Tagline = document.querySelector('.BTA-Artikeldetail-aSide-2 .Tagline');
5304      const bta4Headline = document.querySelector('.BTA-Artikeldetail-aSide-2 .Headline');
5305      const bta4href = document.querySelector('.BTA-Artikeldetail-aSide-2 .btaAside2Link');
5306
5307      bta4Els.forEach(bta4El => {
5308        const bta_kicker = bta4El.getAttribute('data-kicker');
5309        if (bta4Tagline && bta_kicker) {
5310          bta4Tagline.textContent = bta_kicker;
5311        }
5312        const bta_titel = bta4El.getAttribute('data-titel');
5313        if (bta4Headline && bta_titel) {
5314          bta4Headline.textContent = bta_titel;
5315        }
5316        const bta_url = bta4El.getAttribute('data-targeturl');
5317        if (bta4href && bta_url) {
5318          bta4href.href = bta_url;
5319        }
5320
5321        addAsideEventListeners();
5322
5323        /* Initiale Positionierung */
5324        document.addEventListener('DOMContentLoaded', positionAsideBta);
5325        btaAsideExists = true;
5326        insertAdvTag('Anzeige', bta4Tagline);
5327      });
5328    } else {
5329      const btaAsideContainer = document.querySelector('.btaAsideContainer');
5330      if (btaAsideContainer && (bta3Els.length < 1)) {
5331        btaAsideContainer.style.display = 'none';
5332      }
5333    }
5334
5335    if (bta5Els.length > 0) {
5336      btaStageExists = true;
5337      const bta5Tagline = document.querySelector('.BTA-Artikeldetail-Stage-1 .Tagline');
5338      const bta5Headline = document.querySelector('.BTA-Artikeldetail-Stage-1 .Headline');
5339      const bta5hrefs = document.querySelectorAll('.BTA-Artikeldetail-Stage-1 a.ArticleTeaser_link');
5340      const bta5Text = document.querySelector('.BTA-Artikeldetail-Stage-1 .ArticleTeaser_abstract a.ArticleTeaser_link');
5341
5342      bta5Els.forEach(bta5El => {
5343        const bta_kicker = bta5El.getAttribute('data-kicker');
5344        if (bta5Tagline && bta_kicker) {
5345          bta5Tagline.textContent = bta_kicker;
5346        }
5347        const bta_titel = bta5El.getAttribute('data-titel');
5348        if (bta5Headline && bta_titel) {
5349          bta5Headline.textContent = bta_titel;
5350        }
5351        bta5hrefs.forEach(bta5href => {
5352          const bta_url = bta5El.getAttribute('data-targeturl');
5353          if (bta_url) {
5354            bta5href.href = bta_url;
5355            bta5href.setAttribute('target', '_blank');
5356          }
5357        });
5358        const bta_text = bta5El.getAttribute('data-text_content');
5359        if (bta5Text) {
5360          bta5Text.textContent = bta_text;
5361        }
5362        setBtaFrameHeight(bta5El);
5363        insertAdvTag('Anzeige', bta5Tagline);
5364      });
5365
5366    }
5367
5368    if (bta6Els.length > 0) {
5369      btaStageExists = true;
5370      const bta6Tagline = document.querySelector('.BTA-Artikeldetail-Stage-2 .Tagline');
5371      const bta6Headline = document.querySelector('.BTA-Artikeldetail-Stage-2 .Headline');
5372      const bta6hrefs = document.querySelectorAll('.BTA-Artikeldetail-Stage-2 a.ArticleTeaser_link');
5373      const bta6Text = document.querySelector('.BTA-Artikeldetail-Stage-2 .ArticleTeaser_abstract a.ArticleTeaser_link');
5374
5375      bta6Els.forEach(bta6El => {
5376        const bta_kicker = bta6El.getAttribute('data-kicker');
5377        if (bta6Tagline && bta_kicker) {
5378          bta6Tagline.textContent = bta_kicker;
5379        }
5380        const bta_titel = bta6El.getAttribute('data-titel');
5381        if (bta6Headline && bta_titel) {
5382          bta6Headline.textContent = bta_titel;
5383        }
5384        bta6hrefs.forEach(bta6href => {
5385          const bta_url = bta6El.getAttribute('data-targeturl');
5386          if (bta_url) {
5387            bta6href.href = bta_url;
5388            bta6href.setAttribute('target', '_blank');
5389          }
5390        });
5391        const bta_text = bta6El.getAttribute('data-text_content');
5392        if (bta6Text) {
5393          bta6Text.textContent = bta_text;
5394        }
5395        setBtaFrameHeight(bta6El);
5396        insertAdvTag('Anzeige', bta6Tagline);
5397      });
5398    }
5399
5400    if (bta7Els.length > 0) {
5401      btaStageExists = true;
5402      const bta7Tagline = document.querySelector('.BTA-Artikeldetail-Stage-3 .Tagline');
5403      const bta7Headline = document.querySelector('.BTA-Artikeldetail-Stage-3 .Headline');
5404      const bta7hrefs = document.querySelectorAll('.BTA-Artikeldetail-Stage-3 a.ArticleTeaser_link');
5405      const bta7Text = document.querySelector('.BTA-Artikeldetail-Stage-3 .ArticleTeaser_abstract a.ArticleTeaser_link');
5406
5407      bta7Els.forEach(bta7El => {
5408        const bta_kicker = bta7El.getAttribute('data-kicker');
5409        if (bta7Tagline && bta_kicker) {
5410          bta7Tagline.textContent = bta_kicker;
5411        }
5412        const bta_titel = bta7El.getAttribute('data-titel');
5413        if (bta7Headline && bta_titel) {
5414          bta7Headline.textContent = bta_titel;
5415        }
5416        bta7hrefs.forEach(bta7href => {
5417          const bta_url = bta7El.getAttribute('data-targeturl');
5418          if (bta_url) {
5419            bta7href.href = bta_url;
5420            bta7href.setAttribute('target', '_blank');
5421          }
5422        });
5423        const bta_text = bta7El.getAttribute('data-text_content');
5424        if (bta7Text) {
5425          bta7Text.textContent = bta_text;
5426        }
5427        setBtaFrameHeight(bta7El);
5428        insertAdvTag('Anzeige', bta7Tagline);
5429      });
5430    }
5431
5432    setBtaStageMargin();
5433    eraseEmptyStageArticles();
5434
5435
5436
5437  }); /* end btaTeasering */
5438
5439
5440  function isStageSlotFilled(slotElement) {
5441    if (!slotElement) return false;
5442
5443    // Echte Anzeige vorhanden
5444    const adIframe = slotElement.querySelector('iframe');
5445    if (adIframe) {
5446      return adIframe.offsetHeight > 0 || adIframe.dataset.loadComplete === 'true';
5447    }
5448
5449    // GAM-Container ohne iframe -> nur als gefuellt werten, wenn sichtbar > 0
5450    const gamContainer = slotElement.querySelector('div[id$="__container__"]');
5451    if (gamContainer) {
5452      return gamContainer.offsetHeight > 0;
5453    }
5454
5455    return false;
5456  }
5457
5458
5459  function eraseEmptyStageArticles() {
5460    const btaStageSection = document.querySelector('.StageAdvertNativeTextAds');
5461
5462    if (btaStageSection) {
5463      const stageElements = btaStageSection.querySelectorAll('[id^="renderSlot_BTA-Artikeldetail-Stage-"]');
5464      let hiddenArticles = 0;
5465      stageElements.forEach((element) => {
5466        const isFilled = isStageSlotFilled(element);
5467        if (!isFilled) {
5468          const articleElement = element.closest('article');
5469          if (articleElement) {
5470            articleElement.style.display = 'none';
5471            articleElement.classList.add('noDisplay');
5472            hiddenArticles++;
5473
5474          } else {
5475
5476          }
5477        }
5478      });
5479
5480      if (hiddenArticles === 2) {
5481        layoutSingleArticle();
5482      }
5483
5484    }
5485  }
5486
5487  function layoutSingleArticle() {
5488    window.onload = () => {
5489      console.log('Seite vollständig geladen');
5490
5491      setTimeout(() => {
5492        const singleArticleEl = Array.from(document.querySelectorAll('[class*="BTA-Artikeldetail-Stage-"]')).find(element => {
5493          const style = window.getComputedStyle(element);
5494          return (style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0') &&
5495            !element.classList.contains('noDisplay');
5496        });
5497
5498        if (singleArticleEl) {
5499          const anchorTag = singleArticleEl.querySelector('a.ArticleTeaser_imgWrapper');
5500          if (anchorTag) {
5501            anchorTag.style.float = 'left';
5502            anchorTag.style.marginRight = '1em';
5503          }
5504        } else {
5505          console.log('Kein sichtbares Element gefunden.');
5506        }
5507      }, 150);
5508    };
5509
5510
5511  }
5512
5513  /* in BTA-Bühne Höhe des iFrames an img anpassen */
5514  function setBtaFrameHeight(btaFrame) {
5515    if (btaFrame) {
5516      btaFrame.onload = function() {
5517        const btaFrameDocument = btaFrame.contentDocument || btaFrame.contentWindow.document;
5518        const bannerImage = btaFrameDocument.getElementById('banner_image');
5519        if (bannerImage) {
5520          const bannerHeight = bannerImage.offsetHeight;
5521
5522          requestAnimationFrame(() => {
5523            btaFrame.style.height = bannerHeight + 'px';
5524          });
5525        } else {
5526          console.error('Das <img>-Element mit der ID "banner_image" wurde im btaFrame nicht gefunden.');
5527        }
5528      };
5529    }
5530  }
5531
5532  /*
5533  START
5534  check ob bta-Bühne leer ist, dann nicht anzeigen
5535  */
5536  function waitForLoad() {
5537    return new Promise((resolve) => {
5538      window.onload = resolve;
5539    });
5540  }
5541
5542  function waitForAdditionalTime(ms) {
5543    return new Promise((resolve) => setTimeout(resolve, ms));
5544  }
5545
5546  waitForLoad().then(() => {
5547    return waitForAdditionalTime(1000);
5548  }).then(() => {
5549    const bta5Els = document.querySelector('.btaFrame[data-ad_position="bta5"]');
5550    const bta6Els = document.querySelector('.btaFrame[data-ad_position="bta6"]');
5551    const bta7Els = document.querySelector('.btaFrame[data-ad_position="bta7"]');
5552
5553    if (!bta5Els && !bta6Els && !bta7Els) {
5554      const btaStageSection = document.querySelector('.StageAdvertNativeTextAds');
5555      if (btaStageSection) {
5556        btaStageSection.style.display = 'none';
5557      }
5558    }
5559  });
5560  /*
5561   END
5562   check ob bta-Bühne leer ist, dann nicht anzeigen
5563   */
5564
5565
5566
5567})();
5568
5569
5570/* Event-Listener Adition iframe */
5571if (typeof window.googletag === 'undefined') {
5572  window.googletag = { cmd: [] };
5573}
5574
5575window.addEventListener('message',function(event) {
5576  const origin = window.location.origin;
5577  if(event.origin !== origin) return;
5578
5579  let currentUrl = window.location.href;
5580
5581  let be_domainsInsertAdvTextDiv = [
5582    'iz.de',
5583    'handelextra.pl',
5584    'how-green-works.de',
5585    'foodservice24.pl',
5586    'horizont.net',
5587    'mmponline.pl',
5588    'lebensmittelzeitung.net',
5589    'tw-media.com',
5590    'pebbles.dfv-is.de',
5591    'fibers-in-process.de',
5592    'umweltwirtschaft.com',
5593    'wwt-online.de',
5594    'changement-magazin.de',
5595    'zoe-online.org'
5596  ];
5597
5598  let be_domainsAddSliderControl = ['ahgz.at', 'lebensmittelzeitung.net'];
5599
5600  let be_domainsContainerClass = {
5601    'default': 'PageFrame',
5602    'the-spin-off.com' : 'container',
5603    'horizont.net' : 'SiteHeader',
5604    'dfv-is.de' : 'SiteHeader',
5605    'fibers-in-process.de' : 'SiteHeader',
5606    'umweltwirtschaft.com' : 'SiteHeader',
5607    'wwt-online.de' : 'SiteHeader',
5608    'changement-magazin.de' : 'SiteHeader',
5609    'zoe-online.org' : 'SiteHeader'
5610  };
5611
5612  let be_domainsWideLayout = [
5613    'horizont.net',
5614    'mmponline.pl',
5615    'dfv-is.de',
5616    'fibers-in-process.de',
5617    'umweltwirtschaft.com',
5618    'wwt-online.de',
5619    'changement-magazin.de',
5620    'zoe-online.org'
5621  ];
5622
5623  function be_isDomainInUrl(domainsArray, currentUrl) {
5624    return domainsArray.some(domain => currentUrl.includes(domain));
5625  }
5626
5627  let wideLayout = false;
5628  if (be_isDomainInUrl(be_domainsWideLayout, currentUrl)) {
5629    wideLayout = true;
5630  }
5631
5632  let be_containerClass;
5633  const matchingKey = Object.keys(be_domainsContainerClass).find(key => currentUrl.includes(key));
5634
5635  if (matchingKey) {
5636    be_containerClass = be_domainsContainerClass[matchingKey];
5637  } else {
5638    be_containerClass = be_domainsContainerClass['default'];
5639  }
5640
5641  switch(event.data) {
5642
5643    case 'textAd': $(document).trigger('textAd');
5644      break;
5645    /*
5646     case 'teadsResize':
5647     $(document).trigger('teadsResize');
5648     break;
5649
5650     */
5651    case 'parallax':
5652      if (be_isDomainInUrl(be_domainsInsertAdvTextDiv, currentUrl)) {
5653        $(document).trigger('insertAdvTextDiv');
5654      }
5655      $(document).trigger('parallax');
5656      break;
5657    case 'bannerinit':
5658      //$(document).trigger('resizeIframe');
5659      $(document).trigger('advertOnImage');
5660      $(document).trigger('clsAlignSuperbanner');
5661      $(document).trigger('clsAlignBillboard');
5662      $(document).trigger('BillboardHeight');
5663
5664
5665      if (be_isDomainInUrl(be_domainsAddSliderControl,currentUrl)) {
5666        $(document).trigger('adSliderControl');
5667      }
5668      if (be_isDomainInUrl(be_domainsInsertAdvTextDiv, currentUrl)) {
5669        $(document).trigger('insertAdvTextDiv');
5670      }
5671      break;
5672    case 'singlebanner':
5673      $(document).trigger('clsAlignSuperbanner');
5674      $(document).trigger('clsAlignBillboard');
5675      break;
5676    case 'halfpage':
5677      $(document).trigger('halfpage', [be_containerClass]);
5678      break;
5679    case 'floorAd':
5680      $(document).trigger('floorAd');
5681      //$(document).trigger('resizeIframe');
5682      break;
5683    /*
5684     case 'html5floorAd':
5685     $(document).trigger('html5floorAd');
5686     break;
5687     case 'HTML5sitebar':
5688     $(document).trigger('html5sitebar');
5689     break;
5690     */
5691    case 'layerAd':
5692      $(document).trigger('layerAd');
5693      break;
5694
5695    case 'bridgeAd':
5696      $(document).trigger('alignSkyscraperLeft');
5697      $(document).trigger('alignSkyscraperRight');
5698      $(document).trigger('bridgeAd');
5699      break;
5700    case 'bridgeAdSticky':
5701      $(document).trigger('alignSkyscraperLeft');
5702      $(document).trigger('alignSkyscraperRight');
5703      $(document).trigger('bridgeAdSticky');
5704      $(document).trigger('billboardSticky');
5705      break;
5706
5707    case 'bridgeAdComp':
5708      $(document).trigger('bridgeAdComp');
5709      break;
5710
5711    case 'fullWidthBillboard':
5712      $(document).trigger('fullWidthBillboard');
5713      break;
5714
5715    case 'valueAd':
5716      $(document).trigger('valueAd');
5717      break;
5718    /*
5719     case 'exitintent':
5720     $(document).trigger('exitintent');
5721     break;
5722     case 'background':
5723     $(document).trigger('changeBackgroundColor');
5724     break;
5725     case 'backgroundclick':
5726     $(document).trigger('isBackgroundClick');
5727     break;
5728     case 'counterAd':
5729     $(document).trigger('counterAd');
5730     break;
5731     case 'centerFrame': $(document).trigger('centerIframe');
5732     break;
5733     case 'blockadvertisement':
5734     $(document).trigger('blockadvertisement');
5735     break;
5736     case 'wallpapercolor':
5737     $(document).trigger('wallpapercolor');
5738     break;
5739     */
5740    case 'sitebar':
5741    case 'sitebarHTML5':
5742      $(document).trigger('sitebar', [wideLayout]);
5743      break;
5744    case 'sitebar-switch':
5745      $(document).trigger('sitebar-switch', [be_domainsContainerClass, wideLayout]);
5746      break;
5747    case 'sitebarLeft':
5748      $(document).trigger('sitebarLeft', [wideLayout]);
5749      break;
5750    case 'pushdown':
5751    case 'pushdown2':
5752    case 'pushdown3':
5753    case 'pushdown4':
5754    case 'pushdown5':
5755    case 'pushdown6':
5756    case 'pushdown7':
5757      const elementclass = event.data;
5758      $(document).trigger('pushdown', [elementclass]);
5759      break;
5760    case 'parallax_outstream':
5761      $(document).trigger('parallax_outstream');
5762      break;
5763    case 'dynamic_sitebar':
5764      $(document).trigger('dynamic_sitebar');
5765      break;
5766    case 'billboardSticky':
5767      $(document).trigger('billboardSticky');
5768      break;
5769    case 'dfvSolutionAd':
5770      $(document).trigger('dfvSolutionAd');
5771      break;
5772    case 'welcomeVideo':
5773      $(document).trigger('welcomeAdVideo');  break;
5774    case 'welcomeVideoMobil':
5775      $(document).trigger('welcomeAdVideoMobil');  break;
5776    case 'welcomeImage':
5777      $(document).trigger('welcomeAdImage');  break;
5778    case 'welcomeImageMobil':
5779      $(document).trigger('welcomeAdImageMobil');  break;
5780    case 'understitial':
5781      $(document).trigger('understitial');
5782      break;
5783    case 'bbreminder':
5784      $(document).trigger('bbReminder');
5785      break;
5786    case 'fadeoutadvertisement':
5787      $(document).trigger('fadeoutadvertisement');
5788      break;
5789    default:
5790      return;
5791  }
5792
5793},false);
5794
5795/**
5796 *  billboardHeight
5797 *  billboard pushdown - margin bottom / overflow hidden
5798 */
5799$(document).one('billboardHeight', function() {
5800  const slots = document.querySelectorAll('#renderSlot_Billboard, #renderSlot_Mobil-Billboard');
5801
5802  slots.forEach(slot => {
5803    let banner_div = slot.querySelector('div');
5804    if (banner_div) {
5805      const checkStyleInterval = setInterval(() => {
5806        if (banner_div.getAttribute('style')) {
5807          banner_div.style.marginBottom = '20px';
5808          if (slot.offsetHeight < 290) { /* CLS */
5809            slot.style.marginBottom = '20px';
5810          }
5811          slot.style.overflow = 'hidden';
5812          clearInterval(checkStyleInterval);
5813        }
5814      }, 100);
5815    } else {
5816      const observer = new MutationObserver((mutationsList, observer) => {
5817        mutationsList.forEach(mutation => {
5818          if (mutation.type === 'childList') {
5819            banner_div = slot.querySelector('div');
5820            if (banner_div) {
5821              const checkStyleInterval = setInterval(() => {
5822                if (banner_div.getAttribute('style')) {
5823                  banner_div.style.marginBottom = '20px';
5824                  if (slot.offsetHeight < 290) { /* CLS */
5825                    slot.style.marginBottom = '20px';
5826                  }
5827                  slot.style.overflow = 'hidden';
5828                  clearInterval(checkStyleInterval);
5829                }
5830              }, 100);
5831              observer.disconnect();
5832            }
5833          }
5834        });
5835      });
5836      observer.observe(slot, { childList: true, subtree: true });
5837    }
5838  });
5839});
5840
5841/**
5842 *  billboardSticky
5843 */
5844$(document).on('billboardSticky', function() {
5845  const slot = document.querySelector('#renderSlot_Billboard, #renderSlot_Mobil-Billboard');
5846  if (!slot) return;
5847
5848  const billboardIframe = document.querySelector('.billboardSticky');
5849  const stickyHeader = document.querySelector('.SiteHeaderSticky');
5850
5851  const stickyHeaderHeight = stickyHeader ? stickyHeader.offsetHeight : 0;
5852  const billboardPositionTop = slot.getBoundingClientRect().top + window.scrollY;
5853
5854  const parentMarginTop = billboardIframe ? parseFloat(getComputedStyle(billboardIframe.parentNode).marginTop) : 0;
5855  let billboardStickyOffsetTop = stickyHeaderHeight + 5;
5856  billboardStickyOffsetTop += (Math.sign(parentMarginTop) === -1) ? Math.abs(parentMarginTop) : -Math.abs(parentMarginTop);
5857
5858  // Banner-ID aus iframe.id erzeugen (zwischen erstem und zweitem "/")
5859  const idParts = billboardIframe.id.split('/');
5860  let bId = idParts[1] || 'default';
5861  const lsKey = 'stickyBillboard_' + bId;
5862  let sTimer = null;
5863  let ticking = false;
5864  let animationFrameId = null;
5865
5866  const scrollDuration = 300;
5867
5868  // LocalStorage prüfen
5869  const lsValue = localStorage.getItem(lsKey);
5870  if (lsValue) {
5871    const expireDate = JSON.parse(lsValue).expireAt;
5872    if (expireDate >= Date.now()) return;
5873    else localStorage.removeItem(lsKey);
5874  }
5875
5876  function animateSlot(from, to, duration) {
5877    let startTime = null;
5878    function animate(time) {
5879      if (!startTime) startTime = time;
5880      const progress = Math.min((time - startTime) / duration, 1);
5881      slot.style.top = from + (to - from) * progress + 'px';
5882      if (progress < 1) animationFrameId = requestAnimationFrame(animate);
5883      else animationFrameId = null;
5884    }
5885    animationFrameId = requestAnimationFrame(animate);
5886  }
5887
5888  function handleScroll() {
5889    const scrollTop = window.scrollY;
5890
5891    if (scrollTop > billboardPositionTop) {
5892      if (!slot.classList.contains('isStickyBillboard') && !sTimer && !localStorage.getItem(lsKey)) {
5893        slot.classList.add('isStickyBillboard');
5894        slot.style.position = 'fixed';
5895        slot.style.top = billboardStickyOffsetTop + 'px';
5896        slot.style.zIndex = 999;
5897
5898        sTimer = setTimeout(() => {
5899          animateSlot(billboardStickyOffsetTop, -600, 3000);
5900          sTimer = null;
5901          const expireAt = Date.now() + 60000 * 1440;
5902          localStorage.setItem(lsKey, JSON.stringify({ expireAt }));
5903        }, 2000);
5904      }
5905    } else {
5906      if (sTimer) {
5907        clearTimeout(sTimer);
5908        sTimer = null;
5909      }
5910      if (animationFrameId) {
5911        cancelAnimationFrame(animationFrameId);
5912        animationFrameId = null;
5913      }
5914      const currentTop = parseFloat(getComputedStyle(slot).top) || 0;
5915      animateSlot(currentTop, 0, scrollDuration);
5916      slot.classList.remove('isStickyBillboard');
5917      slot.style.position = '';
5918    }
5919
5920    ticking = false;
5921  }
5922
5923  window.addEventListener('scroll', function() {
5924    if (!ticking) {
5925      window.requestAnimationFrame(handleScroll);
5926      ticking = true;
5927    }
5928  });
5929});
5930
5931
5932
5933/**
5934 *  parallax
5935 */
5936$(document).on("parallax", function(event){
5937  'use strict';
5938  const htmlTag = document.getElementsByTagName('html')[0];
5939  const peephole = $(".parallax").parent().parent();
5940  const parallax_div = $(".parallax").parent();
5941  const parallax_iframe = $(".parallax");
5942
5943  const peephole_width = peephole.width();
5944  const peephole_height = peephole.height();
5945
5946  const bgcolor = parallax_iframe.data("bgcolor");
5947  const parallax_ratio = parallax_iframe.data("height") / parallax_iframe.data("width");
5948
5949  htmlTag.classList.add('Ad_setZindex'); /* Workaround für Safari < v15 */
5950
5951  let viewportHeight = window.innerHeight - $(".SiteHeaderSticky").outerHeight(true);
5952  if (window.innerWidth < 768) {
5953    viewportHeight = window.innerHeight;
5954  }
5955  if (parallax_iframe.data("width") >= parallax_div.width()){
5956    parallax_iframe.height( parallax_div.width() * parallax_ratio);
5957  }
5958
5959  let ad_top = parseInt(viewportHeight - parallax_iframe.height()) / 2;
5960  const parallax_height_diff = Math.abs(viewportHeight - parallax_iframe.height()) * parallax_ratio;
5961  const parallax_width_diff = Math.floor(parallax_height_diff);
5962
5963  if ((parallax_iframe.data("height") >= viewportHeight) || (ad_top < parseInt($(".SiteHeaderSticky").outerHeight(true)))) {
5964    ad_top = $(".SiteHeaderSticky").outerHeight(true) +"px";
5965  }
5966
5967  peephole.height(viewportHeight);
5968  peephole.css("position","relative");
5969  peephole.prepend('<span class=\"Ad_parallax-borderTop\" style=\"width: ' + peephole_width + 'px;\"></span>'); /*Chrome-Render-Fix*/
5970
5971  parallax_div.css('width', peephole_width + 'px');
5972  parallax_div.css("height",viewportHeight);
5973  if (bgcolor) {
5974    parallax_div.css("background-color", bgcolor);
5975  }
5976  parallax_div.addClass('Ad_parallax-innerWrapper');
5977  parallax_div.css('margin', '0 auto');
5978  parallax_iframe.height(viewportHeight);
5979  const parallax_width = parallax_div.height() / parallax_ratio;
5980
5981  if ((peephole_height > viewportHeight) && (window.innerWidth < 768)) {
5982    parallax_iframe.width(parallax_width-parallax_width_diff);
5983  } else {
5984    parallax_iframe.width(parallax_width);
5985  }
5986
5987  if (parallax_width > peephole_width) {
5988    parallax_iframe.width(peephole_width);
5989  }
5990
5991  if (parallax_div.width() - parallax_iframe.width() > 48 ){
5992    parallax_iframe.css("margin-left", ((parallax_div.width() - parallax_iframe.width()) / 2) + "px");
5993  } else {
5994    parallax_iframe.css("margin-left", "0px");
5995  }
5996  parallax_iframe.css("position","fixed");
5997  parallax_iframe.css("bottom",ad_top);
5998  parallax_iframe.css("top",ad_top);
5999
6000});
6001
6002/**
6003 *  textAd
6004 */
6005$(document).one("textAd", function() {
6006  $("iframe.textAd").each(function() {
6007
6008    const $iframe = $(this);
6009
6010    $.each(this.attributes, function() {
6011      if(this.name.startsWith('data-')) {
6012        /* console.log(this.name + ': ' + $iframe.attr(this.name)); */
6013      }
6014    });
6015
6016    // Füge ein leeres DIV direkt unter das nächste Elternelement mit id^="renderSlot_"
6017    const $container = $iframe.closest('[id^="renderSlot_"]');
6018    if ($container.length) {
6019      $('<div class="AnzHelper"></div>').insertBefore($container.children().first());
6020    }
6021
6022    const headline = $iframe.attr("data-headline") || "";
6023    const text = $iframe.attr("data-text") || "";
6024    const imgPos = ($iframe.attr("data-img-pos") || "top").toLowerCase();
6025    const moreButton = $iframe.attr("data-more_button") === "ja";
6026    const buttonText = $iframe.attr("data-button_text") || "Mehr";
6027    const clickUrl = $iframe.attr("data-clickurl") || "#";
6028    const centerAd = $iframe.attr("data-center_ad") === "1";
6029    const marginTop = parseInt($iframe.attr("data-margin-top") || "0", 10);
6030
6031    const $textWrapper = $("<div class=\"ArticleTeaser_content\"><div class='textAd-text-wrapper ArticleTeaser_content'></div></div>")
6032      .css({
6033        "line-height": "1.4em",
6034        "white-space": "normal",
6035        "font-family": "inherit",
6036        "font-size": "16px",
6037        "text-align": centerAd ? "center" : "left",
6038        "margin-top": `${marginTop}px`
6039      })
6040      .html(`
6041        <h2 class="Headline ArticleTeaser_headline TextAdHeadLine">${headline}</h2>
6042        <div class="ArticleTeaser_abstract TextAdContent">${text}</div>
6043      `);
6044
6045    if (moreButton) {
6046      const btn = document.createElement("a");
6047      btn.href = clickUrl;
6048      btn.target = "_blank";
6049      btn.innerHTML  = buttonText;
6050      btn.className = "ReadMore ArticleTeaser_readMore";
6051      btn.setAttribute("data-pw-ev", "arena-more");
6052
6053      //$textWrapper[0].appendChild(btn);
6054      $textWrapper.append(btn);
6055    }
6056
6057    if (imgPos === "left") {
6058      const $parent = $iframe.parent();
6059      $parent.css({
6060        display: "flex",
6061        "align-items": "flex-start",
6062        "gap": "16px"
6063      });
6064
6065      // Responsive Mobile: auf kleinen Bildschirmen Block-Layout
6066      if (window.innerWidth <= 480) {
6067        $parent.css({ display: "block" });
6068      }
6069
6070      $iframe.after($textWrapper);
6071    } else if (imgPos === "right") {
6072      const $parent = $iframe.parent();
6073      $parent.css({
6074        display: "flex",
6075        "align-items": "flex-start",
6076        "gap": "16px"
6077      });
6078      $iframe.before($textWrapper);
6079    } else if (imgPos === "top") {
6080      $iframe.after($textWrapper);
6081    } else if (imgPos === "bottom") {
6082      $iframe.before($textWrapper);
6083    }
6084  });
6085});
6086
6087/**
6088 *  resizeIframe
6089 */
6090
6091const be_onGptSlotRenderEnded = function(event) {
6092  const $slot = $('#' + event.slot.getSlotElementId());
6093  const $iframe = $slot.find('iframe');
6094  if (event.isEmpty || $iframe.length === 0) return;
6095
6096  /** --- Check, wenn iFrame mit data-is-safeframe-Attribut, dann Parent-Element margin-bottom setzen (mit Retry) --- **/
6097  function setSafeFrameMargin($slot, retries = 3, delay = 300) {
6098    const $safeFrame = $slot.find('iframe[data-is-safeframe]');
6099    if ($safeFrame.length > 0) {
6100      $safeFrame.parent().css('margin-bottom', '1rem');
6101    } else if (retries > 0) {
6102      setTimeout(function() {
6103        setSafeFrameMargin($slot, retries - 1, delay);
6104      }, delay);
6105    }
6106  }
6107  setSafeFrameMargin($slot);
6108
6109  /**  --- NEU: FLUID CHECK ---// Prüfen, ob die Größe "fluid" ist. Falls ja, nichts am Iframe schrauben. */
6110  if (event.size === 'fluid' || (Array.isArray(event.size) && event.size[0] === 0)) {     return; }
6111
6112  const w = event.size[0], h = event.size[1], ratio = h / w;
6113  const isFloorAd = $slot.hasClass('Ad-FloorAd') || $slot.closest('.Ad-FloorAd').length > 0;
6114
6115  const adjustAdSize = function () {
6116    const containerWidth = $slot.parent().width() || 0;
6117    const viewportWidth = $(window).width() - 15;
6118    const adPosition = String($iframe.data('ad_position') || '').toLowerCase();
6119    const isBtaStageSlot = ['bta5', 'bta6', 'bta7'].includes(adPosition);
6120
6121    // Nicht-FloorAds nur am Viewport begrenzen, da Parent-Container oft schmaler sind.
6122    const availableSpace = isFloorAd ? Math.min(containerWidth, viewportWidth) : viewportWidth;
6123
6124    if (!isBtaStageSlot) {
6125      const targetWidth = w > availableSpace ? availableSpace : w;
6126      const targetHeight = w > availableSpace ? (availableSpace * ratio) : h;
6127
6128      $iframe.css({
6129        'width': targetWidth + 'px',
6130        'max-width': 'none',
6131        'height': targetHeight + 'px',
6132        'display': 'block'
6133      });
6134    }
6135
6136    // Zentrierung für Bühne (nicht FloorAd)
6137    if (!isFloorAd) {
6138      $iframe.css({'margin-left': 'auto', 'margin-right': 'auto'});
6139    }
6140
6141    function isValidPxValue(val) {
6142      return val && !["0", "NULL", ""].includes(val);
6143    }
6144
6145    const pxLeftValue = $iframe.data('pxleft');
6146    if (isValidPxValue(pxLeftValue)) {
6147      $iframe.css('margin-left', pxLeftValue + 'px');
6148    }
6149
6150    const pxRightValue = $iframe.data('pxright');
6151    if (isValidPxValue(pxRightValue)) {
6152      $iframe.css('margin-right', pxRightValue + 'px');
6153    }
6154
6155  };
6156
6157  const injectStyles = function() {
6158    try {
6159      const doc = $iframe[0].contentDocument || $iframe[0].contentWindow.document;
6160      if (doc && !doc.getElementById('ad-res-style')) {
6161        const style = doc.createElement('style');
6162        style.id = 'ad-res-style';
6163        style.innerHTML = 'img, canvas { max-width: 100% !important; height: auto !important; display: block; margin: 0 auto; } body { margin: 0; padding: 0; }';
6164        doc.head.appendChild(style);
6165      }
6166    } catch (e) {}
6167  };
6168
6169  adjustAdSize();
6170  injectStyles();
6171  $iframe.on('load', injectStyles);
6172  $(window).off('resize.' + event.slot.getSlotElementId()).on('resize.' + event.slot.getSlotElementId(), adjustAdSize);
6173
6174  // Fallback: Auf manchen Seiten wird insertAdvTextDiv zu frueh getriggert.
6175  // Wenn der Billboard-Slot jetzt da ist, aber noch kein Ad_text hat, erneut triggern.
6176  if ($slot.is('#renderSlot_Billboard, #renderSlot_Mobil-Billboard') && $slot.find('.Ad_text').length === 0) {
6177    setTimeout(function() {
6178      $(document).trigger('insertAdvTextDiv');
6179    }, 0);
6180  }
6181
6182  if ($slot.closest('.slick-track').length) { $('.SliderBannerArticleDetail_dots').show(); }
6183};
6184
6185if (window.googletag && typeof window.googletag.pubads === 'function' &&
6186    typeof window.googletag.pubads().addEventListener === 'function') {
6187  window.googletag.pubads().addEventListener('slotRenderEnded', be_onGptSlotRenderEnded);
6188} else if (window.googletag && Array.isArray(window.googletag.cmd)) {
6189  window.googletag.cmd.push(function() {
6190    if (window.googletag && typeof window.googletag.pubads === 'function' &&
6191        typeof window.googletag.pubads().addEventListener === 'function') {
6192      window.googletag.pubads().addEventListener('slotRenderEnded', be_onGptSlotRenderEnded);
6193    }
6194  });
6195}
6196
6197/**
6198 * adSliderControl
6199 */
6200$(document).one("adSliderControl", function(event) {
6201  /**
6202   *  Nur geschaltete Banner in Banner-Slider auf Artikelseite zeigen.
6203   *  Wenn es nur einen geschalteten Banner gibt, dann wird Auto-Slide deaktiviert
6204   *  und zum Slide mit dem Banner gesprungen. Sind beide Banner vorhanden,
6205   *  wird der Auto-Slide des Sliders wieder aktiviert.
6206   *
6207   *  Eine Umsetzung mit sowohl "unslick" als auch "slickRemove" funktionierte nicht,
6208   *  da dann alle Werbemittel nicht mehr sichtbar waren. Auch vornherein den Slider nur
6209   *  anzuwenden, wenn es mehr als einen Banner gibt, hatte nicht funktioniert, da das Banner-JS bereits
6210   *  verarbeitet war.
6211   */
6212  'use strict';
6213  const bannerSlider = '.SliderBannerArticleDetail';
6214  const bannerSliderDots = bannerSlider + '_dots';
6215  const slideSelectors = ['slick-slide00', 'slick-slide01'];
6216  const slideState = [];
6217
6218  $(bannerSliderDots).css('display', 'none');
6219  $(bannerSlider).slick('slickPause');
6220  $(bannerSlider).slick('slickGoTo', 0); /* Slider refreshen, damit Slides aufrufbar sind */
6221
6222  const waitForEl = function (slideSelectors, callback) {
6223    const startTimeInMs = Date.now();
6224
6225    for (let i = 0; i < slideSelectors.length; i++) {
6226      const selectorObj = document.getElementById(slideSelectors[i]);
6227      if (selectorObj && selectorObj.children.length && selectorObj.children[0].tagName === 'DIV') {
6228        slideState[i] = 1;
6229      } else {
6230        slideState[i] = 0;
6231      }
6232    }
6233
6234    if (slideState[0] === 1 && slideState[1] === 0) {
6235      $(bannerSlider).slick('slickGoTo', 0);
6236      callback();
6237      return;
6238    } else if (slideState[0] === 0 && slideState[1] === 1) {
6239      $(bannerSlider).slick('slickGoTo', 1);
6240      callback();
6241      return;
6242    } else if (slideState[0] === 1 && slideState[1] === 1) {
6243      $(bannerSlider).slick('slickPlay');
6244      $(bannerSliderDots + ' li').css('padding-left', '0');
6245      $(bannerSliderDots).css('display', 'block');
6246      callback();
6247      return;
6248    } else {
6249      setTimeout(function () {
6250        if (Date.now() - startTimeInMs > 10000) {
6251          /*Callback spätestens nach 10 Sekunden abbrechen */
6252          return;
6253        }
6254        waitForEl(slideSelectors, callback);
6255      }, 10);
6256    }
6257  };
6258
6259  waitForEl(slideSelectors, function() {});
6260
6261});
6262
6263/**
6264 * halfpage
6265 */
6266$(document).on("halfpage", function(event, be_containerClass){
6267
6268  /*
6269   const $iframes = $("iframe.halfpage");
6270
6271   $iframes.each(function(){
6272   const slot = $(this).parent().parent();
6273   slot.css("width","300px");
6274   });
6275   */
6276
6277  function halfpageResize() {
6278    /* Class-Name für sitebarContainer und .page-footer entsprechend einsetzen */
6279    const halfpageContainer = '.Ad-skyscraper-right';
6280
6281    const stageWidth = $("." + be_containerClass).width();
6282    let halfpageSpace = ($(this).width() - stageWidth) / 2;
6283    halfpageSpace = Math.floor(halfpageSpace) -15;
6284
6285    if ($(halfpageContainer + ' iframe.responsiveFrame').data("width") > halfpageSpace ) {
6286      $(halfpageContainer + ' iframe.responsiveFrame').width(halfpageSpace);
6287    }
6288
6289    const halfpageAd = $('.halfpage').parent().parent();
6290    const halfpage = $('.halfpage');
6291    const halfpage_width = halfpage.data('width');
6292
6293    if (halfpage_width > halfpageSpace ) {
6294      halfpage.width(halfpageSpace);
6295      halfpageAd.css("width",halfpageSpace+"px");
6296      halfpage.css("width",halfpageSpace+"px");
6297
6298      $(document).ready(function(){
6299        const halfpageDOM = halfpage.contents();
6300        halfpageDOM.find("iframe").css("width", halfpageSpace+"px");
6301        const currWinHeight = $(window).height();
6302        halfpageDOM.find("iframe").css("max-height", currWinHeight+"px");
6303      });
6304    }
6305  }
6306
6307  const halfpageAd = $('.halfpage').parent().parent();
6308  const halfpage    = $('.halfpage');
6309
6310  const halfpage_width = halfpage.data('width');
6311  halfpageAd.css("width",halfpage_width+'px');
6312  halfpageAd.css("max-width",halfpage_width+'px');
6313
6314  const halfpage_fixed = halfpage.data('fixed');
6315  if (halfpage_fixed != 'false') {
6316    halfpageAd.css("position","fixed");
6317  }
6318
6319  /* Resize halfpage when the window is resized */
6320  $( window ).resize( function() {
6321    halfpageResize();
6322    /* Resize to fix halfpage on page load. */
6323  }).resize();
6324
6325}
6325);
6326
6327
6328/**
6329 * floorAd
6330 */
6331$(document).on('floorAd', function(event) {
6332  //console.log('[DEBUG] floorAd Event ausgelöst:', event);
6333
6334  const floorAd = $('.floorAd').parent().parent();
6335  const floorAdIframe = $('.floorAd');
6336  const floorAdIframeContent = $('.floorAd').contents();
6337  const scroll_pos = floorAdIframe.data('display-at-pixel');
6338  const display_on_scroll = floorAdIframe.data('display-on-scroll');
6339  let isHidden = false;
6340
6341  /*
6342   console.log('[DEBUG] floorAd Variablen:', {
6343   floorAd,
6344   floorAdIframe,
6345   floorAdIframeContent,
6346   scroll_pos,
6347   display_on_scroll,
6348   center_ad,
6349   });
6350   */
6351
6352  floorAd.css('z-index', floorAdIframe.data('zindex'));
6353  if (display_on_scroll === "1" || display_on_scroll === 1 || display_on_scroll === true) {
6354    //console.log('[DEBUG] floorAd wird nur beim Scrollen angezeigt.');
6355    floorAd.css('display', 'none');
6356  }
6357
6358  floorAd.css('position', 'fixed');
6359  floorAd.css('bottom', '0');
6360  //floorAd.css('min-height', '90px'); // Fallback-Mindesthöhe
6361
6362  // Dynamische Höhe anhand des Bildes im iFrame setzen
6363  function setFloorAdHeightFromImage() {
6364    try {
6365      var iframe = floorAdIframe.get(0);
6366      if (!iframe || !iframe.contentWindow || !iframe.contentDocument) return;
6367      var doc = iframe.contentDocument || iframe.contentWindow.document;
6368      var img = doc.querySelector('img');
6369      if (img && img.complete) {
6370        var imgHeight = img.naturalHeight || img.height;
6371        if (imgHeight > 0) {
6372          floorAd.height(imgHeight);
6373          floorAdIframe.height(imgHeight);
6374        }
6375      } else if (img) {
6376        img.addEventListener('load', function() {
6377          var imgHeight = img.naturalHeight || img.height;
6378          if (imgHeight > 0) {
6379            floorAd.height(imgHeight);
6380            floorAdIframe.height(imgHeight);
6381          }
6382        });
6383      }
6384    } catch (e) {
6385      // Cross-Origin: keine Aktion möglich
6386    }
6387  }
6388
6389  // Nach dem Laden des iFrames prüfen
6390  floorAdIframe.on('load', function() {
6391    setFloorAdHeightFromImage();
6392  });
6393  // Falls das iFrame schon geladen ist
6394  setFloorAdHeightFromImage();
6395
6396  $(window).on('resize', function() {
6397    $('#renderSlot_Layer-Ad, #renderSlot_Layer-Ad > div, #renderSlot_Layer-Ad iframe').css({
6398      width: '100%',
6399      minWidth: 0,
6400      maxWidth: '100vw',
6401      boxSizing: 'border-box'
6402    });
6403  }).trigger('resize');
6404
6405  if (display_on_scroll == 1 || display_on_scroll === true) {
6406    window.onscroll = function() {
6407      if (window && !isHidden) {
6408        var currentScroll = window.pageYOffset !== undefined ? window.pageYOffset : document.documentElement.scrollTop;
6409        if (currentScroll > scroll_pos) {
6410          $(floorAd).fadeIn("slow");
6411        } else if (currentScroll < scroll_pos) {
6412          $(floorAd).fadeOut("slow");
6413        }
6414      }
6415    };
6416  }
6417
6418  floorAdIframeContent.find('.CloseAd').click(function() {
6419    $(floorAd).fadeOut('slow');
6420    isHidden = true;
6421  });
6422
6423});
6424
6425
6426/**
6427 * layerAd
6428 */
6429$(document).on('layerAd', function(event) {
6430  const layerAd = $('.layerAd').parent().parent();
6431  const layerAdWrapper = $('.layerAd').parent();
6432  const layerAdIframe = $('.layerAd');
6433  const ad_close_time = layerAdIframe.data('ad-close-time');
6434
6435  const bg_color = layerAdIframe.data('bgcolor');
6436  const bg_opacity = layerAdIframe.data('bgopacity');
6437
6438  const align_banner = layerAdIframe.data('align');
6439  const vertical_px_offset = layerAdIframe.data('vertical-px-offset');
6440  const vertical_pos = layerAdIframe.data('vertical-pos');
6441  const horizontal_px_offset = layerAdIframe.data('horizontal-px-offset');
6442  const horizontal_pos = layerAdIframe.data('horizontal-pos');
6443
6444  function convertHex(hex,opacity){
6445    hex = hex.replace('#','');
6446    r = parseInt(hex.substring(0,2), 16);
6447    g = parseInt(hex.substring(2,4), 16);
6448    b = parseInt(hex.substring(4,6), 16);
6449
6450    return 'rgba(' + r + ',' + g + ',' + b + ',' + opacity / 100 + ')';
6451  }
6452
6453  const bgColor_rgb = convertHex(bg_color, bg_opacity);
6454
6455  layerAd.css('width', '100%');
6456  layerAd.css('height', '100%');
6457  layerAd.css('background', bgColor_rgb);
6458  layerAd.css('position', 'fixed');
6459  layerAd.css('top', '0');
6460  layerAd.css('left', '0');
6461  layerAd.css('z-index', '12000');
6462
6463  layerAd.css('display', 'flex');
6464  layerAd.css('display', '-webkit-box');
6465  layerAd.css('display', '-webkit-flex');
6466  layerAd.css('display', '-ms-flexbox');
6467
6468  layerAd.css('-webkit-box-align', 'center');
6469  layerAd.css('-webkit-align-items', 'center');
6470  layerAd.css('-ms-flex-align', 'center');
6471  layerAd.css('align-items', 'center');
6472
6473  layerAd.css('-webkit-box-pack', 'center');
6474  layerAd.css('-webkit-justify-content', 'center');
6475  layerAd.css('-ms-flex-pack', 'center');
6476  layerAd.css('justify-content', 'center');
6477
6478
6479  layerAd.css('z-index', '12000');
6480
6481  layerAdWrapper.css('position', 'absolute');
6482  layerAdWrapper.prepend("<div class='layer_close' style='z-index: 13000; position:absolute; color: #ffffff; top:0; right:0;'><i title =\"schließen\" class=\"fa fa-close fa-2x\"></i></div>");
6483
6484  layerAdWrapper.css('margin', 'auto');
6485
6486  if (align_banner == 1) {
6487    if (vertical_pos == 'bottom') {
6488      layerAdWrapper.css('margin-bottom', vertical_px_offset+'px');
6489    } else {
6490      layerAdWrapper.css('margin-top', vertical_px_offset+'px');
6491    }
6492    if (horizontal_pos == 'left') {
6493      layerAdWrapper.css('margin-left', horizontal_px_offset+'px');
6494    } else {
6495      layerAdWrapper.css('margin-right', horizontal_px_offset+'px');
6496    }
6497  }
6498
6499  function showLayerAd() {
6500    layerAd.show();
6501  }
6502
6503  function closeLayerAd() {
6504    layerAd.hide();
6505  }
6506
6507  if (ad_close_time > 0){
6508    setTimeout(function(){closeLayerAd();}, ad_close_time*1000);
6509  }
6510
6511  $( ".layer_close" ).click(function() {
6512    layerAd.hide();
6513  });
6514});
6515
6516/**
6517 * exitintent
6518 */
6519$(document).one("exitintent", function(event){
6520  $( "html" ).one( "mouseleave", function() {
6521    $("#LayerModal").addClass("show");
6522  });
6523});
6524
6525/**
6526 * changeBackgroundColor
6527 */
6528$(document).on('changeBackgroundColor',function(event){
6529  const iframe = $('.fireplace'),
6530    bg_color = iframe.data('bgcolor');
6531  $(".Body").css('background-color', bg_color);
6532});
6533
6534/**
6535 * isBackgroundClick
6536 * On Background click go to clickurl
6537 */
6538$(document).on('isBackgroundClick',function(event){
6539
6540  $("#usercentrics-root").click(function(event ) {
6541    event.stopPropagation();
6542  });
6543
6544  $(".PageFrame").click(function(event ) {
6545    event.stopPropagation();
6546  });
6547
6548  $("#uc-center-container").click(function(event ) {
6549    event.stopPropagation();
6550  });
6551
6552  $(".Body").click(function() {
6553    const iframe = $('.bgclickplace');
6554    const clickurl = iframe.data('clickurl');
6555    window.open(clickurl, '_blank');
6556  });
6557});
6558
6559/**
6560 * counterAd
6561 */
6562$(document).one('counterAd', function(event) {
6563  const counterAd = $('.counterAd').parent().parent();
6564  const counterAdIframe = $('.counterAd');
6565
6566  const pl_id = counterAdIframe.data('contentunit');
6567  const clickurl = counterAdIframe.data('clickurl');
6568  const enddatum = counterAdIframe.data('enddatum');
6569  const counterimage = counterAdIframe.data('counterimage');
6570  const layout = counterAdIframe.data('layout');
6571
6572  let countertext = '';
6573
6574  countertext = countertext + '<div id=\"'+pl_id+'\" class="noanzeige" width=\"300\" height=\"300\">\n';
6575  countertext = countertext + '	<div>\n' ;
6576  countertext = countertext + '		<a target=\"_blank\" href=\"'+clickurl+'\">\n';
6577  if(typeof layout !== 'undefined' && layout === 'image') {
6578    countertext = countertext + '			<img src=\"' + counterimage + '\" title=\"\" alt=\"\" border=\"0\" width=\"300\" height=\"150\"/>\n';
6579  }
6580  countertext = countertext + '		</a>\n';
6581  countertext = countertext + '		<div class=\"banner_counter\" border=\"0\" width=\"300\" height=\"150\" style=\"max-width: 300px !important;\"> 	\n';
6582  countertext = countertext + '			<span id=\"clockline\"></span>\n';
6583  countertext = countertext + '				<div id=\"banner_counter\"></div>\n';
6584  countertext = countertext + '			<div  id=\"name_time_block\">\n';
6585  countertext = countertext + '				<span class=\"name_time\">Tage</span>\n';
6586  countertext = countertext + '				<span class=\"name_time\">Stunden</span>\n';
6587  countertext = countertext + '				<span class=\"name_time\">Minuten</span>\n';
6588  countertext = countertext + '			</div>\n';
6589  countertext = countertext + '		</div>	  \n';
6590  countertext = countertext + '	 \n';
6591  countertext = countertext + '	</div>\n';
6592  countertext = countertext + '\n';
6593  countertext = countertext + '</div>\n';
6594  counterAd.append(countertext);
6595  if(typeof layout !== 'undefined' && layout === 'image'){
6596    counterAdIframe.css("display","none");
6597  }
6598  counterAd.css('margin-top', '10px');
6599  $('.noanzeige').not(':first').remove();
6600  if(typeof jQuery == "function"){
6601    $(function() {
6602      $(document).trigger( "counter", enddatum);
6603    });
6604  }
6605
6606  $( counterAd ).closest('div').next().find('.line').removeClass("line");
6607});
6608
6609/**
6610 * counter
6611 */
6612$(document).on("counter", function(event, endtime){
6613
6614  /* Datum mit Punkt */
6615  let iso_end_date;
6616  if (endtime.match(/\./) ) {
6617    let iso_end_dateArr = endtime.split(".");
6618
6619    /* Umwandlung in Iso-Format */
6620    if (iso_end_dateArr[2] < 100) iso_end_dateArr[2] = "20" + iso_end_dateArr[2];
6621    iso_end_date = iso_end_dateArr[2] + "-" + iso_end_dateArr[0] + "-" +iso_end_dateArr[1];
6622
6623    /* Datum im Iso-Format, z.B. 2020-11-09 */
6624  } else {
6625    iso_end_date = endtime;
6626  }
6627
6628  const end = new Date(iso_end_date);
6629
6630  const _second = 1000;
6631  const _minute = _second * 60;
6632  const _hour = _minute * 60;
6633  const _day = _hour * 24;
6634  let timer;
6635
6636  function showRemaining() {
6637    const now = new Date();
6638    now.setHours(now.getHours() +1);
6639
6640    const distance = end - now;
6641    if (distance < 0) {
6642
6643      clearInterval(timer);
6644      document.getElementById('banner_counter').innerHTML = '<span class="time">0</span> ';
6645      document.getElementById('banner_counter').innerHTML += '<span class="time">0</span> ';
6646      document.getElementById('banner_counter').innerHTML += '<span class="time">0</span> ';
6647      return;
6648    }
6649    const days = Math.floor(distance / _day);
6650    const hours = Math.floor((distance % _day) / _hour);
6651    const minutes = Math.floor((distance % _hour) / _minute);
6652
6653    document.getElementById('banner_counter').innerHTML = '<span class="time">' + days + '</span> ';
6654    document.getElementById('banner_counter').innerHTML += '<span class="time">' + hours + '</span> ';
6655    document.getElementById('banner_counter').innerHTML += '<span class="time">' + minutes + '</span> ';
6656
6657  }
6658  timer = setInterval(showRemaining, 1000);
6659
6660});
6661
6662/**
6663 * centerIframe
6664 */
6665$(document).on('centerIframe', function(event){
6666  const iframe = $('.centeredFrame'),
6667    container = iframe.parent();
6668
6669  container.css('display', 'flex');
6670  container.css('flex-flow','column');
6671  iframe.css('align-self','center');
6672});
6673
6674/**
6675 * blockadvertisement
6676 */
6677$(document).on("blockadvertisement", function(event){
6678
6679  const iframe = $('.blockadvertisement');
6680  let container = iframe.parent();
6681  container.css("display","none");
6682});
6683
6684/**
6685 * wallpapercolor
6686 * Einfärben des body für Wallpaper
6687 */
6688$(document).on("wallpapercolor", function(event){
6689
6690  const iframe = $('.wallpaper_banner');
6691  const wallpapercolor = iframe.data("wallpapercolor");
6692  $('body').css("background-color",wallpapercolor);
6693
6694});
6695
6696/**
6697 * advertOnImage
6698 */
6699$(document).one("advertOnImage", function(event){
6700  const slot = $('[id^="renderSlot_Rectangle-Online-Specials"]');
6701  if (slot.hasClass("Ad-mediumRectangleStageTeaserAdvert")) {
6702    if (slot.children('div').length > 0) {
6703      slot.parent().css('padding', '5px');
6704      slot.parent().css('background-color', '#fff');
6705    }
6706
6707  }
6708
6709});
6710
6711/**
6712 * be_sitebarResize
6713 */
6714function be_sitebarResize(wideLayout, sitebarBid) {
6715  const browser_scrollbar_width = 0;
6716  let offsetLeft = 460;
6717  let outerWidth = 980;
6718  const sitebarContainer = '.Ad-skyscraper-right';
6719  if (($('.SiteFooter').length) && (!wideLayout)) {
6720    offsetLeft = $('.SiteFooter').offset().left + browser_scrollbar_width;
6721    outerWidth = $('.SiteFooter').outerWidth();
6722  } else if (($('.PageGallery').length) && (!wideLayout)) {
6723    offsetLeft = $('.PageGallery').offset().left + browser_scrollbar_width;
6724    outerWidth = $('.PageGallery').outerWidth();
6725  }
6726  if (wideLayout === true) {
6727    let siteHeader = document.querySelector('.SiteHeader') || document.querySelector('.SiteHeaderSticky_firstLine-inner');
6728    if (siteHeader) {
6729      let rect = siteHeader.getBoundingClientRect();
6730      offsetLeft = rect.left + browser_scrollbar_width;
6731
6732      let siteHeaderStyles = window.getComputedStyle(siteHeader);
6733      outerWidth = parseFloat(siteHeaderStyles.getPropertyValue('width'));
6734    }
6735  }
6736
6737  let rightOffset = $(this).width() - (offsetLeft + outerWidth);
6738  rightOffset = Math.floor(rightOffset);
6739
6740  if ($(sitebarContainer + ' iframe.responsiveFrame').data("width") > rightOffset ) {
6741    $(sitebarContainer + ' iframe.responsiveFrame').width(rightOffset);
6742  }
6743
6744  const iframeEl = document.querySelector('iframe.sitebar');
6745  let iFrameElDocument = iframeEl.contentDocument || iframeEl.contentWindow.document;
6746  let imgSitebar = iFrameElDocument.getElementById("sitebar"+sitebarBid);
6747  let imgSky = iFrameElDocument.getElementById("sky"+sitebarBid);
6748  const offsetLowLmt = 135;
6749  const offsetUpLmt = 215;
6750
6751  if (imgSky && imgSitebar) {
6752    if ((offsetLeft >= offsetLowLmt) && (offsetLeft < offsetUpLmt)) {
6753      imgSitebar.style.display = "none";
6754      imgSky.style.display = "inline";
6755    } else if (offsetLeft >= offsetUpLmt) {
6756      imgSitebar.style.display = "inline";
6757      imgSky.style.display = "none";
6758    }
6759    else if (offsetLeft < offsetLowLmt) {
6760      imgSitebar.style.display = "none";
6761      imgSky.style.display = "none";
6762    }
6763  }
6764
6765
6766  const sitebarAd = $('.sitebar').parent().parent();
6767  const sitebar = $('.sitebar');
6768  const sitebar_width = sitebar.data('width');
6769
6770
6771  if (sitebar_width > rightOffset ) {
6772    sitebar.width(rightOffset);
6773    sitebarAd.css("width",rightOffset+"px");
6774    sitebar.css("width",rightOffset+"px");
6775
6776    $(document).ready(function(){
6777      const sitebarDOM = sitebar.contents();
6778      sitebarDOM.find("iframe").css("width", rightOffset+"px");
6779      const currWinHeight = $(window).height();
6780      sitebarDOM.find("iframe").css("max-height", currWinHeight+"px");
6781    });
6782  }
6783}
6784
6785/**
6786 * sitebar
6787 */
6788$(document).on('sitebar',function(event, wideLayout) {
6789  const sitebarAd = $('.sitebar').parent().parent();
6790  const sitebar = $('.sitebar');
6791  const sitebarBid = sitebar[0].getAttribute("data-bid");
6792  const sbAdMarginTop = sitebar[0].getAttribute("data-margintop");
6793  if (sbAdMarginTop !== "0" && sbAdMarginTop !== "NULL") {
6794    sitebarAd.css("margin-top",sbAdMarginTop+'px');
6795  }
6796
6797  if ( sitebar.data('bgcolor') ) {
6798    const bg_color = sitebar.data('bgcolor');
6799    if (bg_color.startsWith("#")) {
6800      document.getElementsByTagName('body')[0].style.backgroundColor = bg_color;
6801    }
6802  }
6803
6804  const sitebar_width = sitebar.data('width');
6805  sitebarAd.css("width",sitebar_width+'px');
6806  sitebarAd.css("max-width",sitebar_width+'px');
6807  sitebar.css("max-height",'100vh');
6808
6809  const sitebar_fixed = sitebar.data('fixed');
6810  if (sitebar_fixed != 'false') {
6811    sitebarAd.css("position","fixed");
6812  }
6813
6814  /* Resize sitebar when the window is resized */
6815  $( window ).resize( function() {
6816    be_sitebarResize(wideLayout, sitebarBid);
6817    /* Resize to fix sitebar on page load. */
6818  }).resize();
6819
6820}
6820);
6821
6822/**
6823 * be_sitebarLeftResize
6824 */
6825function be_sitebarLeftResize(wideLayout, sitebarBid) {
6826  const browser_scrollbar_width = 15;
6827  let offsetLeft = 460;
6828  let outerWidth = 980;
6829  const sitebarLeftContainer = '.Ad-skyscraper-left';
6830  if (($('.SiteFooter').length) && (!wideLayout)) {
6831    offsetLeft = $('.SiteFooter').offset().left + browser_scrollbar_width;
6832    outerWidth = $('.SiteFooter').outerWidth();
6833  } else if (($('.PageGallery').length) && (!wideLayout)) {
6834    offsetLeft = $('.PageGallery').offset().left + browser_scrollbar_width;
6835    outerWidth = $('.PageGallery').outerWidth();
6836  }
6837  if (wideLayout === true) {
6838    let siteHeader = document.querySelector('.SiteHeader') || document.querySelector('.SiteHeaderSticky_firstLine-inner');
6839    if (siteHeader) {
6840      let rect = siteHeader.getBoundingClientRect();
6841      offsetLeft = rect.left + browser_scrollbar_width;
6842
6843      let siteHeaderStyles = window.getComputedStyle(siteHeader);
6844      outerWidth = parseFloat(siteHeaderStyles.getPropertyValue('width'));
6845    }
6846  }
6847
6848  let leftOffset = offsetLeft;
6849  leftOffset = Math.round(leftOffset);
6850
6851  if ($(sitebarLeftContainer + ' iframe.responsiveFrame').data("width") > leftOffset ) {
6852    $(sitebarLeftContainer + ' iframe.responsiveFrame').width(leftOffset);
6853  }
6854
6855  const iframeElLeft = document.querySelector('iframe.sitebarLeft');
6856  let iFrameElLeftDocument = iframeElLeft.contentDocument || iframeElLeft.contentWindow.document;
6857  let imgSitebar = iFrameElLeftDocument.getElementById("sitebar"+sitebarBid);
6858  let imgSky = iFrameElLeftDocument.getElementById("sky"+sitebarBid);
6859  const offsetLowLmt = 140;
6860  const offsetUpLmt = 320;
6861
6862  if (imgSky && imgSitebar) {
6863    if ((offsetLeft >= offsetLowLmt) && (offsetLeft < offsetUpLmt)) {
6864      imgSitebar.style.display = "none";
6865      imgSky.style.display = "inline";
6866    } else if (offsetLeft >= offsetUpLmt) {
6867      imgSitebar.style.display = "inline";
6868      imgSky.style.display = "none";
6869    }
6870    else if (offsetLeft < offsetLowLmt) {
6871      imgSitebar.style.display = "none";
6872      imgSky.style.display = "none";
6873    }
6874  }
6875
6876
6877  const sitebarAd = $('.sitebarLeft').parent().parent();
6878  const sitebar = $('.sitebarLeft');
6879  const sitebar_width = sitebar.data('width');
6880  const hideWidth = (sitebar.data('hidewidth') !== undefined ? sitebar.data('hidewidth') : 0) + 15;
6881
6882  if (leftOffset <= hideWidth) {
6883    sitebarAd.css('display', 'none');
6884    return;
6885  } else {
6886    sitebarAd.css('display', 'block');
6887  }
6888
6889
6890  let sidebarLeftMargin = Math.round(leftOffset);
6891  sitebarAd.css("margin-left","0px");
6892  let currSitebar_width = sitebarAd[0].offsetWidth;
6893
6894  if (sitebar_width >= leftOffset ) {
6895    leftOffset = leftOffset-browser_scrollbar_width;
6896
6897    sitebar.width(leftOffset);
6898    sitebarAd.css("width",leftOffset+"px");
6899    sitebar.css("width",leftOffset+"px");
6900
6901    $(document).ready(function(){
6902      const sitebarDOM = sitebar.contents();
6903      sitebarDOM.find("iframe").css("width", leftOffset+"px");
6904      const currWinHeight = $(window).height();
6905      sitebarDOM.find("iframe").css("max-height", currWinHeight+"px");
6906    });
6907  } else if (sitebar_width < leftOffset) {
6908    let sbMarginLeft = leftOffset - browser_scrollbar_width - sitebar_width;
6909
6910    sitebarAd.css("width",sitebar_width+"px");
6911    sitebar.css("width",sitebar_width+"px");
6912    sitebarAd.css("margin-left",sbMarginLeft+"px");
6913  }
6914}
6915
6916/**
6917 * sitebarLeft
6918 */
6919$(document).on('sitebarLeft',function(event, wideLayout) {
6920  const sitebarLeftAd = $('.sitebarLeft').parent().parent();
6921  const sitebarLeft = $('.sitebarLeft');
6922  const sitebarLeftBid = sitebarLeft[0].getAttribute("data-bid");
6923  const leftSitebarSlot = document.getElementById("renderSlot_Skyscraper-links");
6924  leftSitebarSlot.classList.add("leftSitebarSlot");
6925
6926  const sitebarLeft_width = sitebarLeft.data('width');
6927  sitebarLeftAd.css("width",sitebarLeft_width+'px');
6928  sitebarLeftAd.css("max-width",sitebarLeft_width+'px');
6929
6930  const sitebarLeft_fixed = sitebarLeft.data('fixed');
6931  if (sitebarLeft_fixed != 'false') {
6932    sitebarLeftAd.css("position","fixed");
6933  }
6934
6935  const sbAdLeftMarginTop = sitebarLeft[0].getAttribute("data-margintop");
6936  if (sbAdLeftMarginTop !== "0" && sbAdLeftMarginTop !== "NULL") {
6937    sitebarLeftAd.css("margin-top",sbAdLeftMarginTop+'px');
6938  }
6939
6940  /* Resize sitebarLeft when the window is resized */
6941  $( window ).resize( function() {
6942    be_sitebarLeftResize(wideLayout, sitebarLeftBid);
6943    /* Resize to fix sitebar on page load. */
6944  }).resize();
6945
6946  window.addEventListener('load', function() {
6947    be_sitebarLeftResize(wideLayout, sitebarLeftBid);
6948  });
6949
6950  window.onload = function() {
6951    be_sitebarLeftResize(wideLayout, sitebarLeftBid);
6952  };
6953
6954
6955});
6956
6957/**
6958 * teadsResize
6959 * teads Videos
6960 */
6961$(document).on('teadsResize',function(event){
6962  const iframe = $('.video_ad'),
6963    aspect_ratio = 1.7,
6964    wrapper = iframe.parent();
6965
6966  iframe.height(iframe.width()/aspect_ratio);
6967
6968  wrapper.css('display', 'flex');
6969  wrapper.css('flex-flow','column');
6970  iframe.css('align-self','center');
6971});
6972
6973/**
6974 * pushdown
6975 */
6976$(document).on("pushdown", function(event, elementclass){
6977
6978  const pushdown_iframe = $("." + elementclass);
6979  const pushdown_container = pushdown_iframe.parent();
6980
6981  const ad_height = pushdown_iframe.data("height");
6982  const ad_width = pushdown_iframe.data("width");
6983  const ad_margin_bottom = parseInt(pushdown_container.css("height")) - ad_height;
6984  const pushdownheight = pushdown_iframe.data("pushdownheight") + ad_margin_bottom;
6985  const pushdowntime = pushdown_iframe.data("pushdowntime"); /* Dauer der Animation */
6986  const closingtime = pushdown_iframe.data("closingtime") * 1000;   /* Initiales Einfahren */
6987  const pushdown_center_ad = pushdown_iframe.data("center_ad");
6988  const pushdown_func = pushdown_iframe.data("pushdown-func") ? 1 : 0;
6989  const no_initialpushdown = pushdown_iframe.data("no_initialpushdown") ? 1 : 0;
6990
6991  /* Werbemittel zentrieren */
6992  if(pushdown_center_ad == 1){
6993    pushdown_container.css("text-align","center");
6994  }
6995
6996  if(pushdown_func == 0){
6997
6998    /* prevent too large iFrame-height on smaller stage */
6999    let pushdown_iframeWidth = pushdown_iframe[0].clientWidth;
7000    let pushdownRatio = ad_height / ad_width;
7001    let pushdownHeight = Math.ceil(pushdown_iframeWidth * pushdownRatio);
7002    pushdown_iframe.css("height",pushdownHeight + "px");
7003
7004    return;
7005  }
7006
7007  /* Nutzer-Handling */
7008  pushdown_iframe.on("mouseover", function(event){
7009    clearTimeout(waiting_for_closing);
7010    $(document).trigger('pushdown-animation', [pushdown_container, pushdown_iframe, '1', pushdownheight]);
7011
7012    pushdown_iframe.one("mouseout", function(event){
7013      $(document).trigger('pushdown-animation', [pushdown_container, pushdown_iframe, '1', ad_height]);
7014    });
7015  });
7016
7017  /* Initiales Ausfahren */
7018  if(no_initialpushdown != 1) {
7019    $(document).trigger('pushdown-animation', [pushdown_container, pushdown_iframe, pushdowntime, pushdownheight]);
7020  }
7021
7022  /* Einfahren nach initialem Ausfahren */
7023  let waiting_for_closing = window.setTimeout(function(){
7024    $(document).trigger('pushdown-animation', [pushdown_container, pushdown_iframe, pushdowntime, ad_height]);
7025  }, closingtime);
7026
7027});
7028
7029/**
7030 * pushdown-animation
7031 */
7032$(document).on("pushdown-animation", function(event, pushdown_container, pushdown_iframe, movingtime, newheight){
7033
7034  pushdown_container.css({
7035    height           : newheight,
7036    WebkitTransition : 'height ' + movingtime + 's ease-in-out',
7037    MozTransition    : 'height ' + movingtime + 's ease-in-out',
7038    MsTransition     : 'height ' + movingtime + 's ease-in-out',
7039    OTransition      : 'height ' + movingtime + 's ease-in-out',
7040    transition       : 'height ' + movingtime + 's ease-in-out'
7041  });
7042  pushdown_iframe.css({
7043    height           : newheight,
7044    WebkitTransition : 'height ' + movingtime + 's ease-in-out',
7045    MozTransition    : 'height ' + movingtime + 's ease-in-out',
7046    MsTransition     : 'height ' + movingtime + 's ease-in-out',
7047    OTransition      : 'height ' + movingtime + 's ease-in-out',
7048    transition       : 'height ' + movingtime + 's ease-in-out'
7049  });
7050});
7051
7052/**
7053 * parallax_outstream
7054 */
7055$(document).on("parallax_outstream", function(event){
7056  const iframe = $('.parallax_outstream');
7057  const container = iframe.parent();
7058  container.attr("id","parallax_outstream");
7059  iframe.css("height","0px");
7060  iframe.css("width","0px");
7061});
7062
7063/**
7064 * dynamic_sitebar
7065 */
7066$(document).on("dynamic_sitebar", function(event){
7067  const iframe = $('.dynamic_sitebar');
7068  const container = iframe.parent();
7069  const dynamic_space = ($('.PageFrame').outerWidth(true) - $('.PageFrame').outerWidth()) / 2;
7070  container.css("width", dynamic_space +"px");
7071  container.css("position","fixed");
7072});
7073
7074/**
7075 * insertAdvTextDiv
7076 *
7077 * "Anzeige"-Position und Border an Werbemittelgroesse positionieren/anpassen
7078 */
7079$(document).on("insertAdvTextDiv", function(event) {
7080  const $iframes = $('[id^="renderSlot_"] iframe');
7081  let el = $('<div class="Ad_text"></div>');
7082
7083  $iframes.each(function () {
7084    if ($(this).data("width") == '1') {
7085      $(this).parent('div').css('height', '0');
7086      return;
7087    }
7088
7089    const slot = $(this).parent().parent();
7090    if ($(this).parent().parent().length) {
7091      if (slot.attr('id').match(/renderSlot_(Super*|Sky*|Rectangle-Gal|Mobil-Rectangle-Gal)/)) {
7092        return;
7093      }
7094    } else {
7095      return;
7096    }
7097    if (slot.parent().length && slot.parent().hasClass() ){
7098      if(slot.parent().attr('class').match(/slick-track/)){
7099        /* SliderBannerArticleDetail_dots nur einblenden, wenn auch was geschaltet ist */
7100        $('.SliderBannerArticleDetail_dots').css('display', 'block');
7101      }
7102    }
7103
7104    let ad_text_div = $(this).parent().find('.Ad_text');
7105    let ad_text_parallax_div = $(this).parent().parent().find('.Ad_text');
7106
7107    ad_text_div.css('margin', '');
7108    if ($(this).hasClass('parallax')) {
7109
7110      if(!ad_text_parallax_div.length > 0){
7111        $(this).parent().parent('div').prepend(el);
7112        ad_text_parallax_div = $(this).parent().parent().find('.Ad_text');
7113      }
7114      ad_text_parallax_div.css("margin", "0 auto");
7115      ad_text_parallax_div.css("width", '100%');
7116      if ($(this).data("ad_text_bgc")) {
7117        ad_text_parallax_div.css("background-color", $(this).data("ad_text_bgc"));
7118      }
7119      if ($(this).data("ad_text_margintop")) {
7120        ad_text_parallax_div.css("margin-top", $(this).data("ad_text_margintop"));
7121      }
7122      if ($(this).data("ad_text_maxheight")) {
7123        ad_text_parallax_div.css("max-height", $(this).data("ad_text_maxheight"));
7124      }
7125      if ($(this).data("ad_text_noborder")) {
7126        ad_text_parallax_div.addClass('html5BannerBefore');
7127      }
7128      ad_text_parallax_div.css("z-index", '10');
7129    } else {
7130      if (!ad_text_div.length > 0) {
7131        $(this).parent('div').prepend(el);
7132        ad_text_div = $(this).parent().find('.Ad_text');
7133      }
7134      if (slot.attr('id').match(/renderSlot_(Rectangle-Aufmacher)/)) {
7135        ad_text_div.css("width", '100%');
7136      } else {
7137        const dataWidthRaw = $(this).data('width');
7138        const dataWidth = (dataWidthRaw !== undefined && dataWidthRaw !== null) ? String(dataWidthRaw).trim() : '';
7139        const widthAttr = parseInt($(this).attr('width'), 10) || 0;
7140        const cssWidth = parseInt($(this).css('width'), 10) || 0;
7141        const effectiveWidth = (dataWidth && dataWidth !== 'NULL' && dataWidth !== '0') ? dataWidth : (widthAttr || cssWidth || 0);
7142
7143        ad_text_div.css('width', /^\d+$/.test(String(effectiveWidth)) ? (effectiveWidth + 'px') : effectiveWidth);
7144        ad_text_div.css("margin", "0 auto");
7145      }
7146
7147    }
7148
7149    if (/[^-]?width\s?:\s?100%/.test($(this).attr('style'))) {
7150      ad_text_div.css("margin", "0 auto");
7151    }
7152    el = el.clone();
7153  });
7154});
7155
7156/**
7157 * fadeoutadvertisement
7158 * Hierüber kann eine Platzierung animiert ausgeblendet werden
7159 */
7160$(document).on("fadeoutadvertisement", function(event){
7161
7162  const iframe = $('.fadeoutadvertisement');
7163  let container = iframe.parent();
7164  container.animate({
7165    height: "0px"
7166  }, 2000, function() {
7167    container.css("display","none");
7168  });
7169
7170});
7171
7172/**
7173 * be_reduceBackgroundOpacity
7174 * @param element
7175 * @param opacity
7176 */
7177function be_reduceBackgroundOpacity(element, opacity) {
7178  let backgroundColor = element.style.backgroundColor;
7179  if (backgroundColor.substring(0, 4) === "rgba") {
7180    /* if rgba format is already used, just update the alpha value */
7181    backgroundColor = backgroundColor.replace(/[^,]+(?=\))/, opacity);
7182  } else {
7183    /* convert hexadecimal or RGB format to rgba format and add alpha value */
7184    let r = 0, g = 0, b = 0;
7185    if (backgroundColor.substring(0, 1) === "#") {
7186      /* convert hexadecimal to RGB */
7187      const hex = backgroundColor.substring(1);
7188      r = parseInt(hex.substring(0, 2), 16);
7189      g = parseInt(hex.substring(2, 4), 16);
7190      b = parseInt(hex.substring(4, 6), 16);
7191    } else if (backgroundColor.substring(0, 3) === "rgb") {
7192      /* extract RGB values from comma-separated string */
7193      const values = backgroundColor.match(/\d+/g);
7194      r = parseInt(values[0]);
7195      g = parseInt(values[1]);
7196      b = parseInt(values[2]);
7197    }
7198    /* convert RGB to rgba */
7199    backgroundColor = "rgba(" + r + ", " + g + ", " + b + ", " + opacity + ")";
7200  }
7201  element.style.backgroundColor = backgroundColor;
7202}
7203
7204/**
7205 * be_changeBGColor
7206 * @param element
7207 * @param color1
7208 * @param color2
7209 * @param mixVal
7210 */
7211function be_changeBGColor(element, color1, color2, mixVal) {
7212  const hexToRgb = function (hex) {
7213    const r = parseInt(hex.slice(1, 3), 16);
7214    const g = parseInt(hex.slice(3, 5), 16);
7215    const b = parseInt(hex.slice(5, 7), 16);
7216
7217    return [r, g, b];
7218  };
7219
7220  const rgbToHex = function (rgb) {
7221    const componentToHex = function (component) {
7222      const hex = component.toString();
7223      return hex.length == 1 ? "0" + hex : hex;
7224    };
7225
7226    const r = componentToHex(rgb[0]);
7227    const g = componentToHex(rgb[1]);
7228    const b = componentToHex(rgb[2]);
7229
7230    return "#" + r + g + b;
7231  };
7232
7233  const color1Rgb = hexToRgb(color1);
7234  const color2Rgb = hexToRgb(color2);
7235
7236  const r = Math.round((1 - mixVal) * color1Rgb[0] + mixVal * color2Rgb[0]);
7237  const g = Math.round((1 - mixVal) * color1Rgb[1] + mixVal * color2Rgb[1]);
7238  const b = Math.round((1 - mixVal) * color1Rgb[2] + mixVal * color2Rgb[2]);
7239
7240  element.style.backgroundColor = rgbToHex([r, g, b]);
7241}
7242
7243/**
7244 * be_rgbToHex
7245 * @param rgb
7246 * @returns {string}
7247 */
7248function be_rgbToHex(rgb) {
7249  /* Liefert nur die Ziffern 0-9 und a-f */
7250  function hex(x) {
7251    return ("0" + parseInt(x).toString(16)).slice(-2);
7252  }
7253
7254  /* Konvertiere den RGB-String in eine Array */
7255  const rgbArray = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
7256  /* Wandle die RGB-Werte in Hexadezimalwerte um */
7257  return "#" + hex(rgbArray[1]) + hex(rgbArray[2]) + hex(rgbArray[3]);
7258}
7259
7260/**
7261 * welcomeAdVideo
7262 * WelcomeAd mit Video-URL, wird beim Scrollen ausgeblendet, hat Close-Button
7263 */
7264$(document).on('welcomeAdVideo', function(event) {
7265
7266  let welcomeAdIframe = $('.welcomeFrame');
7267  let wcVideoSrc = welcomeAdIframe.data('videosrc');
7268  let wcVideoCodecs = welcomeAdIframe.data('videocodecs');
7269  let wcBgColor = welcomeAdIframe.data('bgcolor');
7270  let wcClickUrl = welcomeAdIframe.data('clickurl');
7271  let wcStageMarginTop = welcomeAdIframe.data('stagemargintop');
7272  let wcMuteButton = welcomeAdIframe.data('mutebutton');
7273  let bodyEl = document.getElementsByTagName("BODY")[0];
7274  let superbannerAd = document.getElementById('renderSlot_Superbanner');
7275  let defaultBgColor = window.getComputedStyle(document.body).getPropertyValue('background-color');
7276  defaultBgColor = be_rgbToHex(defaultBgColor);
7277  if(wcBgColor != 'default') {
7278    bodyEl.style.backgroundColor = wcBgColor;
7279  }
7280  let bgEl = document.createElement("div");
7281  const stageEl = document.querySelector('.PageFrame');
7282  bgEl.classList.add("wcVideo");
7283  let videoEl = document.createElement("video");
7284  videoEl.setAttribute("preload", "auto");
7285  videoEl.setAttribute("loop", "");
7286  //videoEl.setAttribute("autoplay", "");
7287  videoEl.setAttribute("muted", "");
7288  videoEl.classList.add("wcVideoTag");
7289
7290  let wcCloseButton = document.createElement("button");
7291  let closeBtnTxt = welcomeAdIframe.data('closebtntxt');
7292  let wcCloseButtonText = closeBtnTxt != 'default' ? closeBtnTxt : 'schließen';
7293  wcCloseButton.classList.add("wcCloseButton");
7294  wcCloseButton.prepend(wcCloseButtonText);
7295
7296  let playBtnTxt = welcomeAdIframe.data('playbtntxt');
7297  let pauseBtnTxt = welcomeAdIframe.data('pausebtntxt');
7298
7299  bgEl.prepend(videoEl);
7300  bodyEl.prepend(wcCloseButton);
7301
7302  if (playBtnTxt != 'default') {
7303    let wcPlayButton = document.createElement("button");
7304    let wcPlayButtonText = welcomeAdIframe.data('playbtntxt');
7305    let wcPauseButtonText = welcomeAdIframe.data('pausebtntxt');
7306    wcPlayButton.classList.add("wcPlayButton");
7307    wcPlayButton.prepend(wcPlayButtonText);
7308    bodyEl.prepend(wcPlayButton);
7309  }
7310
7311  if (wcMuteButton) {
7312    let wcMuteButtonEl = document.createElement("button");
7313    wcMuteButtonEl.classList.add("wcMuteButton");
7314    let wcMuteButtonElText = "<i class='fa fa-volume-off fa-2x'> </i>";
7315    wcMuteButtonEl.innerHTML = wcMuteButtonElText;
7316    bodyEl.prepend(wcMuteButtonEl);
7317
7318  }
7319
7320  let sourceEl = document.createElement("source");
7321  sourceEl.setAttribute("src", wcVideoSrc);
7322  sourceEl.setAttribute("type", "video/mp4");
7323  sourceEl.setAttribute("codecs", wcVideoCodecs);
7324
7325  videoEl.prepend(sourceEl);
7326  bodyEl.prepend(bgEl);
7327
7328  function playWcVideo() {
7329    videoEl.play();
7330  }
7331
7332  function pauseWcVideo() {
7333    videoEl.pause();
7334  }
7335
7336  function toggleWcVideo() {
7337    if(wcVideo.paused){
7338      wcVideo.play();
7339      if (wcPlayButton) {
7340        wcPlayButton.className = "wcPauseButton";
7341        if (playBtnTxt != 'default') {
7342          let wcPauseButtonText = welcomeAdIframe.data('pausebtntxt');
7343          wcPlayButton.innerText = wcPauseButtonText;
7344        }
7345
7346      }
7347    }else{
7348      wcVideo.pause();
7349      if (wcPlayButton) {
7350        wcPlayButton.className = "wcPlayButton";
7351        if (playBtnTxt != 'default') {
7352          let wcPlayButtonText = welcomeAdIframe.data('playbtntxt');
7353          wcPlayButton.innerText = wcPlayButtonText;
7354        }
7355      }
7356    }
7357
7358    /*
7359     if(wcVideo.muted){
7360     wcVideo.muted = false;
7361     }else{
7362     wcVideo.muted = true;
7363     }
7364     */
7365  }
7366
7367  function toggleMuteButton() {
7368    if (wcVideo.muted) {
7369      wcVideo.muted = false;
7370      wcMuteButtonEl.classList.add("wcMuteOn");
7371      wcMuteButtonEl.classList.remove("wcMuteOff");
7372      wcMuteButtonEl.innerHTML = "<i class='fa fa-volume-up fa-2x'> </i>";
7373    } else {
7374      wcVideo.muted = true;
7375      wcMuteButtonEl.classList.add("wcMuteOff");
7376      wcMuteButtonEl.classList.remove("wcMuteOn");
7377      wcMuteButtonEl.innerHTML = "<i class='fa fa-volume-off fa-2x'> </i>";
7378    }
7379  }
7380
7381  let wcVideo = document.getElementsByClassName("wcVideoTag")[0];
7382  wcVideo.addEventListener("click", toggleWcVideo);
7383  wcVideo.muted = true;
7384  wcVideo.autoplay = true;
7385
7386
7387  let wcPlayButton = document.querySelector(".wcPlayButton");
7388  wcPlayButton.innerText = pauseBtnTxt;
7389
7390  if (wcPlayButton) {
7391    wcPlayButton.addEventListener("click", toggleWcVideo);
7392  }
7393
7394  let wcPauseButton = document.querySelector(".wcPauseButton");
7395  if (wcPauseButton) {
7396    wcPauseButton.addEventListener("click", toggleWcVideo);
7397  }
7398
7399  let wcMuteButtonEl = document.querySelector(".wcMuteButton");
7400  if (wcMuteButtonEl) {
7401    wcMuteButtonEl.addEventListener("click", toggleMuteButton);
7402  }
7403
7404  /* clickable background -> */
7405  const wcMouseOverHandler = function (event) {
7406    if (event.target === document.body) {
7407      document.body.style.cursor = 'pointer';
7408    }
7409  };
7410  document.addEventListener('mouseover', wcMouseOverHandler);
7411
7412  const wcMouseOutHandler = function (event) {
7413    if (event.target === document.body) {
7414      document.body.style.cursor = 'auto';
7415    }
7416  };
7417  document.addEventListener('mouseout', wcMouseOutHandler);
7418
7419  const clickHandler = function (event) {
7420    if (event.target === document.body) {
7421      window.open(wcClickUrl, '_blank');
7422    }
7423  };
7424  document.addEventListener('click', clickHandler);
7425  /* <- clickable background */
7426
7427  function fadeOutOnScroll(element, stageEl) {
7428    if (!element || !stageEl) {
7429      return;
7430    }
7431
7432    let distanceToTop = window.pageYOffset + element.getBoundingClientRect().top;
7433    const elementHeight = element.offsetHeight;
7434    const scrollTop = document.documentElement.scrollTop;
7435
7436    let opacity = 1;
7437    distanceToTop = 0;
7438    element.style.position = 'fixed';
7439
7440    if (scrollTop > distanceToTop) {
7441      opacity = 1 - (scrollTop - distanceToTop) / elementHeight;
7442      opacity = (opacity < 0) ? 0 : opacity;
7443      opacity = (opacity > 0.95) ? 1 : opacity;
7444    }
7445
7446    if (opacity >= 0) {
7447      element.style.opacity = opacity;
7448      /* be_reduceBackgroundOpacity(superbannerAd, opacity); */
7449      if(wcBgColor != 'default') {
7450        be_changeBGColor(bodyEl, defaultBgColor, wcBgColor, opacity);
7451      }
7452    }
7453  }
7454
7455  function scrollHandler() {
7456    fadeOutOnScroll(wcVideo, bgEl);
7457  }
7458
7459  window.addEventListener('scroll', scrollHandler, {passive: true});
7460
7461  /**
7462   * Close Button
7463   */
7464  function closeWcVideo() {
7465    wcVideo.remove();
7466    bodyEl.style.backgroundColor = defaultBgColor;
7467    superbannerAd.firstElementChild.remove();
7468    wcCloseButton.remove();
7469    if (wcPlayButton) {
7470      wcPlayButton.remove();
7471    }
7472    if (wcMuteButtonEl) {
7473      wcMuteButtonEl.remove();
7474    }
7475    window.removeEventListener('scroll', scrollHandler, {passive: true});
7476    document.removeEventListener('click', clickHandler);
7477    document.removeEventListener('mouseover', wcMouseOverHandler);
7478    document.removeEventListener('mouseout', wcMouseOutHandler);
7479    stageEl.style.transition = 'margin 1s';
7480    stageEl.style.marginTop = '0px';
7481  }
7482
7483  wcCloseButton.addEventListener("click", closeWcVideo);
7484
7485  /* wait until bg-video is available */
7486  let wcInterval = setInterval(function() {
7487    document.getElementById("renderSlot_Superbanner").style.height = "0";
7488    if (videoEl) {
7489      clearInterval(wcInterval);
7490      let OriginalStageMarginTop = wcStageMarginTop;
7491      let videoElStyle = getComputedStyle(videoEl);
7492      let videoElHeight = parseInt(videoElStyle.height);
7493      let videoElOrigHeight = videoEl.naturalHeight;
7494      videoElOrigHeight = videoElOrigHeight || welcomeAdIframe.data('height');
7495      if (videoElHeight > videoElOrigHeight) {
7496
7497        videoElHeight = videoElOrigHeight;
7498      }
7499
7500      let videoElRatio = (videoElHeight / videoElOrigHeight).toFixed(2);
7501      let StageMarginTop = Math.round(OriginalStageMarginTop * videoElRatio);
7502
7503      stageEl.style.marginTop = StageMarginTop+'px';
7504    }
7505    clearInterval(wcInterval);
7506  }, 200);
7507
7508});
7509
7510/**
7511 * welcomeAdImage
7512 * WelcomeAd mit Hintergrund-Image, wird beim Scrollen ausgeblendet, hat Close-Button
7513 */
7514$(document).on('welcomeAdImage', function(event) {
7515
7516  let welcomeAd = $('.welcomeFrame').parent().parent();
7517  let welcomeAdIframe = $('.welcomeFrame');
7518  let wcBgColor = welcomeAdIframe.data('bgcolor');
7519  let wcClickUrl = welcomeAdIframe.data('clickurl');
7520  let bodyEl = document.getElementsByTagName("BODY")[0];
7521  let superbannerAd = document.getElementById('renderSlot_Superbanner');
7522  let defaultBgColor = window.getComputedStyle(document.body).getPropertyValue('background-color');
7523  defaultBgColor = be_rgbToHex(defaultBgColor);
7524
7525  if(wcBgColor != 'default') {
7526    bodyEl.style.backgroundColor = wcBgColor;
7527  }
7528  let bgEl = document.createElement("div");
7529  const stageEl = document.querySelector('.PageFrame');
7530
7531  bgEl.classList.add("wcBgImage");
7532  let imgEl = document.createElement("img");
7533  imgEl.classList.add("wcBgImageTag");
7534
7535  let wcCloseButton = document.createElement("button");
7536  let closeBtnTxt = welcomeAdIframe.data('closebtntxt');
7537  let wcCloseButtonText = closeBtnTxt != 'default' ? closeBtnTxt : 'schließen';
7538
7539  wcCloseButton.classList.add("wcCloseButton");
7540  wcCloseButton.prepend(wcCloseButtonText);
7541
7542  bgEl.prepend(imgEl);
7543  bodyEl.prepend(wcCloseButton);
7544
7545  let bgImgSource = welcomeAdIframe.data('bgimagesrc');
7546
7547  imgEl.setAttribute('src',bgImgSource);
7548  bodyEl.prepend(bgEl);
7549
7550  /* clickable background -> */
7551  const wcMouseOverHandler = function (event) {
7552    if (event.target === document.body) {
7553      document.body.style.cursor = 'pointer';
7554    }
7555  };
7556  document.addEventListener('mouseover', wcMouseOverHandler);
7557
7558  const wcMouseOutHandler = function (event) {
7559    if (event.target === document.body) {
7560      document.body.style.cursor = 'auto';
7561    }
7562  };
7563  document.addEventListener('mouseout', wcMouseOutHandler);
7564
7565  const clickHandler = function (event) {
7566    if (event.target === document.body) {
7567      window.open(wcClickUrl, '_blank');
7568    }
7569  };
7570  document.addEventListener('click', clickHandler);
7571  /* <- clickable background */
7572
7573  /* Superbanner in Hintergrund und sticky -> */
7574  superbannerAd.classList.add("wcfixedSuperbanner");
7575  const stageElStyles = window.getComputedStyle(stageEl);
7576  const stageElMarginTop = stageElStyles.getPropertyValue('margin-top');
7577  stageEl.style.marginTop = superbannerAd.offsetHeight+'px';
7578  /*
7579   * Calculation of the distance from the stage to the top of the screen
7580   * in a fixed ratio of 1080 (width of background image) to 520 (original distance from stage to top of screen)
7581   */
7582  let wcInterval2 = setInterval(function() {
7583
7584    if (imgEl) {
7585      clearInterval(wcInterval2);
7586
7587      let imgElStyle = getComputedStyle(imgEl);
7588      let imgElCurrHeight = parseInt(imgElStyle.height);
7589
7590      let imgHeight = 520;
7591      let imgElOrigHeight = 1080;
7592      let imgElRatio = (imgHeight / imgElOrigHeight).toFixed(2);
7593      let StageMarginTop = Math.round(imgElCurrHeight * imgElRatio);
7594
7595      stageEl.style.marginTop = StageMarginTop+'px';
7596    }
7597    clearInterval(wcInterval2);
7598  }, 200);
7599
7600
7601  /* <- Superbanner in Hintergrund und sticky */
7602
7603  /* clickable superbanner -> */
7604
7605  superbannerAd.addEventListener('mouseover', function() {
7606    superbannerAd.style.cursor = 'pointer';
7607  });
7608
7609  superbannerAd.addEventListener('mouseout', function() {
7610    superbannerAd.style.cursor = 'auto';
7611  });
7612
7613  superbannerAd.addEventListener('click', function() {
7614    window.open(wcClickUrl, '_blank');
7615  });
7616  /* <- clickable superbanner */
7617
7618  function fadeOutOnScroll(element, stageEl) {
7619    if (!element || !stageEl) {
7620      return;
7621    }
7622
7623    let distanceToTop = window.pageYOffset + element.getBoundingClientRect().top;
7624    const elementHeight = element.offsetHeight;
7625    const scrollTop = document.documentElement.scrollTop;
7626
7627    let opacity = 1;
7628    distanceToTop = 0;
7629    element.style.position = 'fixed';
7630
7631    if (scrollTop > distanceToTop) {
7632      opacity = 1 - (scrollTop - distanceToTop) / elementHeight;
7633      opacity = (opacity < 0) ? 0 : opacity;
7634      opacity = (opacity > 0.95) ? 1 : opacity;
7635    }
7636
7637    if (opacity >= 0) {
7638      element.style.opacity = opacity;
7639      /* be_reduceBackgroundOpacity(superbannerAd, opacity); */
7640      if(wcBgColor != 'default') {
7641        be_changeBGColor(bodyEl, defaultBgColor, wcBgColor, opacity);
7642      }
7643    }
7644  }
7645
7646  function scrollHandler() {
7647    fadeOutOnScroll(bgEl, stageEl);
7648  }
7649
7650  window.addEventListener('scroll', scrollHandler, {passive: true});
7651
7652  /*
7653   * Close Button
7654   */
7655  function closewcBgImage() {
7656    bgEl.remove();
7657    bodyEl.style.backgroundColor = defaultBgColor;
7658    superbannerAd.firstElementChild.remove();
7659    wcCloseButton.remove();
7660    window.removeEventListener('scroll', scrollHandler, {passive: true});
7661    document.removeEventListener('click', clickHandler);
7662    document.removeEventListener('mouseover', wcMouseOverHandler);
7663    document.removeEventListener('mouseout', wcMouseOutHandler);
7664    stageEl.style.transition = "margin-top 0.5s ease";
7665    stageEl.style.marginTop = stageElMarginTop;
7666  }
7667
7668  wcCloseButton.addEventListener("click", closewcBgImage);
7669
7670});
7671
7672/**
7673 * welcomeAdVideoMobil
7674 * WelcomeAd mit Video-URL für Mobil, hat Close-Button
7675 */
7676$(document).on('welcomeAdVideoMobil', function(event) {
7677
7678  let welcomeAdIframe = document.getElementById('welcomeFrameMobil');
7679
7680  let bodyEl = document.getElementsByTagName("BODY")[0];
7681  let superbannerAd = document.getElementById('renderSlot_Mobil-Superbanner');
7682
7683  let wcCloseButton = document.createElement("button");
7684  let closeBtnTxt = welcomeAdIframe.getAttribute('data-closebtntxt');
7685  let wcCloseButtonText = closeBtnTxt != 'default' ? closeBtnTxt : 'schließen';
7686  wcCloseButton.classList.add("wcCloseButtonMobil");
7687  wcCloseButton.prepend(wcCloseButtonText);
7688
7689  bodyEl.prepend(wcCloseButton);
7690
7691  let adHeight = superbannerAd.clientHeight;
7692
7693  welcomeAdIframe.style.position = "fixed";
7694  welcomeAdIframe.style.zIndex = "-1";
7695  superbannerAd.style.height = adHeight+"px";
7696
7697  wcCloseButton.style.top = adHeight-35+"px";
7698
7699
7700  /*
7701   * Create Video Tag
7702   */
7703  let bgEl = document.createElement("div");
7704  bgEl.classList.add("wcVideo");
7705  bgEl.classList.add("wcMobil");
7706
7707  let videoEl = document.createElement("video");
7708  videoEl.setAttribute("preload", "auto");
7709  videoEl.setAttribute("loop", "");
7710  videoEl.setAttribute("muted", "");
7711  videoEl.setAttribute("id", "wcVideoTag");
7712  videoEl.classList.add("wcVideoTag");
7713
7714  let wcVideoSrc = welcomeAdIframe.getAttribute('data-videosrc');
7715  let wcVideoCodecs = welcomeAdIframe.getAttribute('data-videocodecs');
7716  let sourceEl = document.createElement("source");
7717  sourceEl.setAttribute("src", wcVideoSrc);
7718  sourceEl.setAttribute("type", "video/mp4");
7719  sourceEl.setAttribute("codecs", wcVideoCodecs);
7720
7721  videoEl.prepend(sourceEl);
7722  bgEl.prepend(videoEl);
7723  bodyEl.prepend(bgEl);
7724
7725
7726
7727  /*
7728   * Close Button
7729   */
7730  function closeWcVideo() {
7731    superbannerAd.remove();
7732    wcCloseButton.remove();
7733    wcPlayButton.remove();
7734  }
7735
7736  wcCloseButton.addEventListener("click", closeWcVideo);
7737
7738
7739  /*
7740   * Play/Stop Button
7741   */
7742  let wcPlayBtnTxt = welcomeAdIframe.getAttribute('data-playbtntxt');
7743  let wcPauseBtnTxt = welcomeAdIframe.getAttribute('data-pausebtntxt');
7744
7745  let wcPlayButton = document.createElement("button");
7746  wcPlayButton.classList.add("wcPlayButtonMobil");
7747  wcPlayButton.prepend(wcPlayBtnTxt);
7748  bodyEl.prepend(wcPlayButton);
7749
7750  wcPlayButton.style.top = adHeight-35+"px";
7751
7752  wcPlayButton.addEventListener("click", toggleWcVideo);
7753
7754  let wcVideo = document.getElementById('wcVideo');
7755  wcVideo = videoEl;
7756
7757  function toggleWcVideo() {
7758    if(wcVideo.paused){
7759      wcVideo.play();
7760      if (wcPlayButton) {
7761        wcPlayButton.className = "wcPauseButtonMobil";
7762        if (wcPlayBtnTxt != 'default') {
7763          wcPlayButton.innerText = wcPauseBtnTxt;
7764        }
7765
7766      }
7767    }else{
7768      wcVideo.pause();
7769      if (wcPlayButton) {
7770        wcPlayButton.className = "wcPlayButtonMobil";
7771        if (wcPlayBtnTxt != 'default') {
7772          wcPlayButton.innerText = wcPlayBtnTxt;
7773        }
7774      }
7775    }
7776
7777    /*
7778     if(wcVideo.muted){
7779     wcVideo.muted = false;
7780     }else{
7781     wcVideo.muted = true;
7782     }
7783     */
7784  }
7785
7786});
7787
7788
7789/**
7790 * alignSkyscraperLeft
7791 */
7792$(document).one("alignSkyscraperLeft", function(event){
7793  if ($("#renderSlot_Skyscraper-links > div > iframe").length){
7794    let leftSkyEl = document.getElementById("renderSlot_Skyscraper-links");
7795
7796
7797    if($("#renderSlot_Skyscraper-links > div > iframe").length){
7798
7799      let elementSkyLeft = document.querySelector('.Ad-skyscraper-left');
7800      if(!elementSkyLeft) return;
7801      let style             = window.getComputedStyle(elementSkyLeft);
7802      let marginLeftSkyLeft = parseFloat(style.getPropertyValue('margin-left'));
7803
7804      const bannerFrame     = $("#renderSlot_Skyscraper-links > div > iframe");
7805      let bannerFrameWidth  = bannerFrame.data("width");
7806      let bannerFrameHeight = bannerFrame.data('height');
7807      let bannerFrameZIndex = bannerFrame.data('z-index');
7808
7809      if(bannerFrameWidth){
7810        let offset = bannerFrameWidth - Math.abs(marginLeftSkyLeft);
7811        offset     = Math.abs(offset);
7812        if(offset <= 20){ /* wenn versucht wurde durch css Abstand zur Bühne herzustellen */
7813          bannerFrameWidth = bannerFrameWidth + offset;
7814        }
7815        $("#renderSlot_Skyscraper-links").css("margin-left", "-" + bannerFrameWidth + "px");
7816        $("#renderSlot_Skyscraper-links").css("width", bannerFrameWidth + "px");
7817        $("#renderSlot_Skyscraper-links > div > iframe").css("height", bannerFrameHeight + "px");
7818      }
7819      if(bannerFrameZIndex){
7820        $('#renderSlot_Skyscraper-links').css('z-index', bannerFrameZIndex);
7821      }
7822    }
7823  }
7824
7825});
7826
7827/**
7828 * alignSkyscraperRight
7829 * Positioniert den rechten Skyscraper so, dass sein linker Rand am rechten Rand der Bühne (.PageFrame) anliegt.
7830 * Sitebar wird ausgeschlossen
7831 */
7832$(document).one("alignSkyscraperRight", function(event){
7833  var selector = "#renderSlot_Skyscraper-rechts iframe";
7834  var maxTries = 10;
7835  var tryCount = 0;
7836  function tryAlign() {
7837    var bannerFrame = $(selector);
7838    //console.log('[DEBUG] Versuch', tryCount+1, 'Gefundene iFrames:', bannerFrame.length, bannerFrame);
7839    if (bannerFrame.length) {
7840
7841      var bannerFrameWidth = bannerFrame.data("width");
7842      var marginTop = bannerFrame.data("margin-top");
7843      var marginBottom = bannerFrame.data("margin-bottom");
7844      var marginLeft = bannerFrame.data("margin-left");
7845      var marginRight = bannerFrame.data("margin-right");
7846      //console.log('[DEBUG] data-width:', bannerFrameWidth, 'marginTop:', marginTop, 'marginBottom:', marginBottom, 'marginLeft:', marginLeft, 'marginRight:', marginRight);
7847      var $pageFrame = $('.PageFrame');
7848      if (bannerFrameWidth && $pageFrame.length) {
7849        var pageFrameRight = $pageFrame.offset().left + $pageFrame.outerWidth();
7850        var $skyContainer = $("#renderSlot_Skyscraper-rechts");
7851        // Position berechnen: linker Rand des Skyscrapers = rechter Rand der Bühne
7852        var newLeft = pageFrameRight;
7853        var cssProps = {
7854          position: 'absolute',
7855          left: newLeft + 'px',
7856          width: bannerFrameWidth + 'px',
7857          'margin-left': 0
7858        };
7859        // Margin-Attribute aus dem Template
7860        if (typeof marginTop !== 'undefined' && marginTop !== null && marginTop !== '' && marginTop !== '0') {
7861          cssProps['margin-top'] = marginTop + 'px';
7862        }
7863        if (typeof marginBottom !== 'undefined' && marginBottom !== null && marginBottom !== '' && marginBottom !== '0') {
7864          cssProps['margin-bottom'] = marginBottom + 'px';
7865        }
7866        if (typeof marginLeft !== 'undefined' && marginLeft !== null && marginLeft !== '' && marginLeft !== '0') {
7867          cssProps['margin-left'] = marginLeft + 'px';
7868        }
7869        if (typeof marginRight !== 'undefined' && marginRight !== null && marginRight !== '' && marginRight !== '0') {
7870          cssProps['margin-right'] = marginRight + 'px';
7871        }
7872        $skyContainer.css(cssProps);
7873        console.log('[DEBUG] Skyscraper rechts positioniert:', cssProps);
7874      } else {
7875        //console.warn('[DEBUG] Kein data-width oder keine .PageFrame gefunden!');
7876      }
7877    } else if (++tryCount < maxTries) {
7878      setTimeout(tryAlign, 100);
7879    } else {
7880      //console.warn('[DEBUG] Kein iFrame gefunden für Selector nach', maxTries, 'Versuchen:', selector);
7881    }
7882  }
7883  tryAlign();
7884});
7885
7886/**
7887 * bridgeAd
7888 */
7889$(document).on("bridgeAd", function(event){
7890  const bA_iframe = document.querySelector('.bridgeAdFrame');
7891  const bA_renderSlot = document.querySelector('.Ad-billboard');
7892  bA_renderSlot.classList.add('bridgeAdSlot');
7893});
7894
7895/**
7896 * bridgeAdSticky
7897 */
7898$(document).on("bridgeAdSticky", function(event){
7899  const bA_iframe = document.querySelector('.bridgeAdFrame');
7900  const bA_renderSlot = document.querySelector('.Ad-billboard');
7901  bA_renderSlot.classList.add('bridgeAdSlot');
7902  bA_iframe.classList.add('billboardSticky');
7903});
7904
7905/**
7906 * Rechts-Ausrichtung
7907 * wird inbridgeAdComp aufgerufen, nachdem Skyscraper iFrame mit Grafik gefüllt wurde
7908 */
7909$(document).on("alignSkyscraperRightBridgeAd", function(event) {
7910  var selector = ".Ad-skyscraper-right iframe.CompFrame";
7911  var maxTries = 15;
7912  var tryCount = 0;
7913
7914  function tryAlign() {
7915    var $bannerFrame = $(selector).first();
7916    var $billboard = $('#renderSlot_Billboard');
7917
7918    if ($bannerFrame.length && $billboard.length) {
7919      var bannerFrameWidth = parseFloat($bannerFrame.attr("data-width"));
7920      if (!bannerFrameWidth) {
7921        if (++tryCount < maxTries) setTimeout(tryAlign, 100);
7922        return;
7923      }
7924
7925      var $skyContainer = $bannerFrame.closest('.Ad-skyscraper-right');
7926      var billboardRect = $billboard[0].getBoundingClientRect();
7927      var finalLeft = billboardRect.right;
7928
7929      var cssProps = {
7930        'position': 'fixed',
7931        // 'top': billboardRect.top + 'px', // Bei Bedarf aktivieren für vertikale Billboard-Bindung
7932        'left': finalLeft + 'px',
7933        'right': 'auto',
7934        'width': bannerFrameWidth + 'px',
7935        'margin': '0',
7936        'transform': 'none',
7937        'z-index': '100'
7938      };
7939
7940      // Optionaler Margin-Top aus dem iFrame
7941      var mTop = parseFloat($bannerFrame.attr("data-margin-top"));
7942      if (mTop) cssProps['top'] = (billboardRect.top + mTop) + 'px';
7943
7944      $skyContainer.css(cssProps);
7945    } else if (++tryCount < maxTries) {
7946      setTimeout(tryAlign, 100);
7947    }
7948  }
7949  tryAlign();
7950});
7951
7952/**
7953 * Links-Ausrichtung
7954 * wird in bridgeAdComp aufgerufen, nachdem Skyscraper iFrame mit Grafik gefüllt wurde
7955 */
7956$(document).on("alignSkyscraperLeftBridgeAd", function(event) {
7957  var selector = ".Ad-skyscraper-left iframe.CompFrame";
7958  var maxTries = 15;
7959  var tryCount = 0;
7960
7961  function tryAlign() {
7962    var $bannerFrame = $(selector).first();
7963    var $billboard = $('#renderSlot_Billboard');
7964
7965    if ($bannerFrame.length && $billboard.length) {
7966      var bannerFrameWidth = parseFloat($bannerFrame.attr("data-width"));
7967      if (!bannerFrameWidth) {
7968        if (++tryCount < maxTries) setTimeout(tryAlign, 100);
7969        return;
7970      }
7971
7972      var $skyContainer = $bannerFrame.closest('.Ad-skyscraper-left');
7973      var billboardRect = $billboard[0].getBoundingClientRect();
7974      var finalLeft = billboardRect.left - bannerFrameWidth;
7975
7976      var cssProps = {
7977        'position': 'fixed',
7978        // 'top': billboardRect.top + 'px', // Bei Bedarf aktivieren für vertikale Billboard-Bindung
7979        'left': finalLeft + 'px',
7980        'right': 'auto',
7981        'width': bannerFrameWidth + 'px',
7982        'margin': '0',
7983        'transform': 'none',
7984        'z-index': '100'
7985      };
7986
7987      var mTop = parseFloat($bannerFrame.attr("data-margin-top"));
7988      if (mTop) cssProps['top'] = (billboardRect.top + mTop) + 'px';
7989
7990      $skyContainer.css(cssProps);
7991    } else if (++tryCount < maxTries) {
7992      setTimeout(tryAlign, 100);
7993    }
7994  }
7995  tryAlign();
7996});
7997
7998$(document).on('valueAd', function() {
7999  const valueAdFrame = document.querySelector('#renderSlot_Billboard iframe.valueAdFrame, #renderSlot_Mobil-Billboard iframe.valueAdFrame, iframe.valueAdFrame');
8000  if (!valueAdFrame) return;
8001
8002  const bgImage = valueAdFrame.getAttribute('data-bgimage') || '';
8003  const bgColor = valueAdFrame.getAttribute('data-bgcolor') || '';
8004  if (bgImage && bgImage.indexOf('[%') === -1) {
8005    document.body.style.backgroundImage = 'url("' + bgImage + '")';
8006    document.body.style.backgroundRepeat = 'no-repeat';
8007    document.body.style.backgroundPosition = 'center top';
8008  }
8009  if (bgColor && bgColor.indexOf('[%') === -1) {
8010    document.body.style.backgroundColor = bgColor;
8011  }
8012
8013  const billboardSlot = valueAdFrame.closest('#renderSlot_Billboard, #renderSlot_Mobil-Billboard');
8014  if (billboardSlot) {
8015    // Bei ValueAd darf seitlich kein Padding bleiben, damit Sky direkt am Billboard anliegt.
8016    billboardSlot.style.paddingLeft = '0px';
8017    billboardSlot.style.paddingRight = '0px';
8018  }
8019
8020  if (valueAdFrame.parentElement) {
8021    valueAdFrame.parentElement.style.paddingLeft = '0px';
8022    valueAdFrame.parentElement.style.paddingRight = '0px';
8023  }
8024
8025  // Vorhandene BridgeAd-Logik wiederverwenden: ValueAd-iframe als Quelle markieren.
8026  valueAdFrame.classList.add('bridgeAdFrame');
8027
8028  const imgLeft = valueAdFrame.getAttribute('data-img_left') || '';
8029  const imgRight = valueAdFrame.getAttribute('data-img_right') || '';
8030  if (!imgLeft && !imgRight) return;
8031  if (imgLeft.indexOf('[%') !== -1 && imgRight.indexOf('[%') !== -1) return;
8032
8033  $(document).trigger('bridgeAdComp');
8034});
8035
8036
8037/**
8038 * bridgeAdComp
8039 * Hauptfunktion: Bridge-Ad Kompatibilität
8040 */
8041$(document).on("bridgeAdComp", function(event) {
8042  const bA_iframe = document.querySelector('.bridgeAdFrame');
8043  if (!bA_iframe) return;
8044
8045  const skyRight_Slot = document.querySelector('.Ad-skyscraper-right');
8046  const skyLeft_Slot = document.querySelector('.Ad-skyscraper-left');
8047  const commonClickUrl = bA_iframe.dataset.click_url;
8048
8049  const setupSkyscraper = (slot, imgUrl, linkUrl, eventName) => {
8050    if (!slot || !imgUrl) return;
8051
8052    const googleDiv = Array.from(slot.querySelectorAll('div'))
8053      .find(div => div.id && div.id.startsWith('google_ads_iframe_'));
8054
8055    if (googleDiv) {
8056      const imgLoader = new Image();
8057      imgLoader.src = imgUrl;
8058
8059      imgLoader.onload = function() {
8060        const realWidth = imgLoader.naturalWidth;
8061        const realHeight = imgLoader.naturalHeight;
8062
8063        googleDiv.innerHTML = '';
8064        let customFrame = document.createElement('iframe');
8065        customFrame.classList.add('responsiveFrame', 'CompFrame');
8066        customFrame.dataset.width = realWidth;
8067        customFrame.dataset.height = realHeight;
8068
8069        Object.assign(customFrame.style, {
8070          width: '100%',
8071          maxWidth: `${realWidth}px`,
8072          height: 'auto',
8073          aspectRatio: `${realWidth} / ${realHeight}`,
8074          border: 'none',
8075          display: 'block'
8076        });
8077
8078        customFrame.src = 'about:blank';
8079        googleDiv.appendChild(customFrame);
8080
8081        const finalizeFrame = () => {
8082          try {
8083            const doc = customFrame.contentDocument || customFrame.contentWindow.document;
8084            if (doc) {
8085              doc.open();
8086              // Einbau des Links um das Bild herum
8087              doc.write(`
8088                <!DOCTYPE html>
8089                <html>
8090                  <body style="margin:0;padding:0;overflow:hidden;">
8091                    <a href="${linkUrl || '#'}" target="_blank" style="display:block;text-decoration:none;outline:none;">
8092                      <img src="${imgUrl}" style="width:100%;display:block;border:none;-webkit-user-drag:none;" />
8093                    </a>
8094                  </body>
8095                </html>
8096              `);
8097              doc.close();
8098
8099              setTimeout(() => {
8100                $(document).trigger(eventName);
8101                console.log(`[DEBUG] ${eventName} mit Link ausgeführt`);
8102              }, 10);
8103            }
8104          } catch (e) {
8105            console.error("Fehler beim Finalisieren des iFrames:", e);
8106          }
8107        };
8108
8109        if (customFrame.contentDocument && customFrame.contentDocument.readyState === 'complete') {
8110          finalizeFrame();
8111        } else {
8112          customFrame.onload = finalizeFrame;
8113        }
8114      };
8115    }
8116  };
8117
8118  setupSkyscraper(
8119    skyRight_Slot,
8120    bA_iframe.dataset.img_right,
8121    // bA_iframe.dataset.click_right,
8122    commonClickUrl,
8123    "alignSkyscraperRightBridgeAd"
8124  );
8125
8126  setupSkyscraper(
8127    skyLeft_Slot,
8128    bA_iframe.dataset.img_left,
8129    // bA_iframe.dataset.click_left,
8130    commonClickUrl,
8131    "alignSkyscraperLeftBridgeAd"
8132  );
8133});
8134
8135/**
8136 * Magnet-Effekt bei Resize
8137 */
8138$(window).on('resize', function() {
8139  if ($('.Ad-skyscraper-right iframe.CompFrame').length) $(document).trigger("alignSkyscraperRightBridgeAd");
8140  if ($('.Ad-skyscraper-left iframe.CompFrame').length) $(document).trigger("alignSkyscraperLeftBridgeAd");
8141});
8142
8143/**
8144 * fullWidthBillboard
8145 */
8146$(document).on("fullWidthBillboard", function(event){
8147  const fw_renderSlot = document.querySelector('#renderSlot_Billboard');
8148  fw_renderSlot.classList.add('fullWidthBillboard');
8149});
8150
8151/**
8152 *  billboardSticky
8153 */
8154$(document).on('billboardSticky', function(){
8155  const slot = $('#renderSlot_Billboard, #renderSlot_Mobil-Billboard');
8156  const billboardAdIframe = $('.billboardSticky');
8157  const stickyHeaderHeight = $('.SiteHeaderSticky').height();
8158
8159  const billboardPositionTop = slot.offset().top;
8160  const billboardMarginTop = parseFloat(billboardAdIframe.parent().css('margin-top'));
8161  let billboardStickyOffsetTop = stickyHeaderHeight + 5;
8162  let sTimer = 0;
8163  if (Math.sign(billboardMarginTop) === -1) {
8164    billboardStickyOffsetTop = billboardStickyOffsetTop + Math.abs(billboardMarginTop);
8165  } else {
8166    billboardStickyOffsetTop = billboardStickyOffsetTop - Math.abs(billboardMarginTop);
8167  }
8168
8169  const bId = String(billboardAdIframe.data('bannerid'));
8170  const lsKey = 'stickyBillboard_' + bId;
8171  const lsValue = localStorage.getItem(lsKey);
8172
8173  if (lsValue !== null) {
8174    const expireDate = JSON.parse(lsValue).expireAt;
8175    if (expireDate < new Date().getTime()) {
8176      localStorage.removeItem(lsKey);
8177    } else {
8178      return false;
8179    }
8180  }
8181
8182  if ($('.PageFrame').height() > 2000) {
8183    $(window).scroll(function () {
8184      if ($(window).scrollTop() > billboardPositionTop) {
8185        if (localStorage.getItem(lsKey) === null && !sTimer && !slot.hasClass('isStickyBillboard')) {
8186          slot.css({top: billboardStickyOffsetTop + 'px'});
8187          slot.addClass('isStickyBillboard');
8188
8189          sTimer = setTimeout(function () {
8190            slot.css({'zIndex': 998});
8191            slot.animate({'top': -600}, 3000, function () {
8192            });
8193            sTimer = 0;
8194            const expireAt = new Date(new Date().getTime() + (60000 * 1440)).getTime();
8195            localStorage.setItem(lsKey, JSON.stringify({expireAt: expireAt}));
8196          }, 2000);
8197        }
8198      } else {
8199        if (sTimer) {
8200          clearTimeout(sTimer);
8201          sTimer = 0;
8202        }
8203        slot.css({top: '0px'});
8204        slot.removeClass('isStickyBillboard');
8205      }
8206    });
8207  }
8208});
8209
8210
8211window.googletag = window.googletag || { cmd: [] };
8212function initPremiumPaywallExpandOnAnker(get_status) {
8213  var url;
8214  var anker_exists;
8215
8216  url = window.location.href;
8217  anker_exists = url.indexOf("#formRegisterNG");
8218
8219  if ( anker_exists >= 0) {
8220    if (get_status !== true) {
8221      $('.FormRegisterNG_secondWrapper').addClass('isExpanded');
8222    } else {
8223      return true;
8224    }
8225  }
8226}
8227
8228function getQueryVariable(variable) {
8229  var query = window.location.search.substring(1);
8230  var vars = query.split("&");
8231  for (var i=0;i<vars.length;i++) {
8232    var pair = vars[i].split("=");
8233    if (pair[0] == variable) {
8234      return pair[1];
8235    }
8236  }
8237  return "";
8238}
8239
8240function fillForm(field_id,value, formID) {
8241  $('#'+formID + ' #'+field_id).val(decodeURIComponent(value));
8242}
8243
8244function initPremiumPaywallToggle() {
8245  var is_expanded;
8246  is_expanded = initPremiumPaywallExpandOnAnker(true);
8247
8248  // Diese Variablen dürfen per Get an die Reg-Bühne übergeben werden
8249  var allowed_get_params = ['email', 'firstname', 'lastname'];
8250
8251  // Werte holen für formFillers und Formular vorbelegen
8252  allowed_get_params.forEach( function(entry)  {
8253    form_val = getQueryVariable(entry);
8254    if  (form_val.length > 0) {
8255      fillForm('i_' + entry, form_val,  'nl_order_single_form' )
8256    }
8257  });
8258
8259
8260  if ( is_expanded || $('.FormRegisterNG_secondWrapper').hasClass('isExpanded') ) {
8261    $('.FormRegisterNG_toggleButton-arrows').css('transform', 'rotate(180deg)');
8262  }
8263
8264  $('.StagePremiumPaywall .FormRegisterNG_firstWrapper').click(function() {
8265    var paywall = '.FormRegisterNG_secondWrapper';
8266
8267    if ( $(paywall+':visible').length === 0 ) {
8268      $(paywall).slideDown(225);
8269      $('.FormRegisterNG_toggleButton').addClass('isActive');
8270      $('.FormRegisterNG_toggleButton-arrows').css('transform', 'rotate(180deg)');
8271    } else if ( $(paywall+':visible').length > 0) {
8272      $(paywall).slideUp(225);
8273      $('.FormRegisterNG_toggleButton').removeClass('isActive');
8274      $('.FormRegisterNG_toggleButton-arrows').css('transform', 'rotate(0deg)');
8275    }
8276  });
8277}
8278
8279$(document).ready( function() {
8280  initPremiumPaywallToggle();
8281  initPremiumPaywallExpandOnAnker(false);
8282});
8283
8284!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(){var e=0;return function(t,o){var s,n=this;n.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:i(t),appendDots:i(t),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(t),n.$slidesCache=null,n.transformType=null,n.transitionType=null,n.visibilityChange="visibilitychange",n.windowWidth=0,n.windowTimer=null,s=i(t).data("slick")||{},n.options=i.extend({},n.defaults,o,s),n.currentSlide=n.options.initialSlide,n.originalSettings=n.options,void 0!==document.mozHidden?(n.hidden="mozHidden",n.visibilityChange="mozvisibilitychange"):void 0!==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=e++,n.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,n.registerBreakpoints(),n.init(!0)}}()).prototype.activateADA=function(){this.$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)):!0===o?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&&!0===i.options.adaptiveHeight&&!1===i.options.vertical){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(),!0===s.options.rtl&&!1===s.options.vertical&&(e=-e),!1===s.transformsEnabled?!1===s.options.vertical?s.$slideTrack.animate({left:e},s.options.speed,s.options.easing,t):s.$slideTrack.animate({top:e},s.options.speed,s.options.easing,t):!1===s.cssTransitions?(!0===s.options.rtl&&(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),!1===s.options.vertical?(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),!1===s.options.vertical?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.getNavTarget();null!==t&&"object"==typeof t&&t.each(function(){var t=i(this).slick("getSlick");t.unslicked||t.slideHandler(e,!0)})},e.prototype.applyTransition=function(i){var e=this,t={};!1===e.options.fade?t[e.transitionType]=e.transformType+" "+e.options.speed+"ms "+e.options.cssEase:t[e.transitionType]="opacity "+e.options.speed+"ms "+e.options.cssEase,!1===e.options.fade?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||(!1===i.options.infinite&&(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;!0===e.options.arrows&&(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),!0!==e.options.infinite&&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(!0===o.options.dots){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),!0!==e.options.centerMode&&!0!==e.options.swipeToSlide||(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),!0===e.options.draggable&&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.o
vendor: 3,442 bytes, line 8284
8284ptions.rows>1){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)&&(!1===r.originalSettings.mobileFirst?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]),!0===e&&(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]),!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):null!==r.activeBreakpoint&&(r.activeBreakpoint=null,r.options=r.originalSettings,!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e),l=s),e||!1===l||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;if(e=this.getNavigableIndexes(),t=0,i>e[e.length-1])i=e[e.length-1];else for(var o in e){if(i<e[o]){i=t;break}t=e[o]}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)),!0===e.options.accessibility&&e.$dots.off("keydown.slick",e.keyHandler)),e.$slider.off("focus.slick blur.slick"),!0===e.options.arrows&&e.slideCount>e.options.slidesToShow&&(e.$prevArrow&&e.$prevArrow.off("click.slick",e.changeSlide),e.$nextArrow&&e.$nextArrow.off("click.slick",e.changeSlide),!0===e.options.accessibility&&(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.
8284slick",e.swipeHandler),e.$list.off("click.slick",e.clickHandler),i(document).off(e.visibilityChange,e.visibility),e.cleanUpSlideEvents(),!0===e.options.accessibility&&e.$list.off("keydown.slick",e.keyHandler),!0===e.options.focusOnSelect&&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>1&&((i=e.$slides.children().children()).removeAttr("style"),e.$slider.empty().append(i))},e.prototype.clickHandler=function(i){!1===this.shouldClick&&(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]="",!1===e.options.fade?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.fadeSlide=function(i,e){var t=this;!1===t.cssTransitions?(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;!1===e.cssTransitions?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 blur.slick","*",function(t){t.stopImmediatePropagation();var o=i(this);setTimeout(function(){e.options.pauseOnFocus&&(e.focussed=o.is(":focus"),e.autoPlay())},0)})},e.prototype.getCurrent=e.prototype.slickCurrentSlide=function(){return this.currentSlide},e.prototype.getDotCount=function(){var i=this,e=0,t=0,o=0;if(!0===i.options.infinite)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(!0===i.options.centerMode)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),!0===n.options.infinite?(n.slideCount>n.options.slidesToShow&&(n.slideOffset=n.slideWidth*n.options.slidesToShow*-1,s=-1,!0===n.options.vertical&&!0===n.options.centerMode&&(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),!0===n.options.centerMode&&n.slideCount<=n.options.slidesToShow?n.slideOffset=n.slideWidth*Math.floor(n.options.slidesToShow)/2-n.slideWidth*n.slideCount/2:!0===n.options.centerMode&&!0===n.options.infinite?n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)-n.slideWidth:!0===n.options.centerMode&&(n.slideOffset=0,n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)),e=!1===n.options.vertical?i*n.slideWidth*-1+n.slideOffset:i*t*-1+r,!0===n.options.variableWidth&&(o=n.slideCount<=n.options.slidesToShow||!1===n.options.infinite?n.$slideTrack.children(".slick-slide").eq(i):n.$slideTrack.children(".slick-slide").eq(i+n.options.slidesToShow),e=!0===n.options.rtl?o[0]?-1*(n.$slideTrack.width()-o[0].offsetLeft-o.width()):0:o[0]?-1*o[0].offsetLeft:0,!0===n.options.centerMode&&(o=n.slideCount<=n.options.slidesToShow||!1===n.options.infinite?n.$slideTrack.children(".slick-slide").eq(i):n.$slideTrack.children(".slick-slide").eq(i+n.options.slidesToShow+1),e=!0===n.options.rtl?o[0]?-1*(n.$slideTrack.width()-o[0].offsetLeft-o.width()):0:o[0]?-1*o[0].offsetLeft:0,e+=(n.$list.width()-o.outerWidth())/2)),e},e.prototype.getOption=e.prototype.slickGetOption=function(i){return this.options[i]},e.prototype.getNavigableIndexes=function(){var i,e=this,t=0,o=0,s=[];for(!1===e.options.infinite?i=e.slideCount:(t=-1*e.options.slidesToScroll,o=-1*e.options.slidesToScroll,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=this;return t=!0===o.options.centerMode?o.slideWidth*Math.floor(o.options.slidesToShow/2):0,!0===o.options.swipeToSlide?(o.$slideTrack.find(".slick-slide").each(function(s,n){if(n.offsetLeft-t+i(n).outerWidth()/2>-1*o.swipeLeft)return e=n,!1}),Math.abs(i(e).attr("data-slick-index")-o.currentSlide)||1):o.options.slidesToScroll},e.prototype.goTo=e.prototype.slickGoTo=function(i,e){this.changeSlide({data:{message:"index",index:
8284parseInt(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]),!0===t.options.accessibility&&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);i(this).attr({role:"tabpanel",id:"slick-slide"+e.instanceUid+t,tabindex:-1}),-1!==s&&i(this).attr({"aria-describedby":"slick-slide-control"+e.instanceUid+s})}),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.$slides.eq(s).attr("tabindex",0);e.activateADA()},e.prototype.initArrowEvents=function(){var i=this;!0===i.options.arrows&&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),!0===i.options.accessibility&&(i.$prevArrow.on("keydown.slick",i.keyHandler),i.$nextArrow.on("keydown.slick",i.keyHandler)))},e.prototype.initDotEvents=function(){var e=this;!0===e.options.dots&&(i("li",e.$dots).on("click.slick",{message:"index"},e.changeSlide),!0===e.options.accessibility&&e.$dots.on("keydown.slick",e.keyHandler)),!0===e.options.dots&&!0===e.options.pauseOnDotsHover&&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"}
8284,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)),!0===e.options.accessibility&&e.$list.on("keydown.slick",e.keyHandler),!0===e.options.focusOnSelect&&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;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.show(),i.$nextArrow.show()),!0===i.options.dots&&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&&!0===e.options.accessibility?e.changeSlide({data:{message:!0===e.options.rtl?"next":"previous"}}):39===i.keyCode&&!0===e.options.accessibility&&e.changeSlide({data:{message:!0===e.options.rtl?"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")||n.$slider.attr("data-sizes"),r=document.createElement("img");r.onload=function(){e.animate({opacity:0}
vendor: 5,619 bytes, line 8284
8284,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")}),n.$slider.trigger("lazyLoaded",[n,e,t])})},r.onerror=function(){e.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),n.$slider.trigger("lazyLoadError",[n,e,t])},r.src=t})}var t,o,s,n=this;if(!0===n.options.centerMode?!0===n.options.infinite?s=(o=n.currentSlide+(n.options.slidesToShow/2+1))+n.options.slidesToShow+2:(o=Math.max(0,n.currentSlide-(n.options.slidesToShow/2+1)),s=n.options.slidesToShow/2+1+2+n.currentSlide):(o=n.options.infinite?n.options.slidesToShow+n.currentSlide:n.currentSlide,s=Math.ceil(o+n.options.slidesToShow),!0===n.options.fade&&(o>0&&o--,s<=n.slideCount&&s++)),t=n.$slider.find(".slick-slide").slice(o,s),"anticipated"===n.options.lazyLoad)for(var r=o-1,l=s,d=n.$slider.find(".slick-slide"),a=0;a<n.options.slidesToScroll;a++)r<0&&(r=n.slideCount-1),t=(t=t.add(d.eq(r))).add(d.eq(l)),r--,l++;e(t),n.slideCount<=n.options.slidesToShow?e(n.$slider.find(".slick-slide")):n.currentSlide>=n.slideCount-n.options.slidesToShow?e(n.$slider.find(".slick-cloned").slice(0,n.options.slidesToShow)):0===n.currentSlide&&e(n.$slider.find(".slick-cloned").slice(-1*n.options.slidesToShow))},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(){this.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;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(),!0===t.options.accessibility&&(t.initADA(),t.options.focusOnChange&&i(t.$slides.get(t.currentSlide)).attr("tabindex",0).focus()))},e.prototype.prev=e.prototype.slickPrev=function(){this.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")).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"),!0===l.options.adaptiveHeight&&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),!0===e.options.focusOnSelect&&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;if(i="boolean"==typeof i?!0===(e=i)?0:o.slideCount-1:!0===e?--i:i,o.slideCount<1||i<0||i>o.slideCount-1)return!1;o.unload(),!0===t?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,o.reinit()},e.prototype.setCSS=function(i){var e,t,o=this,s={};
8284!0===o.options.rtl&&(i=-i),e="left"==o.positionProp?Math.ceil(i)+"px":"0px",t="top"==o.positionProp?Math.ceil(i)+"px":"0px",s[o.positionProp]=i,!1===o.transformsEnabled?o.$slideTrack.css(s):(s={},!1===o.cssTransitions?(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;!1===i.options.vertical?!0===i.options.centerMode&&i.$list.css({padding:"0px "+i.options.centerPadding}):(i.$list.height(i.$slides.first().outerHeight(!0)*i.options.slidesToShow),!0===i.options.centerMode&&i.$list.css({padding:i.options.centerPadding+" 0px"})),i.listWidth=i.$list.width(),i.listHeight=i.$list.height(),!1===i.options.vertical&&!1===i.options.variableWidth?(i.slideWidth=Math.ceil(i.listWidth/i.options.slidesToShow),i.$slideTrack.width(Math.ceil(i.slideWidth*i.$slideTrack.children(".slick-slide").length))):!0===i.options.variableWidth?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();!1===i.options.variableWidth&&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,!0===t.options.rtl?i(s).css({position:"relative",right:e,top:0,zIndex:t.options.zIndex-2,opacity:0}
8284):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&&!0===i.options.adaptiveHeight&&!1===i.options.vertical){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":void 0!==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(),!1===i.options.fade?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=!0===i.options.vertical?"top":"left","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||!0===i.options.useCSS&&(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&&!1!==i.animType&&(i.animType="transform",i.transformType="transform",i.transitionType="transition"),i.transformsEnabled=i.options.useTransform&&null!==i.animType&&!1!==i.animType},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"),!0===n.options.centerMode){var r=n.options.slidesToShow%2==0?1:0;e=Math.floor(n.options.slidesToShow/2),!0===n.options.infinite&&(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=!0===n.options.infinite?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(!0===s.options.fade&&(s.options.centerMode=!1),!0===s.options.infinite&&!1===s.options.fade&&(t=null,s.slideCount>s.options.slidesToShow)){for(o=!0===s.options.centerMode?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"));s||(s=0),t.slideCount<=t.options.slidesToShow?t.slideHandler(s,!1,!0):t.slideHandler(s)},e.prototype.slideHandler=function(i,e,t){var o,s,n,r,l,d=null,a=this;if(e=e||!1,!(!0===a.animating&&!0===a.options.waitForAnimate||!0===a.options.fade&&a.currentSlide===i))if(!1===e&&a.asNavFor(i),o=i,d=a.getLeft(o),r=a.getLeft(a.currentSlide),a.currentLeft=null===a.swipeLeft?r:a.swipeLeft,!1===a.options.infinite&&!1===a.options.centerMode&&(i<0||i>a.getDotCount()*a.options.slidesToScroll))!1===a.options.fade&&(o=a.currentSlide,!0!==t?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o));else if(!1===a.options.infinite&&!0===a.options.centerMode&&(i<0||i>a.slideCount-a.options.slidesToScroll))!1===a.options.fade&&(o=a.currentSlide,!0!==t?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o));else{if(a.options.autoplay&&clearInterval(a.autoPlayTimer),s=o<0?a.slideCount%a.options.slidesToScroll!=0?a.slideCount-a.slideCount%a.options.slidesToScroll:a.slideCount+
8284o: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=(l=a.getNavTarget()).slick("getSlick")).slideCount<=l.options.slidesToShow&&l.setSlideClasses(a.currentSlide),a.updateDots(),a.updateArrows(),!0===a.options.fade)return!0!==t?(a.fadeSlideOut(n),a.fadeSlide(s,function(){a.postSlide(s)})):a.postSlide(s),void a.animateHeight();!0!==t?a.animateSlide(d,function(){a.postSlide(s)}):a.postSlide(s)}},e.prototype.startLoad=function(){var i=this;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.hide(),i.$nextArrow.hide()),!0===i.options.dots&&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))<0&&(o=360-Math.abs(o)),o<=45&&o>=0?!1===s.options.rtl?"left":"right":o<=360&&o>=315?!1===s.options.rtl?"left":"right":o>=135&&o<=225?!1===s.options.rtl?"right":"left":!0===s.options.verticalSwiping?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(!0===o.touchObject.edgeHit&&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(!(!1===e.options.swipe||"ontouchend"in document&&!1===e.options.swipe||!1===e.options.draggable&&-1!==i.type.indexOf("mouse")))switch(e.touchObject.fingerCount=i.originalEvent&&void 0!==i.originalEvent.touches?i.originalEvent.touches.length:1,e.touchObject.minSwipe=e.listWidth/e.options.touchThreshold,!0===e.options.verticalSwiping&&(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):(!0===l.options.verticalSwiping&&(l.touchObject.swipeLength=r),t=l.swipeDirection(),void 0!==i.originalEvent&&l.touchObject.swipeLength>4&&(l.swiping=!0,i.preventDefault()),s=(!1===l.options.rtl?1:-1)*(l.touchObject.curX>l.touchObject.startX?1:-1),!0===l.options.verticalSwiping&&(s=l.touchObject.curY>l.touchObject.startY?1:-1),o=l.touchObject.swipeLength,l.touchObject.edgeHit=!1,!1===l.options.infinite&&(0===l.currentSlide&&"right"===t||l.currentSlide>=l.getDotCount()&&"left"===t)&&(o=l.touchObject.swipeLength*l.options.edgeFriction,l.touchObject.edgeHit=!0),!1===l.options.vertical?l.swipeLeft=e+o*s:l.swipeLeft=e+o*(l.$list.height()/l.listWidth)*s,!0===l.options.verticalSwiping&&(l.swipeLeft=e+o*s),!0!==l.options.fade&&!1!==l.options.touchMove&&(!0===l.animating?(l.swipeLeft=null,!1):void l.setCSS(l.swipeLeft))))},e.prototype.swipeStart=function(i){var e,t=this;if(t.interrupted=!0,1!==t.touchObject.fingerCount||t.slideCount<=t.options.slidesToShow)return 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,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","")}
8284,e.prototype.unslick=function(i){var e=this;e.$slider.trigger("unslick",[e,i]),e.destroy()},e.prototype.updateArrows=function(){var i=this;Math.floor(i.options.slidesToShow/2),!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&!i.options.infinite&&(i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false"),i.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false"),0===i.currentSlide?(i.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false")):i.currentSlide>=i.slideCount-i.options.slidesToShow&&!1===i.options.centerMode?(i.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")):i.currentSlide>=i.slideCount-1&&!0===i.options.centerMode&&(i.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$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||void 0===s?o[i].slick=new e(o[i],s):t=o[i].slick[s].apply(o[i].slick,n),void 0!==t)return t;return o}});
8285
8286$().ready(function() {
8287  
8288  $('#comments').on("click", ".ev-comment-reply, .ev-comment-edit", function() {
8289    var cmtempl = $('.cm_template_form').clone();
8290    cmtempl.show();
8291    var parent_cm_id = $(this).closest('.ArticleComment_item').find('.comments-anchor').attr('data-cmid');
8292    var parent_level = $(this).closest('.ArticleComment_item').attr('data-level');
8293    cmtempl.find('.cm_parent_id').val(parent_cm_id); 
8294    cmtempl.find('.parent_level').val(parent_level); 
8295    $(this).after(cmtempl);
8296    console.log(cmtempl);
8297    cmtempl.find("textarea").focus();
8298    if ($(this).hasClass('ev-comment-edit')) {
8299      var $cm_content = $(this).closest('.ArticleComment_block').find(".ArticleComment_content p");
8300      cmtempl.find("textarea").val($cm_content.text());
8301      $cm_content.hide();
8302      cmtempl.find('.button-cm-send').val('Änderungen absenden');
8303    }
8304    $(".ev-comment-reply, .ev-comment-edit").hide();          
8305  }); 
8306  
8307  
8308  $('#comments').on("click", ".button-cm-cancel", function() {
8309    if (confirm("Wollen Sie die Eingabe wirklich abbrechen?")) {
8310      $(".ev-comment-reply, .ev-comment-edit, .ArticleComment_content p").show();
8311      $(this).closest('section').remove();
8312    }
8313    return false;
8314  });
8315    
8316  // -- Kommentar per Ajax 
8317  $('#comments').on('click', '.button-cm-send', function() {
8318    var settings = {
8319      ajaxUrl : "/comments/ajax-comments.php",
8320    }
8321    var cmtempl = $(this).closest('section');
8322    var $li_closest = $(this).closest('.ArticleComment_item');
8323    var $cm_content = $(this).closest('.ArticleComment_item')
8324                    .children('.ArticleComment_block')
8325                    .find(".ArticleComment_content p");
8326    $.ajax({        
8327      type: "POST",
8328      async: true,
8329      url: settings.ajaxUrl,
8330      dataType: 'json',
8331      data: $(this).closest('form').serialize() + "&OK=1"
8332    }).done(function(data) {
8333      if (data['mode'] == 'edit') {
8334        $cm_content.text(cmtempl.find("textarea").val());
8335        $cm_content.show();
8336      } else {
8337        $li_closest.children('.ArticleComment_children').append(data['listtext']);
8338      }  
8339      $(".ev-comment-reply, .ev-comment-edit").show();
8340      cmtempl.remove();
8341    }).fail(function() {
8342      alert('Ihre Eingabe konnte nicht gespeichert werden.');
8343    });
8344    return false;
8345  });
8346
8347});
8348
8349
8350/**
8351 * Swiper 12.0.3
8352 * Most modern mobile touch slider and framework with hardware accelerated transitions
8353 * https://swiperjs.com
8354 *
8355 * Copyright 2014-2025 Vladimir Kharlampidi
8356 *
8357 * Released under the MIT License
8358 *
8359 * Released on: October 21, 2025
8360 */
8361
8362var Swiper = (function () {
8363  'use strict';
8364
8365  /**
8366   * SSR Window 5.0.1
8367   * Better handling for window object in SSR environment
8368   * https://github.com/nolimits4web/ssr-window
8369   *
8370   * Copyright 2025, Vladimir Kharlampidi
8371   *
8372   * Licensed under MIT
8373   *
8374   * Released on: June 27, 2025
8375   */
8376  /* eslint-disable no-param-reassign */
8377  function isObject$1(obj) {
8378    return obj !== null && typeof obj === 'object' && 'constructor' in obj && obj.constructor === Object;
8379  }
8380  function extend$1(target = {}, src = {}) {
8381    const noExtend = ['__proto__', 'constructor', 'prototype'];
vendor: 5,054 bytes, lines 8382-8580
8382    Object.keys(src).filter(key => noExtend.indexOf(key) < 0).forEach(key => {
8383      if (typeof target[key] === 'undefined') target[key] = src[key];else if (isObject$1(src[key]) && isObject$1(target[key]) && Object.keys(src[key]).length > 0) {
8384        extend$1(target[key], src[key]);
8385      }
8386    });
8387  }
8388  const ssrDocument = {
8389    body: {},
8390    addEventListener() {},
8391    removeEventListener() {},
8392    activeElement: {
8393      blur() {},
8394      nodeName: ''
8395    },
8396    querySelector() {
8397      return null;
8398    },
8399    querySelectorAll() {
8400      return [];
8401    },
8402    getElementById() {
8403      return null;
8404    },
8405    createEvent() {
8406      return {
8407        initEvent() {}
8408      };
8409    },
8410    createElement() {
8411      return {
8412        children: [],
8413        childNodes: [],
8414        style: {},
8415        setAttribute() {},
8416        getElementsByTagName() {
8417          return [];
8418        }
8419      };
8420    },
8421    createElementNS() {
8422      return {};
8423    },
8424    importNode() {
8425      return null;
8426    },
8427    location: {
8428      hash: '',
8429      host: '',
8430      hostname: '',
8431      href: '',
8432      origin: '',
8433      pathname: '',
8434      protocol: '',
8435      search: ''
8436    }
8437  };
8438  function getDocument() {
8439    const doc = typeof document !== 'undefined' ? document : {};
8440    extend$1(doc, ssrDocument);
8441    return doc;
8442  }
8443  const ssrWindow = {
8444    document: ssrDocument,
8445    navigator: {
8446      userAgent: ''
8447    },
8448    location: {
8449      hash: '',
8450      host: '',
8451      hostname: '',
8452      href: '',
8453      origin: '',
8454      pathname: '',
8455      protocol: '',
8456      search: ''
8457    },
8458    history: {
8459      replaceState() {},
8460      pushState() {},
8461      go() {},
8462      back() {}
8463    },
8464    CustomEvent: function CustomEvent() {
8465      return this;
8466    },
8467    addEventListener() {},
8468    removeEventListener() {},
8469    getComputedStyle() {
8470      return {
8471        getPropertyValue() {
8472          return '';
8473        }
8474      };
8475    },
8476    Image() {},
8477    Date() {},
8478    screen: {},
8479    setTimeout() {},
8480    clearTimeout() {},
8481    matchMedia() {
8482      return {};
8483    },
8484    requestAnimationFrame(callback) {
8485      if (typeof setTimeout === 'undefined') {
8486        callback();
8487        return null;
8488      }
8489      return setTimeout(callback, 0);
8490    },
8491    cancelAnimationFrame(id) {
8492      if (typeof setTimeout === 'undefined') {
8493        return;
8494      }
8495      clearTimeout(id);
8496    }
8497  };
8498  function getWindow() {
8499    const win = typeof window !== 'undefined' ? window : {};
8500    extend$1(win, ssrWindow);
8501    return win;
8502  }
8503
8504  function classesToTokens(classes = '') {
8505    return classes.trim().split(' ').filter(c => !!c.trim());
8506  }
8507
8508  function deleteProps(obj) {
8509    const object = obj;
8510    Object.keys(object).forEach(key => {
8511      try {
8512        object[key] = null;
8513      } catch (e) {
8514        // no getter for object
8515      }
8516      try {
8517        delete object[key];
8518      } catch (e) {
8519        // something got wrong
8520      }
8521    });
8522  }
8523  function nextTick(callback, delay = 0) {
8524    return setTimeout(callback, delay);
8525  }
8526  function now() {
8527    return Date.now();
8528  }
8529  function getComputedStyle$1(el) {
8530    const window = getWindow();
8531    let style;
8532    if (window.getComputedStyle) {
8533      style = window.getComputedStyle(el, null);
8534    }
8535    if (!style && el.currentStyle) {
8536      style = el.currentStyle;
8537    }
8538    if (!style) {
8539      style = el.style;
8540    }
8541    return style;
8542  }
8543  function getTranslate(el, axis = 'x') {
8544    const window = getWindow();
8545    let matrix;
8546    let curTransform;
8547    let transformMatrix;
8548    const curStyle = getComputedStyle$1(el);
8549    if (window.WebKitCSSMatrix) {
8550      curTransform = curStyle.transform || curStyle.webkitTransform;
8551      if (curTransform.split(',').length > 6) {
8552        curTransform = curTransform.split(', ').map(a => a.replace(',', '.')).join(', ');
8553      }
8554      // Some old versions of Webkit choke when 'none' is passed; pass
8555      // empty string instead in this case
8556      transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
8557    } else {
8558      transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
8559      matrix = transformMatrix.toString().split(',');
8560    }
8561    if (axis === 'x') {
8562      // Latest Chrome and webkits Fix
8563      if (window.WebKitCSSMatrix) curTransform = transformMatrix.m41;
8564      // Crazy IE10 Matrix
8565      else if (matrix.length === 16) curTransform = parseFloat(matrix[12]);
8566      // Normal Browsers
8567      else curTransform = parseFloat(matrix[4]);
8568    }
8569    if (axis === 'y') {
8570      // Latest Chrome and webkits Fix
8571      if (window.WebKitCSSMatrix) curTransform = transformMatrix.m42;
8572      // Crazy IE10 Matrix
8573      else if (matrix.length === 16) curTransform = parseFloat(matrix[13]);
8574      // Normal Browsers
8575      else curTransform = parseFloat(matrix[5]);
8576    }
8577    return curTransform || 0;
8578  }
8579  function isObject(o) {
8580    return typeof o === 'object' && o !== null && o.constructor && Ob
vendor: 9,136 bytes, lines 8580-8844
8580ject.prototype.toString.call(o).slice(8, -1) === 'Object';
8581  }
8582  function isNode(node) {
8583    // eslint-disable-next-line
8584    if (typeof window !== 'undefined' && typeof window.HTMLElement !== 'undefined') {
8585      return node instanceof HTMLElement;
8586    }
8587    return node && (node.nodeType === 1 || node.nodeType === 11);
8588  }
8589  function extend(...args) {
8590    const to = Object(args[0]);
8591    const noExtend = ['__proto__', 'constructor', 'prototype'];
8592    for (let i = 1; i < args.length; i += 1) {
8593      const nextSource = args[i];
8594      if (nextSource !== undefined && nextSource !== null && !isNode(nextSource)) {
8595        const keysArray = Object.keys(Object(nextSource)).filter(key => noExtend.indexOf(key) < 0);
8596        for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) {
8597          const nextKey = keysArray[nextIndex];
8598          const desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
8599          if (desc !== undefined && desc.enumerable) {
8600            if (isObject(to[nextKey]) && isObject(nextSource[nextKey])) {
8601              if (nextSource[nextKey].__swiper__) {
8602                to[nextKey] = nextSource[nextKey];
8603              } else {
8604                extend(to[nextKey], nextSource[nextKey]);
8605              }
8606            } else if (!isObject(to[nextKey]) && isObject(nextSource[nextKey])) {
8607              to[nextKey] = {};
8608              if (nextSource[nextKey].__swiper__) {
8609                to[nextKey] = nextSource[nextKey];
8610              } else {
8611                extend(to[nextKey], nextSource[nextKey]);
8612              }
8613            } else {
8614              to[nextKey] = nextSource[nextKey];
8615            }
8616          }
8617        }
8618      }
8619    }
8620    return to;
8621  }
8622  function setCSSProperty(el, varName, varValue) {
8623    el.style.setProperty(varName, varValue);
8624  }
8625  function animateCSSModeScroll({
8626    swiper,
8627    targetPosition,
8628    side
8629  }) {
8630    const window = getWindow();
8631    const startPosition = -swiper.translate;
8632    let startTime = null;
8633    let time;
8634    const duration = swiper.params.speed;
8635    swiper.wrapperEl.style.scrollSnapType = 'none';
8636    window.cancelAnimationFrame(swiper.cssModeFrameID);
8637    const dir = targetPosition > startPosition ? 'next' : 'prev';
8638    const isOutOfBound = (current, target) => {
8639      return dir === 'next' && current >= target || dir === 'prev' && current <= target;
8640    };
8641    const animate = () => {
8642      time = new Date().getTime();
8643      if (startTime === null) {
8644        startTime = time;
8645      }
8646      const progress = Math.max(Math.min((time - startTime) / duration, 1), 0);
8647      const easeProgress = 0.5 - Math.cos(progress * Math.PI) / 2;
8648      let currentPosition = startPosition + easeProgress * (targetPosition - startPosition);
8649      if (isOutOfBound(currentPosition, targetPosition)) {
8650        currentPosition = targetPosition;
8651      }
8652      swiper.wrapperEl.scrollTo({
8653        [side]: currentPosition
8654      });
8655      if (isOutOfBound(currentPosition, targetPosition)) {
8656        swiper.wrapperEl.style.overflow = 'hidden';
8657        swiper.wrapperEl.style.scrollSnapType = '';
8658        setTimeout(() => {
8659          swiper.wrapperEl.style.overflow = '';
8660          swiper.wrapperEl.scrollTo({
8661            [side]: currentPosition
8662          });
8663        });
8664        window.cancelAnimationFrame(swiper.cssModeFrameID);
8665        return;
8666      }
8667      swiper.cssModeFrameID = window.requestAnimationFrame(animate);
8668    };
8669    animate();
8670  }
8671  function getSlideTransformEl(slideEl) {
8672    return slideEl.querySelector('.swiper-slide-transform') || slideEl.shadowRoot && slideEl.shadowRoot.querySelector('.swiper-slide-transform') || slideEl;
8673  }
8674  function elementChildren(element, selector = '') {
8675    const window = getWindow();
8676    const children = [...element.children];
8677    if (window.HTMLSlotElement && element instanceof HTMLSlotElement) {
8678      children.push(...element.assignedElements());
8679    }
8680    if (!selector) {
8681      return children;
8682    }
8683    return children.filter(el => el.matches(selector));
8684  }
8685  function elementIsChildOfSlot(el, slot) {
8686    // Breadth-first search through all parent's children and assigned elements
8687    const elementsQueue = [slot];
8688    while (elementsQueue.length > 0) {
8689      const elementToCheck = elementsQueue.shift();
8690      if (el === elementToCheck) {
8691        return true;
8692      }
8693      elementsQueue.push(...elementToCheck.children, ...(elementToCheck.shadowRoot ? elementToCheck.shadowRoot.children : []), ...(elementToCheck.assignedElements ? elementToCheck.assignedElements() : []));
8694    }
8695  }
8696  function elementIsChildOf(el, parent) {
8697    const window = getWindow();
8698    let isChild = parent.contains(el);
8699    if (!isChild && window.HTMLSlotElement && parent instanceof HTMLSlotElement) {
8700      const children = [...parent.assignedElements()];
8701      isChild = children.includes(el);
8702      if (!isChild) {
8703        isChild = elementIsChildOfSlot(el, parent);
8704      }
8705    }
8706    return isChild;
8707  }
8708  function showWarning(text) {
8709    try {
8710      console.warn(text);
8711      return;
8712    } catch (err) {
8713      // err
8714    }
8715  }
8716  function createElement(tag, classes = []) {
8717    const el = document.createElement(tag);
8718    el.classList.add(...(Array.isArray(classes) ? classes : classesToTokens(classes)));
8719    return el;
8720  }
8721  function elementOffset(el) {
8722    const window = getWindow();
8723    const document = getDocument();
8724    const box = el.getBoundingClientRect();
8725    const body = document.body;
8726    const clientTop = el.clientTop || body.clientTop || 0;
8727    const clientLeft = el.clientLeft || body.clientLeft || 0;
8728    const scrollTop = el === window ? window.scrollY : el.scrollTop;
8729    const scrollLeft = el === window ? window.scrollX : el.scrollLeft;
8730    return {
8731      top: box.top + scrollTop - clientTop,
8732      left: box.left + scrollLeft - clientLeft
8733    };
8734  }
8735  function elementPrevAll(el, selector) {
8736    const prevEls = [];
8737    while (el.previousElementSibling) {
8738      const prev = el.previousElementSibling; // eslint-disable-line
8739      if (selector) {
8740        if (prev.matches(selector)) prevEls.push(prev);
8741      } else prevEls.push(prev);
8742      el = prev;
8743    }
8744    return prevEls;
8745  }
8746  function elementNextAll(el, selector) {
8747    const nextEls = [];
8748    while (el.nextElementSibling) {
8749      const next = el.nextElementSibling; // eslint-disable-line
8750      if (selector) {
8751        if (next.matches(selector)) nextEls.push(next);
8752      } else nextEls.push(next);
8753      el = next;
8754    }
8755    return nextEls;
8756  }
8757  function elementStyle(el, prop) {
8758    const window = getWindow();
8759    return window.getComputedStyle(el, null).getPropertyValue(prop);
8760  }
8761  function elementIndex(el) {
8762    let child = el;
8763    let i;
8764    if (child) {
8765      i = 0;
8766      // eslint-disable-next-line
8767      while ((child = child.previousSibling) !== null) {
8768        if (child.nodeType === 1) i += 1;
8769      }
8770      return i;
8771    }
8772    return undefined;
8773  }
8774  function elementParents(el, selector) {
8775    const parents = []; // eslint-disable-line
8776    let parent = el.parentElement; // eslint-disable-line
8777    while (parent) {
8778      if (selector) {
8779        if (parent.matches(selector)) parents.push(parent);
8780      } else {
8781        parents.push(parent);
8782      }
8783      parent = parent.parentElement;
8784    }
8785    return parents;
8786  }
8787  function elementTransitionEnd(el, callback) {
8788    function fireCallBack(e) {
8789      if (e.target !== el) return;
8790      callback.call(el, e);
8791      el.removeEventListener('transitionend', fireCallBack);
8792    }
8793    if (callback) {
8794      el.addEventListener('transitionend', fireCallBack);
8795    }
8796  }
8797  function elementOuterSize(el, size, includeMargins) {
8798    const window = getWindow();
8799    if (includeMargins) {
8800      return el[size === 'width' ? 'offsetWidth' : 'offsetHeight'] + parseFloat(window.getComputedStyle(el, null).getPropertyValue(size === 'width' ? 'margin-right' : 'margin-top')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue(size === 'width' ? 'margin-left' : 'margin-bottom'));
8801    }
8802    return el.offsetWidth;
8803  }
8804  function makeElementsArray(el) {
8805    return (Array.isArray(el) ? el : [el]).filter(e => !!e);
8806  }
8807  function getRotateFix(swiper) {
8808    return v => {
8809      if (Math.abs(v) > 0 && swiper.browser && swiper.browser.need3dFix && Math.abs(v) % 90 === 0) {
8810        return v + 0.001;
8811      }
8812      return v;
8813    };
8814  }
8815  function setInnerHTML(el, html = '') {
8816    if (typeof trustedTypes !== 'undefined') {
8817      el.innerHTML = trustedTypes.createPolicy('html', {
8818        createHTML: s => s
8819      }).createHTML(html);
8820    } else {
8821      el.innerHTML = html;
8822    }
8823  }
8824
8825  let support;
8826  function calcSupport() {
8827    const window = getWindow();
8828    const document = getDocument();
8829    return {
8830      smoothScroll: document.documentElement && document.documentElement.style && 'scrollBehavior' in document.documentElement.style,
8831      touch: !!('ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch)
8832    };
8833  }
8834  function getSupport() {
8835    if (!support) {
8836      support = calcSupport();
8837    }
8838    return support;
8839  }
8840
8841  let deviceCached;
8842  function calcDevice({
8843    userAgent
8844  } = {}) {
vendor: 13,243 bytes, lines 8845-9232
8845    const support = getSupport();
8846    const window = getWindow();
8847    const platform = window.navigator.platform;
8848    const ua = userAgent || window.navigator.userAgent;
8849    const device = {
8850      ios: false,
8851      android: false
8852    };
8853    const screenWidth = window.screen.width;
8854    const screenHeight = window.screen.height;
8855    const android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); // eslint-disable-line
8856    let ipad = ua.match(/(iPad)(?!\1).*OS\s([\d_]+)/);
8857    const ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
8858    const iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/);
8859    const windows = platform === 'Win32';
8860    let macos = platform === 'MacIntel';
8861
8862    // iPadOs 13 fix
8863    const iPadScreens = ['1024x1366', '1366x1024', '834x1194', '1194x834', '834x1112', '1112x834', '768x1024', '1024x768', '820x1180', '1180x820', '810x1080', '1080x810'];
8864    if (!ipad && macos && support.touch && iPadScreens.indexOf(`${screenWidth}x${screenHeight}`) >= 0) {
8865      ipad = ua.match(/(Version)\/([\d.]+)/);
8866      if (!ipad) ipad = [0, 1, '13_0_0'];
8867      macos = false;
8868    }
8869
8870    // Android
8871    if (android && !windows) {
8872      device.os = 'android';
8873      device.android = true;
8874    }
8875    if (ipad || iphone || ipod) {
8876      device.os = 'ios';
8877      device.ios = true;
8878    }
8879
8880    // Export object
8881    return device;
8882  }
8883  function getDevice(overrides = {}) {
8884    if (!deviceCached) {
8885      deviceCached = calcDevice(overrides);
8886    }
8887    return deviceCached;
8888  }
8889
8890  let browser;
8891  function calcBrowser() {
8892    const window = getWindow();
8893    const device = getDevice();
8894    let needPerspectiveFix = false;
8895    function isSafari() {
8896      const ua = window.navigator.userAgent.toLowerCase();
8897      return ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0;
8898    }
8899    if (isSafari()) {
8900      const ua = String(window.navigator.userAgent);
8901      if (ua.includes('Version/')) {
8902        const [major, minor] = ua.split('Version/')[1].split(' ')[0].split('.').map(num => Number(num));
8903        needPerspectiveFix = major < 16 || major === 16 && minor < 2;
8904      }
8905    }
8906    const isWebView = /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(window.navigator.userAgent);
8907    const isSafariBrowser = isSafari();
8908    const need3dFix = isSafariBrowser || isWebView && device.ios;
8909    return {
8910      isSafari: needPerspectiveFix || isSafariBrowser,
8911      needPerspectiveFix,
8912      need3dFix,
8913      isWebView
8914    };
8915  }
8916  function getBrowser() {
8917    if (!browser) {
8918      browser = calcBrowser();
8919    }
8920    return browser;
8921  }
8922
8923  function Resize({
8924    swiper,
8925    on,
8926    emit
8927  }) {
8928    const window = getWindow();
8929    let observer = null;
8930    let animationFrame = null;
8931    const resizeHandler = () => {
8932      if (!swiper || swiper.destroyed || !swiper.initialized) return;
8933      emit('beforeResize');
8934      emit('resize');
8935    };
8936    const createObserver = () => {
8937      if (!swiper || swiper.destroyed || !swiper.initialized) return;
8938      observer = new ResizeObserver(entries => {
8939        animationFrame = window.requestAnimationFrame(() => {
8940          const {
8941            width,
8942            height
8943          } = swiper;
8944          let newWidth = width;
8945          let newHeight = height;
8946          entries.forEach(({
8947            contentBoxSize,
8948            contentRect,
8949            target
8950          }) => {
8951            if (target && target !== swiper.el) return;
8952            newWidth = contentRect ? contentRect.width : (contentBoxSize[0] || contentBoxSize).inlineSize;
8953            newHeight = contentRect ? contentRect.height : (contentBoxSize[0] || contentBoxSize).blockSize;
8954          });
8955          if (newWidth !== width || newHeight !== height) {
8956            resizeHandler();
8957          }
8958        });
8959      });
8960      observer.observe(swiper.el);
8961    };
8962    const removeObserver = () => {
8963      if (animationFrame) {
8964        window.cancelAnimationFrame(animationFrame);
8965      }
8966      if (observer && observer.unobserve && swiper.el) {
8967        observer.unobserve(swiper.el);
8968        observer = null;
8969      }
8970    };
8971    const orientationChangeHandler = () => {
8972      if (!swiper || swiper.destroyed || !swiper.initialized) return;
8973      emit('orientationchange');
8974    };
8975    on('init', () => {
8976      if (swiper.params.resizeObserver && typeof window.ResizeObserver !== 'undefined') {
8977        createObserver();
8978        return;
8979      }
8980      window.addEventListener('resize', resizeHandler);
8981      window.addEventListener('orientationchange', orientationChangeHandler);
8982    });
8983    on('destroy', () => {
8984      removeObserver();
8985      window.removeEventListener('resize', resizeHandler);
8986      window.removeEventListener('orientationchange', orientationChangeHandler);
8987    });
8988  }
8989
8990  function Observer({
8991    swiper,
8992    extendParams,
8993    on,
8994    emit
8995  }) {
8996    const observers = [];
8997    const window = getWindow();
8998    const attach = (target, options = {}) => {
8999      const ObserverFunc = window.MutationObserver || window.WebkitMutationObserver;
9000      const observer = new ObserverFunc(mutations => {
9001        // The observerUpdate event should only be triggered
9002        // once despite the number of mutations.  Additional
9003        // triggers are redundant and are very costly
9004        if (swiper.__preventObserver__) return;
9005        if (mutations.length === 1) {
9006          emit('observerUpdate', mutations[0]);
9007          return;
9008        }
9009        const observerUpdate = function observerUpdate() {
9010          emit('observerUpdate', mutations[0]);
9011        };
9012        if (window.requestAnimationFrame) {
9013          window.requestAnimationFrame(observerUpdate);
9014        } else {
9015          window.setTimeout(observerUpdate, 0);
9016        }
9017      });
9018      observer.observe(target, {
9019        attributes: typeof options.attributes === 'undefined' ? true : options.attributes,
9020        childList: swiper.isElement || (typeof options.childList === 'undefined' ? true : options).childList,
9021        characterData: typeof options.characterData === 'undefined' ? true : options.characterData
9022      });
9023      observers.push(observer);
9024    };
9025    const init = () => {
9026      if (!swiper.params.observer) return;
9027      if (swiper.params.observeParents) {
9028        const containerParents = elementParents(swiper.hostEl);
9029        for (let i = 0; i < containerParents.length; i += 1) {
9030          attach(containerParents[i]);
9031        }
9032      }
9033      // Observe container
9034      attach(swiper.hostEl, {
9035        childList: swiper.params.observeSlideChildren
9036      });
9037
9038      // Observe wrapper
9039      attach(swiper.wrapperEl, {
9040        attributes: false
9041      });
9042    };
9043    const destroy = () => {
9044      observers.forEach(observer => {
9045        observer.disconnect();
9046      });
9047      observers.splice(0, observers.length);
9048    };
9049    extendParams({
9050      observer: false,
9051      observeParents: false,
9052      observeSlideChildren: false
9053    });
9054    on('init', init);
9055    on('destroy', destroy);
9056  }
9057
9058  /* eslint-disable no-underscore-dangle */
9059
9060  var eventsEmitter = {
9061    on(events, handler, priority) {
9062      const self = this;
9063      if (!self.eventsListeners || self.destroyed) return self;
9064      if (typeof handler !== 'function') return self;
9065      const method = priority ? 'unshift' : 'push';
9066      events.split(' ').forEach(event => {
9067        if (!self.eventsListeners[event]) self.eventsListeners[event] = [];
9068        self.eventsListeners[event][method](handler);
9069      });
9070      return self;
9071    },
9072    once(events, handler, priority) {
9073      const self = this;
9074      if (!self.eventsListeners || self.destroyed) return self;
9075      if (typeof handler !== 'function') return self;
9076      function onceHandler(...args) {
9077        self.off(events, onceHandler);
9078        if (onceHandler.__emitterProxy) {
9079          delete onceHandler.__emitterProxy;
9080        }
9081        handler.apply(self, args);
9082      }
9083      onceHandler.__emitterProxy = handler;
9084      return self.on(events, onceHandler, priority);
9085    },
9086    onAny(handler, priority) {
9087      const self = this;
9088      if (!self.eventsListeners || self.destroyed) return self;
9089      if (typeof handler !== 'function') return self;
9090      const method = priority ? 'unshift' : 'push';
9091      if (self.eventsAnyListeners.indexOf(handler) < 0) {
9092        self.eventsAnyListeners[method](handler);
9093      }
9094      return self;
9095    },
9096    offAny(handler) {
9097      const self = this;
9098      if (!self.eventsListeners || self.destroyed) return self;
9099      if (!self.eventsAnyListeners) return self;
9100      const index = self.eventsAnyListeners.indexOf(handler);
9101      if (index >= 0) {
9102        self.eventsAnyListeners.splice(index, 1);
9103      }
9104      return self;
9105    },
9106    off(events, handler) {
9107      const self = this;
9108      if (!self.eventsListeners || self.destroyed) return self;
9109      if (!self.eventsListeners) return self;
9110      events.split(' ').forEach(event => {
9111        if (typeof handler === 'undefined') {
9112          self.eventsListeners[event] = [];
9113        } else if (self.eventsListeners[event]) {
9114          self.eventsListeners[event].forEach((eventHandler, index) => {
9115            if (eventHandler === handler || eventHandler.__emitterProxy && eventHandler.__emitterProxy === handler) {
9116              self.eventsListeners[event].splice(index, 1);
9117            }
9118          });
9119        }
9120      });
9121      return self;
9122    },
9123    emit(...args) {
9124      const self = this;
9125      if (!self.eventsListeners || self.destroyed) return self;
9126      if (!self.eventsListeners) return self;
9127      let events;
9128      let data;
9129      let context;
9130      if (typeof args[0] === 'string' || Array.isArray(args[0])) {
9131        events = args[0];
9132        data = args.slice(1, args.length);
9133        context = self;
9134      } else {
9135        events = args[0].events;
9136        data = args[0].data;
9137        context = args[0].context || self;
9138      }
9139      data.unshift(context);
9140      const eventsArray = Array.isArray(events) ? events : events.split(' ');
9141      eventsArray.forEach(event => {
9142        if (self.eventsAnyListeners && self.eventsAnyListeners.length) {
9143          self.eventsAnyListeners.forEach(eventHandler => {
9144            eventHandler.apply(context, [event, ...data]);
9145          });
9146        }
9147        if (self.eventsListeners && self.eventsListeners[event]) {
9148          self.eventsListeners[event].forEach(eventHandler => {
9149            eventHandler.apply(context, data);
9150          });
9151        }
9152      });
9153      return self;
9154    }
9155  };
9156
9157  function updateSize() {
9158    const swiper = this;
9159    let width;
9160    let height;
9161    const el = swiper.el;
9162    if (typeof swiper.params.width !== 'undefined' && swiper.params.width !== null) {
9163      width = swiper.params.width;
9164    } else {
9165      width = el.clientWidth;
9166    }
9167    if (typeof swiper.params.height !== 'undefined' && swiper.params.height !== null) {
9168      height = swiper.params.height;
9169    } else {
9170      height = el.clientHeight;
9171    }
9172    if (width === 0 && swiper.isHorizontal() || height === 0 && swiper.isVertical()) {
9173      return;
9174    }
9175
9176    // Subtract paddings
9177    width = width - parseInt(elementStyle(el, 'padding-left') || 0, 10) - parseInt(elementStyle(el, 'padding-right') || 0, 10);
9178    height = height - parseInt(elementStyle(el, 'padding-top') || 0, 10) - parseInt(elementStyle(el, 'padding-bottom') || 0, 10);
9179    if (Number.isNaN(width)) width = 0;
9180    if (Number.isNaN(height)) height = 0;
9181    Object.assign(swiper, {
9182      width,
9183      height,
9184      size: swiper.isHorizontal() ? width : height
9185    });
9186  }
9187
9188  function updateSlides() {
9189    const swiper = this;
9190    function getDirectionPropertyValue(node, label) {
9191      return parseFloat(node.getPropertyValue(swiper.getDirectionLabel(label)) || 0);
9192    }
9193    const params = swiper.params;
9194    const {
9195      wrapperEl,
9196      slidesEl,
9197      rtlTranslate: rtl,
9198      wrongRTL
9199    } = swiper;
9200    const isVirtual = swiper.virtual && params.virtual.enabled;
9201    const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length;
9202    const slides = elementChildren(slidesEl, `.${swiper.params.slideClass}, swiper-slide`);
9203    const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length;
9204    let snapGrid = [];
9205    const slidesGrid = [];
9206    const slidesSizesGrid = [];
9207    let offsetBefore = params.slidesOffsetBefore;
9208    if (typeof offsetBefore === 'function') {
9209      offsetBefore = params.slidesOffsetBefore.call(swiper);
9210    }
9211    let offsetAfter = params.slidesOffsetAfter;
9212    if (typeof offsetAfter === 'function') {
9213      offsetAfter = params.slidesOffsetAfter.call(swiper);
9214    }
9215    const previousSnapGridLength = swiper.snapGrid.length;
9216    const previousSlidesGridLength = swiper.slidesGrid.length;
9217    const swiperSize = swiper.size - offsetBefore - offsetAfter;
9218    let spaceBetween = params.spaceBetween;
9219    let slidePosition = -offsetBefore;
9220    let prevSlideSize = 0;
9221    let index = 0;
9222    if (typeof swiperSize === 'undefined') {
9223      return;
9224    }
9225    if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
9226      spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiperSize;
9227    } else if (typeof spaceBetween === 'string') {
9228      spaceBetween = parseFloat(spaceBetween);
9229    }
9230    swiper.virtualSize = -spaceBetween - offsetBefore - offsetAfter;
9231
9232    // reset margins
vendor: 5,708 bytes, lines 9233-9363
9233    slides.forEach(slideEl => {
9234      if (rtl) {
9235        slideEl.style.marginLeft = '';
9236      } else {
9237        slideEl.style.marginRight = '';
9238      }
9239      slideEl.style.marginBottom = '';
9240      slideEl.style.marginTop = '';
9241    });
9242
9243    // reset cssMode offsets
9244    if (params.centeredSlides && params.cssMode) {
9245      setCSSProperty(wrapperEl, '--swiper-centered-offset-before', '');
9246      setCSSProperty(wrapperEl, '--swiper-centered-offset-after', '');
9247    }
9248    const gridEnabled = params.grid && params.grid.rows > 1 && swiper.grid;
9249    if (gridEnabled) {
9250      swiper.grid.initSlides(slides);
9251    } else if (swiper.grid) {
9252      swiper.grid.unsetSlides();
9253    }
9254
9255    // Calc slides
9256    let slideSize;
9257    const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => {
9258      return typeof params.breakpoints[key].slidesPerView !== 'undefined';
9259    }).length > 0;
9260    for (let i = 0; i < slidesLength; i += 1) {
9261      slideSize = 0;
9262      const slide = slides[i];
9263      if (slide) {
9264        if (gridEnabled) {
9265          swiper.grid.updateSlide(i, slide, slides);
9266        }
9267        if (elementStyle(slide, 'display') === 'none') continue; // eslint-disable-line
9268      }
9269
9270      if (isVirtual && params.slidesPerView === 'auto') {
9271        if (params.virtual.slidesPerViewAutoSlideSize) {
9272          slideSize = params.virtual.slidesPerViewAutoSlideSize;
9273        }
9274        if (slideSize && slide) {
9275          if (params.roundLengths) slideSize = Math.floor(slideSize);
9276          slide.style[swiper.getDirectionLabel('width')] = `${slideSize}px`;
9277        }
9278      } else if (params.slidesPerView === 'auto') {
9279        if (shouldResetSlideSize) {
9280          slide.style[swiper.getDirectionLabel('width')] = ``;
9281        }
9282        const slideStyles = getComputedStyle(slide);
9283        const currentTransform = slide.style.transform;
9284        const currentWebKitTransform = slide.style.webkitTransform;
9285        if (currentTransform) {
9286          slide.style.transform = 'none';
9287        }
9288        if (currentWebKitTransform) {
9289          slide.style.webkitTransform = 'none';
9290        }
9291        if (params.roundLengths) {
9292          slideSize = swiper.isHorizontal() ? elementOuterSize(slide, 'width', true) : elementOuterSize(slide, 'height', true);
9293        } else {
9294          // eslint-disable-next-line
9295          const width = getDirectionPropertyValue(slideStyles, 'width');
9296          const paddingLeft = getDirectionPropertyValue(slideStyles, 'padding-left');
9297          const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right');
9298          const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left');
9299          const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right');
9300          const boxSizing = slideStyles.getPropertyValue('box-sizing');
9301          if (boxSizing && boxSizing === 'border-box') {
9302            slideSize = width + marginLeft + marginRight;
9303          } else {
9304            const {
9305              clientWidth,
9306              offsetWidth
9307            } = slide;
9308            slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight + (offsetWidth - clientWidth);
9309          }
9310        }
9311        if (currentTransform) {
9312          slide.style.transform = currentTransform;
9313        }
9314        if (currentWebKitTransform) {
9315          slide.style.webkitTransform = currentWebKitTransform;
9316        }
9317        if (params.roundLengths) slideSize = Math.floor(slideSize);
9318      } else {
9319        slideSize = (swiperSize - (params.slidesPerView - 1) * spaceBetween) / params.slidesPerView;
9320        if (params.roundLengths) slideSize = Math.floor(slideSize);
9321        if (slide) {
9322          slide.style[swiper.getDirectionLabel('width')] = `${slideSize}px`;
9323        }
9324      }
9325      if (slide) {
9326        slide.swiperSlideSize = slideSize;
9327      }
9328      slidesSizesGrid.push(slideSize);
9329      if (params.centeredSlides) {
9330        slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;
9331        if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
9332        if (i === 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;
9333        if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;
9334        if (params.roundLengths) slidePosition = Math.floor(slidePosition);
9335        if (index % params.slidesPerGroup === 0) snapGrid.push(slidePosition);
9336        slidesGrid.push(slidePosition);
9337      } else {
9338        if (params.roundLengths) slidePosition = Math.floor(slidePosition);
9339        if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) snapGrid.push(slidePosition);
9340        slidesGrid.push(slidePosition);
9341        slidePosition = slidePosition + slideSize + spaceBetween;
9342      }
9343      swiper.virtualSize += slideSize + spaceBetween;
9344      prevSlideSize = slideSize;
9345      index += 1;
9346    }
9347    swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter;
9348    if (rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) {
9349      wrapperEl.style.width = `${swiper.virtualSize + spaceBetween}px`;
9350    }
9351    if (params.setWrapperSize) {
9352      wrapperEl.style[swiper.getDirectionLabel('width')] = `${swiper.virtualSize + spaceBetween}px`;
9353    }
9354    if (gridEnabled) {
9355      swiper.grid.updateWrapperSize(slideSize, snapGrid);
9356    }
9357
9358    // Remove last grid elements depending on width
9359    if (!params.centeredSlides) {
9360      const newSlidesGrid = [];
9361      for (let i = 0; i < snapGrid.length; i += 1) {
9362        let slidesGridItem = snapGrid[i];
9363        if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);
vendor: 1,485 bytes, lines 9364-9399
9364        if (snapGrid[i] <= swiper.virtualSize - swiperSize) {
9365          newSlidesGrid.push(slidesGridItem);
9366        }
9367      }
9368      snapGrid = newSlidesGrid;
9369      if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {
9370        snapGrid.push(swiper.virtualSize - swiperSize);
9371      }
9372    }
9373    if (isVirtual && params.loop) {
9374      const size = slidesSizesGrid[0] + spaceBetween;
9375      if (params.slidesPerGroup > 1) {
9376        const groups = Math.ceil((swiper.virtual.slidesBefore + swiper.virtual.slidesAfter) / params.slidesPerGroup);
9377        const groupSize = size * params.slidesPerGroup;
9378        for (let i = 0; i < groups; i += 1) {
9379          snapGrid.push(snapGrid[snapGrid.length - 1] + groupSize);
9380        }
9381      }
9382      for (let i = 0; i < swiper.virtual.slidesBefore + swiper.virtual.slidesAfter; i += 1) {
9383        if (params.slidesPerGroup === 1) {
9384          snapGrid.push(snapGrid[snapGrid.length - 1] + size);
9385        }
9386        slidesGrid.push(slidesGrid[slidesGrid.length - 1] + size);
9387        swiper.virtualSize += size;
9388      }
9389    }
9390    if (snapGrid.length === 0) snapGrid = [0];
9391    if (spaceBetween !== 0) {
9392      const key = swiper.isHorizontal() && rtl ? 'marginLeft' : swiper.getDirectionLabel('marginRight');
9393      slides.filter((_, slideIndex) => {
9394        if (!params.cssMode || params.loop) return true;
9395        if (slideIndex === slides.length - 1) {
9396          return false;
9397        }
9398        return true;
9399      }
vendor: 65,509 bytes, lines 9399-11145
9399).forEach(slideEl => {
9400        slideEl.style[key] = `${spaceBetween}px`;
9401      });
9402    }
9403    if (params.centeredSlides && params.centeredSlidesBounds) {
9404      let allSlidesSize = 0;
9405      slidesSizesGrid.forEach(slideSizeValue => {
9406        allSlidesSize += slideSizeValue + (spaceBetween || 0);
9407      });
9408      allSlidesSize -= spaceBetween;
9409      const maxSnap = allSlidesSize > swiperSize ? allSlidesSize - swiperSize : 0;
9410      snapGrid = snapGrid.map(snap => {
9411        if (snap <= 0) return -offsetBefore;
9412        if (snap > maxSnap) return maxSnap + offsetAfter;
9413        return snap;
9414      });
9415    }
9416    if (params.centerInsufficientSlides) {
9417      let allSlidesSize = 0;
9418      slidesSizesGrid.forEach(slideSizeValue => {
9419        allSlidesSize += slideSizeValue + (spaceBetween || 0);
9420      });
9421      allSlidesSize -= spaceBetween;
9422      const offsetSize = (offsetBefore || 0) + (offsetAfter || 0);
9423      if (allSlidesSize + offsetSize < swiperSize) {
9424        const allSlidesOffset = (swiperSize - allSlidesSize - offsetSize) / 2;
9425        snapGrid.forEach((snap, snapIndex) => {
9426          snapGrid[snapIndex] = snap - allSlidesOffset;
9427        });
9428        slidesGrid.forEach((snap, snapIndex) => {
9429          slidesGrid[snapIndex] = snap + allSlidesOffset;
9430        });
9431      }
9432    }
9433    Object.assign(swiper, {
9434      slides,
9435      snapGrid,
9436      slidesGrid,
9437      slidesSizesGrid
9438    });
9439    if (params.centeredSlides && params.cssMode && !params.centeredSlidesBounds) {
9440      setCSSProperty(wrapperEl, '--swiper-centered-offset-before', `${-snapGrid[0]}px`);
9441      setCSSProperty(wrapperEl, '--swiper-centered-offset-after', `${swiper.size / 2 - slidesSizesGrid[slidesSizesGrid.length - 1] / 2}px`);
9442      const addToSnapGrid = -swiper.snapGrid[0];
9443      const addToSlidesGrid = -swiper.slidesGrid[0];
9444      swiper.snapGrid = swiper.snapGrid.map(v => v + addToSnapGrid);
9445      swiper.slidesGrid = swiper.slidesGrid.map(v => v + addToSlidesGrid);
9446    }
9447    if (slidesLength !== previousSlidesLength) {
9448      swiper.emit('slidesLengthChange');
9449    }
9450    if (snapGrid.length !== previousSnapGridLength) {
9451      if (swiper.params.watchOverflow) swiper.checkOverflow();
9452      swiper.emit('snapGridLengthChange');
9453    }
9454    if (slidesGrid.length !== previousSlidesGridLength) {
9455      swiper.emit('slidesGridLengthChange');
9456    }
9457    if (params.watchSlidesProgress) {
9458      swiper.updateSlidesOffset();
9459    }
9460    swiper.emit('slidesUpdated');
9461    if (!isVirtual && !params.cssMode && (params.effect === 'slide' || params.effect === 'fade')) {
9462      const backFaceHiddenClass = `${params.containerModifierClass}backface-hidden`;
9463      const hasClassBackfaceClassAdded = swiper.el.classList.contains(backFaceHiddenClass);
9464      if (slidesLength <= params.maxBackfaceHiddenSlides) {
9465        if (!hasClassBackfaceClassAdded) swiper.el.classList.add(backFaceHiddenClass);
9466      } else if (hasClassBackfaceClassAdded) {
9467        swiper.el.classList.remove(backFaceHiddenClass);
9468      }
9469    }
9470  }
9471
9472  function updateAutoHeight(speed) {
9473    const swiper = this;
9474    const activeSlides = [];
9475    const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
9476    let newHeight = 0;
9477    let i;
9478    if (typeof speed === 'number') {
9479      swiper.setTransition(speed);
9480    } else if (speed === true) {
9481      swiper.setTransition(swiper.params.speed);
9482    }
9483    const getSlideByIndex = index => {
9484      if (isVirtual) {
9485        return swiper.slides[swiper.getSlideIndexByData(index)];
9486      }
9487      return swiper.slides[index];
9488    };
9489    // Find slides currently in view
9490    if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) {
9491      if (swiper.params.centeredSlides) {
9492        (swiper.visibleSlides || []).forEach(slide => {
9493          activeSlides.push(slide);
9494        });
9495      } else {
9496        for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {
9497          const index = swiper.activeIndex + i;
9498          if (index > swiper.slides.length && !isVirtual) break;
9499          activeSlides.push(getSlideByIndex(index));
9500        }
9501      }
9502    } else {
9503      activeSlides.push(getSlideByIndex(swiper.activeIndex));
9504    }
9505
9506    // Find new height from highest slide in view
9507    for (i = 0; i < activeSlides.length; i += 1) {
9508      if (typeof activeSlides[i] !== 'undefined') {
9509        const height = activeSlides[i].offsetHeight;
9510        newHeight = height > newHeight ? height : newHeight;
9511      }
9512    }
9513
9514    // Update Height
9515    if (newHeight || newHeight === 0) swiper.wrapperEl.style.height = `${newHeight}px`;
9516  }
9517
9518  function updateSlidesOffset() {
9519    const swiper = this;
9520    const slides = swiper.slides;
9521    // eslint-disable-next-line
9522    const minusOffset = swiper.isElement ? swiper.isHorizontal() ? swiper.wrapperEl.offsetLeft : swiper.wrapperEl.offsetTop : 0;
9523    for (let i = 0; i < slides.length; i += 1) {
9524      slides[i].swiperSlideOffset = (swiper.isHorizontal() ? slides[i].offsetLeft : slides[i].offsetTop) - minusOffset - swiper.cssOverflowAdjustment();
9525    }
9526  }
9527
9528  const toggleSlideClasses$1 = (slideEl, condition, className) => {
9529    if (condition && !slideEl.classList.contains(className)) {
9530      slideEl.classList.add(className);
9531    } else if (!condition && slideEl.classList.contains(className)) {
9532      slideEl.classList.remove(className);
9533    }
9534  };
9535  function updateSlidesProgress(translate = this && this.translate || 0) {
9536    const swiper = this;
9537    const params = swiper.params;
9538    const {
9539      slides,
9540      rtlTranslate: rtl,
9541      snapGrid
9542    } = swiper;
9543    if (slides.length === 0) return;
9544    if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset();
9545    let offsetCenter = -translate;
9546    if (rtl) offsetCenter = translate;
9547    swiper.visibleSlidesIndexes = [];
9548    swiper.visibleSlides = [];
9549    let spaceBetween = params.spaceBetween;
9550    if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
9551      spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiper.size;
9552    } else if (typeof spaceBetween === 'string') {
9553      spaceBetween = parseFloat(spaceBetween);
9554    }
9555    for (let i = 0; i < slides.length; i += 1) {
9556      const slide = slides[i];
9557      let slideOffset = slide.swiperSlideOffset;
9558      if (params.cssMode && params.centeredSlides) {
9559        slideOffset -= slides[0].swiperSlideOffset;
9560      }
9561      const slideProgress = (offsetCenter + (params.centeredSlides ? swiper.minTranslate() : 0) - slideOffset) / (slide.swiperSlideSize + spaceBetween);
9562      const originalSlideProgress = (offsetCenter - snapGrid[0] + (params.centeredSlides ? swiper.minTranslate() : 0) - slideOffset) / (slide.swiperSlideSize + spaceBetween);
9563      const slideBefore = -(offsetCenter - slideOffset);
9564      const slideAfter = slideBefore + swiper.slidesSizesGrid[i];
9565      const isFullyVisible = slideBefore >= 0 && slideBefore <= swiper.size - swiper.slidesSizesGrid[i];
9566      const isVisible = slideBefore >= 0 && slideBefore < swiper.size - 1 || slideAfter > 1 && slideAfter <= swiper.size || slideBefore <= 0 && slideAfter >= swiper.size;
9567      if (isVisible) {
9568        swiper.visibleSlides.push(slide);
9569        swiper.visibleSlidesIndexes.push(i);
9570      }
9571      toggleSlideClasses$1(slide, isVisible, params.slideVisibleClass);
9572      toggleSlideClasses$1(slide, isFullyVisible, params.slideFullyVisibleClass);
9573      slide.progress = rtl ? -slideProgress : slideProgress;
9574      slide.originalProgress = rtl ? -originalSlideProgress : originalSlideProgress;
9575    }
9576  }
9577
9578  function updateProgress(translate) {
9579    const swiper = this;
9580    if (typeof translate === 'undefined') {
9581      const multiplier = swiper.rtlTranslate ? -1 : 1;
9582      // eslint-disable-next-line
9583      translate = swiper && swiper.translate && swiper.translate * multiplier || 0;
9584    }
9585    const params = swiper.params;
9586    const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
9587    let {
9588      progress,
9589      isBeginning,
9590      isEnd,
9591      progressLoop
9592    } = swiper;
9593    const wasBeginning = isBeginning;
9594    const wasEnd = isEnd;
9595    if (translatesDiff === 0) {
9596      progress = 0;
9597      isBeginning = true;
9598      isEnd = true;
9599    } else {
9600      progress = (translate - swiper.minTranslate()) / translatesDiff;
9601      const isBeginningRounded = Math.abs(translate - swiper.minTranslate()) < 1;
9602      const isEndRounded = Math.abs(translate - swiper.maxTranslate()) < 1;
9603      isBeginning = isBeginningRounded || progress <= 0;
9604      isEnd = isEndRounded || progress >= 1;
9605      if (isBeginningRounded) progress = 0;
9606      if (isEndRounded) progress = 1;
9607    }
9608    if (params.loop) {
9609      const firstSlideIndex = swiper.getSlideIndexByData(0);
9610      const lastSlideIndex = swiper.getSlideIndexByData(swiper.slides.length - 1);
9611      const firstSlideTranslate = swiper.slidesGrid[firstSlideIndex];
9612      const lastSlideTranslate = swiper.slidesGrid[lastSlideIndex];
9613      const translateMax = swiper.slidesGrid[swiper.slidesGrid.length - 1];
9614      const translateAbs = Math.abs(translate);
9615      if (translateAbs >= firstSlideTranslate) {
9616        progressLoop = (translateAbs - firstSlideTranslate) / translateMax;
9617      } else {
9618        progressLoop = (translateAbs + translateMax - lastSlideTranslate) / translateMax;
9619      }
9620      if (progressLoop > 1) progressLoop -= 1;
9621    }
9622    Object.assign(swiper, {
9623      progress,
9624      progressLoop,
9625      isBeginning,
9626      isEnd
9627    });
9628    if (params.watchSlidesProgress || params.centeredSlides && params.autoHeight) swiper.updateSlidesProgress(translate);
9629    if (isBeginning && !wasBeginning) {
9630      swiper.emit('reachBeginning toEdge');
9631    }
9632    if (isEnd && !wasEnd) {
9633      swiper.emit('reachEnd toEdge');
9634    }
9635    if (wasBeginning && !isBeginning || wasEnd && !isEnd) {
9636      swiper.emit('fromEdge');
9637    }
9638    swiper.emit('progress', progress);
9639  }
9640
9641  const toggleSlideClasses = (slideEl, condition, className) => {
9642    if (condition && !slideEl.classList.contains(className)) {
9643      slideEl.classList.add(className);
9644    } else if (!condition && slideEl.classList.contains(className)) {
9645      slideEl.classList.remove(className);
9646    }
9647  };
9648  function updateSlidesClasses() {
9649    const swiper = this;
9650    const {
9651      slides,
9652      params,
9653      slidesEl,
9654      activeIndex
9655    } = swiper;
9656    const isVirtual = swiper.virtual && params.virtual.enabled;
9657    const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
9658    const getFilteredSlide = selector => {
9659      return elementChildren(slidesEl, `.${params.slideClass}${selector}, swiper-slide${selector}`)[0];
9660    };
9661    let activeSlide;
9662    let prevSlide;
9663    let nextSlide;
9664    if (isVirtual) {
9665      if (params.loop) {
9666        let slideIndex = activeIndex - swiper.virtual.slidesBefore;
9667        if (slideIndex < 0) slideIndex = swiper.virtual.slides.length + slideIndex;
9668        if (slideIndex >= swiper.virtual.slides.length) slideIndex -= swiper.virtual.slides.length;
9669        activeSlide = getFilteredSlide(`[data-swiper-slide-index="${slideIndex}"]`);
9670      } else {
9671        activeSlide = getFilteredSlide(`[data-swiper-slide-index="${activeIndex}"]`);
9672      }
9673    } else {
9674      if (gridEnabled) {
9675        activeSlide = slides.find(slideEl => slideEl.column === activeIndex);
9676        nextSlide = slides.find(slideEl => slideEl.column === activeIndex + 1);
9677        prevSlide = slides.find(slideEl => slideEl.column === activeIndex - 1);
9678      } else {
9679        activeSlide = slides[activeIndex];
9680      }
9681    }
9682    if (activeSlide) {
9683      if (!gridEnabled) {
9684        // Next Slide
9685        nextSlide = elementNextAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
9686        if (params.loop && !nextSlide) {
9687          nextSlide = slides[0];
9688        }
9689
9690        // Prev Slide
9691        prevSlide = elementPrevAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
9692        if (params.loop && !prevSlide === 0) {
9693          prevSlide = slides[slides.length - 1];
9694        }
9695      }
9696    }
9697    slides.forEach(slideEl => {
9698      toggleSlideClasses(slideEl, slideEl === activeSlide, params.slideActiveClass);
9699      toggleSlideClasses(slideEl, slideEl === nextSlide, params.slideNextClass);
9700      toggleSlideClasses(slideEl, slideEl === prevSlide, params.slidePrevClass);
9701    });
9702    swiper.emitSlidesClasses();
9703  }
9704
9705  const processLazyPreloader = (swiper, imageEl) => {
9706    if (!swiper || swiper.destroyed || !swiper.params) return;
9707    const slideSelector = () => swiper.isElement ? `swiper-slide` : `.${swiper.params.slideClass}`;
9708    const slideEl = imageEl.closest(slideSelector());
9709    if (slideEl) {
9710      let lazyEl = slideEl.querySelector(`.${swiper.params.lazyPreloaderClass}`);
9711      if (!lazyEl && swiper.isElement) {
9712        if (slideEl.shadowRoot) {
9713          lazyEl = slideEl.shadowRoot.querySelector(`.${swiper.params.lazyPreloaderClass}`);
9714        } else {
9715          // init later
9716          requestAnimationFrame(() => {
9717            if (slideEl.shadowRoot) {
9718              lazyEl = slideEl.shadowRoot.querySelector(`.${swiper.params.lazyPreloaderClass}`);
9719              if (lazyEl) lazyEl.remove();
9720            }
9721          });
9722        }
9723      }
9724      if (lazyEl) lazyEl.remove();
9725    }
9726  };
9727  const unlazy = (swiper, index) => {
9728    if (!swiper.slides[index]) return;
9729    const imageEl = swiper.slides[index].querySelector('[loading="lazy"]');
9730    if (imageEl) imageEl.removeAttribute('loading');
9731  };
9732  const preload = swiper => {
9733    if (!swiper || swiper.destroyed || !swiper.params) return;
9734    let amount = swiper.params.lazyPreloadPrevNext;
9735    const len = swiper.slides.length;
9736    if (!len || !amount || amount < 0) return;
9737    amount = Math.min(amount, len);
9738    const slidesPerView = swiper.params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(swiper.params.slidesPerView);
9739    const activeIndex = swiper.activeIndex;
9740    if (swiper.params.grid && swiper.params.grid.rows > 1) {
9741      const activeColumn = activeIndex;
9742      const preloadColumns = [activeColumn - amount];
9743      preloadColumns.push(...Array.from({
9744        length: amount
9745      }).map((_, i) => {
9746        return activeColumn + slidesPerView + i;
9747      }));
9748      swiper.slides.forEach((slideEl, i) => {
9749        if (preloadColumns.includes(slideEl.column)) unlazy(swiper, i);
9750      });
9751      return;
9752    }
9753    const slideIndexLastInView = activeIndex + slidesPerView - 1;
9754    if (swiper.params.rewind || swiper.params.loop) {
9755      for (let i = activeIndex - amount; i <= slideIndexLastInView + amount; i += 1) {
9756        const realIndex = (i % len + len) % len;
9757        if (realIndex < activeIndex || realIndex > slideIndexLastInView) unlazy(swiper, realIndex);
9758      }
9759    } else {
9760      for (let i = Math.max(activeIndex - amount, 0); i <= Math.min(slideIndexLastInView + amount, len - 1); i += 1) {
9761        if (i !== activeIndex && (i > slideIndexLastInView || i < activeIndex)) {
9762          unlazy(swiper, i);
9763        }
9764      }
9765    }
9766  };
9767
9768  function getActiveIndexByTranslate(swiper) {
9769    const {
9770      slidesGrid,
9771      params
9772    } = swiper;
9773    const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
9774    let activeIndex;
9775    for (let i = 0; i < slidesGrid.length; i += 1) {
9776      if (typeof slidesGrid[i + 1] !== 'undefined') {
9777        if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1] - (slidesGrid[i + 1] - slidesGrid[i]) / 2) {
9778          activeIndex = i;
9779        } else if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1]) {
9780          activeIndex = i + 1;
9781        }
9782      } else if (translate >= slidesGrid[i]) {
9783        activeIndex = i;
9784      }
9785    }
9786    // Normalize slideIndex
9787    if (params.normalizeSlideIndex) {
9788      if (activeIndex < 0 || typeof activeIndex === 'undefined') activeIndex = 0;
9789    }
9790    return activeIndex;
9791  }
9792  function updateActiveIndex(newActiveIndex) {
9793    const swiper = this;
9794    const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
9795    const {
9796      snapGrid,
9797      params,
9798      activeIndex: previousIndex,
9799      realIndex: previousRealIndex,
9800      snapIndex: previousSnapIndex
9801    } = swiper;
9802    let activeIndex = newActiveIndex;
9803    let snapIndex;
9804    const getVirtualRealIndex = aIndex => {
9805      let realIndex = aIndex - swiper.virtual.slidesBefore;
9806      if (realIndex < 0) {
9807        realIndex = swiper.virtual.slides.length + realIndex;
9808      }
9809      if (realIndex >= swiper.virtual.slides.length) {
9810        realIndex -= swiper.virtual.slides.length;
9811      }
9812      return realIndex;
9813    };
9814    if (typeof activeIndex === 'undefined') {
9815      activeIndex = getActiveIndexByTranslate(swiper);
9816    }
9817    if (snapGrid.indexOf(translate) >= 0) {
9818      snapIndex = snapGrid.indexOf(translate);
9819    } else {
9820      const skip = Math.min(params.slidesPerGroupSkip, activeIndex);
9821      snapIndex = skip + Math.floor((activeIndex - skip) / params.slidesPerGroup);
9822    }
9823    if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
9824    if (activeIndex === previousIndex && !swiper.params.loop) {
9825      if (snapIndex !== previousSnapIndex) {
9826        swiper.snapIndex = snapIndex;
9827        swiper.emit('snapIndexChange');
9828      }
9829      return;
9830    }
9831    if (activeIndex === previousIndex && swiper.params.loop && swiper.virtual && swiper.params.virtual.enabled) {
9832      swiper.realIndex = getVirtualRealIndex(activeIndex);
9833      return;
9834    }
9835    const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
9836
9837    // Get real index
9838    let realIndex;
9839    if (swiper.virtual && params.virtual.enabled && params.loop) {
9840      realIndex = getVirtualRealIndex(activeIndex);
9841    } else if (gridEnabled) {
9842      const firstSlideInColumn = swiper.slides.find(slideEl => slideEl.column === activeIndex);
9843      let activeSlideIndex = parseInt(firstSlideInColumn.getAttribute('data-swiper-slide-index'), 10);
9844      if (Number.isNaN(activeSlideIndex)) {
9845        activeSlideIndex = Math.max(swiper.slides.indexOf(firstSlideInColumn), 0);
9846      }
9847      realIndex = Math.floor(activeSlideIndex / params.grid.rows);
9848    } else if (swiper.slides[activeIndex]) {
9849      const slideIndex = swiper.slides[activeIndex].getAttribute('data-swiper-slide-index');
9850      if (slideIndex) {
9851        realIndex = parseInt(slideIndex, 10);
9852      } else {
9853        realIndex = activeIndex;
9854      }
9855    } else {
9856      realIndex = activeIndex;
9857    }
9858    Object.assign(swiper, {
9859      previousSnapIndex,
9860      snapIndex,
9861      previousRealIndex,
9862      realIndex,
9863      previousIndex,
9864      activeIndex
9865    });
9866    if (swiper.initialized) {
9867      preload(swiper);
9868    }
9869    swiper.emit('activeIndexChange');
9870    swiper.emit('snapIndexChange');
9871    if (swiper.initialized || swiper.params.runCallbacksOnInit) {
9872      if (previousRealIndex !== realIndex) {
9873        swiper.emit('realIndexChange');
9874      }
9875      swiper.emit('slideChange');
9876    }
9877  }
9878
9879  function updateClickedSlide(el, path) {
9880    const swiper = this;
9881    const params = swiper.params;
9882    let slide = el.closest(`.${params.slideClass}, swiper-slide`);
9883    if (!slide && swiper.isElement && path && path.length > 1 && path.includes(el)) {
9884      [...path.slice(path.indexOf(el) + 1, path.length)].forEach(pathEl => {
9885        if (!slide && pathEl.matches && pathEl.matches(`.${params.slideClass}, swiper-slide`)) {
9886          slide = pathEl;
9887        }
9888      });
9889    }
9890    let slideFound = false;
9891    let slideIndex;
9892    if (slide) {
9893      for (let i = 0; i < swiper.slides.length; i += 1) {
9894        if (swiper.slides[i] === slide) {
9895          slideFound = true;
9896          slideIndex = i;
9897          break;
9898        }
9899      }
9900    }
9901    if (slide && slideFound) {
9902      swiper.clickedSlide = slide;
9903      if (swiper.virtual && swiper.params.virtual.enabled) {
9904        swiper.clickedIndex = parseInt(slide.getAttribute('data-swiper-slide-index'), 10);
9905      } else {
9906        swiper.clickedIndex = slideIndex;
9907      }
9908    } else {
9909      swiper.clickedSlide = undefined;
9910      swiper.clickedIndex = undefined;
9911      return;
9912    }
9913    if (params.slideToClickedSlide && swiper.clickedIndex !== undefined && swiper.clickedIndex !== swiper.activeIndex) {
9914      swiper.slideToClickedSlide();
9915    }
9916  }
9917
9918  var update = {
9919    updateSize,
9920    updateSlides,
9921    updateAutoHeight,
9922    updateSlidesOffset,
9923    updateSlidesProgress,
9924    updateProgress,
9925    updateSlidesClasses,
9926    updateActiveIndex,
9927    updateClickedSlide
9928  };
9929
9930  function getSwiperTranslate(axis = this.isHorizontal() ? 'x' : 'y') {
9931    const swiper = this;
9932    const {
9933      params,
9934      rtlTranslate: rtl,
9935      translate,
9936      wrapperEl
9937    } = swiper;
9938    if (params.virtualTranslate) {
9939      return rtl ? -translate : translate;
9940    }
9941    if (params.cssMode) {
9942      return translate;
9943    }
9944    let currentTranslate = getTranslate(wrapperEl, axis);
9945    currentTranslate += swiper.cssOverflowAdjustment();
9946    if (rtl) currentTranslate = -currentTranslate;
9947    return currentTranslate || 0;
9948  }
9949
9950  function setTranslate(translate, byController) {
9951    const swiper = this;
9952    const {
9953      rtlTranslate: rtl,
9954      params,
9955      wrapperEl,
9956      progress
9957    } = swiper;
9958    let x = 0;
9959    let y = 0;
9960    const z = 0;
9961    if (swiper.isHorizontal()) {
9962      x = rtl ? -translate : translate;
9963    } else {
9964      y = translate;
9965    }
9966    if (params.roundLengths) {
9967      x = Math.floor(x);
9968      y = Math.floor(y);
9969    }
9970    swiper.previousTranslate = swiper.translate;
9971    swiper.translate = swiper.isHorizontal() ? x : y;
9972    if (params.cssMode) {
9973      wrapperEl[swiper.isHorizontal() ? 'scrollLeft' : 'scrollTop'] = swiper.isHorizontal() ? -x : -y;
9974    } else if (!params.virtualTranslate) {
9975      if (swiper.isHorizontal()) {
9976        x -= swiper.cssOverflowAdjustment();
9977      } else {
9978        y -= swiper.cssOverflowAdjustment();
9979      }
9980      wrapperEl.style.transform = `translate3d(${x}px, ${y}px, ${z}px)`;
9981    }
9982
9983    // Check if we need to update progress
9984    let newProgress;
9985    const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
9986    if (translatesDiff === 0) {
9987      newProgress = 0;
9988    } else {
9989      newProgress = (translate - swiper.minTranslate()) / translatesDiff;
9990    }
9991    if (newProgress !== progress) {
9992      swiper.updateProgress(translate);
9993    }
9994    swiper.emit('setTranslate', swiper.translate, byController);
9995  }
9996
9997  function minTranslate() {
9998    return -this.snapGrid[0];
9999  }
10000
10001  function maxTranslate() {
10002    return -this.snapGrid[this.snapGrid.length - 1];
10003  }
10004
10005  function translateTo(translate = 0, speed = this.params.speed, runCallbacks = true, translateBounds = true, internal) {
10006    const swiper = this;
10007    const {
10008      params,
10009      wrapperEl
10010    } = swiper;
10011    if (swiper.animating && params.preventInteractionOnTransition) {
10012      return false;
10013    }
10014    const minTranslate = swiper.minTranslate();
10015    const maxTranslate = swiper.maxTranslate();
10016    let newTranslate;
10017    if (translateBounds && translate > minTranslate) newTranslate = minTranslate;else if (translateBounds && translate < maxTranslate) newTranslate = maxTranslate;else newTranslate = translate;
10018
10019    // Update progress
10020    swiper.updateProgress(newTranslate);
10021    if (params.cssMode) {
10022      const isH = swiper.isHorizontal();
10023      if (speed === 0) {
10024        wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -newTranslate;
10025      } else {
10026        if (!swiper.support.smoothScroll) {
10027          animateCSSModeScroll({
10028            swiper,
10029            targetPosition: -newTranslate,
10030            side: isH ? 'left' : 'top'
10031          });
10032          return true;
10033        }
10034        wrapperEl.scrollTo({
10035          [isH ? 'left' : 'top']: -newTranslate,
10036          behavior: 'smooth'
10037        });
10038      }
10039      return true;
10040    }
10041    if (speed === 0) {
10042      swiper.setTransition(0);
10043      swiper.setTranslate(newTranslate);
10044      if (runCallbacks) {
10045        swiper.emit('beforeTransitionStart', speed, internal);
10046        swiper.emit('transitionEnd');
10047      }
10048    } else {
10049      swiper.setTransition(speed);
10050      swiper.setTranslate(newTranslate);
10051      if (runCallbacks) {
10052        swiper.emit('beforeTransitionStart', speed, internal);
10053        swiper.emit('transitionStart');
10054      }
10055      if (!swiper.animating) {
10056        swiper.animating = true;
10057        if (!swiper.onTranslateToWrapperTransitionEnd) {
10058          swiper.onTranslateToWrapperTransitionEnd = function transitionEnd(e) {
10059            if (!swiper || swiper.destroyed) return;
10060            if (e.target !== this) return;
10061            swiper.wrapperEl.removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);
10062            swiper.onTranslateToWrapperTransitionEnd = null;
10063            delete swiper.onTranslateToWrapperTransitionEnd;
10064            swiper.animating = false;
10065            if (runCallbacks) {
10066              swiper.emit('transitionEnd');
10067            }
10068          };
10069        }
10070        swiper.wrapperEl.addEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);
10071      }
10072    }
10073    return true;
10074  }
10075
10076  var translate = {
10077    getTranslate: getSwiperTranslate,
10078    setTranslate,
10079    minTranslate,
10080    maxTranslate,
10081    translateTo
10082  };
10083
10084  function setTransition(duration, byController) {
10085    const swiper = this;
10086    if (!swiper.params.cssMode) {
10087      swiper.wrapperEl.style.transitionDuration = `${duration}ms`;
10088      swiper.wrapperEl.style.transitionDelay = duration === 0 ? `0ms` : '';
10089    }
10090    swiper.emit('setTransition', duration, byController);
10091  }
10092
10093  function transitionEmit({
10094    swiper,
10095    runCallbacks,
10096    direction,
10097    step
10098  }) {
10099    const {
10100      activeIndex,
10101      previousIndex
10102    } = swiper;
10103    let dir = direction;
10104    if (!dir) {
10105      if (activeIndex > previousIndex) dir = 'next';else if (activeIndex < previousIndex) dir = 'prev';else dir = 'reset';
10106    }
10107    swiper.emit(`transition${step}`);
10108    if (runCallbacks && dir === 'reset') {
10109      swiper.emit(`slideResetTransition${step}`);
10110    } else if (runCallbacks && activeIndex !== previousIndex) {
10111      swiper.emit(`slideChangeTransition${step}`);
10112      if (dir === 'next') {
10113        swiper.emit(`slideNextTransition${step}`);
10114      } else {
10115        swiper.emit(`slidePrevTransition${step}`);
10116      }
10117    }
10118  }
10119
10120  function transitionStart(runCallbacks = true, direction) {
10121    const swiper = this;
10122    const {
10123      params
10124    } = swiper;
10125    if (params.cssMode) return;
10126    if (params.autoHeight) {
10127      swiper.updateAutoHeight();
10128    }
10129    transitionEmit({
10130      swiper,
10131      runCallbacks,
10132      direction,
10133      step: 'Start'
10134    });
10135  }
10136
10137  function transitionEnd(runCallbacks = true, direction) {
10138    const swiper = this;
10139    const {
10140      params
10141    } = swiper;
10142    swiper.animating = false;
10143    if (params.cssMode) return;
10144    swiper.setTransition(0);
10145    transitionEmit({
10146      swiper,
10147      runCallbacks,
10148      direction,
10149      step: 'End'
10150    });
10151  }
10152
10153  var transition = {
10154    setTransition,
10155    transitionStart,
10156    transitionEnd
10157  };
10158
10159  function slideTo(index = 0, speed, runCallbacks = true, internal, initial) {
10160    if (typeof index === 'string') {
10161      index = parseInt(index, 10);
10162    }
10163    const swiper = this;
10164    let slideIndex = index;
10165    if (slideIndex < 0) slideIndex = 0;
10166    const {
10167      params,
10168      snapGrid,
10169      slidesGrid,
10170      previousIndex,
10171      activeIndex,
10172      rtlTranslate: rtl,
10173      wrapperEl,
10174      enabled
10175    } = swiper;
10176    if (!enabled && !internal && !initial || swiper.destroyed || swiper.animating && params.preventInteractionOnTransition) {
10177      return false;
10178    }
10179    if (typeof speed === 'undefined') {
10180      speed = swiper.params.speed;
10181    }
10182    const skip = Math.min(swiper.params.slidesPerGroupSkip, slideIndex);
10183    let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup);
10184    if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
10185    const translate = -snapGrid[snapIndex];
10186    // Normalize slideIndex
10187    if (params.normalizeSlideIndex) {
10188      for (let i = 0; i < slidesGrid.length; i += 1) {
10189        const normalizedTranslate = -Math.floor(translate * 100);
10190        const normalizedGrid = Math.floor(slidesGrid[i] * 100);
10191        const normalizedGridNext = Math.floor(slidesGrid[i + 1] * 100);
10192        if (typeof slidesGrid[i + 1] !== 'undefined') {
10193          if (normalizedTranslate >= normalizedGrid && normalizedTranslate < normalizedGridNext - (normalizedGridNext - normalizedGrid) / 2) {
10194            slideIndex = i;
10195          } else if (normalizedTranslate >= normalizedGrid && normalizedTranslate < normalizedGridNext) {
10196            slideIndex = i + 1;
10197          }
10198        } else if (normalizedTranslate >= normalizedGrid) {
10199          slideIndex = i;
10200        }
10201      }
10202    }
10203    // Directions locks
10204    if (swiper.initialized && slideIndex !== activeIndex) {
10205      if (!swiper.allowSlideNext && (rtl ? translate > swiper.translate && translate > swiper.minTranslate() : translate < swiper.translate && translate < swiper.minTranslate())) {
10206        return false;
10207      }
10208      if (!swiper.allowSlidePrev && translate > swiper.translate && translate > swiper.maxTranslate()) {
10209        if ((activeIndex || 0) !== slideIndex) {
10210          return false;
10211        }
10212      }
10213    }
10214    if (slideIndex !== (previousIndex || 0) && runCallbacks) {
10215      swiper.emit('beforeSlideChangeStart');
10216    }
10217
10218    // Update progress
10219    swiper.updateProgress(translate);
10220    let direction;
10221    if (slideIndex > activeIndex) direction = 'next';else if (slideIndex < activeIndex) direction = 'prev';else direction = 'reset';
10222
10223    // initial virtual
10224    const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
10225    const isInitialVirtual = isVirtual && initial;
10226    // Update Index
10227    if (!isInitialVirtual && (rtl && -translate === swiper.translate || !rtl && translate === swiper.translate)) {
10228      swiper.updateActiveIndex(slideIndex);
10229      // Update Height
10230      if (params.autoHeight) {
10231        swiper.updateAutoHeight();
10232      }
10233      swiper.updateSlidesClasses();
10234      if (params.effect !== 'slide') {
10235        swiper.setTranslate(translate);
10236      }
10237      if (direction !== 'reset') {
10238        swiper.transitionStart(runCallbacks, direction);
10239        swiper.transitionEnd(runCallbacks, direction);
10240      }
10241      return false;
10242    }
10243    if (params.cssMode) {
10244      const isH = swiper.isHorizontal();
10245      const t = rtl ? translate : -translate;
10246      if (speed === 0) {
10247        if (isVirtual) {
10248          swiper.wrapperEl.style.scrollSnapType = 'none';
10249          swiper._immediateVirtual = true;
10250        }
10251        if (isVirtual && !swiper._cssModeVirtualInitialSet && swiper.params.initialSlide > 0) {
10252          swiper._cssModeVirtualInitialSet = true;
10253          requestAnimationFrame(() => {
10254            wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;
10255          });
10256        } else {
10257          wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;
10258        }
10259        if (isVirtual) {
10260          requestAnimationFrame(() => {
10261            swiper.wrapperEl.style.scrollSnapType = '';
10262            swiper._immediateVirtual = false;
10263          });
10264        }
10265      } else {
10266        if (!swiper.support.smoothScroll) {
10267          animateCSSModeScroll({
10268            swiper,
10269            targetPosition: t,
10270            side: isH ? 'left' : 'top'
10271          });
10272          return true;
10273        }
10274        wrapperEl.scrollTo({
10275          [isH ? 'left' : 'top']: t,
10276          behavior: 'smooth'
10277        });
10278      }
10279      return true;
10280    }
10281    const browser = getBrowser();
10282    const isSafari = browser.isSafari;
10283    if (isVirtual && !initial && isSafari && swiper.isElement) {
10284      swiper.virtual.update(false, false, slideIndex);
10285    }
10286    swiper.setTransition(speed);
10287    swiper.setTranslate(translate);
10288    swiper.updateActiveIndex(slideIndex);
10289    swiper.updateSlidesClasses();
10290    swiper.emit('beforeTransitionStart', speed, internal);
10291    swiper.transitionStart(runCallbacks, direction);
10292    if (speed === 0) {
10293      swiper.transitionEnd(runCallbacks, direction);
10294    } else if (!swiper.animating) {
10295      swiper.animating = true;
10296      if (!swiper.onSlideToWrapperTransitionEnd) {
10297        swiper.onSlideToWrapperTransitionEnd = function transitionEnd(e) {
10298          if (!swiper || swiper.destroyed) return;
10299          if (e.target !== this) return;
10300          swiper.wrapperEl.removeEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);
10301          swiper.onSlideToWrapperTransitionEnd = null;
10302          delete swiper.onSlideToWrapperTransitionEnd;
10303          swiper.transitionEnd(runCallbacks, direction);
10304        };
10305      }
10306      swiper.wrapperEl.addEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);
10307    }
10308    return true;
10309  }
10310
10311  function slideToLoop(index = 0, speed, runCallbacks = true, internal) {
10312    if (typeof index === 'string') {
10313      const indexAsNumber = parseInt(index, 10);
10314      index = indexAsNumber;
10315    }
10316    const swiper = this;
10317    if (swiper.destroyed) return;
10318    if (typeof speed === 'undefined') {
10319      speed = swiper.params.speed;
10320    }
10321    const gridEnabled = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1;
10322    let newIndex = index;
10323    if (swiper.params.loop) {
10324      if (swiper.virtual && swiper.params.virtual.enabled) {
10325        // eslint-disable-next-line
10326        newIndex = newIndex + swiper.virtual.slidesBefore;
10327      } else {
10328        let targetSlideIndex;
10329        if (gridEnabled) {
10330          const slideIndex = newIndex * swiper.params.grid.rows;
10331          targetSlideIndex = swiper.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === slideIndex).column;
10332        } else {
10333          targetSlideIndex = swiper.getSlideIndexByData(newIndex);
10334        }
10335        const cols = gridEnabled ? Math.ceil(swiper.slides.length / swiper.params.grid.rows) : swiper.slides.length;
10336        const {
10337          centeredSlides,
10338          slidesOffsetBefore,
10339          slidesOffsetAfter
10340        } = swiper.params;
10341        const bothDirections = centeredSlides || !!slidesOffsetBefore || !!slidesOffsetAfter;
10342        let slidesPerView = swiper.params.slidesPerView;
10343        if (slidesPerView === 'auto') {
10344          slidesPerView = swiper.slidesPerViewDynamic();
10345        } else {
10346          slidesPerView = Math.ceil(parseFloat(swiper.params.slidesPerView, 10));
10347          if (bothDirections && slidesPerView % 2 === 0) {
10348            slidesPerView = slidesPerView + 1;
10349          }
10350        }
10351        let needLoopFix = cols - targetSlideIndex < slidesPerView;
10352        if (bothDirections) {
10353          needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2);
10354        }
10355        if (internal && bothDirections && swiper.params.slidesPerView !== 'auto' && !gridEnabled) {
10356          needLoopFix = false;
10357        }
10358        if (needLoopFix) {
10359          const direction = bothDirections ? targetSlideIndex < swiper.activeIndex ? 'prev' : 'next' : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView ? 'next' : 'prev';
10360          swiper.loopFix({
10361            direction,
10362            slideTo: true,
10363            activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1,
10364            slideRealIndex: direction === 'next' ? swiper.realIndex : undefined
10365          });
10366        }
10367        if (gridEnabled) {
10368          const slideIndex = newIndex * swiper.params.grid.rows;
10369          newIndex = swiper.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === slideIndex).column;
10370        } else {
10371          newIndex = swiper.getSlideIndexByData(newIndex);
10372        }
10373      }
10374    }
10375    requestAnimationFrame(() => {
10376      swiper.slideTo(newIndex, speed, runCallbacks, internal);
10377    });
10378    return swiper;
10379  }
10380
10381  /* eslint no-unused-vars: "off" */
10382  function slideNext(speed, runCallbacks = true, internal) {
10383    const swiper = this;
10384    const {
10385      enabled,
10386      params,
10387      animating
10388    } = swiper;
10389    if (!enabled || swiper.destroyed) return swiper;
10390    if (typeof speed === 'undefined') {
10391      speed = swiper.params.speed;
10392    }
10393    let perGroup = params.slidesPerGroup;
10394    if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {
10395      perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1);
10396    }
10397    const increment = swiper.activeIndex < params.slidesPerGroupSkip ? 1 : perGroup;
10398    const isVirtual = swiper.virtual && params.virtual.enabled;
10399    if (params.loop) {
10400      if (animating && !isVirtual && params.loopPreventsSliding) return false;
10401      swiper.loopFix({
10402        direction: 'next'
10403      });
10404      // eslint-disable-next-line
10405      swiper._clientLeft = swiper.wrapperEl.clientLeft;
10406      if (swiper.activeIndex === swiper.slides.length - 1 && params.cssMode) {
10407        requestAnimationFrame(() => {
10408          swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal);
10409        });
10410        return true;
10411      }
10412    }
10413    if (params.rewind && swiper.isEnd) {
10414      return swiper.slideTo(0, speed, runCallbacks, internal);
10415    }
10416    return swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal);
10417  }
10418
10419  /* eslint no-unused-vars: "off" */
10420  function slidePrev(speed, runCallbacks = true, internal) {
10421    const swiper = this;
10422    const {
10423      params,
10424      snapGrid,
10425      slidesGrid,
10426      rtlTranslate,
10427      enabled,
10428      animating
10429    } = swiper;
10430    if (!enabled || swiper.destroyed) return swiper;
10431    if (typeof speed === 'undefined') {
10432      speed = swiper.params.speed;
10433    }
10434    const isVirtual = swiper.virtual && params.virtual.enabled;
10435    if (params.loop) {
10436      if (animating && !isVirtual && params.loopPreventsSliding) return false;
10437      swiper.loopFix({
10438        direction: 'prev'
10439      });
10440      // eslint-disable-next-line
10441      swiper._clientLeft = swiper.wrapperEl.clientLeft;
10442    }
10443    const translate = rtlTranslate ? swiper.translate : -swiper.translate;
10444    function normalize(val) {
10445      if (val < 0) return -Math.floor(Math.abs(val));
10446      return Math.floor(val);
10447    }
10448    const normalizedTranslate = normalize(translate);
10449    const normalizedSnapGrid = snapGrid.map(val => normalize(val));
10450    const isFreeMode = params.freeMode && params.freeMode.enabled;
10451    let prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1];
10452    if (typeof prevSnap === 'undefined' && (params.cssMode || isFreeMode)) {
10453      let prevSnapIndex;
10454      snapGrid.forEach((snap, snapIndex) => {
10455        if (normalizedTranslate >= snap) {
10456          // prevSnap = snap;
10457          prevSnapIndex = snapIndex;
10458        }
10459      });
10460      if (typeof prevSnapIndex !== 'undefined') {
10461        prevSnap = isFreeMode ? snapGrid[prevSnapIndex] : snapGrid[prevSnapIndex > 0 ? prevSnapIndex - 1 : prevSnapIndex];
10462      }
10463    }
10464    let prevIndex = 0;
10465    if (typeof prevSnap !== 'undefined') {
10466      prevIndex = slidesGrid.indexOf(prevSnap);
10467      if (prevIndex < 0) prevIndex = swiper.activeIndex - 1;
10468      if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {
10469        prevIndex = prevIndex - swiper.slidesPerViewDynamic('previous', true) + 1;
10470        prevIndex = Math.max(prevIndex, 0);
10471      }
10472    }
10473    if (params.rewind && swiper.isBeginning) {
10474      const lastIndex = swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1;
10475      return swiper.slideTo(lastIndex, speed, runCallbacks, internal);
10476    } else if (params.loop && swiper.activeIndex === 0 && params.cssMode) {
10477      requestAnimationFrame(() => {
10478        swiper.slideTo(prevIndex, speed, runCallbacks, internal);
10479      });
10480      return true;
10481    }
10482    return swiper.slideTo(prevIndex, speed, runCallbacks, internal);
10483  }
10484
10485  /* eslint no-unused-vars: "off" */
10486  function slideReset(speed, runCallbacks = true, internal) {
10487    const swiper = this;
10488    if (swiper.destroyed) return;
10489    if (typeof speed === 'undefined') {
10490      speed = swiper.params.speed;
10491    }
10492    return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);
10493  }
10494
10495  /* eslint no-unused-vars: "off" */
10496  function slideToClosest(speed, runCallbacks = true, internal, threshold = 0.5) {
10497    const swiper = this;
10498    if (swiper.destroyed) return;
10499    if (typeof speed === 'undefined') {
10500      speed = swiper.params.speed;
10501    }
10502    let index = swiper.activeIndex;
10503    const skip = Math.min(swiper.params.slidesPerGroupSkip, index);
10504    const snapIndex = skip + Math.floor((index - skip) / swiper.params.slidesPerGroup);
10505    const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
10506    if (translate >= swiper.snapGrid[snapIndex]) {
10507      // The current translate is on or after the current snap index, so the choice
10508      // is between the current index and the one after it.
10509      const currentSnap = swiper.snapGrid[snapIndex];
10510      const nextSnap = swiper.snapGrid[snapIndex + 1];
10511      if (translate - currentSnap > (nextSnap - currentSnap) * threshold) {
10512        index += swiper.params.slidesPerGroup;
10513      }
10514    } else {
10515      // The current translate is before the current snap index, so the choice
10516      // is between the current index and the one before it.
10517      const prevSnap = swiper.snapGrid[snapIndex - 1];
10518      const currentSnap = swiper.snapGrid[snapIndex];
10519      if (translate - prevSnap <= (currentSnap - prevSnap) * threshold) {
10520        index -= swiper.params.slidesPerGroup;
10521      }
10522    }
10523    index = Math.max(index, 0);
10524    index = Math.min(index, swiper.slidesGrid.length - 1);
10525    return swiper.slideTo(index, speed, runCallbacks, internal);
10526  }
10527
10528  function slideToClickedSlide() {
10529    const swiper = this;
10530    if (swiper.destroyed) return;
10531    const {
10532      params,
10533      slidesEl
10534    } = swiper;
10535    const slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : params.slidesPerView;
10536    let slideToIndex = swiper.getSlideIndexWhenGrid(swiper.clickedIndex);
10537    let realIndex;
10538    const slideSelector = swiper.isElement ? `swiper-slide` : `.${params.slideClass}`;
10539    const isGrid = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1;
10540    if (params.loop) {
10541      if (swiper.animating) return;
10542      realIndex = parseInt(swiper.clickedSlide.getAttribute('data-swiper-slide-index'), 10);
10543      if (params.centeredSlides) {
10544        swiper.slideToLoop(realIndex);
10545      } else if (slideToIndex > (isGrid ? (swiper.slides.length - slidesPerView) / 2 - (swiper.params.grid.rows - 1) : swiper.slides.length - slidesPerView)) {
10546        swiper.loopFix();
10547        slideToIndex = swiper.getSlideIndex(elementChildren(slidesEl, `${slideSelector}[data-swiper-slide-index="${realIndex}"]`)[0]);
10548        nextTick(() => {
10549          swiper.slideTo(slideToIndex);
10550        });
10551      } else {
10552        swiper.slideTo(slideToIndex);
10553      }
10554    } else {
10555      swiper.slideTo(slideToIndex);
10556    }
10557  }
10558
10559  var slide = {
10560    slideTo,
10561    slideToLoop,
10562    slideNext,
10563    slidePrev,
10564    slideReset,
10565    slideToClosest,
10566    slideToClickedSlide
10567  };
10568
10569  function loopCreate(slideRealIndex, initial) {
10570    const swiper = this;
10571    const {
10572      params,
10573      slidesEl
10574    } = swiper;
10575    if (!params.loop || swiper.virtual && swiper.params.virtual.enabled) return;
10576    const initSlides = () => {
10577      const slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`);
10578      slides.forEach((el, index) => {
10579        el.setAttribute('data-swiper-slide-index', index);
10580      });
10581    };
10582    const clearBlankSlides = () => {
10583      const slides = elementChildren(slidesEl, `.${params.slideBlankClass}`);
10584      slides.forEach(el => {
10585        el.remove();
10586      });
10587      if (slides.length > 0) {
10588        swiper.recalcSlides();
10589        swiper.updateSlides();
10590      }
10591    };
10592    const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
10593    if (params.loopAddBlankSlides && (params.slidesPerGroup > 1 || gridEnabled)) {
10594      clearBlankSlides();
10595    }
10596    const slidesPerGroup = params.slidesPerGroup * (gridEnabled ? params.grid.rows : 1);
10597    const shouldFillGroup = swiper.slides.length % slidesPerGroup !== 0;
10598    const shouldFillGrid = gridEnabled && swiper.slides.length % params.grid.rows !== 0;
10599    const addBlankSlides = amountOfSlides => {
10600      for (let i = 0; i < amountOfSlides; i += 1) {
10601        const slideEl = swiper.isElement ? createElement('swiper-slide', [params.slideBlankClass]) : createElement('div', [params.slideClass, params.slideBlankClass]);
10602        swiper.slidesEl.append(slideEl);
10603      }
10604    };
10605    if (shouldFillGroup) {
10606      if (params.loopAddBlankSlides) {
10607        const slidesToAdd = slidesPerGroup - swiper.slides.length % slidesPerGroup;
10608        addBlankSlides(slidesToAdd);
10609        swiper.recalcSlides();
10610        swiper.updateSlides();
10611      } else {
10612        showWarning('Swiper Loop Warning: The number of slides is not even to slidesPerGroup, loop mode may not function properly. You need to add more slides (or make duplicates, or empty slides)');
10613      }
10614      initSlides();
10615    } else if (shouldFillGrid) {
10616      if (params.loopAddBlankSlides) {
10617        const slidesToAdd = params.grid.rows - swiper.slides.length % params.grid.rows;
10618        addBlankSlides(slidesToAdd);
10619        swiper.recalcSlides();
10620        swiper.updateSlides();
10621      } else {
10622        showWarning('Swiper Loop Warning: The number of slides is not even to grid.rows, loop mode may not function properly. You need to add more slides (or make duplicates, or empty slides)');
10623      }
10624      initSlides();
10625    } else {
10626      initSlides();
10627    }
10628    const bothDirections = params.centeredSlides || !!params.slidesOffsetBefore || !!params.slidesOffsetAfter;
10629    swiper.loopFix({
10630      slideRealIndex,
10631      direction: bothDirections ? undefined : 'next',
10632      initial
10633    });
10634  }
10635
10636  function loopFix({
10637    slideRealIndex,
10638    slideTo = true,
10639    direction,
10640    setTranslate,
10641    activeSlideIndex,
10642    initial,
10643    byController,
10644    byMousewheel
10645  } = {}) {
10646    const swiper = this;
10647    if (!swiper.params.loop) return;
10648    swiper.emit('beforeLoopFix');
10649    const {
10650      slides,
10651      allowSlidePrev,
10652      allowSlideNext,
10653      slidesEl,
10654      params
10655    } = swiper;
10656    const {
10657      centeredSlides,
10658      slidesOffsetBefore,
10659      slidesOffsetAfter,
10660      initialSlide
10661    } = params;
10662    const bothDirections = centeredSlides || !!slidesOffsetBefore || !!slidesOffsetAfter;
10663    swiper.allowSlidePrev = true;
10664    swiper.allowSlideNext = true;
10665    if (swiper.virtual && params.virtual.enabled) {
10666      if (slideTo) {
10667        if (!bothDirections && swiper.snapIndex === 0) {
10668          swiper.slideTo(swiper.virtual.slides.length, 0, false, true);
10669        } else if (bothDirections && swiper.snapIndex < params.slidesPerView) {
10670          swiper.slideTo(swiper.virtual.slides.length + swiper.snapIndex, 0, false, true);
10671        } else if (swiper.snapIndex === swiper.snapGrid.length - 1) {
10672          swiper.slideTo(swiper.virtual.slidesBefore, 0, false, true);
10673        }
10674      }
10675      swiper.allowSlidePrev = allowSlidePrev;
10676      swiper.allowSlideNext = allowSlideNext;
10677      swiper.emit('loopFix');
10678      return;
10679    }
10680    let slidesPerView = params.slidesPerView;
10681    if (slidesPerView === 'auto') {
10682      slidesPerView = swiper.slidesPerViewDynamic();
10683    } else {
10684      slidesPerView = Math.ceil(parseFloat(params.slidesPerView, 10));
10685      if (bothDirections && slidesPerView % 2 === 0) {
10686        slidesPerView = slidesPerView + 1;
10687      }
10688    }
10689    const slidesPerGroup = params.slidesPerGroupAuto ? slidesPerView : params.slidesPerGroup;
10690    let loopedSlides = bothDirections ? Math.max(slidesPerGroup, Math.ceil(slidesPerView / 2)) : slidesPerGroup;
10691    if (loopedSlides % slidesPerGroup !== 0) {
10692      loopedSlides += slidesPerGroup - loopedSlides % slidesPerGroup;
10693    }
10694    loopedSlides += params.loopAdditionalSlides;
10695    swiper.loopedSlides = loopedSlides;
10696    const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
10697    if (slides.length < slidesPerView + loopedSlides || swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
10698      showWarning('Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled or not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters');
10699    } else if (gridEnabled && params.grid.fill === 'row') {
10700      showWarning('Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`');
10701    }
10702    const prependSlidesIndexes = [];
10703    const appendSlidesIndexes = [];
10704    const cols = gridEnabled ? Math.ceil(slides.length / params.grid.rows) : slides.length;
10705    const isInitialOverflow = initial && cols - initialSlide < slidesPerView && !bothDirections;
10706    let activeIndex = isInitialOverflow ? initialSlide : swiper.activeIndex;
10707    if (typeof activeSlideIndex === 'undefined') {
10708      activeSlideIndex = swiper.getSlideIndex(slides.find(el => el.classList.contains(params.slideActiveClass)));
10709    } else {
10710      activeIndex = activeSlideIndex;
10711    }
10712    const isNext = direction === 'next' || !direction;
10713    const isPrev = direction === 'prev' || !direction;
10714    let slidesPrepended = 0;
10715    let slidesAppended = 0;
10716    const activeColIndex = gridEnabled ? slides[activeSlideIndex].column : activeSlideIndex;
10717    const activeColIndexWithShift = activeColIndex + (bothDirections && typeof setTranslate === 'undefined' ? -slidesPerView / 2 + 0.5 : 0);
10718    // prepend last slides before start
10719    if (activeColIndexWithShift < loopedSlides) {
10720      slidesPrepended = Math.max(loopedSlides - activeColIndexWithShift, slidesPerGroup);
10721      for (let i = 0; i < loopedSlides - activeColIndexWithShift; i += 1) {
10722        const index = i - Math.floor(i / cols) * cols;
10723        if (gridEnabled) {
10724          const colIndexToPrepend = cols - index - 1;
10725          for (let i = slides.length - 1; i >= 0; i -= 1) {
10726            if (slides[i].column === colIndexToPrepend) prependSlidesIndexes.push(i);
10727          }
10728          // slides.forEach((slide, slideIndex) => {
10729          //   if (slide.column === colIndexToPrepend) prependSlidesIndexes.push(slideIndex);
10730          // });
10731        } else {
10732          prependSlidesIndexes.push(cols - index - 1);
10733        }
10734      }
10735    } else if (activeColIndexWithShift + slidesPerView > cols - loopedSlides) {
10736      slidesAppended = Math.max(activeColIndexWithShift - (cols - loopedSlides * 2), slidesPerGroup);
10737      if (isInitialOverflow) {
10738        slidesAppended = Math.max(slidesAppended, slidesPerView - cols + initialSlide + 1);
10739      }
10740      for (let i = 0; i < slidesAppended; i += 1) {
10741        const index = i - Math.floor(i / cols) * cols;
10742        if (gridEnabled) {
10743          slides.forEach((slide, slideIndex) => {
10744            if (slide.column === index) appendSlidesIndexes.push(slideIndex);
10745          });
10746        } else {
10747          appendSlidesIndexes.push(index);
10748        }
10749      }
10750    }
10751    swiper.__preventObserver__ = true;
10752    requestAnimationFrame(() => {
10753      swiper.__preventObserver__ = false;
10754    });
10755    if (swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) {
10756      if (appendSlidesIndexes.includes(activeSlideIndex)) {
10757        appendSlidesIndexes.splice(appendSlidesIndexes.indexOf(activeSlideIndex), 1);
10758      }
10759      if (prependSlidesIndexes.includes(activeSlideIndex)) {
10760        prependSlidesIndexes.splice(prependSlidesIndexes.indexOf(activeSlideIndex), 1);
10761      }
10762    }
10763    if (isPrev) {
10764      prependSlidesIndexes.forEach(index => {
10765        slides[index].swiperLoopMoveDOM = true;
10766        slidesEl.prepend(slides[index]);
10767        slides[index].swiperLoopMoveDOM = false;
10768      });
10769    }
10770    if (isNext) {
10771      appendSlidesIndexes.forEach(index => {
10772        slides[index].swiperLoopMoveDOM = true;
10773        slidesEl.append(slides[index]);
10774        slides[index].swiperLoopMoveDOM = false;
10775      });
10776    }
10777    swiper.recalcSlides();
10778    if (params.slidesPerView === 'auto') {
10779      swiper.updateSlides();
10780    } else if (gridEnabled && (prependSlidesIndexes.length > 0 && isPrev || appendSlidesIndexes.length > 0 && isNext)) {
10781      swiper.slides.forEach((slide, slideIndex) => {
10782        swiper.grid.updateSlide(slideIndex, slide, swiper.slides);
10783      });
10784    }
10785    if (params.watchSlidesProgress) {
10786      swiper.updateSlidesOffset();
10787    }
10788    if (slideTo) {
10789      if (prependSlidesIndexes.length > 0 && isPrev) {
10790        if (typeof slideRealIndex === 'undefined') {
10791          const currentSlideTranslate = swiper.slidesGrid[activeIndex];
10792          const newSlideTranslate = swiper.slidesGrid[activeIndex + slidesPrepended];
10793          const diff = newSlideTranslate - currentSlideTranslate;
10794          if (byMousewheel) {
10795            swiper.setTranslate(swiper.translate - diff);
10796          } else {
10797            swiper.slideTo(activeIndex + Math.ceil(slidesPrepended), 0, false, true);
10798            if (setTranslate) {
10799              swiper.touchEventsData.startTranslate = swiper.touchEventsData.startTranslate - diff;
10800              swiper.touchEventsData.currentTranslate = swiper.touchEventsData.currentTranslate - diff;
10801            }
10802          }
10803        } else {
10804          if (setTranslate) {
10805            const shift = gridEnabled ? prependSlidesIndexes.length / params.grid.rows : prependSlidesIndexes.length;
10806            swiper.slideTo(swiper.activeIndex + shift, 0, false, true);
10807            swiper.touchEventsData.currentTranslate = swiper.translate;
10808          }
10809        }
10810      } else if (appendSlidesIndexes.length > 0 && isNext) {
10811        if (typeof slideRealIndex === 'undefined') {
10812          const currentSlideTranslate = swiper.slidesGrid[activeIndex];
10813          const newSlideTranslate = swiper.slidesGrid[activeIndex - slidesAppended];
10814          const diff = newSlideTranslate - currentSlideTranslate;
10815          if (byMousewheel) {
10816            swiper.setTranslate(swiper.translate - diff);
10817          } else {
10818            swiper.slideTo(activeIndex - slidesAppended, 0, false, true);
10819            if (setTranslate) {
10820              swiper.touchEventsData.startTranslate = swiper.touchEventsData.startTranslate - diff;
10821              swiper.touchEventsData.currentTranslate = swiper.touchEventsData.currentTranslate - diff;
10822            }
10823          }
10824        } else {
10825          const shift = gridEnabled ? appendSlidesIndexes.length / params.grid.rows : appendSlidesIndexes.length;
10826          swiper.slideTo(swiper.activeIndex - shift, 0, false, true);
10827        }
10828      }
10829    }
10830    swiper.allowSlidePrev = allowSlidePrev;
10831    swiper.allowSlideNext = allowSlideNext;
10832    if (swiper.controller && swiper.controller.control && !byController) {
10833      const loopParams = {
10834        slideRealIndex,
10835        direction,
10836        setTranslate,
10837        activeSlideIndex,
10838        byController: true
10839      };
10840      if (Array.isArray(swiper.controller.control)) {
10841        swiper.controller.control.forEach(c => {
10842          if (!c.destroyed && c.params.loop) c.loopFix({
10843            ...loopParams,
10844            slideTo: c.params.slidesPerView === params.slidesPerView ? slideTo : false
10845          });
10846        });
10847      } else if (swiper.controller.control instanceof swiper.constructor && swiper.controller.control.params.loop) {
10848        swiper.controller.control.loopFix({
10849          ...loopParams,
10850          slideTo: swiper.controller.control.params.slidesPerView === params.slidesPerView ? slideTo : false
10851        });
10852      }
10853    }
10854    swiper.emit('loopFix');
10855  }
10856
10857  function loopDestroy() {
10858    const swiper = this;
10859    const {
10860      params,
10861      slidesEl
10862    } = swiper;
10863    if (!params.loop || !slidesEl || swiper.virtual && swiper.params.virtual.enabled) return;
10864    swiper.recalcSlides();
10865    const newSlidesOrder = [];
10866    swiper.slides.forEach(slideEl => {
10867      const index = typeof slideEl.swiperSlideIndex === 'undefined' ? slideEl.getAttribute('data-swiper-slide-index') * 1 : slideEl.swiperSlideIndex;
10868      newSlidesOrder[index] = slideEl;
10869    });
10870    swiper.slides.forEach(slideEl => {
10871      slideEl.removeAttribute('data-swiper-slide-index');
10872    });
10873    newSlidesOrder.forEach(slideEl => {
10874      slidesEl.append(slideEl);
10875    });
10876    swiper.recalcSlides();
10877    swiper.slideTo(swiper.realIndex, 0);
10878  }
10879
10880  var loop = {
10881    loopCreate,
10882    loopFix,
10883    loopDestroy
10884  };
10885
10886  function setGrabCursor(moving) {
10887    const swiper = this;
10888    if (!swiper.params.simulateTouch || swiper.params.watchOverflow && swiper.isLocked || swiper.params.cssMode) return;
10889    const el = swiper.params.touchEventsTarget === 'container' ? swiper.el : swiper.wrapperEl;
10890    if (swiper.isElement) {
10891      swiper.__preventObserver__ = true;
10892    }
10893    el.style.cursor = 'move';
10894    el.style.cursor = moving ? 'grabbing' : 'grab';
10895    if (swiper.isElement) {
10896      requestAnimationFrame(() => {
10897        swiper.__preventObserver__ = false;
10898      });
10899    }
10900  }
10901
10902  function unsetGrabCursor() {
10903    const swiper = this;
10904    if (swiper.params.watchOverflow && swiper.isLocked || swiper.params.cssMode) {
10905      return;
10906    }
10907    if (swiper.isElement) {
10908      swiper.__preventObserver__ = true;
10909    }
10910    swiper[swiper.params.touchEventsTarget === 'container' ? 'el' : 'wrapperEl'].style.cursor = '';
10911    if (swiper.isElement) {
10912      requestAnimationFrame(() => {
10913        swiper.__preventObserver__ = false;
10914      });
10915    }
10916  }
10917
10918  var grabCursor = {
10919    setGrabCursor,
10920    unsetGrabCursor
10921  };
10922
10923  // Modified from https://stackoverflow.com/questions/54520554/custom-element-getrootnode-closest-function-crossing-multiple-parent-shadowd
10924  function closestElement(selector, base = this) {
10925    function __closestFrom(el) {
10926      if (!el || el === getDocument() || el === getWindow()) return null;
10927      if (el.assignedSlot) el = el.assignedSlot;
10928      const found = el.closest(selector);
10929      if (!found && !el.getRootNode) {
10930        return null;
10931      }
10932      return found || __closestFrom(el.getRootNode().host);
10933    }
10934    return __closestFrom(base);
10935  }
10936  function preventEdgeSwipe(swiper, event, startX) {
10937    const window = getWindow();
10938    const {
10939      params
10940    } = swiper;
10941    const edgeSwipeDetection = params.edgeSwipeDetection;
10942    const edgeSwipeThreshold = params.edgeSwipeThreshold;
10943    if (edgeSwipeDetection && (startX <= edgeSwipeThreshold || startX >= window.innerWidth - edgeSwipeThreshold)) {
10944      if (edgeSwipeDetection === 'prevent') {
10945        event.preventDefault();
10946        return true;
10947      }
10948      return false;
10949    }
10950    return true;
10951  }
10952  function onTouchStart(event) {
10953    const swiper = this;
10954    const document = getDocument();
10955    let e = event;
10956    if (e.originalEvent) e = e.originalEvent;
10957    const data = swiper.touchEventsData;
10958    if (e.type === 'pointerdown') {
10959      if (data.pointerId !== null && data.pointerId !== e.pointerId) {
10960        return;
10961      }
10962      data.pointerId = e.pointerId;
10963    } else if (e.type === 'touchstart' && e.targetTouches.length === 1) {
10964      data.touchId = e.targetTouches[0].identifier;
10965    }
10966    if (e.type === 'touchstart') {
10967      // don't proceed touch event
10968      preventEdgeSwipe(swiper, e, e.targetTouches[0].pageX);
10969      return;
10970    }
10971    const {
10972      params,
10973      touches,
10974      enabled
10975    } = swiper;
10976    if (!enabled) return;
10977    if (!params.simulateTouch && e.pointerType === 'mouse') return;
10978    if (swiper.animating && params.preventInteractionOnTransition) {
10979      return;
10980    }
10981    if (!swiper.animating && params.cssMode && params.loop) {
10982      swiper.loopFix();
10983    }
10984    let targetEl = e.target;
10985    if (params.touchEventsTarget === 'wrapper') {
10986      if (!elementIsChildOf(targetEl, swiper.wrapperEl)) return;
10987    }
10988    if ('which' in e && e.which === 3) return;
10989    if ('button' in e && e.button > 0) return;
10990    if (data.isTouched && data.isMoved) return;
10991
10992    // change target el for shadow root component
10993    const swipingClassHasValue = !!params.noSwipingClass && params.noSwipingClass !== '';
10994    // eslint-disable-next-line
10995    const eventPath = e.composedPath ? e.composedPath() : e.path;
10996    if (swipingClassHasValue && e.target && e.target.shadowRoot && eventPath) {
10997      targetEl = eventPath[0];
10998    }
10999    const noSwipingSelector = params.noSwipingSelector ? params.noSwipingSelector : `.${params.noSwipingClass}`;
11000    const isTargetShadow = !!(e.target && e.target.shadowRoot);
11001
11002    // use closestElement for shadow root element to get the actual closest for nested shadow root element
11003    if (params.noSwiping && (isTargetShadow ? closestElement(noSwipingSelector, targetEl) : targetEl.closest(noSwipingSelector))) {
11004      swiper.allowClick = true;
11005      return;
11006    }
11007    if (params.swipeHandler) {
11008      if (!targetEl.closest(params.swipeHandler)) return;
11009    }
11010    touches.currentX = e.pageX;
11011    touches.currentY = e.pageY;
11012    const startX = touches.currentX;
11013    const startY = touches.currentY;
11014
11015    // Do NOT start if iOS edge swipe is detected. Otherwise iOS app cannot swipe-to-go-back anymore
11016
11017    if (!preventEdgeSwipe(swiper, e, startX)) {
11018      return;
11019    }
11020    Object.assign(data, {
11021      isTouched: true,
11022      isMoved: false,
11023      allowTouchCallbacks: true,
11024      isScrolling: undefined,
11025      startMoving: undefined
11026    });
11027    touches.startX = startX;
11028    touches.startY = startY;
11029    data.touchStartTime = now();
11030    swiper.allowClick = true;
11031    swiper.updateSize();
11032    swiper.swipeDirection = undefined;
11033    if (params.threshold > 0) data.allowThresholdMove = false;
11034    let preventDefault = true;
11035    if (targetEl.matches(data.focusableElements)) {
11036      preventDefault = false;
11037      if (targetEl.nodeName === 'SELECT') {
11038        data.isTouched = false;
11039      }
11040    }
11041    if (document.activeElement && document.activeElement.matches(data.focusableElements) && document.activeElement !== targetEl && (e.pointerType === 'mouse' || e.pointerType !== 'mouse' && !targetEl.matches(data.focusableElements))) {
11042      document.activeElement.blur();
11043    }
11044    const shouldPreventDefault = preventDefault && swiper.allowTouchMove && params.touchStartPreventDefault;
11045    if ((params.touchStartForcePreventDefault || shouldPreventDefault) && !targetEl.isContentEditable) {
11046      e.preventDefault();
11047    }
11048    if (params.freeMode && params.freeMode.enabled && swiper.freeMode && swiper.animating && !params.cssMode) {
11049      swiper.freeMode.onTouchStart();
11050    }
11051    swiper.emit('touchStart', e);
11052  }
11053
11054  function onTouchMove(event) {
11055    const document = getDocument();
11056    const swiper = this;
11057    const data = swiper.touchEventsData;
11058    const {
11059      params,
11060      touches,
11061      rtlTranslate: rtl,
11062      enabled
11063    } = swiper;
11064    if (!enabled) return;
11065    if (!params.simulateTouch && event.pointerType === 'mouse') return;
11066    let e = event;
11067    if (e.originalEvent) e = e.originalEvent;
11068    if (e.type === 'pointermove') {
11069      if (data.touchId !== null) return; // return from pointer if we use touch
11070      const id = e.pointerId;
11071      if (id !== data.pointerId) return;
11072    }
11073    let targetTouch;
11074    if (e.type === 'touchmove') {
11075      targetTouch = [...e.changedTouches].find(t => t.identifier === data.touchId);
11076      if (!targetTouch || targetTouch.identifier !== data.touchId) return;
11077    } else {
11078      targetTouch = e;
11079    }
11080    if (!data.isTouched) {
11081      if (data.startMoving && data.isScrolling) {
11082        swiper.emit('touchMoveOpposite', e);
11083      }
11084      return;
11085    }
11086    const pageX = targetTouch.pageX;
11087    const pageY = targetTouch.pageY;
11088    if (e.preventedByNestedSwiper) {
11089      touches.startX = pageX;
11090      touches.startY = pageY;
11091      return;
11092    }
11093    if (!swiper.allowTouchMove) {
11094      if (!e.target.matches(data.focusableElements)) {
11095        swiper.allowClick = false;
11096      }
11097      if (data.isTouched) {
11098        Object.assign(touches, {
11099          startX: pageX,
11100          startY: pageY,
11101          currentX: pageX,
11102          currentY: pageY
11103        });
11104        data.touchStartTime = now();
11105      }
11106      return;
11107    }
11108    if (params.touchReleaseOnEdges && !params.loop) {
11109      if (swiper.isVertical()) {
11110        // Vertical
11111        if (pageY < touches.startY && swiper.translate <= swiper.maxTranslate() || pageY > touches.startY && swiper.translate >= swiper.minTranslate()) {
11112          data.isTouched = false;
11113          data.isMoved = false;
11114          return;
11115        }
11116      } else if (rtl && (pageX > touches.startX && -swiper.translate <= swiper.maxTranslate() || pageX < touches.startX && -swiper.translate >= swiper.minTranslate())) {
11117        return;
11118      } else if (!rtl && (pageX < touches.startX && swiper.translate <= swiper.maxTranslate() || pageX > touches.startX && swiper.translate >= swiper.minTranslate())) {
11119        return;
11120      }
11121    }
11122    if (document.activeElement && document.activeElement.matches(data.focusableElements) && document.activeElement !== e.target && e.pointerType !== 'mouse') {
11123      document.activeElement.blur();
11124    }
11125    if (document.activeElement) {
11126      if (e.target === document.activeElement && e.target.matches(data.focusableElements)) {
11127        data.isMoved = true;
11128        swiper.allowClick = false;
11129        return;
11130      }
11131    }
11132    if (data.allowTouchCallbacks) {
11133      swiper.emit('touchMove', e);
11134    }
11135    touches.previousX = touches.currentX;
11136    touches.previousY = touches.currentY;
11137    touches.currentX = pageX;
11138    touches.currentY = pageY;
11139    const diffX = touches.currentX - touches.startX;
11140    const diffY = touches.currentY - touches.startY;
11141    if (swiper.params.threshold && Math.sqrt(diffX ** 2 + diffY ** 2) < swiper.params.threshold) return;
11142    if (typeof data.isScrolling === 'undefined') {
11143      let touchAngle;
11144      if (swiper.isHorizontal() && touches.currentY === touches.startY || swiper.isVertical() && touches.currentX === touches.startX) {
11145        data.isScrolling = false;
vendor: 8,243 bytes, lines 11146-11351
11146      } else {
11147        // eslint-disable-next-line
11148        if (diffX * diffX + diffY * diffY >= 25) {
11149          touchAngle = Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180 / Math.PI;
11150          data.isScrolling = swiper.isHorizontal() ? touchAngle > params.touchAngle : 90 - touchAngle > params.touchAngle;
11151        }
11152      }
11153    }
11154    if (data.isScrolling) {
11155      swiper.emit('touchMoveOpposite', e);
11156    }
11157    if (typeof data.startMoving === 'undefined') {
11158      if (touches.currentX !== touches.startX || touches.currentY !== touches.startY) {
11159        data.startMoving = true;
11160      }
11161    }
11162    if (data.isScrolling || e.type === 'touchmove' && data.preventTouchMoveFromPointerMove) {
11163      data.isTouched = false;
11164      return;
11165    }
11166    if (!data.startMoving) {
11167      return;
11168    }
11169    swiper.allowClick = false;
11170    if (!params.cssMode && e.cancelable) {
11171      e.preventDefault();
11172    }
11173    if (params.touchMoveStopPropagation && !params.nested) {
11174      e.stopPropagation();
11175    }
11176    let diff = swiper.isHorizontal() ? diffX : diffY;
11177    let touchesDiff = swiper.isHorizontal() ? touches.currentX - touches.previousX : touches.currentY - touches.previousY;
11178    if (params.oneWayMovement) {
11179      diff = Math.abs(diff) * (rtl ? 1 : -1);
11180      touchesDiff = Math.abs(touchesDiff) * (rtl ? 1 : -1);
11181    }
11182    touches.diff = diff;
11183    diff *= params.touchRatio;
11184    if (rtl) {
11185      diff = -diff;
11186      touchesDiff = -touchesDiff;
11187    }
11188    const prevTouchesDirection = swiper.touchesDirection;
11189    swiper.swipeDirection = diff > 0 ? 'prev' : 'next';
11190    swiper.touchesDirection = touchesDiff > 0 ? 'prev' : 'next';
11191    const isLoop = swiper.params.loop && !params.cssMode;
11192    const allowLoopFix = swiper.touchesDirection === 'next' && swiper.allowSlideNext || swiper.touchesDirection === 'prev' && swiper.allowSlidePrev;
11193    if (!data.isMoved) {
11194      if (isLoop && allowLoopFix) {
11195        swiper.loopFix({
11196          direction: swiper.swipeDirection
11197        });
11198      }
11199      data.startTranslate = swiper.getTranslate();
11200      swiper.setTransition(0);
11201      if (swiper.animating) {
11202        const evt = new window.CustomEvent('transitionend', {
11203          bubbles: true,
11204          cancelable: true,
11205          detail: {
11206            bySwiperTouchMove: true
11207          }
11208        });
11209        swiper.wrapperEl.dispatchEvent(evt);
11210      }
11211      data.allowMomentumBounce = false;
11212      // Grab Cursor
11213      if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
11214        swiper.setGrabCursor(true);
11215      }
11216      swiper.emit('sliderFirstMove', e);
11217    }
11218    let loopFixed;
11219    new Date().getTime();
11220    if (params._loopSwapReset !== false && data.isMoved && data.allowThresholdMove && prevTouchesDirection !== swiper.touchesDirection && isLoop && allowLoopFix && Math.abs(diff) >= 1) {
11221      Object.assign(touches, {
11222        startX: pageX,
11223        startY: pageY,
11224        currentX: pageX,
11225        currentY: pageY,
11226        startTranslate: data.currentTranslate
11227      });
11228      data.loopSwapReset = true;
11229      data.startTranslate = data.currentTranslate;
11230      return;
11231    }
11232    swiper.emit('sliderMove', e);
11233    data.isMoved = true;
11234    data.currentTranslate = diff + data.startTranslate;
11235    let disableParentSwiper = true;
11236    let resistanceRatio = params.resistanceRatio;
11237    if (params.touchReleaseOnEdges) {
11238      resistanceRatio = 0;
11239    }
11240    if (diff > 0) {
11241      if (isLoop && allowLoopFix && !loopFixed && data.allowThresholdMove && data.currentTranslate > (params.centeredSlides ? swiper.minTranslate() - swiper.slidesSizesGrid[swiper.activeIndex + 1] - (params.slidesPerView !== 'auto' && swiper.slides.length - params.slidesPerView >= 2 ? swiper.slidesSizesGrid[swiper.activeIndex + 1] + swiper.params.spaceBetween : 0) - swiper.params.spaceBetween : swiper.minTranslate())) {
11242        swiper.loopFix({
11243          direction: 'prev',
11244          setTranslate: true,
11245          activeSlideIndex: 0
11246        });
11247      }
11248      if (data.currentTranslate > swiper.minTranslate()) {
11249        disableParentSwiper = false;
11250        if (params.resistance) {
11251          data.currentTranslate = swiper.minTranslate() - 1 + (-swiper.minTranslate() + data.startTranslate + diff) ** resistanceRatio;
11252        }
11253      }
11254    } else if (diff < 0) {
11255      if (isLoop && allowLoopFix && !loopFixed && data.allowThresholdMove && data.currentTranslate < (params.centeredSlides ? swiper.maxTranslate() + swiper.slidesSizesGrid[swiper.slidesSizesGrid.length - 1] + swiper.params.spaceBetween + (params.slidesPerView !== 'auto' && swiper.slides.length - params.slidesPerView >= 2 ? swiper.slidesSizesGrid[swiper.slidesSizesGrid.length - 1] + swiper.params.spaceBetween : 0) : swiper.maxTranslate())) {
11256        swiper.loopFix({
11257          direction: 'next',
11258          setTranslate: true,
11259          activeSlideIndex: swiper.slides.length - (params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : Math.ceil(parseFloat(params.slidesPerView, 10)))
11260        });
11261      }
11262      if (data.currentTranslate < swiper.maxTranslate()) {
11263        disableParentSwiper = false;
11264        if (params.resistance) {
11265          data.currentTranslate = swiper.maxTranslate() + 1 - (swiper.maxTranslate() - data.startTranslate - diff) ** resistanceRatio;
11266        }
11267      }
11268    }
11269    if (disableParentSwiper) {
11270      e.preventedByNestedSwiper = true;
11271    }
11272
11273    // Directions locks
11274    if (!swiper.allowSlideNext && swiper.swipeDirection === 'next' && data.currentTranslate < data.startTranslate) {
11275      data.currentTranslate = data.startTranslate;
11276    }
11277    if (!swiper.allowSlidePrev && swiper.swipeDirection === 'prev' && data.currentTranslate > data.startTranslate) {
11278      data.currentTranslate = data.startTranslate;
11279    }
11280    if (!swiper.allowSlidePrev && !swiper.allowSlideNext) {
11281      data.currentTranslate = data.startTranslate;
11282    }
11283
11284    // Threshold
11285    if (params.threshold > 0) {
11286      if (Math.abs(diff) > params.threshold || data.allowThresholdMove) {
11287        if (!data.allowThresholdMove) {
11288          data.allowThresholdMove = true;
11289          touches.startX = touches.currentX;
11290          touches.startY = touches.currentY;
11291          data.currentTranslate = data.startTranslate;
11292          touches.diff = swiper.isHorizontal() ? touches.currentX - touches.startX : touches.currentY - touches.startY;
11293          return;
11294        }
11295      } else {
11296        data.currentTranslate = data.startTranslate;
11297        return;
11298      }
11299    }
11300    if (!params.followFinger || params.cssMode) return;
11301
11302    // Update active index in free mode
11303    if (params.freeMode && params.freeMode.enabled && swiper.freeMode || params.watchSlidesProgress) {
11304      swiper.updateActiveIndex();
11305      swiper.updateSlidesClasses();
11306    }
11307    if (params.freeMode && params.freeMode.enabled && swiper.freeMode) {
11308      swiper.freeMode.onTouchMove();
11309    }
11310    // Update progress
11311    swiper.updateProgress(data.currentTranslate);
11312    // Update translate
11313    swiper.setTranslate(data.currentTranslate);
11314  }
11315
11316  function onTouchEnd(event) {
11317    const swiper = this;
11318    const data = swiper.touchEventsData;
11319    let e = event;
11320    if (e.originalEvent) e = e.originalEvent;
11321    let targetTouch;
11322    const isTouchEvent = e.type === 'touchend' || e.type === 'touchcancel';
11323    if (!isTouchEvent) {
11324      if (data.touchId !== null) return; // return from pointer if we use touch
11325      if (e.pointerId !== data.pointerId) return;
11326      targetTouch = e;
11327    } else {
11328      targetTouch = [...e.changedTouches].find(t => t.identifier === data.touchId);
11329      if (!targetTouch || targetTouch.identifier !== data.touchId) return;
11330    }
11331    if (['pointercancel', 'pointerout', 'pointerleave', 'contextmenu'].includes(e.type)) {
11332      const proceed = ['pointercancel', 'contextmenu'].includes(e.type) && (swiper.browser.isSafari || swiper.browser.isWebView);
11333      if (!proceed) {
11334        return;
11335      }
11336    }
11337    data.pointerId = null;
11338    data.touchId = null;
11339    const {
11340      params,
11341      touches,
11342      rtlTranslate: rtl,
11343      slidesGrid,
11344      enabled
11345    } = swiper;
11346    if (!enabled) return;
11347    if (!params.simulateTouch && e.pointerType === 'mouse') return;
11348    if (data.allowTouchCallbacks) {
11349      swiper.emit('touchEnd', e);
11350    }
11351    data.allowTouchCallbacks = false;
vendor: 4,775 bytes, lines 11352-11483
11352    if (!data.isTouched) {
11353      if (data.isMoved && params.grabCursor) {
11354        swiper.setGrabCursor(false);
11355      }
11356      data.isMoved = false;
11357      data.startMoving = false;
11358      return;
11359    }
11360
11361    // Return Grab Cursor
11362    if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
11363      swiper.setGrabCursor(false);
11364    }
11365
11366    // Time diff
11367    const touchEndTime = now();
11368    const timeDiff = touchEndTime - data.touchStartTime;
11369
11370    // Tap, doubleTap, Click
11371    if (swiper.allowClick) {
11372      const pathTree = e.path || e.composedPath && e.composedPath();
11373      swiper.updateClickedSlide(pathTree && pathTree[0] || e.target, pathTree);
11374      swiper.emit('tap click', e);
11375      if (timeDiff < 300 && touchEndTime - data.lastClickTime < 300) {
11376        swiper.emit('doubleTap doubleClick', e);
11377      }
11378    }
11379    data.lastClickTime = now();
11380    nextTick(() => {
11381      if (!swiper.destroyed) swiper.allowClick = true;
11382    });
11383    if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 && !data.loopSwapReset || data.currentTranslate === data.startTranslate && !data.loopSwapReset) {
11384      data.isTouched = false;
11385      data.isMoved = false;
11386      data.startMoving = false;
11387      return;
11388    }
11389    data.isTouched = false;
11390    data.isMoved = false;
11391    data.startMoving = false;
11392    let currentPos;
11393    if (params.followFinger) {
11394      currentPos = rtl ? swiper.translate : -swiper.translate;
11395    } else {
11396      currentPos = -data.currentTranslate;
11397    }
11398    if (params.cssMode) {
11399      return;
11400    }
11401    if (params.freeMode && params.freeMode.enabled) {
11402      swiper.freeMode.onTouchEnd({
11403        currentPos
11404      });
11405      return;
11406    }
11407
11408    // Find current slide
11409    const swipeToLast = currentPos >= -swiper.maxTranslate() && !swiper.params.loop;
11410    let stopIndex = 0;
11411    let groupSize = swiper.slidesSizesGrid[0];
11412    for (let i = 0; i < slidesGrid.length; i += i < params.slidesPerGroupSkip ? 1 : params.slidesPerGroup) {
11413      const increment = i < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;
11414      if (typeof slidesGrid[i + increment] !== 'undefined') {
11415        if (swipeToLast || currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + increment]) {
11416          stopIndex = i;
11417          groupSize = slidesGrid[i + increment] - slidesGrid[i];
11418        }
11419      } else if (swipeToLast || currentPos >= slidesGrid[i]) {
11420        stopIndex = i;
11421        groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2];
11422      }
11423    }
11424    let rewindFirstIndex = null;
11425    let rewindLastIndex = null;
11426    if (params.rewind) {
11427      if (swiper.isBeginning) {
11428        rewindLastIndex = params.virtual && params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1;
11429      } else if (swiper.isEnd) {
11430        rewindFirstIndex = 0;
11431      }
11432    }
11433    // Find current slide size
11434    const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;
11435    const increment = stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;
11436    if (timeDiff > params.longSwipesMs) {
11437      // Long touches
11438      if (!params.longSwipes) {
11439        swiper.slideTo(swiper.activeIndex);
11440        return;
11441      }
11442      if (swiper.swipeDirection === 'next') {
11443        if (ratio >= params.longSwipesRatio) swiper.slideTo(params.rewind && swiper.isEnd ? rewindFirstIndex : stopIndex + increment);else swiper.slideTo(stopIndex);
11444      }
11445      if (swiper.swipeDirection === 'prev') {
11446        if (ratio > 1 - params.longSwipesRatio) {
11447          swiper.slideTo(stopIndex + increment);
11448        } else if (rewindLastIndex !== null && ratio < 0 && Math.abs(ratio) > params.longSwipesRatio) {
11449          swiper.slideTo(rewindLastIndex);
11450        } else {
11451          swiper.slideTo(stopIndex);
11452        }
11453      }
11454    } else {
11455      // Short swipes
11456      if (!params.shortSwipes) {
11457        swiper.slideTo(swiper.activeIndex);
11458        return;
11459      }
11460      const isNavButtonTarget = swiper.navigation && (e.target === swiper.navigation.nextEl || e.target === swiper.navigation.prevEl);
11461      if (!isNavButtonTarget) {
11462        if (swiper.swipeDirection === 'next') {
11463          swiper.slideTo(rewindFirstIndex !== null ? rewindFirstIndex : stopIndex + increment);
11464        }
11465        if (swiper.swipeDirection === 'prev') {
11466          swiper.slideTo(rewindLastIndex !== null ? rewindLastIndex : stopIndex);
11467        }
11468      } else if (e.target === swiper.navigation.nextEl) {
11469        swiper.slideTo(stopIndex + increment);
11470      } else {
11471        swiper.slideTo(stopIndex);
11472      }
11473    }
11474  }
11475
11476  function onResize() {
11477    const swiper = this;
11478    const {
11479      params,
11480      el
11481    } = swiper;
11482    if (el && el.offsetWidth === 0) return;
11483
vendor: 6,853 bytes, lines 11484-11706
11484    // Breakpoints
11485    if (params.breakpoints) {
11486      swiper.setBreakpoint();
11487    }
11488
11489    // Save locks
11490    const {
11491      allowSlideNext,
11492      allowSlidePrev,
11493      snapGrid
11494    } = swiper;
11495    const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
11496
11497    // Disable locks on resize
11498    swiper.allowSlideNext = true;
11499    swiper.allowSlidePrev = true;
11500    swiper.updateSize();
11501    swiper.updateSlides();
11502    swiper.updateSlidesClasses();
11503    const isVirtualLoop = isVirtual && params.loop;
11504    if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.isBeginning && !swiper.params.centeredSlides && !isVirtualLoop) {
11505      swiper.slideTo(swiper.slides.length - 1, 0, false, true);
11506    } else {
11507      if (swiper.params.loop && !isVirtual) {
11508        swiper.slideToLoop(swiper.realIndex, 0, false, true);
11509      } else {
11510        swiper.slideTo(swiper.activeIndex, 0, false, true);
11511      }
11512    }
11513    if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) {
11514      clearTimeout(swiper.autoplay.resizeTimeout);
11515      swiper.autoplay.resizeTimeout = setTimeout(() => {
11516        if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) {
11517          swiper.autoplay.resume();
11518        }
11519      }, 500);
11520    }
11521    // Return locks after resize
11522    swiper.allowSlidePrev = allowSlidePrev;
11523    swiper.allowSlideNext = allowSlideNext;
11524    if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) {
11525      swiper.checkOverflow();
11526    }
11527  }
11528
11529  function onClick(e) {
11530    const swiper = this;
11531    if (!swiper.enabled) return;
11532    if (!swiper.allowClick) {
11533      if (swiper.params.preventClicks) e.preventDefault();
11534      if (swiper.params.preventClicksPropagation && swiper.animating) {
11535        e.stopPropagation();
11536        e.stopImmediatePropagation();
11537      }
11538    }
11539  }
11540
11541  function onScroll() {
11542    const swiper = this;
11543    const {
11544      wrapperEl,
11545      rtlTranslate,
11546      enabled
11547    } = swiper;
11548    if (!enabled) return;
11549    swiper.previousTranslate = swiper.translate;
11550    if (swiper.isHorizontal()) {
11551      swiper.translate = -wrapperEl.scrollLeft;
11552    } else {
11553      swiper.translate = -wrapperEl.scrollTop;
11554    }
11555    // eslint-disable-next-line
11556    if (swiper.translate === 0) swiper.translate = 0;
11557    swiper.updateActiveIndex();
11558    swiper.updateSlidesClasses();
11559    let newProgress;
11560    const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
11561    if (translatesDiff === 0) {
11562      newProgress = 0;
11563    } else {
11564      newProgress = (swiper.translate - swiper.minTranslate()) / translatesDiff;
11565    }
11566    if (newProgress !== swiper.progress) {
11567      swiper.updateProgress(rtlTranslate ? -swiper.translate : swiper.translate);
11568    }
11569    swiper.emit('setTranslate', swiper.translate, false);
11570  }
11571
11572  function onLoad(e) {
11573    const swiper = this;
11574    processLazyPreloader(swiper, e.target);
11575    if (swiper.params.cssMode || swiper.params.slidesPerView !== 'auto' && !swiper.params.autoHeight) {
11576      return;
11577    }
11578    swiper.update();
11579  }
11580
11581  function onDocumentTouchStart() {
11582    const swiper = this;
11583    if (swiper.documentTouchHandlerProceeded) return;
11584    swiper.documentTouchHandlerProceeded = true;
11585    if (swiper.params.touchReleaseOnEdges) {
11586      swiper.el.style.touchAction = 'auto';
11587    }
11588  }
11589
11590  const events = (swiper, method) => {
11591    const document = getDocument();
11592    const {
11593      params,
11594      el,
11595      wrapperEl,
11596      device
11597    } = swiper;
11598    const capture = !!params.nested;
11599    const domMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';
11600    const swiperMethod = method;
11601    if (!el || typeof el === 'string') return;
11602
11603    // Touch Events
11604    document[domMethod]('touchstart', swiper.onDocumentTouchStart, {
11605      passive: false,
11606      capture
11607    });
11608    el[domMethod]('touchstart', swiper.onTouchStart, {
11609      passive: false
11610    });
11611    el[domMethod]('pointerdown', swiper.onTouchStart, {
11612      passive: false
11613    });
11614    document[domMethod]('touchmove', swiper.onTouchMove, {
11615      passive: false,
11616      capture
11617    });
11618    document[domMethod]('pointermove', swiper.onTouchMove, {
11619      passive: false,
11620      capture
11621    });
11622    document[domMethod]('touchend', swiper.onTouchEnd, {
11623      passive: true
11624    });
11625    document[domMethod]('pointerup', swiper.onTouchEnd, {
11626      passive: true
11627    });
11628    document[domMethod]('pointercancel', swiper.onTouchEnd, {
11629      passive: true
11630    });
11631    document[domMethod]('touchcancel', swiper.onTouchEnd, {
11632      passive: true
11633    });
11634    document[domMethod]('pointerout', swiper.onTouchEnd, {
11635      passive: true
11636    });
11637    document[domMethod]('pointerleave', swiper.onTouchEnd, {
11638      passive: true
11639    });
11640    document[domMethod]('contextmenu', swiper.onTouchEnd, {
11641      passive: true
11642    });
11643
11644    // Prevent Links Clicks
11645    if (params.preventClicks || params.preventClicksPropagation) {
11646      el[domMethod]('click', swiper.onClick, true);
11647    }
11648    if (params.cssMode) {
11649      wrapperEl[domMethod]('scroll', swiper.onScroll);
11650    }
11651
11652    // Resize handler
11653    if (params.updateOnWindowResize) {
11654      swiper[swiperMethod](device.ios || device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate', onResize, true);
11655    } else {
11656      swiper[swiperMethod]('observerUpdate', onResize, true);
11657    }
11658
11659    // Images loader
11660    el[domMethod]('load', swiper.onLoad, {
11661      capture: true
11662    });
11663  };
11664  function attachEvents() {
11665    const swiper = this;
11666    const {
11667      params
11668    } = swiper;
11669    swiper.onTouchStart = onTouchStart.bind(swiper);
11670    swiper.onTouchMove = onTouchMove.bind(swiper);
11671    swiper.onTouchEnd = onTouchEnd.bind(swiper);
11672    swiper.onDocumentTouchStart = onDocumentTouchStart.bind(swiper);
11673    if (params.cssMode) {
11674      swiper.onScroll = onScroll.bind(swiper);
11675    }
11676    swiper.onClick = onClick.bind(swiper);
11677    swiper.onLoad = onLoad.bind(swiper);
11678    events(swiper, 'on');
11679  }
11680  function detachEvents() {
11681    const swiper = this;
11682    events(swiper, 'off');
11683  }
11684  var events$1 = {
11685    attachEvents,
11686    detachEvents
11687  };
11688
11689  const isGridEnabled = (swiper, params) => {
11690    return swiper.grid && params.grid && params.grid.rows > 1;
11691  };
11692  function setBreakpoint() {
11693    const swiper = this;
11694    const {
11695      realIndex,
11696      initialized,
11697      params,
11698      el
11699    } = swiper;
11700    const breakpoints = params.breakpoints;
11701    if (!breakpoints || breakpoints && Object.keys(breakpoints).length === 0) return;
11702    const document = getDocument();
11703
11704    // Get breakpoint for window/container width and update parameters
11705    const breakpointsBase = params.breakpointsBase === 'window' || !params.breakpointsBase ? params.breakpointsBase : 'container';
11706    const breakpointContainer = ['window', 'container'].includes(params.breakpointsBase) || !params.breakpointsBase ? swiper.el : document.querySelector(params.breakpointsBase);
vendor: 26,382 bytes, lines 11707-12521
11707    const breakpoint = swiper.getBreakpoint(breakpoints, breakpointsBase, breakpointContainer);
11708    if (!breakpoint || swiper.currentBreakpoint === breakpoint) return;
11709    const breakpointOnlyParams = breakpoint in breakpoints ? breakpoints[breakpoint] : undefined;
11710    const breakpointParams = breakpointOnlyParams || swiper.originalParams;
11711    const wasMultiRow = isGridEnabled(swiper, params);
11712    const isMultiRow = isGridEnabled(swiper, breakpointParams);
11713    const wasGrabCursor = swiper.params.grabCursor;
11714    const isGrabCursor = breakpointParams.grabCursor;
11715    const wasEnabled = params.enabled;
11716    if (wasMultiRow && !isMultiRow) {
11717      el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`);
11718      swiper.emitContainerClasses();
11719    } else if (!wasMultiRow && isMultiRow) {
11720      el.classList.add(`${params.containerModifierClass}grid`);
11721      if (breakpointParams.grid.fill && breakpointParams.grid.fill === 'column' || !breakpointParams.grid.fill && params.grid.fill === 'column') {
11722        el.classList.add(`${params.containerModifierClass}grid-column`);
11723      }
11724      swiper.emitContainerClasses();
11725    }
11726    if (wasGrabCursor && !isGrabCursor) {
11727      swiper.unsetGrabCursor();
11728    } else if (!wasGrabCursor && isGrabCursor) {
11729      swiper.setGrabCursor();
11730    }
11731
11732    // Toggle navigation, pagination, scrollbar
11733    ['navigation', 'pagination', 'scrollbar'].forEach(prop => {
11734      if (typeof breakpointParams[prop] === 'undefined') return;
11735      const wasModuleEnabled = params[prop] && params[prop].enabled;
11736      const isModuleEnabled = breakpointParams[prop] && breakpointParams[prop].enabled;
11737      if (wasModuleEnabled && !isModuleEnabled) {
11738        swiper[prop].disable();
11739      }
11740      if (!wasModuleEnabled && isModuleEnabled) {
11741        swiper[prop].enable();
11742      }
11743    });
11744    const directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction;
11745    const needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged);
11746    const wasLoop = params.loop;
11747    if (directionChanged && initialized) {
11748      swiper.changeDirection();
11749    }
11750    extend(swiper.params, breakpointParams);
11751    const isEnabled = swiper.params.enabled;
11752    const hasLoop = swiper.params.loop;
11753    Object.assign(swiper, {
11754      allowTouchMove: swiper.params.allowTouchMove,
11755      allowSlideNext: swiper.params.allowSlideNext,
11756      allowSlidePrev: swiper.params.allowSlidePrev
11757    });
11758    if (wasEnabled && !isEnabled) {
11759      swiper.disable();
11760    } else if (!wasEnabled && isEnabled) {
11761      swiper.enable();
11762    }
11763    swiper.currentBreakpoint = breakpoint;
11764    swiper.emit('_beforeBreakpoint', breakpointParams);
11765    if (initialized) {
11766      if (needsReLoop) {
11767        swiper.loopDestroy();
11768        swiper.loopCreate(realIndex);
11769        swiper.updateSlides();
11770      } else if (!wasLoop && hasLoop) {
11771        swiper.loopCreate(realIndex);
11772        swiper.updateSlides();
11773      } else if (wasLoop && !hasLoop) {
11774        swiper.loopDestroy();
11775      }
11776    }
11777    swiper.emit('breakpoint', breakpointParams);
11778  }
11779
11780  function getBreakpoint(breakpoints, base = 'window', containerEl) {
11781    if (!breakpoints || base === 'container' && !containerEl) return undefined;
11782    let breakpoint = false;
11783    const window = getWindow();
11784    const currentHeight = base === 'window' ? window.innerHeight : containerEl.clientHeight;
11785    const points = Object.keys(breakpoints).map(point => {
11786      if (typeof point === 'string' && point.indexOf('@') === 0) {
11787        const minRatio = parseFloat(point.substr(1));
11788        const value = currentHeight * minRatio;
11789        return {
11790          value,
11791          point
11792        };
11793      }
11794      return {
11795        value: point,
11796        point
11797      };
11798    });
11799    points.sort((a, b) => parseInt(a.value, 10) - parseInt(b.value, 10));
11800    for (let i = 0; i < points.length; i += 1) {
11801      const {
11802        point,
11803        value
11804      } = points[i];
11805      if (base === 'window') {
11806        if (window.matchMedia(`(min-width: ${value}px)`).matches) {
11807          breakpoint = point;
11808        }
11809      } else if (value <= containerEl.clientWidth) {
11810        breakpoint = point;
11811      }
11812    }
11813    return breakpoint || 'max';
11814  }
11815
11816  var breakpoints = {
11817    setBreakpoint,
11818    getBreakpoint
11819  };
11820
11821  function prepareClasses(entries, prefix) {
11822    const resultClasses = [];
11823    entries.forEach(item => {
11824      if (typeof item === 'object') {
11825        Object.keys(item).forEach(classNames => {
11826          if (item[classNames]) {
11827            resultClasses.push(prefix + classNames);
11828          }
11829        });
11830      } else if (typeof item === 'string') {
11831        resultClasses.push(prefix + item);
11832      }
11833    });
11834    return resultClasses;
11835  }
11836  function addClasses() {
11837    const swiper = this;
11838    const {
11839      classNames,
11840      params,
11841      rtl,
11842      el,
11843      device
11844    } = swiper;
11845    // prettier-ignore
11846    const suffixes = prepareClasses(['initialized', params.direction, {
11847      'free-mode': swiper.params.freeMode && params.freeMode.enabled
11848    }, {
11849      'autoheight': params.autoHeight
11850    }, {
11851      'rtl': rtl
11852    }, {
11853      'grid': params.grid && params.grid.rows > 1
11854    }, {
11855      'grid-column': params.grid && params.grid.rows > 1 && params.grid.fill === 'column'
11856    }, {
11857      'android': device.android
11858    }, {
11859      'ios': device.ios
11860    }, {
11861      'css-mode': params.cssMode
11862    }, {
11863      'centered': params.cssMode && params.centeredSlides
11864    }, {
11865      'watch-progress': params.watchSlidesProgress
11866    }], params.containerModifierClass);
11867    classNames.push(...suffixes);
11868    el.classList.add(...classNames);
11869    swiper.emitContainerClasses();
11870  }
11871
11872  function removeClasses() {
11873    const swiper = this;
11874    const {
11875      el,
11876      classNames
11877    } = swiper;
11878    if (!el || typeof el === 'string') return;
11879    el.classList.remove(...classNames);
11880    swiper.emitContainerClasses();
11881  }
11882
11883  var classes = {
11884    addClasses,
11885    removeClasses
11886  };
11887
11888  function checkOverflow() {
11889    const swiper = this;
11890    const {
11891      isLocked: wasLocked,
11892      params
11893    } = swiper;
11894    const {
11895      slidesOffsetBefore
11896    } = params;
11897    if (slidesOffsetBefore) {
11898      const lastSlideIndex = swiper.slides.length - 1;
11899      const lastSlideRightEdge = swiper.slidesGrid[lastSlideIndex] + swiper.slidesSizesGrid[lastSlideIndex] + slidesOffsetBefore * 2;
11900      swiper.isLocked = swiper.size > lastSlideRightEdge;
11901    } else {
11902      swiper.isLocked = swiper.snapGrid.length === 1;
11903    }
11904    if (params.allowSlideNext === true) {
11905      swiper.allowSlideNext = !swiper.isLocked;
11906    }
11907    if (params.allowSlidePrev === true) {
11908      swiper.allowSlidePrev = !swiper.isLocked;
11909    }
11910    if (wasLocked && wasLocked !== swiper.isLocked) {
11911      swiper.isEnd = false;
11912    }
11913    if (wasLocked !== swiper.isLocked) {
11914      swiper.emit(swiper.isLocked ? 'lock' : 'unlock');
11915    }
11916  }
11917  var checkOverflow$1 = {
11918    checkOverflow
11919  };
11920
11921  var defaults = {
11922    init: true,
11923    direction: 'horizontal',
11924    oneWayMovement: false,
11925    swiperElementNodeName: 'SWIPER-CONTAINER',
11926    touchEventsTarget: 'wrapper',
11927    initialSlide: 0,
11928    speed: 300,
11929    cssMode: false,
11930    updateOnWindowResize: true,
11931    resizeObserver: true,
11932    nested: false,
11933    createElements: false,
11934    eventsPrefix: 'swiper',
11935    enabled: true,
11936    focusableElements: 'input, select, option, textarea, button, video, label',
11937    // Overrides
11938    width: null,
11939    height: null,
11940    //
11941    preventInteractionOnTransition: false,
11942    // ssr
11943    userAgent: null,
11944    url: null,
11945    // To support iOS's swipe-to-go-back gesture (when being used in-app).
11946    edgeSwipeDetection: false,
11947    edgeSwipeThreshold: 20,
11948    // Autoheight
11949    autoHeight: false,
11950    // Set wrapper width
11951    setWrapperSize: false,
11952    // Virtual Translate
11953    virtualTranslate: false,
11954    // Effects
11955    effect: 'slide',
11956    // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
11957
11958    // Breakpoints
11959    breakpoints: undefined,
11960    breakpointsBase: 'window',
11961    // Slides grid
11962    spaceBetween: 0,
11963    slidesPerView: 1,
11964    slidesPerGroup: 1,
11965    slidesPerGroupSkip: 0,
11966    slidesPerGroupAuto: false,
11967    centeredSlides: false,
11968    centeredSlidesBounds: false,
11969    slidesOffsetBefore: 0,
11970    // in px
11971    slidesOffsetAfter: 0,
11972    // in px
11973    normalizeSlideIndex: true,
11974    centerInsufficientSlides: false,
11975    // Disable swiper and hide navigation when container not overflow
11976    watchOverflow: true,
11977    // Round length
11978    roundLengths: false,
11979    // Touches
11980    touchRatio: 1,
11981    touchAngle: 45,
11982    simulateTouch: true,
11983    shortSwipes: true,
11984    longSwipes: true,
11985    longSwipesRatio: 0.5,
11986    longSwipesMs: 300,
11987    followFinger: true,
11988    allowTouchMove: true,
11989    threshold: 5,
11990    touchMoveStopPropagation: false,
11991    touchStartPreventDefault: true,
11992    touchStartForcePreventDefault: false,
11993    touchReleaseOnEdges: false,
11994    // Unique Navigation Elements
11995    uniqueNavElements: true,
11996    // Resistance
11997    resistance: true,
11998    resistanceRatio: 0.85,
11999    // Progress
12000    watchSlidesProgress: false,
12001    // Cursor
12002    grabCursor: false,
12003    // Clicks
12004    preventClicks: true,
12005    preventClicksPropagation: true,
12006    slideToClickedSlide: false,
12007    // loop
12008    loop: false,
12009    loopAddBlankSlides: true,
12010    loopAdditionalSlides: 0,
12011    loopPreventsSliding: true,
12012    // rewind
12013    rewind: false,
12014    // Swiping/no swiping
12015    allowSlidePrev: true,
12016    allowSlideNext: true,
12017    swipeHandler: null,
12018    // '.swipe-handler',
12019    noSwiping: true,
12020    noSwipingClass: 'swiper-no-swiping',
12021    noSwipingSelector: null,
12022    // Passive Listeners
12023    passiveListeners: true,
12024    maxBackfaceHiddenSlides: 10,
12025    // NS
12026    containerModifierClass: 'swiper-',
12027    // NEW
12028    slideClass: 'swiper-slide',
12029    slideBlankClass: 'swiper-slide-blank',
12030    slideActiveClass: 'swiper-slide-active',
12031    slideVisibleClass: 'swiper-slide-visible',
12032    slideFullyVisibleClass: 'swiper-slide-fully-visible',
12033    slideNextClass: 'swiper-slide-next',
12034    slidePrevClass: 'swiper-slide-prev',
12035    wrapperClass: 'swiper-wrapper',
12036    lazyPreloaderClass: 'swiper-lazy-preloader',
12037    lazyPreloadPrevNext: 0,
12038    // Callbacks
12039    runCallbacksOnInit: true,
12040    // Internals
12041    _emitClasses: false
12042  };
12043
12044  function moduleExtendParams(params, allModulesParams) {
12045    return function extendParams(obj = {}) {
12046      const moduleParamName = Object.keys(obj)[0];
12047      const moduleParams = obj[moduleParamName];
12048      if (typeof moduleParams !== 'object' || moduleParams === null) {
12049        extend(allModulesParams, obj);
12050        return;
12051      }
12052      if (params[moduleParamName] === true) {
12053        params[moduleParamName] = {
12054          enabled: true
12055        };
12056      }
12057      if (moduleParamName === 'navigation' && params[moduleParamName] && params[moduleParamName].enabled && !params[moduleParamName].prevEl && !params[moduleParamName].nextEl) {
12058        params[moduleParamName].auto = true;
12059      }
12060      if (['pagination', 'scrollbar'].indexOf(moduleParamName) >= 0 && params[moduleParamName] && params[moduleParamName].enabled && !params[moduleParamName].el) {
12061        params[moduleParamName].auto = true;
12062      }
12063      if (!(moduleParamName in params && 'enabled' in moduleParams)) {
12064        extend(allModulesParams, obj);
12065        return;
12066      }
12067      if (typeof params[moduleParamName] === 'object' && !('enabled' in params[moduleParamName])) {
12068        params[moduleParamName].enabled = true;
12069      }
12070      if (!params[moduleParamName]) params[moduleParamName] = {
12071        enabled: false
12072      };
12073      extend(allModulesParams, obj);
12074    };
12075  }
12076
12077  /* eslint no-param-reassign: "off" */
12078  const prototypes = {
12079    eventsEmitter,
12080    update,
12081    translate,
12082    transition,
12083    slide,
12084    loop,
12085    grabCursor,
12086    events: events$1,
12087    breakpoints,
12088    checkOverflow: checkOverflow$1,
12089    classes
12090  };
12091  const extendedDefaults = {};
12092  class Swiper {
12093    constructor(...args) {
12094      let el;
12095      let params;
12096      if (args.length === 1 && args[0].constructor && Object.prototype.toString.call(args[0]).slice(8, -1) === 'Object') {
12097        params = args[0];
12098      } else {
12099        [el, params] = args;
12100      }
12101      if (!params) params = {};
12102      params = extend({}, params);
12103      if (el && !params.el) params.el = el;
12104      const document = getDocument();
12105      if (params.el && typeof params.el === 'string' && document.querySelectorAll(params.el).length > 1) {
12106        const swipers = [];
12107        document.querySelectorAll(params.el).forEach(containerEl => {
12108          const newParams = extend({}, params, {
12109            el: containerEl
12110          });
12111          swipers.push(new Swiper(newParams));
12112        });
12113        // eslint-disable-next-line no-constructor-return
12114        return swipers;
12115      }
12116
12117      // Swiper Instance
12118      const swiper = this;
12119      swiper.__swiper__ = true;
12120      swiper.support = getSupport();
12121      swiper.device = getDevice({
12122        userAgent: params.userAgent
12123      });
12124      swiper.browser = getBrowser();
12125      swiper.eventsListeners = {};
12126      swiper.eventsAnyListeners = [];
12127      swiper.modules = [...swiper.__modules__];
12128      if (params.modules && Array.isArray(params.modules)) {
12129        swiper.modules.push(...params.modules);
12130      }
12131      const allModulesParams = {};
12132      swiper.modules.forEach(mod => {
12133        mod({
12134          params,
12135          swiper,
12136          extendParams: moduleExtendParams(params, allModulesParams),
12137          on: swiper.on.bind(swiper),
12138          once: swiper.once.bind(swiper),
12139          off: swiper.off.bind(swiper),
12140          emit: swiper.emit.bind(swiper)
12141        });
12142      });
12143
12144      // Extend defaults with modules params
12145      const swiperParams = extend({}, defaults, allModulesParams);
12146
12147      // Extend defaults with passed params
12148      swiper.params = extend({}, swiperParams, extendedDefaults, params);
12149      swiper.originalParams = extend({}, swiper.params);
12150      swiper.passedParams = extend({}, params);
12151
12152      // add event listeners
12153      if (swiper.params && swiper.params.on) {
12154        Object.keys(swiper.params.on).forEach(eventName => {
12155          swiper.on(eventName, swiper.params.on[eventName]);
12156        });
12157      }
12158      if (swiper.params && swiper.params.onAny) {
12159        swiper.onAny(swiper.params.onAny);
12160      }
12161
12162      // Extend Swiper
12163      Object.assign(swiper, {
12164        enabled: swiper.params.enabled,
12165        el,
12166        // Classes
12167        classNames: [],
12168        // Slides
12169        slides: [],
12170        slidesGrid: [],
12171        snapGrid: [],
12172        slidesSizesGrid: [],
12173        // isDirection
12174        isHorizontal() {
12175          return swiper.params.direction === 'horizontal';
12176        },
12177        isVertical() {
12178          return swiper.params.direction === 'vertical';
12179        },
12180        // Indexes
12181        activeIndex: 0,
12182        realIndex: 0,
12183        //
12184        isBeginning: true,
12185        isEnd: false,
12186        // Props
12187        translate: 0,
12188        previousTranslate: 0,
12189        progress: 0,
12190        velocity: 0,
12191        animating: false,
12192        cssOverflowAdjustment() {
12193          // Returns 0 unless `translate` is > 2**23
12194          // Should be subtracted from css values to prevent overflow
12195          return Math.trunc(this.translate / 2 ** 23) * 2 ** 23;
12196        },
12197        // Locks
12198        allowSlideNext: swiper.params.allowSlideNext,
12199        allowSlidePrev: swiper.params.allowSlidePrev,
12200        // Touch Events
12201        touchEventsData: {
12202          isTouched: undefined,
12203          isMoved: undefined,
12204          allowTouchCallbacks: undefined,
12205          touchStartTime: undefined,
12206          isScrolling: undefined,
12207          currentTranslate: undefined,
12208          startTranslate: undefined,
12209          allowThresholdMove: undefined,
12210          // Form elements to match
12211          focusableElements: swiper.params.focusableElements,
12212          // Last click time
12213          lastClickTime: 0,
12214          clickTimeout: undefined,
12215          // Velocities
12216          velocities: [],
12217          allowMomentumBounce: undefined,
12218          startMoving: undefined,
12219          pointerId: null,
12220          touchId: null
12221        },
12222        // Clicks
12223        allowClick: true,
12224        // Touches
12225        allowTouchMove: swiper.params.allowTouchMove,
12226        touches: {
12227          startX: 0,
12228          startY: 0,
12229          currentX: 0,
12230          currentY: 0,
12231          diff: 0
12232        },
12233        // Images
12234        imagesToLoad: [],
12235        imagesLoaded: 0
12236      });
12237      swiper.emit('_swiper');
12238
12239      // Init
12240      if (swiper.params.init) {
12241        swiper.init();
12242      }
12243
12244      // Return app instance
12245      // eslint-disable-next-line no-constructor-return
12246      return swiper;
12247    }
12248    getDirectionLabel(property) {
12249      if (this.isHorizontal()) {
12250        return property;
12251      }
12252      // prettier-ignore
12253      return {
12254        'width': 'height',
12255        'margin-top': 'margin-left',
12256        'margin-bottom ': 'margin-right',
12257        'margin-left': 'margin-top',
12258        'margin-right': 'margin-bottom',
12259        'padding-left': 'padding-top',
12260        'padding-right': 'padding-bottom',
12261        'marginRight': 'marginBottom'
12262      }[property];
12263    }
12264    getSlideIndex(slideEl) {
12265      const {
12266        slidesEl,
12267        params
12268      } = this;
12269      const slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`);
12270      const firstSlideIndex = elementIndex(slides[0]);
12271      return elementIndex(slideEl) - firstSlideIndex;
12272    }
12273    getSlideIndexByData(index) {
12274      return this.getSlideIndex(this.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') * 1 === index));
12275    }
12276    getSlideIndexWhenGrid(index) {
12277      if (this.grid && this.params.grid && this.params.grid.rows > 1) {
12278        if (this.params.grid.fill === 'column') {
12279          index = Math.floor(index / this.params.grid.rows);
12280        } else if (this.params.grid.fill === 'row') {
12281          index = index % Math.ceil(this.slides.length / this.params.grid.rows);
12282        }
12283      }
12284      return index;
12285    }
12286    recalcSlides() {
12287      const swiper = this;
12288      const {
12289        slidesEl,
12290        params
12291      } = swiper;
12292      swiper.slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`);
12293    }
12294    enable() {
12295      const swiper = this;
12296      if (swiper.enabled) return;
12297      swiper.enabled = true;
12298      if (swiper.params.grabCursor) {
12299        swiper.setGrabCursor();
12300      }
12301      swiper.emit('enable');
12302    }
12303    disable() {
12304      const swiper = this;
12305      if (!swiper.enabled) return;
12306      swiper.enabled = false;
12307      if (swiper.params.grabCursor) {
12308        swiper.unsetGrabCursor();
12309      }
12310      swiper.emit('disable');
12311    }
12312    setProgress(progress, speed) {
12313      const swiper = this;
12314      progress = Math.min(Math.max(progress, 0), 1);
12315      const min = swiper.minTranslate();
12316      const max = swiper.maxTranslate();
12317      const current = (max - min) * progress + min;
12318      swiper.translateTo(current, typeof speed === 'undefined' ? 0 : speed);
12319      swiper.updateActiveIndex();
12320      swiper.updateSlidesClasses();
12321    }
12322    emitContainerClasses() {
12323      const swiper = this;
12324      if (!swiper.params._emitClasses || !swiper.el) return;
12325      const cls = swiper.el.className.split(' ').filter(className => {
12326        return className.indexOf('swiper') === 0 || className.indexOf(swiper.params.containerModifierClass) === 0;
12327      });
12328      swiper.emit('_containerClasses', cls.join(' '));
12329    }
12330    getSlideClasses(slideEl) {
12331      const swiper = this;
12332      if (swiper.destroyed) return '';
12333      return slideEl.className.split(' ').filter(className => {
12334        return className.indexOf('swiper-slide') === 0 || className.indexOf(swiper.params.slideClass) === 0;
12335      }).join(' ');
12336    }
12337    emitSlidesClasses() {
12338      const swiper = this;
12339      if (!swiper.params._emitClasses || !swiper.el) return;
12340      const updates = [];
12341      swiper.slides.forEach(slideEl => {
12342        const classNames = swiper.getSlideClasses(slideEl);
12343        updates.push({
12344          slideEl,
12345          classNames
12346        });
12347        swiper.emit('_slideClass', slideEl, classNames);
12348      });
12349      swiper.emit('_slideClasses', updates);
12350    }
12351    slidesPerViewDynamic(view = 'current', exact = false) {
12352      const swiper = this;
12353      const {
12354        params,
12355        slides,
12356        slidesGrid,
12357        slidesSizesGrid,
12358        size: swiperSize,
12359        activeIndex
12360      } = swiper;
12361      let spv = 1;
12362      if (typeof params.slidesPerView === 'number') return params.slidesPerView;
12363      if (params.centeredSlides) {
12364        let slideSize = slides[activeIndex] ? Math.ceil(slides[activeIndex].swiperSlideSize) : 0;
12365        let breakLoop;
12366        for (let i = activeIndex + 1; i < slides.length; i += 1) {
12367          if (slides[i] && !breakLoop) {
12368            slideSize += Math.ceil(slides[i].swiperSlideSize);
12369            spv += 1;
12370            if (slideSize > swiperSize) breakLoop = true;
12371          }
12372        }
12373        for (let i = activeIndex - 1; i >= 0; i -= 1) {
12374          if (slides[i] && !breakLoop) {
12375            slideSize += slides[i].swiperSlideSize;
12376            spv += 1;
12377            if (slideSize > swiperSize) breakLoop = true;
12378          }
12379        }
12380      } else {
12381        // eslint-disable-next-line
12382        if (view === 'current') {
12383          for (let i = activeIndex + 1; i < slides.length; i += 1) {
12384            const slideInView = exact ? slidesGrid[i] + slidesSizesGrid[i] - slidesGrid[activeIndex] < swiperSize : slidesGrid[i] - slidesGrid[activeIndex] < swiperSize;
12385            if (slideInView) {
12386              spv += 1;
12387            }
12388          }
12389        } else {
12390          // previous
12391          for (let i = activeIndex - 1; i >= 0; i -= 1) {
12392            const slideInView = slidesGrid[activeIndex] - slidesGrid[i] < swiperSize;
12393            if (slideInView) {
12394              spv += 1;
12395            }
12396          }
12397        }
12398      }
12399      return spv;
12400    }
12401    update() {
12402      const swiper = this;
12403      if (!swiper || swiper.destroyed) return;
12404      const {
12405        snapGrid,
12406        params
12407      } = swiper;
12408      // Breakpoints
12409      if (params.breakpoints) {
12410        swiper.setBreakpoint();
12411      }
12412      [...swiper.el.querySelectorAll('[loading="lazy"]')].forEach(imageEl => {
12413        if (imageEl.complete) {
12414          processLazyPreloader(swiper, imageEl);
12415        }
12416      });
12417      swiper.updateSize();
12418      swiper.updateSlides();
12419      swiper.updateProgress();
12420      swiper.updateSlidesClasses();
12421      function setTranslate() {
12422        const translateValue = swiper.rtlTranslate ? swiper.translate * -1 : swiper.translate;
12423        const newTranslate = Math.min(Math.max(translateValue, swiper.maxTranslate()), swiper.minTranslate());
12424        swiper.setTranslate(newTranslate);
12425        swiper.updateActiveIndex();
12426        swiper.updateSlidesClasses();
12427      }
12428      let translated;
12429      if (params.freeMode && params.freeMode.enabled && !params.cssMode) {
12430        setTranslate();
12431        if (params.autoHeight) {
12432          swiper.updateAutoHeight();
12433        }
12434      } else {
12435        if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !params.centeredSlides) {
12436          const slides = swiper.virtual && params.virtual.enabled ? swiper.virtual.slides : swiper.slides;
12437          translated = swiper.slideTo(slides.length - 1, 0, false, true);
12438        } else {
12439          translated = swiper.slideTo(swiper.activeIndex, 0, false, true);
12440        }
12441        if (!translated) {
12442          setTranslate();
12443        }
12444      }
12445      if (params.watchOverflow && snapGrid !== swiper.snapGrid) {
12446        swiper.checkOverflow();
12447      }
12448      swiper.emit('update');
12449    }
12450    changeDirection(newDirection, needUpdate = true) {
12451      const swiper = this;
12452      const currentDirection = swiper.params.direction;
12453      if (!newDirection) {
12454        // eslint-disable-next-line
12455        newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal';
12456      }
12457      if (newDirection === currentDirection || newDirection !== 'horizontal' && newDirection !== 'vertical') {
12458        return swiper;
12459      }
12460      swiper.el.classList.remove(`${swiper.params.containerModifierClass}${currentDirection}`);
12461      swiper.el.classList.add(`${swiper.params.containerModifierClass}${newDirection}`);
12462      swiper.emitContainerClasses();
12463      swiper.params.direction = newDirection;
12464      swiper.slides.forEach(slideEl => {
12465        if (newDirection === 'vertical') {
12466          slideEl.style.width = '';
12467        } else {
12468          slideEl.style.height = '';
12469        }
12470      });
12471      swiper.emit('changeDirection');
12472      if (needUpdate) swiper.update();
12473      return swiper;
12474    }
12475    changeLanguageDirection(direction) {
12476      const swiper = this;
12477      if (swiper.rtl && direction === 'rtl' || !swiper.rtl && direction === 'ltr') return;
12478      swiper.rtl = direction === 'rtl';
12479      swiper.rtlTranslate = swiper.params.direction === 'horizontal' && swiper.rtl;
12480      if (swiper.rtl) {
12481        swiper.el.classList.add(`${swiper.params.containerModifierClass}rtl`);
12482        swiper.el.dir = 'rtl';
12483      } else {
12484        swiper.el.classList.remove(`${swiper.params.containerModifierClass}rtl`);
12485        swiper.el.dir = 'ltr';
12486      }
12487      swiper.update();
12488    }
12489    mount(element) {
12490      const swiper = this;
12491      if (swiper.mounted) return true;
12492
12493      // Find el
12494      let el = element || swiper.params.el;
12495      if (typeof el === 'string') {
12496        el = document.querySelector(el);
12497      }
12498      if (!el) {
12499        return false;
12500      }
12501      el.swiper = swiper;
12502      if (el.parentNode && el.parentNode.host && el.parentNode.host.nodeName === swiper.params.swiperElementNodeName.toUpperCase()) {
12503        swiper.isElement = true;
12504      }
12505      const getWrapperSelector = () => {
12506        return `.${(swiper.params.wrapperClass || '').trim().split(' ').join('.')}`;
12507      };
12508      const getWrapper = () => {
12509        if (el && el.shadowRoot && el.shadowRoot.querySelector) {
12510          const res = el.shadowRoot.querySelector(getWrapperSelector());
12511          // Children needs to return slot items
12512          return res;
12513        }
12514        return elementChildren(el, getWrapperSelector())[0];
12515      };
12516      // Find Wrapper
12517      let wrapperEl = getWrapper();
12518      if (!wrapperEl && swiper.params.createElements) {
12519        wrapperEl = createElement('div', swiper.params.wrapperClass);
12520        el.append(wrapperEl);
12521        elementChildren(el, `.${swiper.params.slideClass}
12521`).forEach(slideEl => {
12522          wrapperEl.append(slideEl);
12523        });
12524      }
12525      Object.assign(swiper, {
12526        el,
12527        wrapperEl,
12528        slidesEl: swiper.isElement && !el.parentNode.host.slideSlots ? el.parentNode.host : wrapperEl,
12529        hostEl: swiper.isElement ? el.parentNode.host : el,
12530        mounted: true,
12531        // RTL
12532        rtl: el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl',
12533        rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl'),
12534        wrongRTL: elementStyle(wrapperEl, 'display') === '-webkit-box'
12535      });
12536      return true;
12537    }
12538    init(el) {
12539      const swiper = this;
12540      if (swiper.initialized) return swiper;
12541      const mounted = swiper.mount(el);
12542      if (mounted === false) return swiper;
12543      swiper.emit('beforeInit');
12544
12545      // Set breakpoint
12546      if (swiper.params.breakpoints) {
12547        swiper.setBreakpoint();
12548      }
12549
12550      // Add Classes
12551      swiper.addClasses();
12552
12553      // Update size
12554      swiper.updateSize();
12555
12556      // Update slides
12557      swiper.updateSlides();
12558      if (swiper.params.watchOverflow) {
12559        swiper.checkOverflow();
12560      }
12561
12562      // Set Grab Cursor
12563      if (swiper.params.grabCursor && swiper.enabled) {
12564        swiper.setGrabCursor();
12565      }
12566
12567      // Slide To Initial Slide
12568      if (swiper.params.loop && swiper.virtual && swiper.params.virtual.enabled) {
12569        swiper.slideTo(swiper.params.initialSlide + swiper.virtual.slidesBefore, 0, swiper.params.runCallbacksOnInit, false, true);
12570      } else {
12571        swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true);
12572      }
12573
12574      // Create loop
12575      if (swiper.params.loop) {
12576        swiper.loopCreate(undefined, true);
12577      }
12578
12579      // Attach events
12580      swiper.attachEvents();
12581      const lazyElements = [...swiper.el.querySelectorAll('[loading="lazy"]')];
12582      if (swiper.isElement) {
12583        lazyElements.push(...swiper.hostEl.querySelectorAll('[loading="lazy"]'));
12584      }
12585      lazyElements.forEach(imageEl => {
12586        if (imageEl.complete) {
12587          processLazyPreloader(swiper, imageEl);
12588        } else {
12589          imageEl.addEventListener('load', e => {
12590            processLazyPreloader(swiper, e.target);
12591          });
12592        }
12593      });
12594      preload(swiper);
12595
12596      // Init Flag
12597      swiper.initialized = true;
12598      preload(swiper);
12599
12600      // Emit
12601      swiper.emit('init');
12602      swiper.emit('afterInit');
12603      return swiper;
12604    }
12605    destroy(deleteInstance = true, cleanStyles = true) {
12606      const swiper = this;
12607      const {
12608        params,
12609        el,
12610        wrapperEl,
12611        slides
12612      } = swiper;
12613      if (typeof swiper.params === 'undefined' || swiper.destroyed) {
12614        return null;
12615      }
12616      swiper.emit('beforeDestroy');
12617
12618      // Init Flag
12619      swiper.initialized = false;
12620
12621      // Detach events
12622      swiper.detachEvents();
12623
12624      // Destroy loop
12625      if (params.loop) {
12626        swiper.loopDestroy();
12627      }
12628
12629      // Cleanup styles
12630      if (cleanStyles) {
12631        swiper.removeClasses();
12632        if (el && typeof el !== 'string') {
12633          el.removeAttribute('style');
12634        }
12635        if (wrapperEl) {
12636          wrapperEl.removeAttribute('style');
12637        }
12638        if (slides && slides.length) {
vendor: 6,255 bytes, lines 12639-12831
12639          slides.forEach(slideEl => {
12640            slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
12641            slideEl.removeAttribute('style');
12642            slideEl.removeAttribute('data-swiper-slide-index');
12643          });
12644        }
12645      }
12646      swiper.emit('destroy');
12647
12648      // Detach emitter events
12649      Object.keys(swiper.eventsListeners).forEach(eventName => {
12650        swiper.off(eventName);
12651      });
12652      if (deleteInstance !== false) {
12653        if (swiper.el && typeof swiper.el !== 'string') {
12654          swiper.el.swiper = null;
12655        }
12656        deleteProps(swiper);
12657      }
12658      swiper.destroyed = true;
12659      return null;
12660    }
12661    static extendDefaults(newDefaults) {
12662      extend(extendedDefaults, newDefaults);
12663    }
12664    static get extendedDefaults() {
12665      return extendedDefaults;
12666    }
12667    static get defaults() {
12668      return defaults;
12669    }
12670    static installModule(mod) {
12671      if (!Swiper.prototype.__modules__) Swiper.prototype.__modules__ = [];
12672      const modules = Swiper.prototype.__modules__;
12673      if (typeof mod === 'function' && modules.indexOf(mod) < 0) {
12674        modules.push(mod);
12675      }
12676    }
12677    static use(module) {
12678      if (Array.isArray(module)) {
12679        module.forEach(m => Swiper.installModule(m));
12680        return Swiper;
12681      }
12682      Swiper.installModule(module);
12683      return Swiper;
12684    }
12685  }
12686  Object.keys(prototypes).forEach(prototypeGroup => {
12687    Object.keys(prototypes[prototypeGroup]).forEach(protoMethod => {
12688      Swiper.prototype[protoMethod] = prototypes[prototypeGroup][protoMethod];
12689    });
12690  });
12691  Swiper.use([Resize, Observer]);
12692
12693  function Virtual({
12694    swiper,
12695    extendParams,
12696    on,
12697    emit
12698  }) {
12699    extendParams({
12700      virtual: {
12701        enabled: false,
12702        slides: [],
12703        cache: true,
12704        slidesPerViewAutoSlideSize: 320,
12705        renderSlide: null,
12706        renderExternal: null,
12707        renderExternalUpdate: true,
12708        addSlidesBefore: 0,
12709        addSlidesAfter: 0
12710      }
12711    });
12712    let cssModeTimeout;
12713    const document = getDocument();
12714    swiper.virtual = {
12715      cache: {},
12716      from: undefined,
12717      to: undefined,
12718      slides: [],
12719      offset: 0,
12720      slidesGrid: []
12721    };
12722    const tempDOM = document.createElement('div');
12723    function renderSlide(slide, index) {
12724      const params = swiper.params.virtual;
12725      if (params.cache && swiper.virtual.cache[index]) {
12726        return swiper.virtual.cache[index];
12727      }
12728      // eslint-disable-next-line
12729      let slideEl;
12730      if (params.renderSlide) {
12731        slideEl = params.renderSlide.call(swiper, slide, index);
12732        if (typeof slideEl === 'string') {
12733          setInnerHTML(tempDOM, slideEl);
12734          slideEl = tempDOM.children[0];
12735        }
12736      } else if (swiper.isElement) {
12737        slideEl = createElement('swiper-slide');
12738      } else {
12739        slideEl = createElement('div', swiper.params.slideClass);
12740      }
12741      slideEl.setAttribute('data-swiper-slide-index', index);
12742      if (!params.renderSlide) {
12743        setInnerHTML(slideEl, slide);
12744      }
12745      if (params.cache) {
12746        swiper.virtual.cache[index] = slideEl;
12747      }
12748      return slideEl;
12749    }
12750    function update(force, beforeInit, forceActiveIndex) {
12751      const {
12752        slidesPerGroup,
12753        centeredSlides,
12754        slidesPerView,
12755        loop: isLoop,
12756        initialSlide
12757      } = swiper.params;
12758      if (beforeInit && !isLoop && initialSlide > 0) {
12759        return;
12760      }
12761      const {
12762        addSlidesBefore,
12763        addSlidesAfter,
12764        slidesPerViewAutoSlideSize
12765      } = swiper.params.virtual;
12766      const {
12767        from: previousFrom,
12768        to: previousTo,
12769        slides,
12770        slidesGrid: previousSlidesGrid,
12771        offset: previousOffset
12772      } = swiper.virtual;
12773      if (!swiper.params.cssMode) {
12774        swiper.updateActiveIndex();
12775      }
12776      const activeIndex = typeof forceActiveIndex === 'undefined' ? swiper.activeIndex || 0 : forceActiveIndex;
12777      let offsetProp;
12778      if (swiper.rtlTranslate) offsetProp = 'right';else offsetProp = swiper.isHorizontal() ? 'left' : 'top';
12779      let slidesPerViewNumeric;
12780      if (slidesPerView === 'auto') {
12781        if (slidesPerViewAutoSlideSize) {
12782          let swiperSize = swiper.size;
12783          if (!swiperSize) {
12784            swiperSize = swiper.isHorizontal() ? swiper.el.getBoundingClientRect().width : swiper.el.getBoundingClientRect().height;
12785          }
12786          slidesPerViewNumeric = Math.max(1, Math.ceil(swiperSize / slidesPerViewAutoSlideSize));
12787        } else {
12788          slidesPerViewNumeric = 1;
12789        }
12790      } else {
12791        slidesPerViewNumeric = slidesPerView;
12792      }
12793      let slidesAfter;
12794      let slidesBefore;
12795      if (centeredSlides) {
12796        slidesAfter = Math.floor(slidesPerViewNumeric / 2) + slidesPerGroup + addSlidesAfter;
12797        slidesBefore = Math.floor(slidesPerViewNumeric / 2) + slidesPerGroup + addSlidesBefore;
12798      } else {
12799        slidesAfter = slidesPerViewNumeric + (slidesPerGroup - 1) + addSlidesAfter;
12800        slidesBefore = (isLoop ? slidesPerViewNumeric : slidesPerGroup) + addSlidesBefore;
12801      }
12802      let from = activeIndex - slidesBefore;
12803      let to = activeIndex + slidesAfter;
12804      if (!isLoop) {
12805        from = Math.max(from, 0);
12806        to = Math.min(to, slides.length - 1);
12807      }
12808      let offset = (swiper.slidesGrid[from] || 0) - (swiper.slidesGrid[0] || 0);
12809      if (isLoop && activeIndex >= slidesBefore) {
12810        from -= slidesBefore;
12811        if (!centeredSlides) offset += swiper.slidesGrid[0];
12812      } else if (isLoop && activeIndex < slidesBefore) {
12813        from = -slidesBefore;
12814        if (centeredSlides) offset += swiper.slidesGrid[0];
12815      }
12816      Object.assign(swiper.virtual, {
12817        from,
12818        to,
12819        offset,
12820        slidesGrid: swiper.slidesGrid,
12821        slidesBefore,
12822        slidesAfter
12823      });
12824      function onRendered() {
12825        swiper.updateSlides();
12826        swiper.updateProgress();
12827        swiper.updateSlidesClasses();
12828        emit('virtualUpdate');
12829      }
12830      if (previousFrom === from && previousTo === to && !force) {
12831        if (swiper.slidesGrid !== previousSlidesGrid && offset !== previousOffset) {
vendor: 1,316 bytes, lines 12832-12873
12832          swiper.slides.forEach(slideEl => {
12833            slideEl.style[offsetProp] = `${offset - Math.abs(swiper.cssOverflowAdjustment())}px`;
12834          });
12835        }
12836        swiper.updateProgress();
12837        emit('virtualUpdate');
12838        return;
12839      }
12840      if (swiper.params.virtual.renderExternal) {
12841        swiper.params.virtual.renderExternal.call(swiper, {
12842          offset,
12843          from,
12844          to,
12845          slides: function getSlides() {
12846            const slidesToRender = [];
12847            for (let i = from; i <= to; i += 1) {
12848              slidesToRender.push(slides[i]);
12849            }
12850            return slidesToRender;
12851          }()
12852        });
12853        if (swiper.params.virtual.renderExternalUpdate) {
12854          onRendered();
12855        } else {
12856          emit('virtualUpdate');
12857        }
12858        return;
12859      }
12860      const prependIndexes = [];
12861      const appendIndexes = [];
12862      const getSlideIndex = index => {
12863        let slideIndex = index;
12864        if (index < 0) {
12865          slideIndex = slides.length + index;
12866        } else if (slideIndex >= slides.length) {
12867          // eslint-disable-next-line
12868          slideIndex = slideIndex - slides.length;
12869        }
12870        return slideIndex;
12871      };
12872      if (force) {
12873        swiper.slides.filter(el => el.matches(`.${swiper.params.slideClass}
12873, swiper-slide`)).forEach(slideEl => {
12874          slideEl.remove();
12875        });
12876      } else {
12877        for (let i = previousFrom; i <= previousTo; i += 1) {
12878          if (i < from || i > to) {
12879            const slideIndex = getSlideIndex(i);
12880            swiper.slides.filter(el => el.matches(`.${swiper.params.slideClass}[data-swiper-slide-index="${slideIndex}"], swiper-slide[data-swiper-slide-index="${slideIndex}"]`)).forEach(slideEl => {
12881              slideEl.remove();
12882            });
12883          }
12884        }
12885      }
12886      const loopFrom = isLoop ? -slides.length : 0;
12887      const loopTo = isLoop ? slides.length * 2 : slides.length;
12888      for (let i = loopFrom; i < loopTo; i += 1) {
12889        if (i >= from && i <= to) {
12890          const slideIndex = getSlideIndex(i);
12891          if (typeof previousTo === 'undefined' || force) {
12892            appendIndexes.push(slideIndex);
12893          } else {
12894            if (i > previousTo) appendIndexes.push(slideIndex);
12895            if (i < previousFrom) prependIndexes.push(slideIndex);
12896          }
12897        }
12898      }
12899      appendIndexes.forEach(index => {
12900        swiper.slidesEl.append(renderSlide(slides[index], index));
12901      });
12902      if (isLoop) {
12903        for (let i = prependIndexes.length - 1; i >= 0; i -= 1) {
12904          const index = prependIndexes[i];
12905          swiper.slidesEl.prepend(renderSlide(slides[index], index));
12906        }
12907      } else {
12908        prependIndexes.sort((a, b) => b - a);
12909        prependIndexes.forEach(index => {
12910          swiper.slidesEl.prepend(renderSlide(slides[index], index));
12911        });
12912      }
12913      elementChildren(swiper.slidesEl, '.swiper-slide, swiper-slide').forEach(sli
vendor: 28,679 bytes, lines 12913-13653
12913deEl => {
12914        slideEl.style[offsetProp] = `${offset - Math.abs(swiper.cssOverflowAdjustment())}px`;
12915      });
12916      onRendered();
12917    }
12918    function appendSlide(slides) {
12919      if (typeof slides === 'object' && 'length' in slides) {
12920        for (let i = 0; i < slides.length; i += 1) {
12921          if (slides[i]) swiper.virtual.slides.push(slides[i]);
12922        }
12923      } else {
12924        swiper.virtual.slides.push(slides);
12925      }
12926      update(true);
12927    }
12928    function prependSlide(slides) {
12929      const activeIndex = swiper.activeIndex;
12930      let newActiveIndex = activeIndex + 1;
12931      let numberOfNewSlides = 1;
12932      if (Array.isArray(slides)) {
12933        for (let i = 0; i < slides.length; i += 1) {
12934          if (slides[i]) swiper.virtual.slides.unshift(slides[i]);
12935        }
12936        newActiveIndex = activeIndex + slides.length;
12937        numberOfNewSlides = slides.length;
12938      } else {
12939        swiper.virtual.slides.unshift(slides);
12940      }
12941      if (swiper.params.virtual.cache) {
12942        const cache = swiper.virtual.cache;
12943        const newCache = {};
12944        Object.keys(cache).forEach(cachedIndex => {
12945          const cachedEl = cache[cachedIndex];
12946          const cachedElIndex = cachedEl.getAttribute('data-swiper-slide-index');
12947          if (cachedElIndex) {
12948            cachedEl.setAttribute('data-swiper-slide-index', parseInt(cachedElIndex, 10) + numberOfNewSlides);
12949          }
12950          newCache[parseInt(cachedIndex, 10) + numberOfNewSlides] = cachedEl;
12951        });
12952        swiper.virtual.cache = newCache;
12953      }
12954      update(true);
12955      swiper.slideTo(newActiveIndex, 0);
12956    }
12957    function removeSlide(slidesIndexes) {
12958      if (typeof slidesIndexes === 'undefined' || slidesIndexes === null) return;
12959      let activeIndex = swiper.activeIndex;
12960      if (Array.isArray(slidesIndexes)) {
12961        for (let i = slidesIndexes.length - 1; i >= 0; i -= 1) {
12962          if (swiper.params.virtual.cache) {
12963            delete swiper.virtual.cache[slidesIndexes[i]];
12964            // shift cache indexes
12965            Object.keys(swiper.virtual.cache).forEach(key => {
12966              if (key > slidesIndexes) {
12967                swiper.virtual.cache[key - 1] = swiper.virtual.cache[key];
12968                swiper.virtual.cache[key - 1].setAttribute('data-swiper-slide-index', key - 1);
12969                delete swiper.virtual.cache[key];
12970              }
12971            });
12972          }
12973          swiper.virtual.slides.splice(slidesIndexes[i], 1);
12974          if (slidesIndexes[i] < activeIndex) activeIndex -= 1;
12975          activeIndex = Math.max(activeIndex, 0);
12976        }
12977      } else {
12978        if (swiper.params.virtual.cache) {
12979          delete swiper.virtual.cache[slidesIndexes];
12980          // shift cache indexes
12981          Object.keys(swiper.virtual.cache).forEach(key => {
12982            if (key > slidesIndexes) {
12983              swiper.virtual.cache[key - 1] = swiper.virtual.cache[key];
12984              swiper.virtual.cache[key - 1].setAttribute('data-swiper-slide-index', key - 1);
12985              delete swiper.virtual.cache[key];
12986            }
12987          });
12988        }
12989        swiper.virtual.slides.splice(slidesIndexes, 1);
12990        if (slidesIndexes < activeIndex) activeIndex -= 1;
12991        activeIndex = Math.max(activeIndex, 0);
12992      }
12993      update(true);
12994      swiper.slideTo(activeIndex, 0);
12995    }
12996    function removeAllSlides() {
12997      swiper.virtual.slides = [];
12998      if (swiper.params.virtual.cache) {
12999        swiper.virtual.cache = {};
13000      }
13001      update(true);
13002      swiper.slideTo(0, 0);
13003    }
13004    on('beforeInit', () => {
13005      if (!swiper.params.virtual.enabled) return;
13006      let domSlidesAssigned;
13007      if (typeof swiper.passedParams.virtual.slides === 'undefined') {
13008        const slides = [...swiper.slidesEl.children].filter(el => el.matches(`.${swiper.params.slideClass}, swiper-slide`));
13009        if (slides && slides.length) {
13010          swiper.virtual.slides = [...slides];
13011          domSlidesAssigned = true;
13012          slides.forEach((slideEl, slideIndex) => {
13013            slideEl.setAttribute('data-swiper-slide-index', slideIndex);
13014            swiper.virtual.cache[slideIndex] = slideEl;
13015            slideEl.remove();
13016          });
13017        }
13018      }
13019      if (!domSlidesAssigned) {
13020        swiper.virtual.slides = swiper.params.virtual.slides;
13021      }
13022      swiper.classNames.push(`${swiper.params.containerModifierClass}virtual`);
13023      swiper.params.watchSlidesProgress = true;
13024      swiper.originalParams.watchSlidesProgress = true;
13025      update(false, true);
13026    });
13027    on('setTranslate', () => {
13028      if (!swiper.params.virtual.enabled) return;
13029      if (swiper.params.cssMode && !swiper._immediateVirtual) {
13030        clearTimeout(cssModeTimeout);
13031        cssModeTimeout = setTimeout(() => {
13032          update();
13033        }, 100);
13034      } else {
13035        update();
13036      }
13037    });
13038    on('init update resize', () => {
13039      if (!swiper.params.virtual.enabled) return;
13040      if (swiper.params.cssMode) {
13041        setCSSProperty(swiper.wrapperEl, '--swiper-virtual-size', `${swiper.virtualSize}px`);
13042      }
13043    });
13044    Object.assign(swiper.virtual, {
13045      appendSlide,
13046      prependSlide,
13047      removeSlide,
13048      removeAllSlides,
13049      update
13050    });
13051  }
13052
13053  /* eslint-disable consistent-return */
13054  function Keyboard({
13055    swiper,
13056    extendParams,
13057    on,
13058    emit
13059  }) {
13060    const document = getDocument();
13061    const window = getWindow();
13062    swiper.keyboard = {
13063      enabled: false
13064    };
13065    extendParams({
13066      keyboard: {
13067        enabled: false,
13068        onlyInViewport: true,
13069        pageUpDown: true
13070      }
13071    });
13072    function handle(event) {
13073      if (!swiper.enabled) return;
13074      const {
13075        rtlTranslate: rtl
13076      } = swiper;
13077      let e = event;
13078      if (e.originalEvent) e = e.originalEvent; // jquery fix
13079      const kc = e.keyCode || e.charCode;
13080      const pageUpDown = swiper.params.keyboard.pageUpDown;
13081      const isPageUp = pageUpDown && kc === 33;
13082      const isPageDown = pageUpDown && kc === 34;
13083      const isArrowLeft = kc === 37;
13084      const isArrowRight = kc === 39;
13085      const isArrowUp = kc === 38;
13086      const isArrowDown = kc === 40;
13087      // Directions locks
13088      if (!swiper.allowSlideNext && (swiper.isHorizontal() && isArrowRight || swiper.isVertical() && isArrowDown || isPageDown)) {
13089        return false;
13090      }
13091      if (!swiper.allowSlidePrev && (swiper.isHorizontal() && isArrowLeft || swiper.isVertical() && isArrowUp || isPageUp)) {
13092        return false;
13093      }
13094      if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {
13095        return undefined;
13096      }
13097      if (document.activeElement && (document.activeElement.isContentEditable || document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea'))) {
13098        return undefined;
13099      }
13100      if (swiper.params.keyboard.onlyInViewport && (isPageUp || isPageDown || isArrowLeft || isArrowRight || isArrowUp || isArrowDown)) {
13101        let inView = false;
13102        // Check that swiper should be inside of visible area of window
13103        if (elementParents(swiper.el, `.${swiper.params.slideClass}, swiper-slide`).length > 0 && elementParents(swiper.el, `.${swiper.params.slideActiveClass}`).length === 0) {
13104          return undefined;
13105        }
13106        const el = swiper.el;
13107        const swiperWidth = el.clientWidth;
13108        const swiperHeight = el.clientHeight;
13109        const windowWidth = window.innerWidth;
13110        const windowHeight = window.innerHeight;
13111        const swiperOffset = elementOffset(el);
13112        if (rtl) swiperOffset.left -= el.scrollLeft;
13113        const swiperCoord = [[swiperOffset.left, swiperOffset.top], [swiperOffset.left + swiperWidth, swiperOffset.top], [swiperOffset.left, swiperOffset.top + swiperHeight], [swiperOffset.left + swiperWidth, swiperOffset.top + swiperHeight]];
13114        for (let i = 0; i < swiperCoord.length; i += 1) {
13115          const point = swiperCoord[i];
13116          if (point[0] >= 0 && point[0] <= windowWidth && point[1] >= 0 && point[1] <= windowHeight) {
13117            if (point[0] === 0 && point[1] === 0) continue; // eslint-disable-line
13118            inView = true;
13119          }
13120        }
13121        if (!inView) return undefined;
13122      }
13123      if (swiper.isHorizontal()) {
13124        if (isPageUp || isPageDown || isArrowLeft || isArrowRight) {
13125          if (e.preventDefault) e.preventDefault();else e.returnValue = false;
13126        }
13127        if ((isPageDown || isArrowRight) && !rtl || (isPageUp || isArrowLeft) && rtl) swiper.slideNext();
13128        if ((isPageUp || isArrowLeft) && !rtl || (isPageDown || isArrowRight) && rtl) swiper.slidePrev();
13129      } else {
13130        if (isPageUp || isPageDown || isArrowUp || isArrowDown) {
13131          if (e.preventDefault) e.preventDefault();else e.returnValue = false;
13132        }
13133        if (isPageDown || isArrowDown) swiper.slideNext();
13134        if (isPageUp || isArrowUp) swiper.slidePrev();
13135      }
13136      emit('keyPress', kc);
13137      return undefined;
13138    }
13139    function enable() {
13140      if (swiper.keyboard.enabled) return;
13141      document.addEventListener('keydown', handle);
13142      swiper.keyboard.enabled = true;
13143    }
13144    function disable() {
13145      if (!swiper.keyboard.enabled) return;
13146      document.removeEventListener('keydown', handle);
13147      swiper.keyboard.enabled = false;
13148    }
13149    on('init', () => {
13150      if (swiper.params.keyboard.enabled) {
13151        enable();
13152      }
13153    });
13154    on('destroy', () => {
13155      if (swiper.keyboard.enabled) {
13156        disable();
13157      }
13158    });
13159    Object.assign(swiper.keyboard, {
13160      enable,
13161      disable
13162    });
13163  }
13164
13165  /* eslint-disable consistent-return */
13166  function Mousewheel({
13167    swiper,
13168    extendParams,
13169    on,
13170    emit
13171  }) {
13172    const window = getWindow();
13173    extendParams({
13174      mousewheel: {
13175        enabled: false,
13176        releaseOnEdges: false,
13177        invert: false,
13178        forceToAxis: false,
13179        sensitivity: 1,
13180        eventsTarget: 'container',
13181        thresholdDelta: null,
13182        thresholdTime: null,
13183        noMousewheelClass: 'swiper-no-mousewheel'
13184      }
13185    });
13186    swiper.mousewheel = {
13187      enabled: false
13188    };
13189    let timeout;
13190    let lastScrollTime = now();
13191    let lastEventBeforeSnap;
13192    const recentWheelEvents = [];
13193    function normalize(e) {
13194      // Reasonable defaults
13195      const PIXEL_STEP = 10;
13196      const LINE_HEIGHT = 40;
13197      const PAGE_HEIGHT = 800;
13198      let sX = 0;
13199      let sY = 0; // spinX, spinY
13200      let pX = 0;
13201      let pY = 0; // pixelX, pixelY
13202
13203      // Legacy
13204      if ('detail' in e) {
13205        sY = e.detail;
13206      }
13207      if ('wheelDelta' in e) {
13208        sY = -e.wheelDelta / 120;
13209      }
13210      if ('wheelDeltaY' in e) {
13211        sY = -e.wheelDeltaY / 120;
13212      }
13213      if ('wheelDeltaX' in e) {
13214        sX = -e.wheelDeltaX / 120;
13215      }
13216
13217      // side scrolling on FF with DOMMouseScroll
13218      if ('axis' in e && e.axis === e.HORIZONTAL_AXIS) {
13219        sX = sY;
13220        sY = 0;
13221      }
13222      pX = sX * PIXEL_STEP;
13223      pY = sY * PIXEL_STEP;
13224      if ('deltaY' in e) {
13225        pY = e.deltaY;
13226      }
13227      if ('deltaX' in e) {
13228        pX = e.deltaX;
13229      }
13230      if (e.shiftKey && !pX) {
13231        // if user scrolls with shift he wants horizontal scroll
13232        pX = pY;
13233        pY = 0;
13234      }
13235      if ((pX || pY) && e.deltaMode) {
13236        if (e.deltaMode === 1) {
13237          // delta in LINE units
13238          pX *= LINE_HEIGHT;
13239          pY *= LINE_HEIGHT;
13240        } else {
13241          // delta in PAGE units
13242          pX *= PAGE_HEIGHT;
13243          pY *= PAGE_HEIGHT;
13244        }
13245      }
13246
13247      // Fall-back if spin cannot be determined
13248      if (pX && !sX) {
13249        sX = pX < 1 ? -1 : 1;
13250      }
13251      if (pY && !sY) {
13252        sY = pY < 1 ? -1 : 1;
13253      }
13254      return {
13255        spinX: sX,
13256        spinY: sY,
13257        pixelX: pX,
13258        pixelY: pY
13259      };
13260    }
13261    function handleMouseEnter() {
13262      if (!swiper.enabled) return;
13263      swiper.mouseEntered = true;
13264    }
13265    function handleMouseLeave() {
13266      if (!swiper.enabled) return;
13267      swiper.mouseEntered = false;
13268    }
13269    function animateSlider(newEvent) {
13270      if (swiper.params.mousewheel.thresholdDelta && newEvent.delta < swiper.params.mousewheel.thresholdDelta) {
13271        // Prevent if delta of wheel scroll delta is below configured threshold
13272        return false;
13273      }
13274      if (swiper.params.mousewheel.thresholdTime && now() - lastScrollTime < swiper.params.mousewheel.thresholdTime) {
13275        // Prevent if time between scrolls is below configured threshold
13276        return false;
13277      }
13278
13279      // If the movement is NOT big enough and
13280      // if the last time the user scrolled was too close to the current one (avoid continuously triggering the slider):
13281      //   Don't go any further (avoid insignificant scroll movement).
13282      if (newEvent.delta >= 6 && now() - lastScrollTime < 60) {
13283        // Return false as a default
13284        return true;
13285      }
13286      // If user is scrolling towards the end:
13287      //   If the slider hasn't hit the latest slide or
13288      //   if the slider is a loop and
13289      //   if the slider isn't moving right now:
13290      //     Go to next slide and
13291      //     emit a scroll event.
13292      // Else (the user is scrolling towards the beginning) and
13293      // if the slider hasn't hit the first slide or
13294      // if the slider is a loop and
13295      // if the slider isn't moving right now:
13296      //   Go to prev slide and
13297      //   emit a scroll event.
13298      if (newEvent.direction < 0) {
13299        if ((!swiper.isEnd || swiper.params.loop) && !swiper.animating) {
13300          swiper.slideNext();
13301          emit('scroll', newEvent.raw);
13302        }
13303      } else if ((!swiper.isBeginning || swiper.params.loop) && !swiper.animating) {
13304        swiper.slidePrev();
13305        emit('scroll', newEvent.raw);
13306      }
13307      // If you got here is because an animation has been triggered so store the current time
13308      lastScrollTime = new window.Date().getTime();
13309      // Return false as a default
13310      return false;
13311    }
13312    function releaseScroll(newEvent) {
13313      const params = swiper.params.mousewheel;
13314      if (newEvent.direction < 0) {
13315        if (swiper.isEnd && !swiper.params.loop && params.releaseOnEdges) {
13316          // Return true to animate scroll on edges
13317          return true;
13318        }
13319      } else if (swiper.isBeginning && !swiper.params.loop && params.releaseOnEdges) {
13320        // Return true to animate scroll on edges
13321        return true;
13322      }
13323      return false;
13324    }
13325    function handle(event) {
13326      let e = event;
13327      let disableParentSwiper = true;
13328      if (!swiper.enabled) return;
13329
13330      // Ignore event if the target or its parents have the swiper-no-mousewheel class
13331      if (event.target.closest(`.${swiper.params.mousewheel.noMousewheelClass}`)) return;
13332      const params = swiper.params.mousewheel;
13333      if (swiper.params.cssMode) {
13334        e.preventDefault();
13335      }
13336      let targetEl = swiper.el;
13337      if (swiper.params.mousewheel.eventsTarget !== 'container') {
13338        targetEl = document.querySelector(swiper.params.mousewheel.eventsTarget);
13339      }
13340      const targetElContainsTarget = targetEl && targetEl.contains(e.target);
13341      if (!swiper.mouseEntered && !targetElContainsTarget && !params.releaseOnEdges) return true;
13342      if (e.originalEvent) e = e.originalEvent; // jquery fix
13343      let delta = 0;
13344      const rtlFactor = swiper.rtlTranslate ? -1 : 1;
13345      const data = normalize(e);
13346      if (params.forceToAxis) {
13347        if (swiper.isHorizontal()) {
13348          if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) delta = -data.pixelX * rtlFactor;else return true;
13349        } else if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) delta = -data.pixelY;else return true;
13350      } else {
13351        delta = Math.abs(data.pixelX) > Math.abs(data.pixelY) ? -data.pixelX * rtlFactor : -data.pixelY;
13352      }
13353      if (delta === 0) return true;
13354      if (params.invert) delta = -delta;
13355
13356      // Get the scroll positions
13357      let positions = swiper.getTranslate() + delta * params.sensitivity;
13358      if (positions >= swiper.minTranslate()) positions = swiper.minTranslate();
13359      if (positions <= swiper.maxTranslate()) positions = swiper.maxTranslate();
13360
13361      // When loop is true:
13362      //     the disableParentSwiper will be true.
13363      // When loop is false:
13364      //     if the scroll positions is not on edge,
13365      //     then the disableParentSwiper will be true.
13366      //     if the scroll on edge positions,
13367      //     then the disableParentSwiper will be false.
13368      disableParentSwiper = swiper.params.loop ? true : !(positions === swiper.minTranslate() || positions === swiper.maxTranslate());
13369      if (disableParentSwiper && swiper.params.nested) e.stopPropagation();
13370      if (!swiper.params.freeMode || !swiper.params.freeMode.enabled) {
13371        // Register the new event in a variable which stores the relevant data
13372        const newEvent = {
13373          time: now(),
13374          delta: Math.abs(delta),
13375          direction: Math.sign(delta),
13376          raw: event
13377        };
13378
13379        // Keep the most recent events
13380        if (recentWheelEvents.length >= 2) {
13381          recentWheelEvents.shift(); // only store the last N events
13382        }
13383
13384        const prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined;
13385        recentWheelEvents.push(newEvent);
13386
13387        // If there is at least one previous recorded event:
13388        //   If direction has changed or
13389        //   if the scroll is quicker than the previous one:
13390        //     Animate the slider.
13391        // Else (this is the first time the wheel is moved):
13392        //     Animate the slider.
13393        if (prevEvent) {
13394          if (newEvent.direction !== prevEvent.direction || newEvent.delta > prevEvent.delta || newEvent.time > prevEvent.time + 150) {
13395            animateSlider(newEvent);
13396          }
13397        } else {
13398          animateSlider(newEvent);
13399        }
13400
13401        // If it's time to release the scroll:
13402        //   Return now so you don't hit the preventDefault.
13403        if (releaseScroll(newEvent)) {
13404          return true;
13405        }
13406      } else {
13407        // Freemode or scrollContainer:
13408
13409        // If we recently snapped after a momentum scroll, then ignore wheel events
13410        // to give time for the deceleration to finish. Stop ignoring after 500 msecs
13411        // or if it's a new scroll (larger delta or inverse sign as last event before
13412        // an end-of-momentum snap).
13413        const newEvent = {
13414          time: now(),
13415          delta: Math.abs(delta),
13416          direction: Math.sign(delta)
13417        };
13418        const ignoreWheelEvents = lastEventBeforeSnap && newEvent.time < lastEventBeforeSnap.time + 500 && newEvent.delta <= lastEventBeforeSnap.delta && newEvent.direction === lastEventBeforeSnap.direction;
13419        if (!ignoreWheelEvents) {
13420          lastEventBeforeSnap = undefined;
13421          let position = swiper.getTranslate() + delta * params.sensitivity;
13422          const wasBeginning = swiper.isBeginning;
13423          const wasEnd = swiper.isEnd;
13424          if (position >= swiper.minTranslate()) position = swiper.minTranslate();
13425          if (position <= swiper.maxTranslate()) position = swiper.maxTranslate();
13426          swiper.setTransition(0);
13427          swiper.setTranslate(position);
13428          swiper.updateProgress();
13429          swiper.updateActiveIndex();
13430          swiper.updateSlidesClasses();
13431          if (!wasBeginning && swiper.isBeginning || !wasEnd && swiper.isEnd) {
13432            swiper.updateSlidesClasses();
13433          }
13434          if (swiper.params.loop) {
13435            swiper.loopFix({
13436              direction: newEvent.direction < 0 ? 'next' : 'prev',
13437              byMousewheel: true
13438            });
13439          }
13440          if (swiper.params.freeMode.sticky) {
13441            // When wheel scrolling starts with sticky (aka snap) enabled, then detect
13442            // the end of a momentum scroll by storing recent (N=15?) wheel events.
13443            // 1. do all N events have decreasing or same (absolute value) delta?
13444            // 2. did all N events arrive in the last M (M=500?) msecs?
13445            // 3. does the earliest event have an (absolute value) delta that's
13446            //    at least P (P=1?) larger than the most recent event's delta?
13447            // 4. does the latest event have a delta that's smaller than Q (Q=6?) pixels?
13448            // If 1-4 are "yes" then we're near the end of a momentum scroll deceleration.
13449            // Snap immediately and ignore remaining wheel events in this scroll.
13450            // See comment above for "remaining wheel events in this scroll" determination.
13451            // If 1-4 aren't satisfied, then wait to snap until 500ms after the last event.
13452            clearTimeout(timeout);
13453            timeout = undefined;
13454            if (recentWheelEvents.length >= 15) {
13455              recentWheelEvents.shift(); // only store the last N events
13456            }
13457
13458            const prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined;
13459            const firstEvent = recentWheelEvents[0];
13460            recentWheelEvents.push(newEvent);
13461            if (prevEvent && (newEvent.delta > prevEvent.delta || newEvent.direction !== prevEvent.direction)) {
13462              // Increasing or reverse-sign delta means the user started scrolling again. Clear the wheel event log.
13463              recentWheelEvents.splice(0);
13464            } else if (recentWheelEvents.length >= 15 && newEvent.time - firstEvent.time < 500 && firstEvent.delta - newEvent.delta >= 1 && newEvent.delta <= 6) {
13465              // We're at the end of the deceleration of a momentum scroll, so there's no need
13466              // to wait for more events. Snap ASAP on the next tick.
13467              // Also, because there's some remaining momentum we'll bias the snap in the
13468              // direction of the ongoing scroll because it's better UX for the scroll to snap
13469              // in the same direction as the scroll instead of reversing to snap.  Therefore,
13470              // if it's already scrolled more than 20% in the current direction, keep going.
13471              const snapToThreshold = delta > 0 ? 0.8 : 0.2;
13472              lastEventBeforeSnap = newEvent;
13473              recentWheelEvents.splice(0);
13474              timeout = nextTick(() => {
13475                if (swiper.destroyed || !swiper.params) return;
13476                swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);
13477              }, 0); // no delay; move on next tick
13478            }
13479
13480            if (!timeout) {
13481              // if we get here, then we haven't detected the end of a momentum scroll, so
13482              // we'll consider a scroll "complete" when there haven't been any wheel events
13483              // for 500ms.
13484              timeout = nextTick(() => {
13485                if (swiper.destroyed || !swiper.params) return;
13486                const snapToThreshold = 0.5;
13487                lastEventBeforeSnap = newEvent;
13488                recentWheelEvents.splice(0);
13489                swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);
13490              }, 500);
13491            }
13492          }
13493
13494          // Emit event
13495          if (!ignoreWheelEvents) emit('scroll', e);
13496
13497          // Stop autoplay
13498          if (swiper.params.autoplay && swiper.params.autoplay.disableOnInteraction) swiper.autoplay.stop();
13499          // Return page scroll on edge positions
13500          if (params.releaseOnEdges && (position === swiper.minTranslate() || position === swiper.maxTranslate())) {
13501            return true;
13502          }
13503        }
13504      }
13505      if (e.preventDefault) e.preventDefault();else e.returnValue = false;
13506      return false;
13507    }
13508    function events(method) {
13509      let targetEl = swiper.el;
13510      if (swiper.params.mousewheel.eventsTarget !== 'container') {
13511        targetEl = document.querySelector(swiper.params.mousewheel.eventsTarget);
13512      }
13513      targetEl[method]('mouseenter', handleMouseEnter);
13514      targetEl[method]('mouseleave', handleMouseLeave);
13515      targetEl[method]('wheel', handle);
13516    }
13517    function enable() {
13518      if (swiper.params.cssMode) {
13519        swiper.wrapperEl.removeEventListener('wheel', handle);
13520        return true;
13521      }
13522      if (swiper.mousewheel.enabled) return false;
13523      events('addEventListener');
13524      swiper.mousewheel.enabled = true;
13525      return true;
13526    }
13527    function disable() {
13528      if (swiper.params.cssMode) {
13529        swiper.wrapperEl.addEventListener(event, handle);
13530        return true;
13531      }
13532      if (!swiper.mousewheel.enabled) return false;
13533      events('removeEventListener');
13534      swiper.mousewheel.enabled = false;
13535      return true;
13536    }
13537    on('init', () => {
13538      if (!swiper.params.mousewheel.enabled && swiper.params.cssMode) {
13539        disable();
13540      }
13541      if (swiper.params.mousewheel.enabled) enable();
13542    });
13543    on('destroy', () => {
13544      if (swiper.params.cssMode) {
13545        enable();
13546      }
13547      if (swiper.mousewheel.enabled) disable();
13548    });
13549    Object.assign(swiper.mousewheel, {
13550      enable,
13551      disable
13552    });
13553  }
13554
13555  function createElementIfNotDefined(swiper, originalParams, params, checkProps) {
13556    if (swiper.params.createElements) {
13557      Object.keys(checkProps).forEach(key => {
13558        if (!params[key] && params.auto === true) {
13559          let element = elementChildren(swiper.el, `.${checkProps[key]}`)[0];
13560          if (!element) {
13561            element = createElement('div', checkProps[key]);
13562            element.className = checkProps[key];
13563            swiper.el.append(element);
13564          }
13565          params[key] = element;
13566          originalParams[key] = element;
13567        }
13568      });
13569    }
13570    return params;
13571  }
13572
13573  const arrowSvg = `<svg class="swiper-navigation-icon" width="11" height="20" viewBox="0 0 11 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0.38296 20.0762C0.111788 19.805 0.111788 19.3654 0.38296 19.0942L9.19758 10.2796L0.38296 1.46497C0.111788 1.19379 0.111788 0.754138 0.38296 0.482966C0.654131 0.211794 1.09379 0.211794 1.36496 0.482966L10.4341 9.55214C10.8359 9.9539 10.8359 10.6053 10.4341 11.007L1.36496 20.0762C1.09379 20.3474 0.654131 20.3474 0.38296 20.0762Z" fill="currentColor"/></svg>`;
13574  function Navigation({
13575    swiper,
13576    extendParams,
13577    on,
13578    emit
13579  }) {
13580    extendParams({
13581      navigation: {
13582        nextEl: null,
13583        prevEl: null,
13584        addIcons: true,
13585        hideOnClick: false,
13586        disabledClass: 'swiper-button-disabled',
13587        hiddenClass: 'swiper-button-hidden',
13588        lockClass: 'swiper-button-lock',
13589        navigationDisabledClass: 'swiper-navigation-disabled'
13590      }
13591    });
13592    swiper.navigation = {
13593      nextEl: null,
13594      prevEl: null,
13595      arrowSvg
13596    };
13597    function getEl(el) {
13598      let res;
13599      if (el && typeof el === 'string' && swiper.isElement) {
13600        res = swiper.el.querySelector(el) || swiper.hostEl.querySelector(el);
13601        if (res) return res;
13602      }
13603      if (el) {
13604        if (typeof el === 'string') res = [...document.querySelectorAll(el)];
13605        if (swiper.params.uniqueNavElements && typeof el === 'string' && res && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {
13606          res = swiper.el.querySelector(el);
13607        } else if (res && res.length === 1) {
13608          res = res[0];
13609        }
13610      }
13611      if (el && !res) return el;
13612      // if (Array.isArray(res) && res.length === 1) res = res[0];
13613      return res;
13614    }
13615    function toggleEl(el, disabled) {
13616      const params = swiper.params.navigation;
13617      el = makeElementsArray(el);
13618      el.forEach(subEl => {
13619        if (subEl) {
13620          subEl.classList[disabled ? 'add' : 'remove'](...params.disabledClass.split(' '));
13621          if (subEl.tagName === 'BUTTON') subEl.disabled = disabled;
13622          if (swiper.params.watchOverflow && swiper.enabled) {
13623            subEl.classList[swiper.isLocked ? 'add' : 'remove'](params.lockClass);
13624          }
13625        }
13626      });
13627    }
13628    function update() {
13629      // Update Navigation Buttons
13630      const {
13631        nextEl,
13632        prevEl
13633      } = swiper.navigation;
13634      if (swiper.params.loop) {
13635        toggleEl(prevEl, false);
13636        toggleEl(nextEl, false);
13637        return;
13638      }
13639      toggleEl(prevEl, swiper.isBeginning && !swiper.params.rewind);
13640      toggleEl(nextEl, swiper.isEnd && !swiper.params.rewind);
13641    }
13642    function onPrevClick(e) {
13643      e.preventDefault();
13644      if (swiper.isBeginning && !swiper.params.loop && !swiper.params.rewind) return;
13645      swiper.slidePrev();
13646      emit('navigationPrev');
13647    }
13648    function onNextClick(e) {
13649      e.preventDefault();
13650      if (swiper.isEnd && !swiper.params.loop && !swiper.params.rewind) return;
13651      swiper.slideNext();
13652      emit('navigationNext');
13653    }
vendor: 4,164 bytes, lines 13654-13767
13654    function init() {
13655      const params = swiper.params.navigation;
13656      swiper.params.navigation = createElementIfNotDefined(swiper, swiper.originalParams.navigation, swiper.params.navigation, {
13657        nextEl: 'swiper-button-next',
13658        prevEl: 'swiper-button-prev'
13659      });
13660      if (!(params.nextEl || params.prevEl)) return;
13661      let nextEl = getEl(params.nextEl);
13662      let prevEl = getEl(params.prevEl);
13663      Object.assign(swiper.navigation, {
13664        nextEl,
13665        prevEl
13666      });
13667      nextEl = makeElementsArray(nextEl);
13668      prevEl = makeElementsArray(prevEl);
13669      const initButton = (el, dir) => {
13670        if (el) {
13671          if (params.addIcons && el.matches('.swiper-button-next,.swiper-button-prev') && !el.querySelector('svg')) {
13672            const tempEl = document.createElement('div');
13673            setInnerHTML(tempEl, arrowSvg);
13674            el.appendChild(tempEl.querySelector('svg'));
13675            tempEl.remove();
13676          }
13677          el.addEventListener('click', dir === 'next' ? onNextClick : onPrevClick);
13678        }
13679        if (!swiper.enabled && el) {
13680          el.classList.add(...params.lockClass.split(' '));
13681        }
13682      };
13683      nextEl.forEach(el => initButton(el, 'next'));
13684      prevEl.forEach(el => initButton(el, 'prev'));
13685    }
13686    function destroy() {
13687      let {
13688        nextEl,
13689        prevEl
13690      } = swiper.navigation;
13691      nextEl = makeElementsArray(nextEl);
13692      prevEl = makeElementsArray(prevEl);
13693      const destroyButton = (el, dir) => {
13694        el.removeEventListener('click', dir === 'next' ? onNextClick : onPrevClick);
13695        el.classList.remove(...swiper.params.navigation.disabledClass.split(' '));
13696      };
13697      nextEl.forEach(el => destroyButton(el, 'next'));
13698      prevEl.forEach(el => destroyButton(el, 'prev'));
13699    }
13700    on('init', () => {
13701      if (swiper.params.navigation.enabled === false) {
13702        // eslint-disable-next-line
13703        disable();
13704      } else {
13705        init();
13706        update();
13707      }
13708    });
13709    on('toEdge fromEdge lock unlock', () => {
13710      update();
13711    });
13712    on('destroy', () => {
13713      destroy();
13714    });
13715    on('enable disable', () => {
13716      let {
13717        nextEl,
13718        prevEl
13719      } = swiper.navigation;
13720      nextEl = makeElementsArray(nextEl);
13721      prevEl = makeElementsArray(prevEl);
13722      if (swiper.enabled) {
13723        update();
13724        return;
13725      }
13726      [...nextEl, ...prevEl].filter(el => !!el).forEach(el => el.classList.add(swiper.params.navigation.lockClass));
13727    });
13728    on('click', (_s, e) => {
13729      let {
13730        nextEl,
13731        prevEl
13732      } = swiper.navigation;
13733      nextEl = makeElementsArray(nextEl);
13734      prevEl = makeElementsArray(prevEl);
13735      const targetEl = e.target;
13736      let targetIsButton = prevEl.includes(targetEl) || nextEl.includes(targetEl);
13737      if (swiper.isElement && !targetIsButton) {
13738        const path = e.path || e.composedPath && e.composedPath();
13739        if (path) {
13740          targetIsButton = path.find(pathEl => nextEl.includes(pathEl) || prevEl.includes(pathEl));
13741        }
13742      }
13743      if (swiper.params.navigation.hideOnClick && !targetIsButton) {
13744        if (swiper.pagination && swiper.params.pagination && swiper.params.pagination.clickable && (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) return;
13745        let isHidden;
13746        if (nextEl.length) {
13747          isHidden = nextEl[0].classList.contains(swiper.params.navigation.hiddenClass);
13748        } else if (prevEl.length) {
13749          isHidden = prevEl[0].classList.contains(swiper.params.navigation.hiddenClass);
13750        }
13751        if (isHidden === true) {
13752          emit('navigationShow');
13753        } else {
13754          emit('navigationHide');
13755        }
13756        [...nextEl, ...prevEl].filter(el => !!el).forEach(el => el.classList.toggle(swiper.params.navigation.hiddenClass));
13757      }
13758    });
13759    const enable = () => {
13760      swiper.el.classList.remove(...swiper.params.navigation.navigationDisabledClass.split(' '));
13761      init();
13762      update();
13763    };
13764    const disable = () => {
13765      swiper.el.classList.add(...swiper.params.navigation.navigationDisabledClass.split(' '));
13766      destroy();
13767    };
vendor: 5,665 bytes, lines 13768-13919
13768    Object.assign(swiper.navigation, {
13769      enable,
13770      disable,
13771      update,
13772      init,
13773      destroy
13774    });
13775  }
13776
13777  function classesToSelector(classes = '') {
13778    return `.${classes.trim().replace(/([\.:!+\/()[\]])/g, '\\$1') // eslint-disable-line
13779  .replace(/ /g, '.')}`;
13780  }
13781
13782  function Pagination({
13783    swiper,
13784    extendParams,
13785    on,
13786    emit
13787  }) {
13788    const pfx = 'swiper-pagination';
13789    extendParams({
13790      pagination: {
13791        el: null,
13792        bulletElement: 'span',
13793        clickable: false,
13794        hideOnClick: false,
13795        renderBullet: null,
13796        renderProgressbar: null,
13797        renderFraction: null,
13798        renderCustom: null,
13799        progressbarOpposite: false,
13800        type: 'bullets',
13801        // 'bullets' or 'progressbar' or 'fraction' or 'custom'
13802        dynamicBullets: false,
13803        dynamicMainBullets: 1,
13804        formatFractionCurrent: number => number,
13805        formatFractionTotal: number => number,
13806        bulletClass: `${pfx}-bullet`,
13807        bulletActiveClass: `${pfx}-bullet-active`,
13808        modifierClass: `${pfx}-`,
13809        currentClass: `${pfx}-current`,
13810        totalClass: `${pfx}-total`,
13811        hiddenClass: `${pfx}-hidden`,
13812        progressbarFillClass: `${pfx}-progressbar-fill`,
13813        progressbarOppositeClass: `${pfx}-progressbar-opposite`,
13814        clickableClass: `${pfx}-clickable`,
13815        lockClass: `${pfx}-lock`,
13816        horizontalClass: `${pfx}-horizontal`,
13817        verticalClass: `${pfx}-vertical`,
13818        paginationDisabledClass: `${pfx}-disabled`
13819      }
13820    });
13821    swiper.pagination = {
13822      el: null,
13823      bullets: []
13824    };
13825    let bulletSize;
13826    let dynamicBulletIndex = 0;
13827    function isPaginationDisabled() {
13828      return !swiper.params.pagination.el || !swiper.pagination.el || Array.isArray(swiper.pagination.el) && swiper.pagination.el.length === 0;
13829    }
13830    function setSideBullets(bulletEl, position) {
13831      const {
13832        bulletActiveClass
13833      } = swiper.params.pagination;
13834      if (!bulletEl) return;
13835      bulletEl = bulletEl[`${position === 'prev' ? 'previous' : 'next'}ElementSibling`];
13836      if (bulletEl) {
13837        bulletEl.classList.add(`${bulletActiveClass}-${position}`);
13838        bulletEl = bulletEl[`${position === 'prev' ? 'previous' : 'next'}ElementSibling`];
13839        if (bulletEl) {
13840          bulletEl.classList.add(`${bulletActiveClass}-${position}-${position}`);
13841        }
13842      }
13843    }
13844    function getMoveDirection(prevIndex, nextIndex, length) {
13845      prevIndex = prevIndex % length;
13846      nextIndex = nextIndex % length;
13847      if (nextIndex === prevIndex + 1) {
13848        return 'next';
13849      } else if (nextIndex === prevIndex - 1) {
13850        return 'previous';
13851      }
13852      return;
13853    }
13854    function onBulletClick(e) {
13855      const bulletEl = e.target.closest(classesToSelector(swiper.params.pagination.bulletClass));
13856      if (!bulletEl) {
13857        return;
13858      }
13859      e.preventDefault();
13860      const index = elementIndex(bulletEl) * swiper.params.slidesPerGroup;
13861      if (swiper.params.loop) {
13862        if (swiper.realIndex === index) return;
13863        const moveDirection = getMoveDirection(swiper.realIndex, index, swiper.slides.length);
13864        if (moveDirection === 'next') {
13865          swiper.slideNext();
13866        } else if (moveDirection === 'previous') {
13867          swiper.slidePrev();
13868        } else {
13869          swiper.slideToLoop(index);
13870        }
13871      } else {
13872        swiper.slideTo(index);
13873      }
13874    }
13875    function update() {
13876      // Render || Update Pagination bullets/items
13877      const rtl = swiper.rtl;
13878      const params = swiper.params.pagination;
13879      if (isPaginationDisabled()) return;
13880      let el = swiper.pagination.el;
13881      el = makeElementsArray(el);
13882      // Current/Total
13883      let current;
13884      let previousIndex;
13885      const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
13886      const total = swiper.params.loop ? Math.ceil(slidesLength / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
13887      if (swiper.params.loop) {
13888        previousIndex = swiper.previousRealIndex || 0;
13889        current = swiper.params.slidesPerGroup > 1 ? Math.floor(swiper.realIndex / swiper.params.slidesPerGroup) : swiper.realIndex;
13890      } else if (typeof swiper.snapIndex !== 'undefined') {
13891        current = swiper.snapIndex;
13892        previousIndex = swiper.previousSnapIndex;
13893      } else {
13894        previousIndex = swiper.previousIndex || 0;
13895        current = swiper.activeIndex || 0;
13896      }
13897      // Types
13898      if (params.type === 'bullets' && swiper.pagination.bullets && swiper.pagination.bullets.length > 0) {
13899        const bullets = swiper.pagination.bullets;
13900        let firstIndex;
13901        let lastIndex;
13902        let midIndex;
13903        if (params.dynamicBullets) {
13904          bulletSize = elementOuterSize(bullets[0], swiper.isHorizontal() ? 'width' : 'height', true);
13905          el.forEach(subEl => {
13906            subEl.style[swiper.isHorizontal() ? 'width' : 'height'] = `${bulletSize * (params.dynamicMainBullets + 4)}px`;
13907          });
13908          if (params.dynamicMainBullets > 1 && previousIndex !== undefined) {
13909            dynamicBulletIndex += current - (previousIndex || 0);
13910            if (dynamicBulletIndex > params.dynamicMainBullets - 1) {
13911              dynamicBulletIndex = params.dynamicMainBullets - 1;
13912            } else if (dynamicBulletIndex < 0) {
13913              dynamicBulletIndex = 0;
13914            }
13915          }
13916          firstIndex = Math.max(current - dynamicBulletIndex, 0);
13917          lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
13918          midIndex = (lastIndex + firstIndex) / 2;
13919        }
vendor: 9,584 bytes, lines 13920-14137
13920        bullets.forEach(bulletEl => {
13921          const classesToRemove = [...['', '-next', '-next-next', '-prev', '-prev-prev', '-main'].map(suffix => `${params.bulletActiveClass}${suffix}`)].map(s => typeof s === 'string' && s.includes(' ') ? s.split(' ') : s).flat();
13922          bulletEl.classList.remove(...classesToRemove);
13923        });
13924        if (el.length > 1) {
13925          bullets.forEach(bullet => {
13926            const bulletIndex = elementIndex(bullet);
13927            if (bulletIndex === current) {
13928              bullet.classList.add(...params.bulletActiveClass.split(' '));
13929            } else if (swiper.isElement) {
13930              bullet.setAttribute('part', 'bullet');
13931            }
13932            if (params.dynamicBullets) {
13933              if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
13934                bullet.classList.add(...`${params.bulletActiveClass}-main`.split(' '));
13935              }
13936              if (bulletIndex === firstIndex) {
13937                setSideBullets(bullet, 'prev');
13938              }
13939              if (bulletIndex === lastIndex) {
13940                setSideBullets(bullet, 'next');
13941              }
13942            }
13943          });
13944        } else {
13945          const bullet = bullets[current];
13946          if (bullet) {
13947            bullet.classList.add(...params.bulletActiveClass.split(' '));
13948          }
13949          if (swiper.isElement) {
13950            bullets.forEach((bulletEl, bulletIndex) => {
13951              bulletEl.setAttribute('part', bulletIndex === current ? 'bullet-active' : 'bullet');
13952            });
13953          }
13954          if (params.dynamicBullets) {
13955            const firstDisplayedBullet = bullets[firstIndex];
13956            const lastDisplayedBullet = bullets[lastIndex];
13957            for (let i = firstIndex; i <= lastIndex; i += 1) {
13958              if (bullets[i]) {
13959                bullets[i].classList.add(...`${params.bulletActiveClass}-main`.split(' '));
13960              }
13961            }
13962            setSideBullets(firstDisplayedBullet, 'prev');
13963            setSideBullets(lastDisplayedBullet, 'next');
13964          }
13965        }
13966        if (params.dynamicBullets) {
13967          const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
13968          const bulletsOffset = (bulletSize * dynamicBulletsLength - bulletSize) / 2 - midIndex * bulletSize;
13969          const offsetProp = rtl ? 'right' : 'left';
13970          bullets.forEach(bullet => {
13971            bullet.style[swiper.isHorizontal() ? offsetProp : 'top'] = `${bulletsOffset}px`;
13972          });
13973        }
13974      }
13975      el.forEach((subEl, subElIndex) => {
13976        if (params.type === 'fraction') {
13977          subEl.querySelectorAll(classesToSelector(params.currentClass)).forEach(fractionEl => {
13978            fractionEl.textContent = params.formatFractionCurrent(current + 1);
13979          });
13980          subEl.querySelectorAll(classesToSelector(params.totalClass)).forEach(totalEl => {
13981            totalEl.textContent = params.formatFractionTotal(total);
13982          });
13983        }
13984        if (params.type === 'progressbar') {
13985          let progressbarDirection;
13986          if (params.progressbarOpposite) {
13987            progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
13988          } else {
13989            progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
13990          }
13991          const scale = (current + 1) / total;
13992          let scaleX = 1;
13993          let scaleY = 1;
13994          if (progressbarDirection === 'horizontal') {
13995            scaleX = scale;
13996          } else {
13997            scaleY = scale;
13998          }
13999          subEl.querySelectorAll(classesToSelector(params.progressbarFillClass)).forEach(progressEl => {
14000            progressEl.style.transform = `translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`;
14001            progressEl.style.transitionDuration = `${swiper.params.speed}ms`;
14002          });
14003        }
14004        if (params.type === 'custom' && params.renderCustom) {
14005          setInnerHTML(subEl, params.renderCustom(swiper, current + 1, total));
14006          if (subElIndex === 0) emit('paginationRender', subEl);
14007        } else {
14008          if (subElIndex === 0) emit('paginationRender', subEl);
14009          emit('paginationUpdate', subEl);
14010        }
14011        if (swiper.params.watchOverflow && swiper.enabled) {
14012          subEl.classList[swiper.isLocked ? 'add' : 'remove'](params.lockClass);
14013        }
14014      });
14015    }
14016    function render() {
14017      // Render Container
14018      const params = swiper.params.pagination;
14019      if (isPaginationDisabled()) return;
14020      const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.grid && swiper.params.grid.rows > 1 ? swiper.slides.length / Math.ceil(swiper.params.grid.rows) : swiper.slides.length;
14021      let el = swiper.pagination.el;
14022      el = makeElementsArray(el);
14023      let paginationHTML = '';
14024      if (params.type === 'bullets') {
14025        let numberOfBullets = swiper.params.loop ? Math.ceil(slidesLength / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
14026        if (swiper.params.freeMode && swiper.params.freeMode.enabled && numberOfBullets > slidesLength) {
14027          numberOfBullets = slidesLength;
14028        }
14029        for (let i = 0; i < numberOfBullets; i += 1) {
14030          if (params.renderBullet) {
14031            paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
14032          } else {
14033            // prettier-ignore
14034            paginationHTML += `<${params.bulletElement} ${swiper.isElement ? 'part="bullet"' : ''} class="${params.bulletClass}"></${params.bulletElement}>`;
14035          }
14036        }
14037      }
14038      if (params.type === 'fraction') {
14039        if (params.renderFraction) {
14040          paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
14041        } else {
14042          paginationHTML = `<span class="${params.currentClass}"></span>` + ' / ' + `<span class="${params.totalClass}"></span>`;
14043        }
14044      }
14045      if (params.type === 'progressbar') {
14046        if (params.renderProgressbar) {
14047          paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
14048        } else {
14049          paginationHTML = `<span class="${params.progressbarFillClass}"></span>`;
14050        }
14051      }
14052      swiper.pagination.bullets = [];
14053      el.forEach(subEl => {
14054        if (params.type !== 'custom') {
14055          setInnerHTML(subEl, paginationHTML || '');
14056        }
14057        if (params.type === 'bullets') {
14058          swiper.pagination.bullets.push(...subEl.querySelectorAll(classesToSelector(params.bulletClass)));
14059        }
14060      });
14061      if (params.type !== 'custom') {
14062        emit('paginationRender', el[0]);
14063      }
14064    }
14065    function init() {
14066      swiper.params.pagination = createElementIfNotDefined(swiper, swiper.originalParams.pagination, swiper.params.pagination, {
14067        el: 'swiper-pagination'
14068      });
14069      const params = swiper.params.pagination;
14070      if (!params.el) return;
14071      let el;
14072      if (typeof params.el === 'string' && swiper.isElement) {
14073        el = swiper.el.querySelector(params.el);
14074      }
14075      if (!el && typeof params.el === 'string') {
14076        el = [...document.querySelectorAll(params.el)];
14077      }
14078      if (!el) {
14079        el = params.el;
14080      }
14081      if (!el || el.length === 0) return;
14082      if (swiper.params.uniqueNavElements && typeof params.el === 'string' && Array.isArray(el) && el.length > 1) {
14083        el = [...swiper.el.querySelectorAll(params.el)];
14084        // check if it belongs to another nested Swiper
14085        if (el.length > 1) {
14086          el = el.find(subEl => {
14087            if (elementParents(subEl, '.swiper')[0] !== swiper.el) return false;
14088            return true;
14089          });
14090        }
14091      }
14092      if (Array.isArray(el) && el.length === 1) el = el[0];
14093      Object.assign(swiper.pagination, {
14094        el
14095      });
14096      el = makeElementsArray(el);
14097      el.forEach(subEl => {
14098        if (params.type === 'bullets' && params.clickable) {
14099          subEl.classList.add(...(params.clickableClass || '').split(' '));
14100        }
14101        subEl.classList.add(params.modifierClass + params.type);
14102        subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);
14103        if (params.type === 'bullets' && params.dynamicBullets) {
14104          subEl.classList.add(`${params.modifierClass}${params.type}-dynamic`);
14105          dynamicBulletIndex = 0;
14106          if (params.dynamicMainBullets < 1) {
14107            params.dynamicMainBullets = 1;
14108          }
14109        }
14110        if (params.type === 'progressbar' && params.progressbarOpposite) {
14111          subEl.classList.add(params.progressbarOppositeClass);
14112        }
14113        if (params.clickable) {
14114          subEl.addEventListener('click', onBulletClick);
14115        }
14116        if (!swiper.enabled) {
14117          subEl.classList.add(params.lockClass);
14118        }
14119      });
14120    }
14121    function destroy() {
14122      const params = swiper.params.pagination;
14123      if (isPaginationDisabled()) return;
14124      let el = swiper.pagination.el;
14125      if (el) {
14126        el = makeElementsArray(el);
14127        el.forEach(subEl => {
14128          subEl.classList.remove(params.hiddenClass);
14129          subEl.classList.remove(params.modifierClass + params.type);
14130          subEl.classList.remove(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);
14131          if (params.clickable) {
14132            subEl.classList.remove(...(params.clickableClass || '').split(' '));
14133            subEl.removeEventListener('click', onBulletClick);
14134          }
14135        });
14136      }
14137      if (swiper.pagination.bullets) swiper.pagination.bullets.forEac
vendor: 8,195 bytes, lines 14137-14396
14137h(subEl => subEl.classList.remove(...params.bulletActiveClass.split(' ')));
14138    }
14139    on('changeDirection', () => {
14140      if (!swiper.pagination || !swiper.pagination.el) return;
14141      const params = swiper.params.pagination;
14142      let {
14143        el
14144      } = swiper.pagination;
14145      el = makeElementsArray(el);
14146      el.forEach(subEl => {
14147        subEl.classList.remove(params.horizontalClass, params.verticalClass);
14148        subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);
14149      });
14150    });
14151    on('init', () => {
14152      if (swiper.params.pagination.enabled === false) {
14153        // eslint-disable-next-line
14154        disable();
14155      } else {
14156        init();
14157        render();
14158        update();
14159      }
14160    });
14161    on('activeIndexChange', () => {
14162      if (typeof swiper.snapIndex === 'undefined') {
14163        update();
14164      }
14165    });
14166    on('snapIndexChange', () => {
14167      update();
14168    });
14169    on('snapGridLengthChange', () => {
14170      render();
14171      update();
14172    });
14173    on('destroy', () => {
14174      destroy();
14175    });
14176    on('enable disable', () => {
14177      let {
14178        el
14179      } = swiper.pagination;
14180      if (el) {
14181        el = makeElementsArray(el);
14182        el.forEach(subEl => subEl.classList[swiper.enabled ? 'remove' : 'add'](swiper.params.pagination.lockClass));
14183      }
14184    });
14185    on('lock unlock', () => {
14186      update();
14187    });
14188    on('click', (_s, e) => {
14189      const targetEl = e.target;
14190      const el = makeElementsArray(swiper.pagination.el);
14191      if (swiper.params.pagination.el && swiper.params.pagination.hideOnClick && el && el.length > 0 && !targetEl.classList.contains(swiper.params.pagination.bulletClass)) {
14192        if (swiper.navigation && (swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl || swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl)) return;
14193        const isHidden = el[0].classList.contains(swiper.params.pagination.hiddenClass);
14194        if (isHidden === true) {
14195          emit('paginationShow');
14196        } else {
14197          emit('paginationHide');
14198        }
14199        el.forEach(subEl => subEl.classList.toggle(swiper.params.pagination.hiddenClass));
14200      }
14201    });
14202    const enable = () => {
14203      swiper.el.classList.remove(swiper.params.pagination.paginationDisabledClass);
14204      let {
14205        el
14206      } = swiper.pagination;
14207      if (el) {
14208        el = makeElementsArray(el);
14209        el.forEach(subEl => subEl.classList.remove(swiper.params.pagination.paginationDisabledClass));
14210      }
14211      init();
14212      render();
14213      update();
14214    };
14215    const disable = () => {
14216      swiper.el.classList.add(swiper.params.pagination.paginationDisabledClass);
14217      let {
14218        el
14219      } = swiper.pagination;
14220      if (el) {
14221        el = makeElementsArray(el);
14222        el.forEach(subEl => subEl.classList.add(swiper.params.pagination.paginationDisabledClass));
14223      }
14224      destroy();
14225    };
14226    Object.assign(swiper.pagination, {
14227      enable,
14228      disable,
14229      render,
14230      update,
14231      init,
14232      destroy
14233    });
14234  }
14235
14236  function Scrollbar({
14237    swiper,
14238    extendParams,
14239    on,
14240    emit
14241  }) {
14242    const document = getDocument();
14243    let isTouched = false;
14244    let timeout = null;
14245    let dragTimeout = null;
14246    let dragStartPos;
14247    let dragSize;
14248    let trackSize;
14249    let divider;
14250    extendParams({
14251      scrollbar: {
14252        el: null,
14253        dragSize: 'auto',
14254        hide: false,
14255        draggable: false,
14256        snapOnRelease: true,
14257        lockClass: 'swiper-scrollbar-lock',
14258        dragClass: 'swiper-scrollbar-drag',
14259        scrollbarDisabledClass: 'swiper-scrollbar-disabled',
14260        horizontalClass: `swiper-scrollbar-horizontal`,
14261        verticalClass: `swiper-scrollbar-vertical`
14262      }
14263    });
14264    swiper.scrollbar = {
14265      el: null,
14266      dragEl: null
14267    };
14268    function setTranslate() {
14269      if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
14270      const {
14271        scrollbar,
14272        rtlTranslate: rtl
14273      } = swiper;
14274      const {
14275        dragEl,
14276        el
14277      } = scrollbar;
14278      const params = swiper.params.scrollbar;
14279      const progress = swiper.params.loop ? swiper.progressLoop : swiper.progress;
14280      let newSize = dragSize;
14281      let newPos = (trackSize - dragSize) * progress;
14282      if (rtl) {
14283        newPos = -newPos;
14284        if (newPos > 0) {
14285          newSize = dragSize - newPos;
14286          newPos = 0;
14287        } else if (-newPos + dragSize > trackSize) {
14288          newSize = trackSize + newPos;
14289        }
14290      } else if (newPos < 0) {
14291        newSize = dragSize + newPos;
14292        newPos = 0;
14293      } else if (newPos + dragSize > trackSize) {
14294        newSize = trackSize - newPos;
14295      }
14296      if (swiper.isHorizontal()) {
14297        dragEl.style.transform = `translate3d(${newPos}px, 0, 0)`;
14298        dragEl.style.width = `${newSize}px`;
14299      } else {
14300        dragEl.style.transform = `translate3d(0px, ${newPos}px, 0)`;
14301        dragEl.style.height = `${newSize}px`;
14302      }
14303      if (params.hide) {
14304        clearTimeout(timeout);
14305        el.style.opacity = 1;
14306        timeout = setTimeout(() => {
14307          el.style.opacity = 0;
14308          el.style.transitionDuration = '400ms';
14309        }, 1000);
14310      }
14311    }
14312    function setTransition(duration) {
14313      if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
14314      swiper.scrollbar.dragEl.style.transitionDuration = `${duration}ms`;
14315    }
14316    function updateSize() {
14317      if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
14318      const {
14319        scrollbar
14320      } = swiper;
14321      const {
14322        dragEl,
14323        el
14324      } = scrollbar;
14325      dragEl.style.width = '';
14326      dragEl.style.height = '';
14327      trackSize = swiper.isHorizontal() ? el.offsetWidth : el.offsetHeight;
14328      divider = swiper.size / (swiper.virtualSize + swiper.params.slidesOffsetBefore - (swiper.params.centeredSlides ? swiper.snapGrid[0] : 0));
14329      if (swiper.params.scrollbar.dragSize === 'auto') {
14330        dragSize = trackSize * divider;
14331      } else {
14332        dragSize = parseInt(swiper.params.scrollbar.dragSize, 10);
14333      }
14334      if (swiper.isHorizontal()) {
14335        dragEl.style.width = `${dragSize}px`;
14336      } else {
14337        dragEl.style.height = `${dragSize}px`;
14338      }
14339      if (divider >= 1) {
14340        el.style.display = 'none';
14341      } else {
14342        el.style.display = '';
14343      }
14344      if (swiper.params.scrollbar.hide) {
14345        el.style.opacity = 0;
14346      }
14347      if (swiper.params.watchOverflow && swiper.enabled) {
14348        scrollbar.el.classList[swiper.isLocked ? 'add' : 'remove'](swiper.params.scrollbar.lockClass);
14349      }
14350    }
14351    function getPointerPosition(e) {
14352      return swiper.isHorizontal() ? e.clientX : e.clientY;
14353    }
14354    function setDragPosition(e) {
14355      const {
14356        scrollbar,
14357        rtlTranslate: rtl
14358      } = swiper;
14359      const {
14360        el
14361      } = scrollbar;
14362      let positionRatio;
14363      positionRatio = (getPointerPosition(e) - elementOffset(el)[swiper.isHorizontal() ? 'left' : 'top'] - (dragStartPos !== null ? dragStartPos : dragSize / 2)) / (trackSize - dragSize);
14364      positionRatio = Math.max(Math.min(positionRatio, 1), 0);
14365      if (rtl) {
14366        positionRatio = 1 - positionRatio;
14367      }
14368      const position = swiper.minTranslate() + (swiper.maxTranslate() - swiper.minTranslate()) * positionRatio;
14369      swiper.updateProgress(position);
14370      swiper.setTranslate(position);
14371      swiper.updateActiveIndex();
14372      swiper.updateSlidesClasses();
14373    }
14374    function onDragStart(e) {
14375      const params = swiper.params.scrollbar;
14376      const {
14377        scrollbar,
14378        wrapperEl
14379      } = swiper;
14380      const {
14381        el,
14382        dragEl
14383      } = scrollbar;
14384      isTouched = true;
14385      dragStartPos = e.target === dragEl ? getPointerPosition(e) - e.target.getBoundingClientRect()[swiper.isHorizontal() ? 'left' : 'top'] : null;
14386      e.preventDefault();
14387      e.stopPropagation();
14388      wrapperEl.style.transitionDuration = '100ms';
14389      dragEl.style.transitionDuration = '100ms';
14390      setDragPosition(e);
14391      clearTimeout(dragTimeout);
14392      el.style.transitionDuration = '0ms';
14393      if (params.hide) {
14394        el.style.opacity = 1;
14395      }
14396      if (swiper.params.cssMode) {
vendor: 6,010 bytes, lines 14397-14584
14397        swiper.wrapperEl.style['scroll-snap-type'] = 'none';
14398      }
14399      emit('scrollbarDragStart', e);
14400    }
14401    function onDragMove(e) {
14402      const {
14403        scrollbar,
14404        wrapperEl
14405      } = swiper;
14406      const {
14407        el,
14408        dragEl
14409      } = scrollbar;
14410      if (!isTouched) return;
14411      if (e.preventDefault && e.cancelable) e.preventDefault();else e.returnValue = false;
14412      setDragPosition(e);
14413      wrapperEl.style.transitionDuration = '0ms';
14414      el.style.transitionDuration = '0ms';
14415      dragEl.style.transitionDuration = '0ms';
14416      emit('scrollbarDragMove', e);
14417    }
14418    function onDragEnd(e) {
14419      const params = swiper.params.scrollbar;
14420      const {
14421        scrollbar,
14422        wrapperEl
14423      } = swiper;
14424      const {
14425        el
14426      } = scrollbar;
14427      if (!isTouched) return;
14428      isTouched = false;
14429      if (swiper.params.cssMode) {
14430        swiper.wrapperEl.style['scroll-snap-type'] = '';
14431        wrapperEl.style.transitionDuration = '';
14432      }
14433      if (params.hide) {
14434        clearTimeout(dragTimeout);
14435        dragTimeout = nextTick(() => {
14436          el.style.opacity = 0;
14437          el.style.transitionDuration = '400ms';
14438        }, 1000);
14439      }
14440      emit('scrollbarDragEnd', e);
14441      if (params.snapOnRelease) {
14442        swiper.slideToClosest();
14443      }
14444    }
14445    function events(method) {
14446      const {
14447        scrollbar,
14448        params
14449      } = swiper;
14450      const el = scrollbar.el;
14451      if (!el) return;
14452      const target = el;
14453      const activeListener = params.passiveListeners ? {
14454        passive: false,
14455        capture: false
14456      } : false;
14457      const passiveListener = params.passiveListeners ? {
14458        passive: true,
14459        capture: false
14460      } : false;
14461      if (!target) return;
14462      const eventMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';
14463      target[eventMethod]('pointerdown', onDragStart, activeListener);
14464      document[eventMethod]('pointermove', onDragMove, activeListener);
14465      document[eventMethod]('pointerup', onDragEnd, passiveListener);
14466    }
14467    function enableDraggable() {
14468      if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
14469      events('on');
14470    }
14471    function disableDraggable() {
14472      if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
14473      events('off');
14474    }
14475    function init() {
14476      const {
14477        scrollbar,
14478        el: swiperEl
14479      } = swiper;
14480      swiper.params.scrollbar = createElementIfNotDefined(swiper, swiper.originalParams.scrollbar, swiper.params.scrollbar, {
14481        el: 'swiper-scrollbar'
14482      });
14483      const params = swiper.params.scrollbar;
14484      if (!params.el) return;
14485      let el;
14486      if (typeof params.el === 'string' && swiper.isElement) {
14487        el = swiper.el.querySelector(params.el);
14488      }
14489      if (!el && typeof params.el === 'string') {
14490        el = document.querySelectorAll(params.el);
14491        if (!el.length) return;
14492      } else if (!el) {
14493        el = params.el;
14494      }
14495      if (swiper.params.uniqueNavElements && typeof params.el === 'string' && el.length > 1 && swiperEl.querySelectorAll(params.el).length === 1) {
14496        el = swiperEl.querySelector(params.el);
14497      }
14498      if (el.length > 0) el = el[0];
14499      el.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);
14500      let dragEl;
14501      if (el) {
14502        dragEl = el.querySelector(classesToSelector(swiper.params.scrollbar.dragClass));
14503        if (!dragEl) {
14504          dragEl = createElement('div', swiper.params.scrollbar.dragClass);
14505          el.append(dragEl);
14506        }
14507      }
14508      Object.assign(scrollbar, {
14509        el,
14510        dragEl
14511      });
14512      if (params.draggable) {
14513        enableDraggable();
14514      }
14515      if (el) {
14516        el.classList[swiper.enabled ? 'remove' : 'add'](...classesToTokens(swiper.params.scrollbar.lockClass));
14517      }
14518    }
14519    function destroy() {
14520      const params = swiper.params.scrollbar;
14521      const el = swiper.scrollbar.el;
14522      if (el) {
14523        el.classList.remove(...classesToTokens(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass));
14524      }
14525      disableDraggable();
14526    }
14527    on('changeDirection', () => {
14528      if (!swiper.scrollbar || !swiper.scrollbar.el) return;
14529      const params = swiper.params.scrollbar;
14530      let {
14531        el
14532      } = swiper.scrollbar;
14533      el = makeElementsArray(el);
14534      el.forEach(subEl => {
14535        subEl.classList.remove(params.horizontalClass, params.verticalClass);
14536        subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);
14537      });
14538    });
14539    on('init', () => {
14540      if (swiper.params.scrollbar.enabled === false) {
14541        // eslint-disable-next-line
14542        disable();
14543      } else {
14544        init();
14545        updateSize();
14546        setTranslate();
14547      }
14548    });
14549    on('update resize observerUpdate lock unlock changeDirection', () => {
14550      updateSize();
14551    });
14552    on('setTranslate', () => {
14553      setTranslate();
14554    });
14555    on('setTransition', (_s, duration) => {
14556      setTransition(duration);
14557    });
14558    on('enable disable', () => {
14559      const {
14560        el
14561      } = swiper.scrollbar;
14562      if (el) {
14563        el.classList[swiper.enabled ? 'remove' : 'add'](...classesToTokens(swiper.params.scrollbar.lockClass));
14564      }
14565    });
14566    on('destroy', () => {
14567      destroy();
14568    });
14569    const enable = () => {
14570      swiper.el.classList.remove(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass));
14571      if (swiper.scrollbar.el) {
14572        swiper.scrollbar.el.classList.remove(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass));
14573      }
14574      init();
14575      updateSize();
14576      setTranslate();
14577    };
14578    const disable = () => {
14579      swiper.el.classList.add(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass));
14580      if (swiper.scrollbar.el) {
14581        swiper.scrollbar.el.classList.add(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass));
14582      }
14583      destroy();
14584    };
vendor: 14,492 bytes, lines 14585-14992
14585    Object.assign(swiper.scrollbar, {
14586      enable,
14587      disable,
14588      updateSize,
14589      setTranslate,
14590      init,
14591      destroy
14592    });
14593  }
14594
14595  function Parallax({
14596    swiper,
14597    extendParams,
14598    on
14599  }) {
14600    extendParams({
14601      parallax: {
14602        enabled: false
14603      }
14604    });
14605    const elementsSelector = '[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]';
14606    const setTransform = (el, progress) => {
14607      const {
14608        rtl
14609      } = swiper;
14610      const rtlFactor = rtl ? -1 : 1;
14611      const p = el.getAttribute('data-swiper-parallax') || '0';
14612      let x = el.getAttribute('data-swiper-parallax-x');
14613      let y = el.getAttribute('data-swiper-parallax-y');
14614      const scale = el.getAttribute('data-swiper-parallax-scale');
14615      const opacity = el.getAttribute('data-swiper-parallax-opacity');
14616      const rotate = el.getAttribute('data-swiper-parallax-rotate');
14617      if (x || y) {
14618        x = x || '0';
14619        y = y || '0';
14620      } else if (swiper.isHorizontal()) {
14621        x = p;
14622        y = '0';
14623      } else {
14624        y = p;
14625        x = '0';
14626      }
14627      if (x.indexOf('%') >= 0) {
14628        x = `${parseInt(x, 10) * progress * rtlFactor}%`;
14629      } else {
14630        x = `${x * progress * rtlFactor}px`;
14631      }
14632      if (y.indexOf('%') >= 0) {
14633        y = `${parseInt(y, 10) * progress}%`;
14634      } else {
14635        y = `${y * progress}px`;
14636      }
14637      if (typeof opacity !== 'undefined' && opacity !== null) {
14638        const currentOpacity = opacity - (opacity - 1) * (1 - Math.abs(progress));
14639        el.style.opacity = currentOpacity;
14640      }
14641      let transform = `translate3d(${x}, ${y}, 0px)`;
14642      if (typeof scale !== 'undefined' && scale !== null) {
14643        const currentScale = scale - (scale - 1) * (1 - Math.abs(progress));
14644        transform += ` scale(${currentScale})`;
14645      }
14646      if (rotate && typeof rotate !== 'undefined' && rotate !== null) {
14647        const currentRotate = rotate * progress * -1;
14648        transform += ` rotate(${currentRotate}deg)`;
14649      }
14650      el.style.transform = transform;
14651    };
14652    const setTranslate = () => {
14653      const {
14654        el,
14655        slides,
14656        progress,
14657        snapGrid,
14658        isElement
14659      } = swiper;
14660      const elements = elementChildren(el, elementsSelector);
14661      if (swiper.isElement) {
14662        elements.push(...elementChildren(swiper.hostEl, elementsSelector));
14663      }
14664      elements.forEach(subEl => {
14665        setTransform(subEl, progress);
14666      });
14667      slides.forEach((slideEl, slideIndex) => {
14668        let slideProgress = slideEl.progress;
14669        if (swiper.params.slidesPerGroup > 1 && swiper.params.slidesPerView !== 'auto') {
14670          slideProgress += Math.ceil(slideIndex / 2) - progress * (snapGrid.length - 1);
14671        }
14672        slideProgress = Math.min(Math.max(slideProgress, -1), 1);
14673        slideEl.querySelectorAll(`${elementsSelector}, [data-swiper-parallax-rotate]`).forEach(subEl => {
14674          setTransform(subEl, slideProgress);
14675        });
14676      });
14677    };
14678    const setTransition = (duration = swiper.params.speed) => {
14679      const {
14680        el,
14681        hostEl
14682      } = swiper;
14683      const elements = [...el.querySelectorAll(elementsSelector)];
14684      if (swiper.isElement) {
14685        elements.push(...hostEl.querySelectorAll(elementsSelector));
14686      }
14687      elements.forEach(parallaxEl => {
14688        let parallaxDuration = parseInt(parallaxEl.getAttribute('data-swiper-parallax-duration'), 10) || duration;
14689        if (duration === 0) parallaxDuration = 0;
14690        parallaxEl.style.transitionDuration = `${parallaxDuration}ms`;
14691      });
14692    };
14693    on('beforeInit', () => {
14694      if (!swiper.params.parallax.enabled) return;
14695      swiper.params.watchSlidesProgress = true;
14696      swiper.originalParams.watchSlidesProgress = true;
14697    });
14698    on('init', () => {
14699      if (!swiper.params.parallax.enabled) return;
14700      setTranslate();
14701    });
14702    on('setTranslate', () => {
14703      if (!swiper.params.parallax.enabled) return;
14704      setTranslate();
14705    });
14706    on('setTransition', (_swiper, duration) => {
14707      if (!swiper.params.parallax.enabled) return;
14708      setTransition(duration);
14709    });
14710  }
14711
14712  function Zoom({
14713    swiper,
14714    extendParams,
14715    on,
14716    emit
14717  }) {
14718    const window = getWindow();
14719    extendParams({
14720      zoom: {
14721        enabled: false,
14722        limitToOriginalSize: false,
14723        maxRatio: 3,
14724        minRatio: 1,
14725        panOnMouseMove: false,
14726        toggle: true,
14727        containerClass: 'swiper-zoom-container',
14728        zoomedSlideClass: 'swiper-slide-zoomed'
14729      }
14730    });
14731    swiper.zoom = {
14732      enabled: false
14733    };
14734    let currentScale = 1;
14735    let isScaling = false;
14736    let isPanningWithMouse = false;
14737    let mousePanStart = {
14738      x: 0,
14739      y: 0
14740    };
14741    const mousePanSensitivity = -3; // Negative to invert pan direction
14742    let fakeGestureTouched;
14743    let fakeGestureMoved;
14744    const evCache = [];
14745    const gesture = {
14746      originX: 0,
14747      originY: 0,
14748      slideEl: undefined,
14749      slideWidth: undefined,
14750      slideHeight: undefined,
14751      imageEl: undefined,
14752      imageWrapEl: undefined,
14753      maxRatio: 3
14754    };
14755    const image = {
14756      isTouched: undefined,
14757      isMoved: undefined,
14758      currentX: undefined,
14759      currentY: undefined,
14760      minX: undefined,
14761      minY: undefined,
14762      maxX: undefined,
14763      maxY: undefined,
14764      width: undefined,
14765      height: undefined,
14766      startX: undefined,
14767      startY: undefined,
14768      touchesStart: {},
14769      touchesCurrent: {}
14770    };
14771    const velocity = {
14772      x: undefined,
14773      y: undefined,
14774      prevPositionX: undefined,
14775      prevPositionY: undefined,
14776      prevTime: undefined
14777    };
14778    let scale = 1;
14779    Object.defineProperty(swiper.zoom, 'scale', {
14780      get() {
14781        return scale;
14782      },
14783      set(value) {
14784        if (scale !== value) {
14785          const imageEl = gesture.imageEl;
14786          const slideEl = gesture.slideEl;
14787          emit('zoomChange', value, imageEl, slideEl);
14788        }
14789        scale = value;
14790      }
14791    });
14792    function getDistanceBetweenTouches() {
14793      if (evCache.length < 2) return 1;
14794      const x1 = evCache[0].pageX;
14795      const y1 = evCache[0].pageY;
14796      const x2 = evCache[1].pageX;
14797      const y2 = evCache[1].pageY;
14798      const distance = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
14799      return distance;
14800    }
14801    function getMaxRatio() {
14802      const params = swiper.params.zoom;
14803      const maxRatio = gesture.imageWrapEl.getAttribute('data-swiper-zoom') || params.maxRatio;
14804      if (params.limitToOriginalSize && gesture.imageEl && gesture.imageEl.naturalWidth) {
14805        const imageMaxRatio = gesture.imageEl.naturalWidth / gesture.imageEl.offsetWidth;
14806        return Math.min(imageMaxRatio, maxRatio);
14807      }
14808      return maxRatio;
14809    }
14810    function getScaleOrigin() {
14811      if (evCache.length < 2) return {
14812        x: null,
14813        y: null
14814      };
14815      const box = gesture.imageEl.getBoundingClientRect();
14816      return [(evCache[0].pageX + (evCache[1].pageX - evCache[0].pageX) / 2 - box.x - window.scrollX) / currentScale, (evCache[0].pageY + (evCache[1].pageY - evCache[0].pageY) / 2 - box.y - window.scrollY) / currentScale];
14817    }
14818    function getSlideSelector() {
14819      return swiper.isElement ? `swiper-slide` : `.${swiper.params.slideClass}`;
14820    }
14821    function eventWithinSlide(e) {
14822      const slideSelector = getSlideSelector();
14823      if (e.target.matches(slideSelector)) return true;
14824      if (swiper.slides.filter(slideEl => slideEl.contains(e.target)).length > 0) return true;
14825      return false;
14826    }
14827    function eventWithinZoomContainer(e) {
14828      const selector = `.${swiper.params.zoom.containerClass}`;
14829      if (e.target.matches(selector)) return true;
14830      if ([...swiper.hostEl.querySelectorAll(selector)].filter(containerEl => containerEl.contains(e.target)).length > 0) return true;
14831      return false;
14832    }
14833
14834    // Events
14835    function onGestureStart(e) {
14836      if (e.pointerType === 'mouse') {
14837        evCache.splice(0, evCache.length);
14838      }
14839      if (!eventWithinSlide(e)) return;
14840      const params = swiper.params.zoom;
14841      fakeGestureTouched = false;
14842      fakeGestureMoved = false;
14843      evCache.push(e);
14844      if (evCache.length < 2) {
14845        return;
14846      }
14847      fakeGestureTouched = true;
14848      gesture.scaleStart = getDistanceBetweenTouches();
14849      if (!gesture.slideEl) {
14850        gesture.slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`);
14851        if (!gesture.slideEl) gesture.slideEl = swiper.slides[swiper.activeIndex];
14852        let imageEl = gesture.slideEl.querySelector(`.${params.containerClass}`);
14853        if (imageEl) {
14854          imageEl = imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0];
14855        }
14856        gesture.imageEl = imageEl;
14857        if (imageEl) {
14858          gesture.imageWrapEl = elementParents(gesture.imageEl, `.${params.containerClass}`)[0];
14859        } else {
14860          gesture.imageWrapEl = undefined;
14861        }
14862        if (!gesture.imageWrapEl) {
14863          gesture.imageEl = undefined;
14864          return;
14865        }
14866        gesture.maxRatio = getMaxRatio();
14867      }
14868      if (gesture.imageEl) {
14869        const [originX, originY] = getScaleOrigin();
14870        gesture.originX = originX;
14871        gesture.originY = originY;
14872        gesture.imageEl.style.transitionDuration = '0ms';
14873      }
14874      isScaling = true;
14875    }
14876    function onGestureChange(e) {
14877      if (!eventWithinSlide(e)) return;
14878      const params = swiper.params.zoom;
14879      const zoom = swiper.zoom;
14880      const pointerIndex = evCache.findIndex(cachedEv => cachedEv.pointerId === e.pointerId);
14881      if (pointerIndex >= 0) evCache[pointerIndex] = e;
14882      if (evCache.length < 2) {
14883        return;
14884      }
14885      fakeGestureMoved = true;
14886      gesture.scaleMove = getDistanceBetweenTouches();
14887      if (!gesture.imageEl) {
14888        return;
14889      }
14890      zoom.scale = gesture.scaleMove / gesture.scaleStart * currentScale;
14891      if (zoom.scale > gesture.maxRatio) {
14892        zoom.scale = gesture.maxRatio - 1 + (zoom.scale - gesture.maxRatio + 1) ** 0.5;
14893      }
14894      if (zoom.scale < params.minRatio) {
14895        zoom.scale = params.minRatio + 1 - (params.minRatio - zoom.scale + 1) ** 0.5;
14896      }
14897      gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`;
14898    }
14899    function onGestureEnd(e) {
14900      if (!eventWithinSlide(e)) return;
14901      if (e.pointerType === 'mouse' && e.type === 'pointerout') return;
14902      const params = swiper.params.zoom;
14903      const zoom = swiper.zoom;
14904      const pointerIndex = evCache.findIndex(cachedEv => cachedEv.pointerId === e.pointerId);
14905      if (pointerIndex >= 0) evCache.splice(pointerIndex, 1);
14906      if (!fakeGestureTouched || !fakeGestureMoved) {
14907        return;
14908      }
14909      fakeGestureTouched = false;
14910      fakeGestureMoved = false;
14911      if (!gesture.imageEl) return;
14912      zoom.scale = Math.max(Math.min(zoom.scale, gesture.maxRatio), params.minRatio);
14913      gesture.imageEl.style.transitionDuration = `${swiper.params.speed}ms`;
14914      gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`;
14915      currentScale = zoom.scale;
14916      isScaling = false;
14917      if (zoom.scale > 1 && gesture.slideEl) {
14918        gesture.slideEl.classList.add(`${params.zoomedSlideClass}`);
14919      } else if (zoom.scale <= 1 && gesture.slideEl) {
14920        gesture.slideEl.classList.remove(`${params.zoomedSlideClass}`);
14921      }
14922      if (zoom.scale === 1) {
14923        gesture.originX = 0;
14924        gesture.originY = 0;
14925        gesture.slideEl = undefined;
14926      }
14927    }
14928    let allowTouchMoveTimeout;
14929    function allowTouchMove() {
14930      swiper.touchEventsData.preventTouchMoveFromPointerMove = false;
14931    }
14932    function preventTouchMove() {
14933      clearTimeout(allowTouchMoveTimeout);
14934      swiper.touchEventsData.preventTouchMoveFromPointerMove = true;
14935      allowTouchMoveTimeout = setTimeout(() => {
14936        if (swiper.destroyed) return;
14937        allowTouchMove();
14938      });
14939    }
14940    function onTouchStart(e) {
14941      const device = swiper.device;
14942      if (!gesture.imageEl) return;
14943      if (image.isTouched) return;
14944      if (device.android && e.cancelable) e.preventDefault();
14945      image.isTouched = true;
14946      const event = evCache.length > 0 ? evCache[0] : e;
14947      image.touchesStart.x = event.pageX;
14948      image.touchesStart.y = event.pageY;
14949    }
14950    function onTouchMove(e) {
14951      const isMouseEvent = e.pointerType === 'mouse';
14952      const isMousePan = isMouseEvent && swiper.params.zoom.panOnMouseMove;
14953      if (!eventWithinSlide(e) || !eventWithinZoomContainer(e)) {
14954        return;
14955      }
14956      const zoom = swiper.zoom;
14957      if (!gesture.imageEl) {
14958        return;
14959      }
14960      if (!image.isTouched || !gesture.slideEl) {
14961        if (isMousePan) onMouseMove(e);
14962        return;
14963      }
14964      if (isMousePan) {
14965        onMouseMove(e);
14966        return;
14967      }
14968      if (!image.isMoved) {
14969        image.width = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth;
14970        image.height = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight;
14971        image.startX = getTranslate(gesture.imageWrapEl, 'x') || 0;
14972        image.startY = getTranslate(gesture.imageWrapEl, 'y') || 0;
14973        gesture.slideWidth = gesture.slideEl.offsetWidth;
14974        gesture.slideHeight = gesture.slideEl.offsetHeight;
14975        gesture.imageWrapEl.style.transitionDuration = '0ms';
14976      }
14977      // Define if we need image drag
14978      const scaledWidth = image.width * zoom.scale;
14979      const scaledHeight = image.height * zoom.scale;
14980      image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0);
14981      image.maxX = -image.minX;
14982      image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0);
14983      image.maxY = -image.minY;
14984      image.touchesCurrent.x = evCache.length > 0 ? evCache[0].pageX : e.pageX;
14985      image.touchesCurrent.y = evCache.length > 0 ? evCache[0].pageY : e.pageY;
14986      const touchesDiff = Math.max(Math.abs(image.touchesCurrent.x - image.touchesStart.x), Math.abs(image.touchesCurrent.y - image.touchesStart.y));
14987      if (touchesDiff > 5) {
14988        swiper.allowClick = false;
14989      }
14990      if (!image.isMoved && !isScaling) {
14991        if (swiper.isHorizontal() && (Math.floor(image.minX) === Math.floor(image.startX) && image.touchesCurrent.x < image.touchesStart.x || Math.floor(image.maxX) === Math.floor(image.startX) && image.touchesCurrent.x > image.touchesStart.x)) {
14992          image.isTouched = false;
vendor: 4,335 bytes, lines 14993-15080
14993          allowTouchMove();
14994          return;
14995        }
14996        if (!swiper.isHorizontal() && (Math.floor(image.minY) === Math.floor(image.startY) && image.touchesCurrent.y < image.touchesStart.y || Math.floor(image.maxY) === Math.floor(image.startY) && image.touchesCurrent.y > image.touchesStart.y)) {
14997          image.isTouched = false;
14998          allowTouchMove();
14999          return;
15000        }
15001      }
15002      if (e.cancelable) {
15003        e.preventDefault();
15004      }
15005      e.stopPropagation();
15006      preventTouchMove();
15007      image.isMoved = true;
15008      const scaleRatio = (zoom.scale - currentScale) / (gesture.maxRatio - swiper.params.zoom.minRatio);
15009      const {
15010        originX,
15011        originY
15012      } = gesture;
15013      image.currentX = image.touchesCurrent.x - image.touchesStart.x + image.startX + scaleRatio * (image.width - originX * 2);
15014      image.currentY = image.touchesCurrent.y - image.touchesStart.y + image.startY + scaleRatio * (image.height - originY * 2);
15015      if (image.currentX < image.minX) {
15016        image.currentX = image.minX + 1 - (image.minX - image.currentX + 1) ** 0.8;
15017      }
15018      if (image.currentX > image.maxX) {
15019        image.currentX = image.maxX - 1 + (image.currentX - image.maxX + 1) ** 0.8;
15020      }
15021      if (image.currentY < image.minY) {
15022        image.currentY = image.minY + 1 - (image.minY - image.currentY + 1) ** 0.8;
15023      }
15024      if (image.currentY > image.maxY) {
15025        image.currentY = image.maxY - 1 + (image.currentY - image.maxY + 1) ** 0.8;
15026      }
15027
15028      // Velocity
15029      if (!velocity.prevPositionX) velocity.prevPositionX = image.touchesCurrent.x;
15030      if (!velocity.prevPositionY) velocity.prevPositionY = image.touchesCurrent.y;
15031      if (!velocity.prevTime) velocity.prevTime = Date.now();
15032      velocity.x = (image.touchesCurrent.x - velocity.prevPositionX) / (Date.now() - velocity.prevTime) / 2;
15033      velocity.y = (image.touchesCurrent.y - velocity.prevPositionY) / (Date.now() - velocity.prevTime) / 2;
15034      if (Math.abs(image.touchesCurrent.x - velocity.prevPositionX) < 2) velocity.x = 0;
15035      if (Math.abs(image.touchesCurrent.y - velocity.prevPositionY) < 2) velocity.y = 0;
15036      velocity.prevPositionX = image.touchesCurrent.x;
15037      velocity.prevPositionY = image.touchesCurrent.y;
15038      velocity.prevTime = Date.now();
15039      gesture.imageWrapEl.style.transform = `translate3d(${image.currentX}px, ${image.currentY}px,0)`;
15040    }
15041    function onTouchEnd() {
15042      const zoom = swiper.zoom;
15043      evCache.length = 0;
15044      if (!gesture.imageEl) return;
15045      if (!image.isTouched || !image.isMoved) {
15046        image.isTouched = false;
15047        image.isMoved = false;
15048        return;
15049      }
15050      image.isTouched = false;
15051      image.isMoved = false;
15052      let momentumDurationX = 300;
15053      let momentumDurationY = 300;
15054      const momentumDistanceX = velocity.x * momentumDurationX;
15055      const newPositionX = image.currentX + momentumDistanceX;
15056      const momentumDistanceY = velocity.y * momentumDurationY;
15057      const newPositionY = image.currentY + momentumDistanceY;
15058
15059      // Fix duration
15060      if (velocity.x !== 0) momentumDurationX = Math.abs((newPositionX - image.currentX) / velocity.x);
15061      if (velocity.y !== 0) momentumDurationY = Math.abs((newPositionY - image.currentY) / velocity.y);
15062      const momentumDuration = Math.max(momentumDurationX, momentumDurationY);
15063      image.currentX = newPositionX;
15064      image.currentY = newPositionY;
15065      // Define if we need image drag
15066      const scaledWidth = image.width * zoom.scale;
15067      const scaledHeight = image.height * zoom.scale;
15068      image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0);
15069      image.maxX = -image.minX;
15070      image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0);
15071      image.maxY = -image.minY;
15072      image.currentX = Math.max(Math.min(image.currentX, image.maxX), image.minX);
15073      image.currentY = Math.max(Math.min(image.currentY, image.maxY), image.minY);
15074      gesture.imageWrapEl.style.transitionDuration = `${momentumDuration}ms`;
15075      gesture.imageWrapEl.style.transform = `translate3d(${image.currentX}px, ${image.currentY}px,0)`;
15076    }
15077    function onTransitionEnd() {
15078      const zoom = swiper.zoom;
15079      if (gesture.slideEl && swiper.activeIndex !== swiper.slides.indexOf(gesture.slideEl)) {
15080        if (gesture.imageEl) {
vendor: 65,834 bytes, lines 15081-16926
15081          gesture.imageEl.style.transform = 'translate3d(0,0,0) scale(1)';
15082        }
15083        if (gesture.imageWrapEl) {
15084          gesture.imageWrapEl.style.transform = 'translate3d(0,0,0)';
15085        }
15086        gesture.slideEl.classList.remove(`${swiper.params.zoom.zoomedSlideClass}`);
15087        zoom.scale = 1;
15088        currentScale = 1;
15089        gesture.slideEl = undefined;
15090        gesture.imageEl = undefined;
15091        gesture.imageWrapEl = undefined;
15092        gesture.originX = 0;
15093        gesture.originY = 0;
15094      }
15095    }
15096    function onMouseMove(e) {
15097      // Only pan if zoomed in and mouse panning is enabled
15098      if (currentScale <= 1 || !gesture.imageWrapEl) return;
15099      if (!eventWithinSlide(e) || !eventWithinZoomContainer(e)) return;
15100      const currentTransform = window.getComputedStyle(gesture.imageWrapEl).transform;
15101      const matrix = new window.DOMMatrix(currentTransform);
15102      if (!isPanningWithMouse) {
15103        isPanningWithMouse = true;
15104        mousePanStart.x = e.clientX;
15105        mousePanStart.y = e.clientY;
15106        image.startX = matrix.e;
15107        image.startY = matrix.f;
15108        image.width = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth;
15109        image.height = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight;
15110        gesture.slideWidth = gesture.slideEl.offsetWidth;
15111        gesture.slideHeight = gesture.slideEl.offsetHeight;
15112        return;
15113      }
15114      const deltaX = (e.clientX - mousePanStart.x) * mousePanSensitivity;
15115      const deltaY = (e.clientY - mousePanStart.y) * mousePanSensitivity;
15116      const scaledWidth = image.width * currentScale;
15117      const scaledHeight = image.height * currentScale;
15118      const slideWidth = gesture.slideWidth;
15119      const slideHeight = gesture.slideHeight;
15120      const minX = Math.min(slideWidth / 2 - scaledWidth / 2, 0);
15121      const maxX = -minX;
15122      const minY = Math.min(slideHeight / 2 - scaledHeight / 2, 0);
15123      const maxY = -minY;
15124      const newX = Math.max(Math.min(image.startX + deltaX, maxX), minX);
15125      const newY = Math.max(Math.min(image.startY + deltaY, maxY), minY);
15126      gesture.imageWrapEl.style.transitionDuration = '0ms';
15127      gesture.imageWrapEl.style.transform = `translate3d(${newX}px, ${newY}px, 0)`;
15128      mousePanStart.x = e.clientX;
15129      mousePanStart.y = e.clientY;
15130      image.startX = newX;
15131      image.startY = newY;
15132      image.currentX = newX;
15133      image.currentY = newY;
15134    }
15135    function zoomIn(e) {
15136      const zoom = swiper.zoom;
15137      const params = swiper.params.zoom;
15138      if (!gesture.slideEl) {
15139        if (e && e.target) {
15140          gesture.slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`);
15141        }
15142        if (!gesture.slideEl) {
15143          if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) {
15144            gesture.slideEl = elementChildren(swiper.slidesEl, `.${swiper.params.slideActiveClass}`)[0];
15145          } else {
15146            gesture.slideEl = swiper.slides[swiper.activeIndex];
15147          }
15148        }
15149        let imageEl = gesture.slideEl.querySelector(`.${params.containerClass}`);
15150        if (imageEl) {
15151          imageEl = imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0];
15152        }
15153        gesture.imageEl = imageEl;
15154        if (imageEl) {
15155          gesture.imageWrapEl = elementParents(gesture.imageEl, `.${params.containerClass}`)[0];
15156        } else {
15157          gesture.imageWrapEl = undefined;
15158        }
15159      }
15160      if (!gesture.imageEl || !gesture.imageWrapEl) return;
15161      if (swiper.params.cssMode) {
15162        swiper.wrapperEl.style.overflow = 'hidden';
15163        swiper.wrapperEl.style.touchAction = 'none';
15164      }
15165      gesture.slideEl.classList.add(`${params.zoomedSlideClass}`);
15166      let touchX;
15167      let touchY;
15168      let offsetX;
15169      let offsetY;
15170      let diffX;
15171      let diffY;
15172      let translateX;
15173      let translateY;
15174      let imageWidth;
15175      let imageHeight;
15176      let scaledWidth;
15177      let scaledHeight;
15178      let translateMinX;
15179      let translateMinY;
15180      let translateMaxX;
15181      let translateMaxY;
15182      let slideWidth;
15183      let slideHeight;
15184      if (typeof image.touchesStart.x === 'undefined' && e) {
15185        touchX = e.pageX;
15186        touchY = e.pageY;
15187      } else {
15188        touchX = image.touchesStart.x;
15189        touchY = image.touchesStart.y;
15190      }
15191      const prevScale = currentScale;
15192      const forceZoomRatio = typeof e === 'number' ? e : null;
15193      if (currentScale === 1 && forceZoomRatio) {
15194        touchX = undefined;
15195        touchY = undefined;
15196        image.touchesStart.x = undefined;
15197        image.touchesStart.y = undefined;
15198      }
15199      const maxRatio = getMaxRatio();
15200      zoom.scale = forceZoomRatio || maxRatio;
15201      currentScale = forceZoomRatio || maxRatio;
15202      if (e && !(currentScale === 1 && forceZoomRatio)) {
15203        slideWidth = gesture.slideEl.offsetWidth;
15204        slideHeight = gesture.slideEl.offsetHeight;
15205        offsetX = elementOffset(gesture.slideEl).left + window.scrollX;
15206        offsetY = elementOffset(gesture.slideEl).top + window.scrollY;
15207        diffX = offsetX + slideWidth / 2 - touchX;
15208        diffY = offsetY + slideHeight / 2 - touchY;
15209        imageWidth = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth;
15210        imageHeight = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight;
15211        scaledWidth = imageWidth * zoom.scale;
15212        scaledHeight = imageHeight * zoom.scale;
15213        translateMinX = Math.min(slideWidth / 2 - scaledWidth / 2, 0);
15214        translateMinY = Math.min(slideHeight / 2 - scaledHeight / 2, 0);
15215        translateMaxX = -translateMinX;
15216        translateMaxY = -translateMinY;
15217        if (prevScale > 0 && forceZoomRatio && typeof image.currentX === 'number' && typeof image.currentY === 'number') {
15218          translateX = image.currentX * zoom.scale / prevScale;
15219          translateY = image.currentY * zoom.scale / prevScale;
15220        } else {
15221          translateX = diffX * zoom.scale;
15222          translateY = diffY * zoom.scale;
15223        }
15224        if (translateX < translateMinX) {
15225          translateX = translateMinX;
15226        }
15227        if (translateX > translateMaxX) {
15228          translateX = translateMaxX;
15229        }
15230        if (translateY < translateMinY) {
15231          translateY = translateMinY;
15232        }
15233        if (translateY > translateMaxY) {
15234          translateY = translateMaxY;
15235        }
15236      } else {
15237        translateX = 0;
15238        translateY = 0;
15239      }
15240      if (forceZoomRatio && zoom.scale === 1) {
15241        gesture.originX = 0;
15242        gesture.originY = 0;
15243      }
15244      image.currentX = translateX;
15245      image.currentY = translateY;
15246      gesture.imageWrapEl.style.transitionDuration = '300ms';
15247      gesture.imageWrapEl.style.transform = `translate3d(${translateX}px, ${translateY}px,0)`;
15248      gesture.imageEl.style.transitionDuration = '300ms';
15249      gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`;
15250    }
15251    function zoomOut() {
15252      const zoom = swiper.zoom;
15253      const params = swiper.params.zoom;
15254      if (!gesture.slideEl) {
15255        if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) {
15256          gesture.slideEl = elementChildren(swiper.slidesEl, `.${swiper.params.slideActiveClass}`)[0];
15257        } else {
15258          gesture.slideEl = swiper.slides[swiper.activeIndex];
15259        }
15260        let imageEl = gesture.slideEl.querySelector(`.${params.containerClass}`);
15261        if (imageEl) {
15262          imageEl = imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0];
15263        }
15264        gesture.imageEl = imageEl;
15265        if (imageEl) {
15266          gesture.imageWrapEl = elementParents(gesture.imageEl, `.${params.containerClass}`)[0];
15267        } else {
15268          gesture.imageWrapEl = undefined;
15269        }
15270      }
15271      if (!gesture.imageEl || !gesture.imageWrapEl) return;
15272      if (swiper.params.cssMode) {
15273        swiper.wrapperEl.style.overflow = '';
15274        swiper.wrapperEl.style.touchAction = '';
15275      }
15276      zoom.scale = 1;
15277      currentScale = 1;
15278      image.currentX = undefined;
15279      image.currentY = undefined;
15280      image.touchesStart.x = undefined;
15281      image.touchesStart.y = undefined;
15282      gesture.imageWrapEl.style.transitionDuration = '300ms';
15283      gesture.imageWrapEl.style.transform = 'translate3d(0,0,0)';
15284      gesture.imageEl.style.transitionDuration = '300ms';
15285      gesture.imageEl.style.transform = 'translate3d(0,0,0) scale(1)';
15286      gesture.slideEl.classList.remove(`${params.zoomedSlideClass}`);
15287      gesture.slideEl = undefined;
15288      gesture.originX = 0;
15289      gesture.originY = 0;
15290      if (swiper.params.zoom.panOnMouseMove) {
15291        mousePanStart = {
15292          x: 0,
15293          y: 0
15294        };
15295        if (isPanningWithMouse) {
15296          isPanningWithMouse = false;
15297          image.startX = 0;
15298          image.startY = 0;
15299        }
15300      }
15301    }
15302
15303    // Toggle Zoom
15304    function zoomToggle(e) {
15305      const zoom = swiper.zoom;
15306      if (zoom.scale && zoom.scale !== 1) {
15307        // Zoom Out
15308        zoomOut();
15309      } else {
15310        // Zoom In
15311        zoomIn(e);
15312      }
15313    }
15314    function getListeners() {
15315      const passiveListener = swiper.params.passiveListeners ? {
15316        passive: true,
15317        capture: false
15318      } : false;
15319      const activeListenerWithCapture = swiper.params.passiveListeners ? {
15320        passive: false,
15321        capture: true
15322      } : true;
15323      return {
15324        passiveListener,
15325        activeListenerWithCapture
15326      };
15327    }
15328
15329    // Attach/Detach Events
15330    function enable() {
15331      const zoom = swiper.zoom;
15332      if (zoom.enabled) return;
15333      zoom.enabled = true;
15334      const {
15335        passiveListener,
15336        activeListenerWithCapture
15337      } = getListeners();
15338
15339      // Scale image
15340      swiper.wrapperEl.addEventListener('pointerdown', onGestureStart, passiveListener);
15341      swiper.wrapperEl.addEventListener('pointermove', onGestureChange, activeListenerWithCapture);
15342      ['pointerup', 'pointercancel', 'pointerout'].forEach(eventName => {
15343        swiper.wrapperEl.addEventListener(eventName, onGestureEnd, passiveListener);
15344      });
15345
15346      // Move image
15347      swiper.wrapperEl.addEventListener('pointermove', onTouchMove, activeListenerWithCapture);
15348    }
15349    function disable() {
15350      const zoom = swiper.zoom;
15351      if (!zoom.enabled) return;
15352      zoom.enabled = false;
15353      const {
15354        passiveListener,
15355        activeListenerWithCapture
15356      } = getListeners();
15357
15358      // Scale image
15359      swiper.wrapperEl.removeEventListener('pointerdown', onGestureStart, passiveListener);
15360      swiper.wrapperEl.removeEventListener('pointermove', onGestureChange, activeListenerWithCapture);
15361      ['pointerup', 'pointercancel', 'pointerout'].forEach(eventName => {
15362        swiper.wrapperEl.removeEventListener(eventName, onGestureEnd, passiveListener);
15363      });
15364
15365      // Move image
15366      swiper.wrapperEl.removeEventListener('pointermove', onTouchMove, activeListenerWithCapture);
15367    }
15368    on('init', () => {
15369      if (swiper.params.zoom.enabled) {
15370        enable();
15371      }
15372    });
15373    on('destroy', () => {
15374      disable();
15375    });
15376    on('touchStart', (_s, e) => {
15377      if (!swiper.zoom.enabled) return;
15378      onTouchStart(e);
15379    });
15380    on('touchEnd', (_s, e) => {
15381      if (!swiper.zoom.enabled) return;
15382      onTouchEnd();
15383    });
15384    on('doubleTap', (_s, e) => {
15385      if (!swiper.animating && swiper.params.zoom.enabled && swiper.zoom.enabled && swiper.params.zoom.toggle) {
15386        zoomToggle(e);
15387      }
15388    });
15389    on('transitionEnd', () => {
15390      if (swiper.zoom.enabled && swiper.params.zoom.enabled) {
15391        onTransitionEnd();
15392      }
15393    });
15394    on('slideChange', () => {
15395      if (swiper.zoom.enabled && swiper.params.zoom.enabled && swiper.params.cssMode) {
15396        onTransitionEnd();
15397      }
15398    });
15399    Object.assign(swiper.zoom, {
15400      enable,
15401      disable,
15402      in: zoomIn,
15403      out: zoomOut,
15404      toggle: zoomToggle
15405    });
15406  }
15407
15408  /* eslint no-bitwise: ["error", { "allow": [">>"] }] */
15409  function Controller({
15410    swiper,
15411    extendParams,
15412    on
15413  }) {
15414    extendParams({
15415      controller: {
15416        control: undefined,
15417        inverse: false,
15418        by: 'slide' // or 'container'
15419      }
15420    });
15421
15422    swiper.controller = {
15423      control: undefined
15424    };
15425    function LinearSpline(x, y) {
15426      const binarySearch = function search() {
15427        let maxIndex;
15428        let minIndex;
15429        let guess;
15430        return (array, val) => {
15431          minIndex = -1;
15432          maxIndex = array.length;
15433          while (maxIndex - minIndex > 1) {
15434            guess = maxIndex + minIndex >> 1;
15435            if (array[guess] <= val) {
15436              minIndex = guess;
15437            } else {
15438              maxIndex = guess;
15439            }
15440          }
15441          return maxIndex;
15442        };
15443      }();
15444      this.x = x;
15445      this.y = y;
15446      this.lastIndex = x.length - 1;
15447      // Given an x value (x2), return the expected y2 value:
15448      // (x1,y1) is the known point before given value,
15449      // (x3,y3) is the known point after given value.
15450      let i1;
15451      let i3;
15452      this.interpolate = function interpolate(x2) {
15453        if (!x2) return 0;
15454
15455        // Get the indexes of x1 and x3 (the array indexes before and after given x2):
15456        i3 = binarySearch(this.x, x2);
15457        i1 = i3 - 1;
15458
15459        // We have our indexes i1 & i3, so we can calculate already:
15460        // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1
15461        return (x2 - this.x[i1]) * (this.y[i3] - this.y[i1]) / (this.x[i3] - this.x[i1]) + this.y[i1];
15462      };
15463      return this;
15464    }
15465    function getInterpolateFunction(c) {
15466      swiper.controller.spline = swiper.params.loop ? new LinearSpline(swiper.slidesGrid, c.slidesGrid) : new LinearSpline(swiper.snapGrid, c.snapGrid);
15467    }
15468    function setTranslate(_t, byController) {
15469      const controlled = swiper.controller.control;
15470      let multiplier;
15471      let controlledTranslate;
15472      const Swiper = swiper.constructor;
15473      function setControlledTranslate(c) {
15474        if (c.destroyed) return;
15475
15476        // this will create an Interpolate function based on the snapGrids
15477        // x is the Grid of the scrolled scroller and y will be the controlled scroller
15478        // it makes sense to create this only once and recall it for the interpolation
15479        // the function does a lot of value caching for performance
15480        const translate = swiper.rtlTranslate ? -swiper.translate : swiper.translate;
15481        if (swiper.params.controller.by === 'slide') {
15482          getInterpolateFunction(c);
15483          // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid
15484          // but it did not work out
15485          controlledTranslate = -swiper.controller.spline.interpolate(-translate);
15486        }
15487        if (!controlledTranslate || swiper.params.controller.by === 'container') {
15488          multiplier = (c.maxTranslate() - c.minTranslate()) / (swiper.maxTranslate() - swiper.minTranslate());
15489          if (Number.isNaN(multiplier) || !Number.isFinite(multiplier)) {
15490            multiplier = 1;
15491          }
15492          controlledTranslate = (translate - swiper.minTranslate()) * multiplier + c.minTranslate();
15493        }
15494        if (swiper.params.controller.inverse) {
15495          controlledTranslate = c.maxTranslate() - controlledTranslate;
15496        }
15497        c.updateProgress(controlledTranslate);
15498        c.setTranslate(controlledTranslate, swiper);
15499        c.updateActiveIndex();
15500        c.updateSlidesClasses();
15501      }
15502      if (Array.isArray(controlled)) {
15503        for (let i = 0; i < controlled.length; i += 1) {
15504          if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
15505            setControlledTranslate(controlled[i]);
15506          }
15507        }
15508      } else if (controlled instanceof Swiper && byController !== controlled) {
15509        setControlledTranslate(controlled);
15510      }
15511    }
15512    function setTransition(duration, byController) {
15513      const Swiper = swiper.constructor;
15514      const controlled = swiper.controller.control;
15515      let i;
15516      function setControlledTransition(c) {
15517        if (c.destroyed) return;
15518        c.setTransition(duration, swiper);
15519        if (duration !== 0) {
15520          c.transitionStart();
15521          if (c.params.autoHeight) {
15522            nextTick(() => {
15523              c.updateAutoHeight();
15524            });
15525          }
15526          elementTransitionEnd(c.wrapperEl, () => {
15527            if (!controlled) return;
15528            c.transitionEnd();
15529          });
15530        }
15531      }
15532      if (Array.isArray(controlled)) {
15533        for (i = 0; i < controlled.length; i += 1) {
15534          if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
15535            setControlledTransition(controlled[i]);
15536          }
15537        }
15538      } else if (controlled instanceof Swiper && byController !== controlled) {
15539        setControlledTransition(controlled);
15540      }
15541    }
15542    function removeSpline() {
15543      if (!swiper.controller.control) return;
15544      if (swiper.controller.spline) {
15545        swiper.controller.spline = undefined;
15546        delete swiper.controller.spline;
15547      }
15548    }
15549    on('beforeInit', () => {
15550      if (typeof window !== 'undefined' && (
15551      // eslint-disable-line
15552      typeof swiper.params.controller.control === 'string' || swiper.params.controller.control instanceof HTMLElement)) {
15553        const controlElements = typeof swiper.params.controller.control === 'string' ? [...document.querySelectorAll(swiper.params.controller.control)] : [swiper.params.controller.control];
15554        controlElements.forEach(controlElement => {
15555          if (!swiper.controller.control) swiper.controller.control = [];
15556          if (controlElement && controlElement.swiper) {
15557            swiper.controller.control.push(controlElement.swiper);
15558          } else if (controlElement) {
15559            const eventName = `${swiper.params.eventsPrefix}init`;
15560            const onControllerSwiper = e => {
15561              swiper.controller.control.push(e.detail[0]);
15562              swiper.update();
15563              controlElement.removeEventListener(eventName, onControllerSwiper);
15564            };
15565            controlElement.addEventListener(eventName, onControllerSwiper);
15566          }
15567        });
15568        return;
15569      }
15570      swiper.controller.control = swiper.params.controller.control;
15571    });
15572    on('update', () => {
15573      removeSpline();
15574    });
15575    on('resize', () => {
15576      removeSpline();
15577    });
15578    on('observerUpdate', () => {
15579      removeSpline();
15580    });
15581    on('setTranslate', (_s, translate, byController) => {
15582      if (!swiper.controller.control || swiper.controller.control.destroyed) return;
15583      swiper.controller.setTranslate(translate, byController);
15584    });
15585    on('setTransition', (_s, duration, byController) => {
15586      if (!swiper.controller.control || swiper.controller.control.destroyed) return;
15587      swiper.controller.setTransition(duration, byController);
15588    });
15589    Object.assign(swiper.controller, {
15590      setTranslate,
15591      setTransition
15592    });
15593  }
15594
15595  function A11y({
15596    swiper,
15597    extendParams,
15598    on
15599  }) {
15600    extendParams({
15601      a11y: {
15602        enabled: true,
15603        notificationClass: 'swiper-notification',
15604        prevSlideMessage: 'Previous slide',
15605        nextSlideMessage: 'Next slide',
15606        firstSlideMessage: 'This is the first slide',
15607        lastSlideMessage: 'This is the last slide',
15608        paginationBulletMessage: 'Go to slide {{index}}',
15609        slideLabelMessage: '{{index}} / {{slidesLength}}',
15610        containerMessage: null,
15611        containerRoleDescriptionMessage: null,
15612        containerRole: null,
15613        itemRoleDescriptionMessage: null,
15614        slideRole: 'group',
15615        id: null,
15616        scrollOnFocus: true,
15617        wrapperLiveRegion: true
15618      }
15619    });
15620    swiper.a11y = {
15621      clicked: false
15622    };
15623    let liveRegion = null;
15624    let preventFocusHandler;
15625    let focusTargetSlideEl;
15626    let visibilityChangedTimestamp = new Date().getTime();
15627    function notify(message) {
15628      const notification = liveRegion;
15629      if (notification.length === 0) return;
15630      setInnerHTML(notification, message);
15631    }
15632    function getRandomNumber(size = 16) {
15633      const randomChar = () => Math.round(16 * Math.random()).toString(16);
15634      return 'x'.repeat(size).replace(/x/g, randomChar);
15635    }
15636    function makeElFocusable(el) {
15637      el = makeElementsArray(el);
15638      el.forEach(subEl => {
15639        subEl.setAttribute('tabIndex', '0');
15640      });
15641    }
15642    function makeElNotFocusable(el) {
15643      el = makeElementsArray(el);
15644      el.forEach(subEl => {
15645        subEl.setAttribute('tabIndex', '-1');
15646      });
15647    }
15648    function addElRole(el, role) {
15649      el = makeElementsArray(el);
15650      el.forEach(subEl => {
15651        subEl.setAttribute('role', role);
15652      });
15653    }
15654    function addElRoleDescription(el, description) {
15655      el = makeElementsArray(el);
15656      el.forEach(subEl => {
15657        subEl.setAttribute('aria-roledescription', description);
15658      });
15659    }
15660    function addElControls(el, controls) {
15661      el = makeElementsArray(el);
15662      el.forEach(subEl => {
15663        subEl.setAttribute('aria-controls', controls);
15664      });
15665    }
15666    function addElLabel(el, label) {
15667      el = makeElementsArray(el);
15668      el.forEach(subEl => {
15669        subEl.setAttribute('aria-label', label);
15670      });
15671    }
15672    function addElId(el, id) {
15673      el = makeElementsArray(el);
15674      el.forEach(subEl => {
15675        subEl.setAttribute('id', id);
15676      });
15677    }
15678    function addElLive(el, live) {
15679      el = makeElementsArray(el);
15680      el.forEach(subEl => {
15681        subEl.setAttribute('aria-live', live);
15682      });
15683    }
15684    function disableEl(el) {
15685      el = makeElementsArray(el);
15686      el.forEach(subEl => {
15687        subEl.setAttribute('aria-disabled', true);
15688      });
15689    }
15690    function enableEl(el) {
15691      el = makeElementsArray(el);
15692      el.forEach(subEl => {
15693        subEl.setAttribute('aria-disabled', false);
15694      });
15695    }
15696    function onEnterOrSpaceKey(e) {
15697      if (e.keyCode !== 13 && e.keyCode !== 32) return;
15698      const params = swiper.params.a11y;
15699      const targetEl = e.target;
15700      if (swiper.pagination && swiper.pagination.el && (targetEl === swiper.pagination.el || swiper.pagination.el.contains(e.target))) {
15701        if (!e.target.matches(classesToSelector(swiper.params.pagination.bulletClass))) return;
15702      }
15703      if (swiper.navigation && swiper.navigation.prevEl && swiper.navigation.nextEl) {
15704        const prevEls = makeElementsArray(swiper.navigation.prevEl);
15705        const nextEls = makeElementsArray(swiper.navigation.nextEl);
15706        if (nextEls.includes(targetEl)) {
15707          if (!(swiper.isEnd && !swiper.params.loop)) {
15708            swiper.slideNext();
15709          }
15710          if (swiper.isEnd) {
15711            notify(params.lastSlideMessage);
15712          } else {
15713            notify(params.nextSlideMessage);
15714          }
15715        }
15716        if (prevEls.includes(targetEl)) {
15717          if (!(swiper.isBeginning && !swiper.params.loop)) {
15718            swiper.slidePrev();
15719          }
15720          if (swiper.isBeginning) {
15721            notify(params.firstSlideMessage);
15722          } else {
15723            notify(params.prevSlideMessage);
15724          }
15725        }
15726      }
15727      if (swiper.pagination && targetEl.matches(classesToSelector(swiper.params.pagination.bulletClass))) {
15728        targetEl.click();
15729      }
15730    }
15731    function updateNavigation() {
15732      if (swiper.params.loop || swiper.params.rewind || !swiper.navigation) return;
15733      const {
15734        nextEl,
15735        prevEl
15736      } = swiper.navigation;
15737      if (prevEl) {
15738        if (swiper.isBeginning) {
15739          disableEl(prevEl);
15740          makeElNotFocusable(prevEl);
15741        } else {
15742          enableEl(prevEl);
15743          makeElFocusable(prevEl);
15744        }
15745      }
15746      if (nextEl) {
15747        if (swiper.isEnd) {
15748          disableEl(nextEl);
15749          makeElNotFocusable(nextEl);
15750        } else {
15751          enableEl(nextEl);
15752          makeElFocusable(nextEl);
15753        }
15754      }
15755    }
15756    function hasPagination() {
15757      return swiper.pagination && swiper.pagination.bullets && swiper.pagination.bullets.length;
15758    }
15759    function hasClickablePagination() {
15760      return hasPagination() && swiper.params.pagination.clickable;
15761    }
15762    function updatePagination() {
15763      const params = swiper.params.a11y;
15764      if (!hasPagination()) return;
15765      swiper.pagination.bullets.forEach(bulletEl => {
15766        if (swiper.params.pagination.clickable) {
15767          makeElFocusable(bulletEl);
15768          if (!swiper.params.pagination.renderBullet) {
15769            addElRole(bulletEl, 'button');
15770            addElLabel(bulletEl, params.paginationBulletMessage.replace(/\{\{index\}\}/, elementIndex(bulletEl) + 1));
15771          }
15772        }
15773        if (bulletEl.matches(classesToSelector(swiper.params.pagination.bulletActiveClass))) {
15774          bulletEl.setAttribute('aria-current', 'true');
15775        } else {
15776          bulletEl.removeAttribute('aria-current');
15777        }
15778      });
15779    }
15780    const initNavEl = (el, wrapperId, message) => {
15781      makeElFocusable(el);
15782      if (el.tagName !== 'BUTTON') {
15783        addElRole(el, 'button');
15784        el.addEventListener('keydown', onEnterOrSpaceKey);
15785      }
15786      addElLabel(el, message);
15787      addElControls(el, wrapperId);
15788    };
15789    const handlePointerDown = e => {
15790      if (focusTargetSlideEl && focusTargetSlideEl !== e.target && !focusTargetSlideEl.contains(e.target)) {
15791        preventFocusHandler = true;
15792      }
15793      swiper.a11y.clicked = true;
15794    };
15795    const handlePointerUp = () => {
15796      preventFocusHandler = false;
15797      requestAnimationFrame(() => {
15798        requestAnimationFrame(() => {
15799          if (!swiper.destroyed) {
15800            swiper.a11y.clicked = false;
15801          }
15802        });
15803      });
15804    };
15805    const onVisibilityChange = e => {
15806      visibilityChangedTimestamp = new Date().getTime();
15807    };
15808    const handleFocus = e => {
15809      if (swiper.a11y.clicked || !swiper.params.a11y.scrollOnFocus) return;
15810      if (new Date().getTime() - visibilityChangedTimestamp < 100) return;
15811      const slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`);
15812      if (!slideEl || !swiper.slides.includes(slideEl)) return;
15813      focusTargetSlideEl = slideEl;
15814      const isActive = swiper.slides.indexOf(slideEl) === swiper.activeIndex;
15815      const isVisible = swiper.params.watchSlidesProgress && swiper.visibleSlides && swiper.visibleSlides.includes(slideEl);
15816      if (isActive || isVisible) return;
15817      if (e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents) return;
15818      if (swiper.isHorizontal()) {
15819        swiper.el.scrollLeft = 0;
15820      } else {
15821        swiper.el.scrollTop = 0;
15822      }
15823      requestAnimationFrame(() => {
15824        if (preventFocusHandler) return;
15825        if (swiper.params.loop) {
15826          swiper.slideToLoop(swiper.getSlideIndexWhenGrid(parseInt(slideEl.getAttribute('data-swiper-slide-index'))), 0);
15827        } else {
15828          swiper.slideTo(swiper.getSlideIndexWhenGrid(swiper.slides.indexOf(slideEl)), 0);
15829        }
15830        preventFocusHandler = false;
15831      });
15832    };
15833    const initSlides = () => {
15834      const params = swiper.params.a11y;
15835      if (params.itemRoleDescriptionMessage) {
15836        addElRoleDescription(swiper.slides, params.itemRoleDescriptionMessage);
15837      }
15838      if (params.slideRole) {
15839        addElRole(swiper.slides, params.slideRole);
15840      }
15841      const slidesLength = swiper.slides.length;
15842      if (params.slideLabelMessage) {
15843        swiper.slides.forEach((slideEl, index) => {
15844          const slideIndex = swiper.params.loop ? parseInt(slideEl.getAttribute('data-swiper-slide-index'), 10) : index;
15845          const ariaLabelMessage = params.slideLabelMessage.replace(/\{\{index\}\}/, slideIndex + 1).replace(/\{\{slidesLength\}\}/, slidesLength);
15846          addElLabel(slideEl, ariaLabelMessage);
15847        });
15848      }
15849    };
15850    const init = () => {
15851      const params = swiper.params.a11y;
15852      swiper.el.append(liveRegion);
15853
15854      // Container
15855      const containerEl = swiper.el;
15856      if (params.containerRoleDescriptionMessage) {
15857        addElRoleDescription(containerEl, params.containerRoleDescriptionMessage);
15858      }
15859      if (params.containerMessage) {
15860        addElLabel(containerEl, params.containerMessage);
15861      }
15862      if (params.containerRole) {
15863        addElRole(containerEl, params.containerRole);
15864      }
15865
15866      // Wrapper
15867      const wrapperEl = swiper.wrapperEl;
15868      const wrapperId = params.id || wrapperEl.getAttribute('id') || `swiper-wrapper-${getRandomNumber(16)}`;
15869      addElId(wrapperEl, wrapperId);
15870      if (params.wrapperLiveRegion) {
15871        const live = swiper.params.autoplay && swiper.params.autoplay.enabled ? 'off' : 'polite';
15872        addElLive(wrapperEl, live);
15873      }
15874
15875      // Slide
15876      initSlides();
15877
15878      // Navigation
15879      let {
15880        nextEl,
15881        prevEl
15882      } = swiper.navigation ? swiper.navigation : {};
15883      nextEl = makeElementsArray(nextEl);
15884      prevEl = makeElementsArray(prevEl);
15885      if (nextEl) {
15886        nextEl.forEach(el => initNavEl(el, wrapperId, params.nextSlideMessage));
15887      }
15888      if (prevEl) {
15889        prevEl.forEach(el => initNavEl(el, wrapperId, params.prevSlideMessage));
15890      }
15891
15892      // Pagination
15893      if (hasClickablePagination()) {
15894        const paginationEl = makeElementsArray(swiper.pagination.el);
15895        paginationEl.forEach(el => {
15896          el.addEventListener('keydown', onEnterOrSpaceKey);
15897        });
15898      }
15899
15900      // Tab focus
15901      const document = getDocument();
15902      document.addEventListener('visibilitychange', onVisibilityChange);
15903      swiper.el.addEventListener('focus', handleFocus, true);
15904      swiper.el.addEventListener('focus', handleFocus, true);
15905      swiper.el.addEventListener('pointerdown', handlePointerDown, true);
15906      swiper.el.addEventListener('pointerup', handlePointerUp, true);
15907    };
15908    function destroy() {
15909      if (liveRegion) liveRegion.remove();
15910      let {
15911        nextEl,
15912        prevEl
15913      } = swiper.navigation ? swiper.navigation : {};
15914      nextEl = makeElementsArray(nextEl);
15915      prevEl = makeElementsArray(prevEl);
15916      if (nextEl) {
15917        nextEl.forEach(el => el.removeEventListener('keydown', onEnterOrSpaceKey));
15918      }
15919      if (prevEl) {
15920        prevEl.forEach(el => el.removeEventListener('keydown', onEnterOrSpaceKey));
15921      }
15922
15923      // Pagination
15924      if (hasClickablePagination()) {
15925        const paginationEl = makeElementsArray(swiper.pagination.el);
15926        paginationEl.forEach(el => {
15927          el.removeEventListener('keydown', onEnterOrSpaceKey);
15928        });
15929      }
15930      const document = getDocument();
15931      document.removeEventListener('visibilitychange', onVisibilityChange);
15932      // Tab focus
15933      if (swiper.el && typeof swiper.el !== 'string') {
15934        swiper.el.removeEventListener('focus', handleFocus, true);
15935        swiper.el.removeEventListener('pointerdown', handlePointerDown, true);
15936        swiper.el.removeEventListener('pointerup', handlePointerUp, true);
15937      }
15938    }
15939    on('beforeInit', () => {
15940      liveRegion = createElement('span', swiper.params.a11y.notificationClass);
15941      liveRegion.setAttribute('aria-live', 'assertive');
15942      liveRegion.setAttribute('aria-atomic', 'true');
15943    });
15944    on('afterInit', () => {
15945      if (!swiper.params.a11y.enabled) return;
15946      init();
15947    });
15948    on('slidesLengthChange snapGridLengthChange slidesGridLengthChange', () => {
15949      if (!swiper.params.a11y.enabled) return;
15950      initSlides();
15951    });
15952    on('fromEdge toEdge afterInit lock unlock', () => {
15953      if (!swiper.params.a11y.enabled) return;
15954      updateNavigation();
15955    });
15956    on('paginationUpdate', () => {
15957      if (!swiper.params.a11y.enabled) return;
15958      updatePagination();
15959    });
15960    on('destroy', () => {
15961      if (!swiper.params.a11y.enabled) return;
15962      destroy();
15963    });
15964  }
15965
15966  function History({
15967    swiper,
15968    extendParams,
15969    on
15970  }) {
15971    extendParams({
15972      history: {
15973        enabled: false,
15974        root: '',
15975        replaceState: false,
15976        key: 'slides',
15977        keepQuery: false
15978      }
15979    });
15980    let initialized = false;
15981    let paths = {};
15982    const slugify = text => {
15983      return text.toString().replace(/\s+/g, '-').replace(/[^\w-]+/g, '').replace(/--+/g, '-').replace(/^-+/, '').replace(/-+$/, '');
15984    };
15985    const getPathValues = urlOverride => {
15986      const window = getWindow();
15987      let location;
15988      if (urlOverride) {
15989        location = new URL(urlOverride);
15990      } else {
15991        location = window.location;
15992      }
15993      const pathArray = location.pathname.slice(1).split('/').filter(part => part !== '');
15994      const total = pathArray.length;
15995      const key = pathArray[total - 2];
15996      const value = pathArray[total - 1];
15997      return {
15998        key,
15999        value
16000      };
16001    };
16002    const setHistory = (key, index) => {
16003      const window = getWindow();
16004      if (!initialized || !swiper.params.history.enabled) return;
16005      let location;
16006      if (swiper.params.url) {
16007        location = new URL(swiper.params.url);
16008      } else {
16009        location = window.location;
16010      }
16011      const slide = swiper.virtual && swiper.params.virtual.enabled ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${index}"]`) : swiper.slides[index];
16012      let value = slugify(slide.getAttribute('data-history'));
16013      if (swiper.params.history.root.length > 0) {
16014        let root = swiper.params.history.root;
16015        if (root[root.length - 1] === '/') root = root.slice(0, root.length - 1);
16016        value = `${root}/${key ? `${key}/` : ''}${value}`;
16017      } else if (!location.pathname.includes(key)) {
16018        value = `${key ? `${key}/` : ''}${value}`;
16019      }
16020      if (swiper.params.history.keepQuery) {
16021        value += location.search;
16022      }
16023      const currentState = window.history.state;
16024      if (currentState && currentState.value === value) {
16025        return;
16026      }
16027      if (swiper.params.history.replaceState) {
16028        window.history.replaceState({
16029          value
16030        }, null, value);
16031      } else {
16032        window.history.pushState({
16033          value
16034        }, null, value);
16035      }
16036    };
16037    const scrollToSlide = (speed, value, runCallbacks) => {
16038      if (value) {
16039        for (let i = 0, length = swiper.slides.length; i < length; i += 1) {
16040          const slide = swiper.slides[i];
16041          const slideHistory = slugify(slide.getAttribute('data-history'));
16042          if (slideHistory === value) {
16043            const index = swiper.getSlideIndex(slide);
16044            swiper.slideTo(index, speed, runCallbacks);
16045          }
16046        }
16047      } else {
16048        swiper.slideTo(0, speed, runCallbacks);
16049      }
16050    };
16051    const setHistoryPopState = () => {
16052      paths = getPathValues(swiper.params.url);
16053      scrollToSlide(swiper.params.speed, paths.value, false);
16054    };
16055    const init = () => {
16056      const window = getWindow();
16057      if (!swiper.params.history) return;
16058      if (!window.history || !window.history.pushState) {
16059        swiper.params.history.enabled = false;
16060        swiper.params.hashNavigation.enabled = true;
16061        return;
16062      }
16063      initialized = true;
16064      paths = getPathValues(swiper.params.url);
16065      if (!paths.key && !paths.value) {
16066        if (!swiper.params.history.replaceState) {
16067          window.addEventListener('popstate', setHistoryPopState);
16068        }
16069        return;
16070      }
16071      scrollToSlide(0, paths.value, swiper.params.runCallbacksOnInit);
16072      if (!swiper.params.history.replaceState) {
16073        window.addEventListener('popstate', setHistoryPopState);
16074      }
16075    };
16076    const destroy = () => {
16077      const window = getWindow();
16078      if (!swiper.params.history.replaceState) {
16079        window.removeEventListener('popstate', setHistoryPopState);
16080      }
16081    };
16082    on('init', () => {
16083      if (swiper.params.history.enabled) {
16084        init();
16085      }
16086    });
16087    on('destroy', () => {
16088      if (swiper.params.history.enabled) {
16089        destroy();
16090      }
16091    });
16092    on('transitionEnd _freeModeNoMomentumRelease', () => {
16093      if (initialized) {
16094        setHistory(swiper.params.history.key, swiper.activeIndex);
16095      }
16096    });
16097    on('slideChange', () => {
16098      if (initialized && swiper.params.cssMode) {
16099        setHistory(swiper.params.history.key, swiper.activeIndex);
16100      }
16101    });
16102  }
16103
16104  function HashNavigation({
16105    swiper,
16106    extendParams,
16107    emit,
16108    on
16109  }) {
16110    let initialized = false;
16111    const document = getDocument();
16112    const window = getWindow();
16113    extendParams({
16114      hashNavigation: {
16115        enabled: false,
16116        replaceState: false,
16117        watchState: false,
16118        getSlideIndex(_s, hash) {
16119          if (swiper.virtual && swiper.params.virtual.enabled) {
16120            const slideWithHash = swiper.slides.find(slideEl => slideEl.getAttribute('data-hash') === hash);
16121            if (!slideWithHash) return 0;
16122            const index = parseInt(slideWithHash.getAttribute('data-swiper-slide-index'), 10);
16123            return index;
16124          }
16125          return swiper.getSlideIndex(elementChildren(swiper.slidesEl, `.${swiper.params.slideClass}[data-hash="${hash}"], swiper-slide[data-hash="${hash}"]`)[0]);
16126        }
16127      }
16128    });
16129    const onHashChange = () => {
16130      emit('hashChange');
16131      const newHash = document.location.hash.replace('#', '');
16132      const activeSlideEl = swiper.virtual && swiper.params.virtual.enabled ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${swiper.activeIndex}"]`) : swiper.slides[swiper.activeIndex];
16133      const activeSlideHash = activeSlideEl ? activeSlideEl.getAttribute('data-hash') : '';
16134      if (newHash !== activeSlideHash) {
16135        const newIndex = swiper.params.hashNavigation.getSlideIndex(swiper, newHash);
16136        if (typeof newIndex === 'undefined' || Number.isNaN(newIndex)) return;
16137        swiper.slideTo(newIndex);
16138      }
16139    };
16140    const setHash = () => {
16141      if (!initialized || !swiper.params.hashNavigation.enabled) return;
16142      const activeSlideEl = swiper.virtual && swiper.params.virtual.enabled ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${swiper.activeIndex}"]`) : swiper.slides[swiper.activeIndex];
16143      const activeSlideHash = activeSlideEl ? activeSlideEl.getAttribute('data-hash') || activeSlideEl.getAttribute('data-history') : '';
16144      if (swiper.params.hashNavigation.replaceState && window.history && window.history.replaceState) {
16145        window.history.replaceState(null, null, `#${activeSlideHash}` || '');
16146        emit('hashSet');
16147      } else {
16148        document.location.hash = activeSlideHash || '';
16149        emit('hashSet');
16150      }
16151    };
16152    const init = () => {
16153      if (!swiper.params.hashNavigation.enabled || swiper.params.history && swiper.params.history.enabled) return;
16154      initialized = true;
16155      const hash = document.location.hash.replace('#', '');
16156      if (hash) {
16157        const speed = 0;
16158        const index = swiper.params.hashNavigation.getSlideIndex(swiper, hash);
16159        swiper.slideTo(index || 0, speed, swiper.params.runCallbacksOnInit, true);
16160      }
16161      if (swiper.params.hashNavigation.watchState) {
16162        window.addEventListener('hashchange', onHashChange);
16163      }
16164    };
16165    const destroy = () => {
16166      if (swiper.params.hashNavigation.watchState) {
16167        window.removeEventListener('hashchange', onHashChange);
16168      }
16169    };
16170    on('init', () => {
16171      if (swiper.params.hashNavigation.enabled) {
16172        init();
16173      }
16174    });
16175    on('destroy', () => {
16176      if (swiper.params.hashNavigation.enabled) {
16177        destroy();
16178      }
16179    });
16180    on('transitionEnd _freeModeNoMomentumRelease', () => {
16181      if (initialized) {
16182        setHash();
16183      }
16184    });
16185    on('slideChange', () => {
16186      if (initialized && swiper.params.cssMode) {
16187        setHash();
16188      }
16189    });
16190  }
16191
16192  /* eslint no-underscore-dangle: "off" */
16193  /* eslint no-use-before-define: "off" */
16194  function Autoplay({
16195    swiper,
16196    extendParams,
16197    on,
16198    emit,
16199    params
16200  }) {
16201    swiper.autoplay = {
16202      running: false,
16203      paused: false,
16204      timeLeft: 0
16205    };
16206    extendParams({
16207      autoplay: {
16208        enabled: false,
16209        delay: 3000,
16210        waitForTransition: true,
16211        disableOnInteraction: false,
16212        stopOnLastSlide: false,
16213        reverseDirection: false,
16214        pauseOnMouseEnter: false
16215      }
16216    });
16217    let timeout;
16218    let raf;
16219    let autoplayDelayTotal = params && params.autoplay ? params.autoplay.delay : 3000;
16220    let autoplayDelayCurrent = params && params.autoplay ? params.autoplay.delay : 3000;
16221    let autoplayTimeLeft;
16222    let autoplayStartTime = new Date().getTime();
16223    let wasPaused;
16224    let isTouched;
16225    let pausedByTouch;
16226    let touchStartTimeout;
16227    let slideChanged;
16228    let pausedByInteraction;
16229    let pausedByPointerEnter;
16230    function onTransitionEnd(e) {
16231      if (!swiper || swiper.destroyed || !swiper.wrapperEl) return;
16232      if (e.target !== swiper.wrapperEl) return;
16233      swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd);
16234      if (pausedByPointerEnter || e.detail && e.detail.bySwiperTouchMove) {
16235        return;
16236      }
16237      resume();
16238    }
16239    const calcTimeLeft = () => {
16240      if (swiper.destroyed || !swiper.autoplay.running) return;
16241      if (swiper.autoplay.paused) {
16242        wasPaused = true;
16243      } else if (wasPaused) {
16244        autoplayDelayCurrent = autoplayTimeLeft;
16245        wasPaused = false;
16246      }
16247      const timeLeft = swiper.autoplay.paused ? autoplayTimeLeft : autoplayStartTime + autoplayDelayCurrent - new Date().getTime();
16248      swiper.autoplay.timeLeft = timeLeft;
16249      emit('autoplayTimeLeft', timeLeft, timeLeft / autoplayDelayTotal);
16250      raf = requestAnimationFrame(() => {
16251        calcTimeLeft();
16252      });
16253    };
16254    const getSlideDelay = () => {
16255      let activeSlideEl;
16256      if (swiper.virtual && swiper.params.virtual.enabled) {
16257        activeSlideEl = swiper.slides.find(slideEl => slideEl.classList.contains('swiper-slide-active'));
16258      } else {
16259        activeSlideEl = swiper.slides[swiper.activeIndex];
16260      }
16261      if (!activeSlideEl) return undefined;
16262      const currentSlideDelay = parseInt(activeSlideEl.getAttribute('data-swiper-autoplay'), 10);
16263      return currentSlideDelay;
16264    };
16265    const run = delayForce => {
16266      if (swiper.destroyed || !swiper.autoplay.running) return;
16267      cancelAnimationFrame(raf);
16268      calcTimeLeft();
16269      let delay = typeof delayForce === 'undefined' ? swiper.params.autoplay.delay : delayForce;
16270      autoplayDelayTotal = swiper.params.autoplay.delay;
16271      autoplayDelayCurrent = swiper.params.autoplay.delay;
16272      const currentSlideDelay = getSlideDelay();
16273      if (!Number.isNaN(currentSlideDelay) && currentSlideDelay > 0 && typeof delayForce === 'undefined') {
16274        delay = currentSlideDelay;
16275        autoplayDelayTotal = currentSlideDelay;
16276        autoplayDelayCurrent = currentSlideDelay;
16277      }
16278      autoplayTimeLeft = delay;
16279      const speed = swiper.params.speed;
16280      const proceed = () => {
16281        if (!swiper || swiper.destroyed) return;
16282        if (swiper.params.autoplay.reverseDirection) {
16283          if (!swiper.isBeginning || swiper.params.loop || swiper.params.rewind) {
16284            swiper.slidePrev(speed, true, true);
16285            emit('autoplay');
16286          } else if (!swiper.params.autoplay.stopOnLastSlide) {
16287            swiper.slideTo(swiper.slides.length - 1, speed, true, true);
16288            emit('autoplay');
16289          }
16290        } else {
16291          if (!swiper.isEnd || swiper.params.loop || swiper.params.rewind) {
16292            swiper.slideNext(speed, true, true);
16293            emit('autoplay');
16294          } else if (!swiper.params.autoplay.stopOnLastSlide) {
16295            swiper.slideTo(0, speed, true, true);
16296            emit('autoplay');
16297          }
16298        }
16299        if (swiper.params.cssMode) {
16300          autoplayStartTime = new Date().getTime();
16301          requestAnimationFrame(() => {
16302            run();
16303          });
16304        }
16305      };
16306      if (delay > 0) {
16307        clearTimeout(timeout);
16308        timeout = setTimeout(() => {
16309          proceed();
16310        }, delay);
16311      } else {
16312        requestAnimationFrame(() => {
16313          proceed();
16314        });
16315      }
16316
16317      // eslint-disable-next-line
16318      return delay;
16319    };
16320    const start = () => {
16321      autoplayStartTime = new Date().getTime();
16322      swiper.autoplay.running = true;
16323      run();
16324      emit('autoplayStart');
16325    };
16326    const stop = () => {
16327      swiper.autoplay.running = false;
16328      clearTimeout(timeout);
16329      cancelAnimationFrame(raf);
16330      emit('autoplayStop');
16331    };
16332    const pause = (internal, reset) => {
16333      if (swiper.destroyed || !swiper.autoplay.running) return;
16334      clearTimeout(timeout);
16335      if (!internal) {
16336        pausedByInteraction = true;
16337      }
16338      const proceed = () => {
16339        emit('autoplayPause');
16340        if (swiper.params.autoplay.waitForTransition) {
16341          swiper.wrapperEl.addEventListener('transitionend', onTransitionEnd);
16342        } else {
16343          resume();
16344        }
16345      };
16346      swiper.autoplay.paused = true;
16347      if (reset) {
16348        if (slideChanged) {
16349          autoplayTimeLeft = swiper.params.autoplay.delay;
16350        }
16351        slideChanged = false;
16352        proceed();
16353        return;
16354      }
16355      const delay = autoplayTimeLeft || swiper.params.autoplay.delay;
16356      autoplayTimeLeft = delay - (new Date().getTime() - autoplayStartTime);
16357      if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop) return;
16358      if (autoplayTimeLeft < 0) autoplayTimeLeft = 0;
16359      proceed();
16360    };
16361    const resume = () => {
16362      if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop || swiper.destroyed || !swiper.autoplay.running) return;
16363      autoplayStartTime = new Date().getTime();
16364      if (pausedByInteraction) {
16365        pausedByInteraction = false;
16366        run(autoplayTimeLeft);
16367      } else {
16368        run();
16369      }
16370      swiper.autoplay.paused = false;
16371      emit('autoplayResume');
16372    };
16373    const onVisibilityChange = () => {
16374      if (swiper.destroyed || !swiper.autoplay.running) return;
16375      const document = getDocument();
16376      if (document.visibilityState === 'hidden') {
16377        pausedByInteraction = true;
16378        pause(true);
16379      }
16380      if (document.visibilityState === 'visible') {
16381        resume();
16382      }
16383    };
16384    const onPointerEnter = e => {
16385      if (e.pointerType !== 'mouse') return;
16386      pausedByInteraction = true;
16387      pausedByPointerEnter = true;
16388      if (swiper.animating || swiper.autoplay.paused) return;
16389      pause(true);
16390    };
16391    const onPointerLeave = e => {
16392      if (e.pointerType !== 'mouse') return;
16393      pausedByPointerEnter = false;
16394      if (swiper.autoplay.paused) {
16395        resume();
16396      }
16397    };
16398    const attachMouseEvents = () => {
16399      if (swiper.params.autoplay.pauseOnMouseEnter) {
16400        swiper.el.addEventListener('pointerenter', onPointerEnter);
16401        swiper.el.addEventListener('pointerleave', onPointerLeave);
16402      }
16403    };
16404    const detachMouseEvents = () => {
16405      if (swiper.el && typeof swiper.el !== 'string') {
16406        swiper.el.removeEventListener('pointerenter', onPointerEnter);
16407        swiper.el.removeEventListener('pointerleave', onPointerLeave);
16408      }
16409    };
16410    const attachDocumentEvents = () => {
16411      const document = getDocument();
16412      document.addEventListener('visibilitychange', onVisibilityChange);
16413    };
16414    const detachDocumentEvents = () => {
16415      const document = getDocument();
16416      document.removeEventListener('visibilitychange', onVisibilityChange);
16417    };
16418    on('init', () => {
16419      if (swiper.params.autoplay.enabled) {
16420        attachMouseEvents();
16421        attachDocumentEvents();
16422        start();
16423      }
16424    });
16425    on('destroy', () => {
16426      detachMouseEvents();
16427      detachDocumentEvents();
16428      if (swiper.autoplay.running) {
16429        stop();
16430      }
16431    });
16432    on('_freeModeStaticRelease', () => {
16433      if (pausedByTouch || pausedByInteraction) {
16434        resume();
16435      }
16436    });
16437    on('_freeModeNoMomentumRelease', () => {
16438      if (!swiper.params.autoplay.disableOnInteraction) {
16439        pause(true, true);
16440      } else {
16441        stop();
16442      }
16443    });
16444    on('beforeTransitionStart', (_s, speed, internal) => {
16445      if (swiper.destroyed || !swiper.autoplay.running) return;
16446      if (internal || !swiper.params.autoplay.disableOnInteraction) {
16447        pause(true, true);
16448      } else {
16449        stop();
16450      }
16451    });
16452    on('sliderFirstMove', () => {
16453      if (swiper.destroyed || !swiper.autoplay.running) return;
16454      if (swiper.params.autoplay.disableOnInteraction) {
16455        stop();
16456        return;
16457      }
16458      isTouched = true;
16459      pausedByTouch = false;
16460      pausedByInteraction = false;
16461      touchStartTimeout = setTimeout(() => {
16462        pausedByInteraction = true;
16463        pausedByTouch = true;
16464        pause(true);
16465      }, 200);
16466    });
16467    on('touchEnd', () => {
16468      if (swiper.destroyed || !swiper.autoplay.running || !isTouched) return;
16469      clearTimeout(touchStartTimeout);
16470      clearTimeout(timeout);
16471      if (swiper.params.autoplay.disableOnInteraction) {
16472        pausedByTouch = false;
16473        isTouched = false;
16474        return;
16475      }
16476      if (pausedByTouch && swiper.params.cssMode) resume();
16477      pausedByTouch = false;
16478      isTouched = false;
16479    });
16480    on('slideChange', () => {
16481      if (swiper.destroyed || !swiper.autoplay.running) return;
16482      slideChanged = true;
16483    });
16484    Object.assign(swiper.autoplay, {
16485      start,
16486      stop,
16487      pause,
16488      resume
16489    });
16490  }
16491
16492  function Thumb({
16493    swiper,
16494    extendParams,
16495    on
16496  }) {
16497    extendParams({
16498      thumbs: {
16499        swiper: null,
16500        multipleActiveThumbs: true,
16501        autoScrollOffset: 0,
16502        slideThumbActiveClass: 'swiper-slide-thumb-active',
16503        thumbsContainerClass: 'swiper-thumbs'
16504      }
16505    });
16506    let initialized = false;
16507    let swiperCreated = false;
16508    swiper.thumbs = {
16509      swiper: null
16510    };
16511    function onThumbClick() {
16512      const thumbsSwiper = swiper.thumbs.swiper;
16513      if (!thumbsSwiper || thumbsSwiper.destroyed) return;
16514      const clickedIndex = thumbsSwiper.clickedIndex;
16515      const clickedSlide = thumbsSwiper.clickedSlide;
16516      if (clickedSlide && clickedSlide.classList.contains(swiper.params.thumbs.slideThumbActiveClass)) return;
16517      if (typeof clickedIndex === 'undefined' || clickedIndex === null) return;
16518      let slideToIndex;
16519      if (thumbsSwiper.params.loop) {
16520        slideToIndex = parseInt(thumbsSwiper.clickedSlide.getAttribute('data-swiper-slide-index'), 10);
16521      } else {
16522        slideToIndex = clickedIndex;
16523      }
16524      if (swiper.params.loop) {
16525        swiper.slideToLoop(slideToIndex);
16526      } else {
16527        swiper.slideTo(slideToIndex);
16528      }
16529    }
16530    function init() {
16531      const {
16532        thumbs: thumbsParams
16533      } = swiper.params;
16534      if (initialized) return false;
16535      initialized = true;
16536      const SwiperClass = swiper.constructor;
16537      if (thumbsParams.swiper instanceof SwiperClass) {
16538        if (thumbsParams.swiper.destroyed) {
16539          initialized = false;
16540          return false;
16541        }
16542        swiper.thumbs.swiper = thumbsParams.swiper;
16543        Object.assign(swiper.thumbs.swiper.originalParams, {
16544          watchSlidesProgress: true,
16545          slideToClickedSlide: false
16546        });
16547        Object.assign(swiper.thumbs.swiper.params, {
16548          watchSlidesProgress: true,
16549          slideToClickedSlide: false
16550        });
16551        swiper.thumbs.swiper.update();
16552      } else if (isObject(thumbsParams.swiper)) {
16553        const thumbsSwiperParams = Object.assign({}, thumbsParams.swiper);
16554        Object.assign(thumbsSwiperParams, {
16555          watchSlidesProgress: true,
16556          slideToClickedSlide: false
16557        });
16558        swiper.thumbs.swiper = new SwiperClass(thumbsSwiperParams);
16559        swiperCreated = true;
16560      }
16561      swiper.thumbs.swiper.el.classList.add(swiper.params.thumbs.thumbsContainerClass);
16562      swiper.thumbs.swiper.on('tap', onThumbClick);
16563      return true;
16564    }
16565    function update(initial) {
16566      const thumbsSwiper = swiper.thumbs.swiper;
16567      if (!thumbsSwiper || thumbsSwiper.destroyed) return;
16568      const slidesPerView = thumbsSwiper.params.slidesPerView === 'auto' ? thumbsSwiper.slidesPerViewDynamic() : thumbsSwiper.params.slidesPerView;
16569
16570      // Activate thumbs
16571      let thumbsToActivate = 1;
16572      const thumbActiveClass = swiper.params.thumbs.slideThumbActiveClass;
16573      if (swiper.params.slidesPerView > 1 && !swiper.params.centeredSlides) {
16574        thumbsToActivate = swiper.params.slidesPerView;
16575      }
16576      if (!swiper.params.thumbs.multipleActiveThumbs) {
16577        thumbsToActivate = 1;
16578      }
16579      thumbsToActivate = Math.floor(thumbsToActivate);
16580      thumbsSwiper.slides.forEach(slideEl => slideEl.classList.remove(thumbActiveClass));
16581      if (thumbsSwiper.params.loop || thumbsSwiper.params.virtual && thumbsSwiper.params.virtual.enabled) {
16582        for (let i = 0; i < thumbsToActivate; i += 1) {
16583          elementChildren(thumbsSwiper.slidesEl, `[data-swiper-slide-index="${swiper.realIndex + i}"]`).forEach(slideEl => {
16584            slideEl.classList.add(thumbActiveClass);
16585          });
16586        }
16587      } else {
16588        for (let i = 0; i < thumbsToActivate; i += 1) {
16589          if (thumbsSwiper.slides[swiper.realIndex + i]) {
16590            thumbsSwiper.slides[swiper.realIndex + i].classList.add(thumbActiveClass);
16591          }
16592        }
16593      }
16594      const autoScrollOffset = swiper.params.thumbs.autoScrollOffset;
16595      const useOffset = autoScrollOffset && !thumbsSwiper.params.loop;
16596      if (swiper.realIndex !== thumbsSwiper.realIndex || useOffset) {
16597        const currentThumbsIndex = thumbsSwiper.activeIndex;
16598        let newThumbsIndex;
16599        let direction;
16600        if (thumbsSwiper.params.loop) {
16601          const newThumbsSlide = thumbsSwiper.slides.find(slideEl => slideEl.getAttribute('data-swiper-slide-index') === `${swiper.realIndex}`);
16602          newThumbsIndex = thumbsSwiper.slides.indexOf(newThumbsSlide);
16603          direction = swiper.activeIndex > swiper.previousIndex ? 'next' : 'prev';
16604        } else {
16605          newThumbsIndex = swiper.realIndex;
16606          direction = newThumbsIndex > swiper.previousIndex ? 'next' : 'prev';
16607        }
16608        if (useOffset) {
16609          newThumbsIndex += direction === 'next' ? autoScrollOffset : -1 * autoScrollOffset;
16610        }
16611        if (thumbsSwiper.visibleSlidesIndexes && thumbsSwiper.visibleSlidesIndexes.indexOf(newThumbsIndex) < 0) {
16612          if (thumbsSwiper.params.centeredSlides) {
16613            if (newThumbsIndex > currentThumbsIndex) {
16614              newThumbsIndex = newThumbsIndex - Math.floor(slidesPerView / 2) + 1;
16615            } else {
16616              newThumbsIndex = newThumbsIndex + Math.floor(slidesPerView / 2) - 1;
16617            }
16618          } else if (newThumbsIndex > currentThumbsIndex && thumbsSwiper.params.slidesPerGroup === 1) ;
16619          thumbsSwiper.slideTo(newThumbsIndex, initial ? 0 : undefined);
16620        }
16621      }
16622    }
16623    on('beforeInit', () => {
16624      const {
16625        thumbs
16626      } = swiper.params;
16627      if (!thumbs || !thumbs.swiper) return;
16628      if (typeof thumbs.swiper === 'string' || thumbs.swiper instanceof HTMLElement) {
16629        const document = getDocument();
16630        const getThumbsElementAndInit = () => {
16631          const thumbsElement = typeof thumbs.swiper === 'string' ? document.querySelector(thumbs.swiper) : thumbs.swiper;
16632          if (thumbsElement && thumbsElement.swiper) {
16633            thumbs.swiper = thumbsElement.swiper;
16634            init();
16635            update(true);
16636          } else if (thumbsElement) {
16637            const eventName = `${swiper.params.eventsPrefix}init`;
16638            const onThumbsSwiper = e => {
16639              thumbs.swiper = e.detail[0];
16640              thumbsElement.removeEventListener(eventName, onThumbsSwiper);
16641              init();
16642              update(true);
16643              thumbs.swiper.update();
16644              swiper.update();
16645            };
16646            thumbsElement.addEventListener(eventName, onThumbsSwiper);
16647          }
16648          return thumbsElement;
16649        };
16650        const watchForThumbsToAppear = () => {
16651          if (swiper.destroyed) return;
16652          const thumbsElement = getThumbsElementAndInit();
16653          if (!thumbsElement) {
16654            requestAnimationFrame(watchForThumbsToAppear);
16655          }
16656        };
16657        requestAnimationFrame(watchForThumbsToAppear);
16658      } else {
16659        init();
16660        update(true);
16661      }
16662    });
16663    on('slideChange update resize observerUpdate', () => {
16664      update();
16665    });
16666    on('setTransition', (_s, duration) => {
16667      const thumbsSwiper = swiper.thumbs.swiper;
16668      if (!thumbsSwiper || thumbsSwiper.destroyed) return;
16669      thumbsSwiper.setTransition(duration);
16670    });
16671    on('beforeDestroy', () => {
16672      const thumbsSwiper = swiper.thumbs.swiper;
16673      if (!thumbsSwiper || thumbsSwiper.destroyed) return;
16674      if (swiperCreated) {
16675        thumbsSwiper.destroy();
16676      }
16677    });
16678    Object.assign(swiper.thumbs, {
16679      init,
16680      update
16681    });
16682  }
16683
16684  function freeMode({
16685    swiper,
16686    extendParams,
16687    emit,
16688    once
16689  }) {
16690    extendParams({
16691      freeMode: {
16692        enabled: false,
16693        momentum: true,
16694        momentumRatio: 1,
16695        momentumBounce: true,
16696        momentumBounceRatio: 1,
16697        momentumVelocityRatio: 1,
16698        sticky: false,
16699        minimumVelocity: 0.02
16700      }
16701    });
16702    function onTouchStart() {
16703      if (swiper.params.cssMode) return;
16704      const translate = swiper.getTranslate();
16705      swiper.setTranslate(translate);
16706      swiper.setTransition(0);
16707      swiper.touchEventsData.velocities.length = 0;
16708      swiper.freeMode.onTouchEnd({
16709        currentPos: swiper.rtl ? swiper.translate : -swiper.translate
16710      });
16711    }
16712    function onTouchMove() {
16713      if (swiper.params.cssMode) return;
16714      const {
16715        touchEventsData: data,
16716        touches
16717      } = swiper;
16718      // Velocity
16719      if (data.velocities.length === 0) {
16720        data.velocities.push({
16721          position: touches[swiper.isHorizontal() ? 'startX' : 'startY'],
16722          time: data.touchStartTime
16723        });
16724      }
16725      data.velocities.push({
16726        position: touches[swiper.isHorizontal() ? 'currentX' : 'currentY'],
16727        time: now()
16728      });
16729    }
16730    function onTouchEnd({
16731      currentPos
16732    }) {
16733      if (swiper.params.cssMode) return;
16734      const {
16735        params,
16736        wrapperEl,
16737        rtlTranslate: rtl,
16738        snapGrid,
16739        touchEventsData: data
16740      } = swiper;
16741      // Time diff
16742      const touchEndTime = now();
16743      const timeDiff = touchEndTime - data.touchStartTime;
16744      if (currentPos < -swiper.minTranslate()) {
16745        swiper.slideTo(swiper.activeIndex);
16746        return;
16747      }
16748      if (currentPos > -swiper.maxTranslate()) {
16749        if (swiper.slides.length < snapGrid.length) {
16750          swiper.slideTo(snapGrid.length - 1);
16751        } else {
16752          swiper.slideTo(swiper.slides.length - 1);
16753        }
16754        return;
16755      }
16756      if (params.freeMode.momentum) {
16757        if (data.velocities.length > 1) {
16758          const lastMoveEvent = data.velocities.pop();
16759          const velocityEvent = data.velocities.pop();
16760          const distance = lastMoveEvent.position - velocityEvent.position;
16761          const time = lastMoveEvent.time - velocityEvent.time;
16762          swiper.velocity = distance / time;
16763          swiper.velocity /= 2;
16764          if (Math.abs(swiper.velocity) < params.freeMode.minimumVelocity) {
16765            swiper.velocity = 0;
16766          }
16767          // this implies that the user stopped moving a finger then released.
16768          // There would be no events with distance zero, so the last event is stale.
16769          if (time > 150 || now() - lastMoveEvent.time > 300) {
16770            swiper.velocity = 0;
16771          }
16772        } else {
16773          swiper.velocity = 0;
16774        }
16775        swiper.velocity *= params.freeMode.momentumVelocityRatio;
16776        data.velocities.length = 0;
16777        let momentumDuration = 1000 * params.freeMode.momentumRatio;
16778        const momentumDistance = swiper.velocity * momentumDuration;
16779        let newPosition = swiper.translate + momentumDistance;
16780        if (rtl) newPosition = -newPosition;
16781        let doBounce = false;
16782        let afterBouncePosition;
16783        const bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeMode.momentumBounceRatio;
16784        let needsLoopFix;
16785        if (newPosition < swiper.maxTranslate()) {
16786          if (params.freeMode.momentumBounce) {
16787            if (newPosition + swiper.maxTranslate() < -bounceAmount) {
16788              newPosition = swiper.maxTranslate() - bounceAmount;
16789            }
16790            afterBouncePosition = swiper.maxTranslate();
16791            doBounce = true;
16792            data.allowMomentumBounce = true;
16793          } else {
16794            newPosition = swiper.maxTranslate();
16795          }
16796          if (params.loop && params.centeredSlides) needsLoopFix = true;
16797        } else if (newPosition > swiper.minTranslate()) {
16798          if (params.freeMode.momentumBounce) {
16799            if (newPosition - swiper.minTranslate() > bounceAmount) {
16800              newPosition = swiper.minTranslate() + bounceAmount;
16801            }
16802            afterBouncePosition = swiper.minTranslate();
16803            doBounce = true;
16804            data.allowMomentumBounce = true;
16805          } else {
16806            newPosition = swiper.minTranslate();
16807          }
16808          if (params.loop && params.centeredSlides) needsLoopFix = true;
16809        } else if (params.freeMode.sticky) {
16810          let nextSlide;
16811          for (let j = 0; j < snapGrid.length; j += 1) {
16812            if (snapGrid[j] > -newPosition) {
16813              nextSlide = j;
16814              break;
16815            }
16816          }
16817          if (Math.abs(snapGrid[nextSlide] - newPosition) < Math.abs(snapGrid[nextSlide - 1] - newPosition) || swiper.swipeDirection === 'next') {
16818            newPosition = snapGrid[nextSlide];
16819          } else {
16820            newPosition = snapGrid[nextSlide - 1];
16821          }
16822          newPosition = -newPosition;
16823        }
16824        if (needsLoopFix) {
16825          once('transitionEnd', () => {
16826            swiper.loopFix();
16827          });
16828        }
16829        // Fix duration
16830        if (swiper.velocity !== 0) {
16831          if (rtl) {
16832            momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity);
16833          } else {
16834            momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity);
16835          }
16836          if (params.freeMode.sticky) {
16837            // If freeMode.sticky is active and the user ends a swipe with a slow-velocity
16838            // event, then durations can be 20+ seconds to slide one (or zero!) slides.
16839            // It's easy to see this when simulating touch with mouse events. To fix this,
16840            // limit single-slide swipes to the default slide duration. This also has the
16841            // nice side effect of matching slide speed if the user stopped moving before
16842            // lifting finger or mouse vs. moving slowly before lifting the finger/mouse.
16843            // For faster swipes, also apply limits (albeit higher ones).
16844            const moveDistance = Math.abs((rtl ? -newPosition : newPosition) - swiper.translate);
16845            const currentSlideSize = swiper.slidesSizesGrid[swiper.activeIndex];
16846            if (moveDistance < currentSlideSize) {
16847              momentumDuration = params.speed;
16848            } else if (moveDistance < 2 * currentSlideSize) {
16849              momentumDuration = params.speed * 1.5;
16850            } else {
16851              momentumDuration = params.speed * 2.5;
16852            }
16853          }
16854        } else if (params.freeMode.sticky) {
16855          swiper.slideToClosest();
16856          return;
16857        }
16858        if (params.freeMode.momentumBounce && doBounce) {
16859          swiper.updateProgress(afterBouncePosition);
16860          swiper.setTransition(momentumDuration);
16861          swiper.setTranslate(newPosition);
16862          swiper.transitionStart(true, swiper.swipeDirection);
16863          swiper.animating = true;
16864          elementTransitionEnd(wrapperEl, () => {
16865            if (!swiper || swiper.destroyed || !data.allowMomentumBounce) return;
16866            emit('momentumBounce');
16867            swiper.setTransition(params.speed);
16868            setTimeout(() => {
16869              swiper.setTranslate(afterBouncePosition);
16870              elementTransitionEnd(wrapperEl, () => {
16871                if (!swiper || swiper.destroyed) return;
16872                swiper.transitionEnd();
16873              });
16874            }, 0);
16875          });
16876        } else if (swiper.velocity) {
16877          emit('_freeModeNoMomentumRelease');
16878          swiper.updateProgress(newPosition);
16879          swiper.setTransition(momentumDuration);
16880          swiper.setTranslate(newPosition);
16881          swiper.transitionStart(true, swiper.swipeDirection);
16882          if (!swiper.animating) {
16883            swiper.animating = true;
16884            elementTransitionEnd(wrapperEl, () => {
16885              if (!swiper || swiper.destroyed) return;
16886              swiper.transitionEnd();
16887            });
16888          }
16889        } else {
16890          swiper.updateProgress(newPosition);
16891        }
16892        swiper.updateActiveIndex();
16893        swiper.updateSlidesClasses();
16894      } else if (params.freeMode.sticky) {
16895        swiper.slideToClosest();
16896        return;
16897      } else if (params.freeMode) {
16898        emit('_freeModeNoMomentumRelease');
16899      }
16900      if (!params.freeMode.momentum || timeDiff >= params.longSwipesMs) {
16901        emit('_freeModeStaticRelease');
16902        swiper.updateProgress();
16903        swiper.updateActiveIndex();
16904        swiper.updateSlidesClasses();
16905      }
16906    }
16907    Object.assign(swiper, {
16908      freeMode: {
16909        onTouchStart,
16910        onTouchMove,
16911        onTouchEnd
16912      }
16913    });
16914  }
16915
16916  function Grid({
16917    swiper,
16918    extendParams,
16919    on
16920  }) {
16921    extendParams({
16922      grid: {
16923        rows: 1,
16924        fill: 'column'
16925      }
16926    });
vendor: 1,326 bytes, lines 16927-16961
16927    let slidesNumberEvenToRows;
16928    let slidesPerRow;
16929    let numFullColumns;
16930    let wasMultiRow;
16931    const getSpaceBetween = () => {
16932      let spaceBetween = swiper.params.spaceBetween;
16933      if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
16934        spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiper.size;
16935      } else if (typeof spaceBetween === 'string') {
16936        spaceBetween = parseFloat(spaceBetween);
16937      }
16938      return spaceBetween;
16939    };
16940    const initSlides = slides => {
16941      const {
16942        slidesPerView
16943      } = swiper.params;
16944      const {
16945        rows,
16946        fill
16947      } = swiper.params.grid;
16948      const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : slides.length;
16949      numFullColumns = Math.floor(slidesLength / rows);
16950      if (Math.floor(slidesLength / rows) === slidesLength / rows) {
16951        slidesNumberEvenToRows = slidesLength;
16952      } else {
16953        slidesNumberEvenToRows = Math.ceil(slidesLength / rows) * rows;
16954      }
16955      if (slidesPerView !== 'auto' && fill === 'row') {
16956        slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, slidesPerView * rows);
16957      }
16958      slidesPerRow = slidesNumberEvenToRows / rows;
16959    };
16960    const unsetSlides = () => {
16961      if (swiper.slides) {
vendor: 38,075 bytes, lines 16962-18028
16962        swiper.slides.forEach(slide => {
16963          if (slide.swiperSlideGridSet) {
16964            slide.style.height = '';
16965            slide.style[swiper.getDirectionLabel('margin-top')] = '';
16966          }
16967        });
16968      }
16969    };
16970    const updateSlide = (i, slide, slides) => {
16971      const {
16972        slidesPerGroup
16973      } = swiper.params;
16974      const spaceBetween = getSpaceBetween();
16975      const {
16976        rows,
16977        fill
16978      } = swiper.params.grid;
16979      const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : slides.length;
16980      // Set slides order
16981      let newSlideOrderIndex;
16982      let column;
16983      let row;
16984      if (fill === 'row' && slidesPerGroup > 1) {
16985        const groupIndex = Math.floor(i / (slidesPerGroup * rows));
16986        const slideIndexInGroup = i - rows * slidesPerGroup * groupIndex;
16987        const columnsInGroup = groupIndex === 0 ? slidesPerGroup : Math.min(Math.ceil((slidesLength - groupIndex * rows * slidesPerGroup) / rows), slidesPerGroup);
16988        row = Math.floor(slideIndexInGroup / columnsInGroup);
16989        column = slideIndexInGroup - row * columnsInGroup + groupIndex * slidesPerGroup;
16990        newSlideOrderIndex = column + row * slidesNumberEvenToRows / rows;
16991        slide.style.order = newSlideOrderIndex;
16992      } else if (fill === 'column') {
16993        column = Math.floor(i / rows);
16994        row = i - column * rows;
16995        if (column > numFullColumns || column === numFullColumns && row === rows - 1) {
16996          row += 1;
16997          if (row >= rows) {
16998            row = 0;
16999            column += 1;
17000          }
17001        }
17002      } else {
17003        row = Math.floor(i / slidesPerRow);
17004        column = i - row * slidesPerRow;
17005      }
17006      slide.row = row;
17007      slide.column = column;
17008      slide.style.height = `calc((100% - ${(rows - 1) * spaceBetween}px) / ${rows})`;
17009      slide.style[swiper.getDirectionLabel('margin-top')] = row !== 0 ? spaceBetween && `${spaceBetween}px` : '';
17010      slide.swiperSlideGridSet = true;
17011    };
17012    const updateWrapperSize = (slideSize, snapGrid) => {
17013      const {
17014        centeredSlides,
17015        roundLengths
17016      } = swiper.params;
17017      const spaceBetween = getSpaceBetween();
17018      const {
17019        rows
17020      } = swiper.params.grid;
17021      swiper.virtualSize = (slideSize + spaceBetween) * slidesNumberEvenToRows;
17022      swiper.virtualSize = Math.ceil(swiper.virtualSize / rows) - spaceBetween;
17023      if (!swiper.params.cssMode) {
17024        swiper.wrapperEl.style[swiper.getDirectionLabel('width')] = `${swiper.virtualSize + spaceBetween}px`;
17025      }
17026      if (centeredSlides) {
17027        const newSlidesGrid = [];
17028        for (let i = 0; i < snapGrid.length; i += 1) {
17029          let slidesGridItem = snapGrid[i];
17030          if (roundLengths) slidesGridItem = Math.floor(slidesGridItem);
17031          if (snapGrid[i] < swiper.virtualSize + snapGrid[0]) newSlidesGrid.push(slidesGridItem);
17032        }
17033        snapGrid.splice(0, snapGrid.length);
17034        snapGrid.push(...newSlidesGrid);
17035      }
17036    };
17037    const onInit = () => {
17038      wasMultiRow = swiper.params.grid && swiper.params.grid.rows > 1;
17039    };
17040    const onUpdate = () => {
17041      const {
17042        params,
17043        el
17044      } = swiper;
17045      const isMultiRow = params.grid && params.grid.rows > 1;
17046      if (wasMultiRow && !isMultiRow) {
17047        el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`);
17048        numFullColumns = 1;
17049        swiper.emitContainerClasses();
17050      } else if (!wasMultiRow && isMultiRow) {
17051        el.classList.add(`${params.containerModifierClass}grid`);
17052        if (params.grid.fill === 'column') {
17053          el.classList.add(`${params.containerModifierClass}grid-column`);
17054        }
17055        swiper.emitContainerClasses();
17056      }
17057      wasMultiRow = isMultiRow;
17058    };
17059    on('init', onInit);
17060    on('update', onUpdate);
17061    swiper.grid = {
17062      initSlides,
17063      unsetSlides,
17064      updateSlide,
17065      updateWrapperSize
17066    };
17067  }
17068
17069  function appendSlide(slides) {
17070    const swiper = this;
17071    const {
17072      params,
17073      slidesEl
17074    } = swiper;
17075    if (params.loop) {
17076      swiper.loopDestroy();
17077    }
17078    const appendElement = slideEl => {
17079      if (typeof slideEl === 'string') {
17080        const tempDOM = document.createElement('div');
17081        setInnerHTML(tempDOM, slideEl);
17082        slidesEl.append(tempDOM.children[0]);
17083        setInnerHTML(tempDOM, '');
17084      } else {
17085        slidesEl.append(slideEl);
17086      }
17087    };
17088    if (typeof slides === 'object' && 'length' in slides) {
17089      for (let i = 0; i < slides.length; i += 1) {
17090        if (slides[i]) appendElement(slides[i]);
17091      }
17092    } else {
17093      appendElement(slides);
17094    }
17095    swiper.recalcSlides();
17096    if (params.loop) {
17097      swiper.loopCreate();
17098    }
17099    if (!params.observer || swiper.isElement) {
17100      swiper.update();
17101    }
17102  }
17103
17104  function prependSlide(slides) {
17105    const swiper = this;
17106    const {
17107      params,
17108      activeIndex,
17109      slidesEl
17110    } = swiper;
17111    if (params.loop) {
17112      swiper.loopDestroy();
17113    }
17114    let newActiveIndex = activeIndex + 1;
17115    const prependElement = slideEl => {
17116      if (typeof slideEl === 'string') {
17117        const tempDOM = document.createElement('div');
17118        setInnerHTML(tempDOM, slideEl);
17119        slidesEl.prepend(tempDOM.children[0]);
17120        setInnerHTML(tempDOM, '');
17121      } else {
17122        slidesEl.prepend(slideEl);
17123      }
17124    };
17125    if (typeof slides === 'object' && 'length' in slides) {
17126      for (let i = 0; i < slides.length; i += 1) {
17127        if (slides[i]) prependElement(slides[i]);
17128      }
17129      newActiveIndex = activeIndex + slides.length;
17130    } else {
17131      prependElement(slides);
17132    }
17133    swiper.recalcSlides();
17134    if (params.loop) {
17135      swiper.loopCreate();
17136    }
17137    if (!params.observer || swiper.isElement) {
17138      swiper.update();
17139    }
17140    swiper.slideTo(newActiveIndex, 0, false);
17141  }
17142
17143  function addSlide(index, slides) {
17144    const swiper = this;
17145    const {
17146      params,
17147      activeIndex,
17148      slidesEl
17149    } = swiper;
17150    let activeIndexBuffer = activeIndex;
17151    if (params.loop) {
17152      activeIndexBuffer -= swiper.loopedSlides;
17153      swiper.loopDestroy();
17154      swiper.recalcSlides();
17155    }
17156    const baseLength = swiper.slides.length;
17157    if (index <= 0) {
17158      swiper.prependSlide(slides);
17159      return;
17160    }
17161    if (index >= baseLength) {
17162      swiper.appendSlide(slides);
17163      return;
17164    }
17165    let newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + 1 : activeIndexBuffer;
17166    const slidesBuffer = [];
17167    for (let i = baseLength - 1; i >= index; i -= 1) {
17168      const currentSlide = swiper.slides[i];
17169      currentSlide.remove();
17170      slidesBuffer.unshift(currentSlide);
17171    }
17172    if (typeof slides === 'object' && 'length' in slides) {
17173      for (let i = 0; i < slides.length; i += 1) {
17174        if (slides[i]) slidesEl.append(slides[i]);
17175      }
17176      newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + slides.length : activeIndexBuffer;
17177    } else {
17178      slidesEl.append(slides);
17179    }
17180    for (let i = 0; i < slidesBuffer.length; i += 1) {
17181      slidesEl.append(slidesBuffer[i]);
17182    }
17183    swiper.recalcSlides();
17184    if (params.loop) {
17185      swiper.loopCreate();
17186    }
17187    if (!params.observer || swiper.isElement) {
17188      swiper.update();
17189    }
17190    if (params.loop) {
17191      swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
17192    } else {
17193      swiper.slideTo(newActiveIndex, 0, false);
17194    }
17195  }
17196
17197  function removeSlide(slidesIndexes) {
17198    const swiper = this;
17199    const {
17200      params,
17201      activeIndex
17202    } = swiper;
17203    let activeIndexBuffer = activeIndex;
17204    if (params.loop) {
17205      activeIndexBuffer -= swiper.loopedSlides;
17206      swiper.loopDestroy();
17207    }
17208    let newActiveIndex = activeIndexBuffer;
17209    let indexToRemove;
17210    if (typeof slidesIndexes === 'object' && 'length' in slidesIndexes) {
17211      for (let i = 0; i < slidesIndexes.length; i += 1) {
17212        indexToRemove = slidesIndexes[i];
17213        if (swiper.slides[indexToRemove]) swiper.slides[indexToRemove].remove();
17214        if (indexToRemove < newActiveIndex) newActiveIndex -= 1;
17215      }
17216      newActiveIndex = Math.max(newActiveIndex, 0);
17217    } else {
17218      indexToRemove = slidesIndexes;
17219      if (swiper.slides[indexToRemove]) swiper.slides[indexToRemove].remove();
17220      if (indexToRemove < newActiveIndex) newActiveIndex -= 1;
17221      newActiveIndex = Math.max(newActiveIndex, 0);
17222    }
17223    swiper.recalcSlides();
17224    if (params.loop) {
17225      swiper.loopCreate();
17226    }
17227    if (!params.observer || swiper.isElement) {
17228      swiper.update();
17229    }
17230    if (params.loop) {
17231      swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
17232    } else {
17233      swiper.slideTo(newActiveIndex, 0, false);
17234    }
17235  }
17236
17237  function removeAllSlides() {
17238    const swiper = this;
17239    const slidesIndexes = [];
17240    for (let i = 0; i < swiper.slides.length; i += 1) {
17241      slidesIndexes.push(i);
17242    }
17243    swiper.removeSlide(slidesIndexes);
17244  }
17245
17246  function Manipulation({
17247    swiper
17248  }) {
17249    Object.assign(swiper, {
17250      appendSlide: appendSlide.bind(swiper),
17251      prependSlide: prependSlide.bind(swiper),
17252      addSlide: addSlide.bind(swiper),
17253      removeSlide: removeSlide.bind(swiper),
17254      removeAllSlides: removeAllSlides.bind(swiper)
17255    });
17256  }
17257
17258  function effectInit(params) {
17259    const {
17260      effect,
17261      swiper,
17262      on,
17263      setTranslate,
17264      setTransition,
17265      overwriteParams,
17266      perspective,
17267      recreateShadows,
17268      getEffectParams
17269    } = params;
17270    on('beforeInit', () => {
17271      if (swiper.params.effect !== effect) return;
17272      swiper.classNames.push(`${swiper.params.containerModifierClass}${effect}`);
17273      if (perspective && perspective()) {
17274        swiper.classNames.push(`${swiper.params.containerModifierClass}3d`);
17275      }
17276      const overwriteParamsResult = overwriteParams ? overwriteParams() : {};
17277      Object.assign(swiper.params, overwriteParamsResult);
17278      Object.assign(swiper.originalParams, overwriteParamsResult);
17279    });
17280    on('setTranslate _virtualUpdated', () => {
17281      if (swiper.params.effect !== effect) return;
17282      setTranslate();
17283    });
17284    on('setTransition', (_s, duration) => {
17285      if (swiper.params.effect !== effect) return;
17286      setTransition(duration);
17287    });
17288    on('transitionEnd', () => {
17289      if (swiper.params.effect !== effect) return;
17290      if (recreateShadows) {
17291        if (!getEffectParams || !getEffectParams().slideShadows) return;
17292        // remove shadows
17293        swiper.slides.forEach(slideEl => {
17294          slideEl.querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').forEach(shadowEl => shadowEl.remove());
17295        });
17296        // create new one
17297        recreateShadows();
17298      }
17299    });
17300    let requireUpdateOnVirtual;
17301    on('virtualUpdate', () => {
17302      if (swiper.params.effect !== effect) return;
17303      if (!swiper.slides.length) {
17304        requireUpdateOnVirtual = true;
17305      }
17306      requestAnimationFrame(() => {
17307        if (requireUpdateOnVirtual && swiper.slides && swiper.slides.length) {
17308          setTranslate();
17309          requireUpdateOnVirtual = false;
17310        }
17311      });
17312    });
17313  }
17314
17315  function effectTarget(effectParams, slideEl) {
17316    const transformEl = getSlideTransformEl(slideEl);
17317    if (transformEl !== slideEl) {
17318      transformEl.style.backfaceVisibility = 'hidden';
17319      transformEl.style['-webkit-backface-visibility'] = 'hidden';
17320    }
17321    return transformEl;
17322  }
17323
17324  function effectVirtualTransitionEnd({
17325    swiper,
17326    duration,
17327    transformElements,
17328    allSlides
17329  }) {
17330    const {
17331      activeIndex
17332    } = swiper;
17333    const getSlide = el => {
17334      if (!el.parentElement) {
17335        // assume shadow root
17336        const slide = swiper.slides.find(slideEl => slideEl.shadowRoot && slideEl.shadowRoot === el.parentNode);
17337        return slide;
17338      }
17339      return el.parentElement;
17340    };
17341    if (swiper.params.virtualTranslate && duration !== 0) {
17342      let eventTriggered = false;
17343      let transitionEndTarget;
17344      if (allSlides) {
17345        transitionEndTarget = transformElements;
17346      } else {
17347        transitionEndTarget = transformElements.filter(transformEl => {
17348          const el = transformEl.classList.contains('swiper-slide-transform') ? getSlide(transformEl) : transformEl;
17349          return swiper.getSlideIndex(el) === activeIndex;
17350        });
17351      }
17352      transitionEndTarget.forEach(el => {
17353        elementTransitionEnd(el, () => {
17354          if (eventTriggered) return;
17355          if (!swiper || swiper.destroyed) return;
17356          eventTriggered = true;
17357          swiper.animating = false;
17358          const evt = new window.CustomEvent('transitionend', {
17359            bubbles: true,
17360            cancelable: true
17361          });
17362          swiper.wrapperEl.dispatchEvent(evt);
17363        });
17364      });
17365    }
17366  }
17367
17368  function EffectFade({
17369    swiper,
17370    extendParams,
17371    on
17372  }) {
17373    extendParams({
17374      fadeEffect: {
17375        crossFade: false
17376      }
17377    });
17378    const setTranslate = () => {
17379      const {
17380        slides
17381      } = swiper;
17382      const params = swiper.params.fadeEffect;
17383      for (let i = 0; i < slides.length; i += 1) {
17384        const slideEl = swiper.slides[i];
17385        const offset = slideEl.swiperSlideOffset;
17386        let tx = -offset;
17387        if (!swiper.params.virtualTranslate) tx -= swiper.translate;
17388        let ty = 0;
17389        if (!swiper.isHorizontal()) {
17390          ty = tx;
17391          tx = 0;
17392        }
17393        const slideOpacity = swiper.params.fadeEffect.crossFade ? Math.max(1 - Math.abs(slideEl.progress), 0) : 1 + Math.min(Math.max(slideEl.progress, -1), 0);
17394        const targetEl = effectTarget(params, slideEl);
17395        targetEl.style.opacity = slideOpacity;
17396        targetEl.style.transform = `translate3d(${tx}px, ${ty}px, 0px)`;
17397      }
17398    };
17399    const setTransition = duration => {
17400      const transformElements = swiper.slides.map(slideEl => getSlideTransformEl(slideEl));
17401      transformElements.forEach(el => {
17402        el.style.transitionDuration = `${duration}ms`;
17403      });
17404      effectVirtualTransitionEnd({
17405        swiper,
17406        duration,
17407        transformElements,
17408        allSlides: true
17409      });
17410    };
17411    effectInit({
17412      effect: 'fade',
17413      swiper,
17414      on,
17415      setTranslate,
17416      setTransition,
17417      overwriteParams: () => ({
17418        slidesPerView: 1,
17419        slidesPerGroup: 1,
17420        watchSlidesProgress: true,
17421        spaceBetween: 0,
17422        virtualTranslate: !swiper.params.cssMode
17423      })
17424    });
17425  }
17426
17427  function EffectCube({
17428    swiper,
17429    extendParams,
17430    on
17431  }) {
17432    extendParams({
17433      cubeEffect: {
17434        slideShadows: true,
17435        shadow: true,
17436        shadowOffset: 20,
17437        shadowScale: 0.94
17438      }
17439    });
17440    const createSlideShadows = (slideEl, progress, isHorizontal) => {
17441      let shadowBefore = isHorizontal ? slideEl.querySelector('.swiper-slide-shadow-left') : slideEl.querySelector('.swiper-slide-shadow-top');
17442      let shadowAfter = isHorizontal ? slideEl.querySelector('.swiper-slide-shadow-right') : slideEl.querySelector('.swiper-slide-shadow-bottom');
17443      if (!shadowBefore) {
17444        shadowBefore = createElement('div', `swiper-slide-shadow-cube swiper-slide-shadow-${isHorizontal ? 'left' : 'top'}`.split(' '));
17445        slideEl.append(shadowBefore);
17446      }
17447      if (!shadowAfter) {
17448        shadowAfter = createElement('div', `swiper-slide-shadow-cube swiper-slide-shadow-${isHorizontal ? 'right' : 'bottom'}`.split(' '));
17449        slideEl.append(shadowAfter);
17450      }
17451      if (shadowBefore) shadowBefore.style.opacity = Math.max(-progress, 0);
17452      if (shadowAfter) shadowAfter.style.opacity = Math.max(progress, 0);
17453    };
17454    const recreateShadows = () => {
17455      // create new ones
17456      const isHorizontal = swiper.isHorizontal();
17457      swiper.slides.forEach(slideEl => {
17458        const progress = Math.max(Math.min(slideEl.progress, 1), -1);
17459        createSlideShadows(slideEl, progress, isHorizontal);
17460      });
17461    };
17462    const setTranslate = () => {
17463      const {
17464        el,
17465        wrapperEl,
17466        slides,
17467        width: swiperWidth,
17468        height: swiperHeight,
17469        rtlTranslate: rtl,
17470        size: swiperSize,
17471        browser
17472      } = swiper;
17473      const r = getRotateFix(swiper);
17474      const params = swiper.params.cubeEffect;
17475      const isHorizontal = swiper.isHorizontal();
17476      const isVirtual = swiper.virtual && swiper.params.virtual.enabled;
17477      let wrapperRotate = 0;
17478      let cubeShadowEl;
17479      if (params.shadow) {
17480        if (isHorizontal) {
17481          cubeShadowEl = swiper.wrapperEl.querySelector('.swiper-cube-shadow');
17482          if (!cubeShadowEl) {
17483            cubeShadowEl = createElement('div', 'swiper-cube-shadow');
17484            swiper.wrapperEl.append(cubeShadowEl);
17485          }
17486          cubeShadowEl.style.height = `${swiperWidth}px`;
17487        } else {
17488          cubeShadowEl = el.querySelector('.swiper-cube-shadow');
17489          if (!cubeShadowEl) {
17490            cubeShadowEl = createElement('div', 'swiper-cube-shadow');
17491            el.append(cubeShadowEl);
17492          }
17493        }
17494      }
17495      for (let i = 0; i < slides.length; i += 1) {
17496        const slideEl = slides[i];
17497        let slideIndex = i;
17498        if (isVirtual) {
17499          slideIndex = parseInt(slideEl.getAttribute('data-swiper-slide-index'), 10);
17500        }
17501        let slideAngle = slideIndex * 90;
17502        let round = Math.floor(slideAngle / 360);
17503        if (rtl) {
17504          slideAngle = -slideAngle;
17505          round = Math.floor(-slideAngle / 360);
17506        }
17507        const progress = Math.max(Math.min(slideEl.progress, 1), -1);
17508        let tx = 0;
17509        let ty = 0;
17510        let tz = 0;
17511        if (slideIndex % 4 === 0) {
17512          tx = -round * 4 * swiperSize;
17513          tz = 0;
17514        } else if ((slideIndex - 1) % 4 === 0) {
17515          tx = 0;
17516          tz = -round * 4 * swiperSize;
17517        } else if ((slideIndex - 2) % 4 === 0) {
17518          tx = swiperSize + round * 4 * swiperSize;
17519          tz = swiperSize;
17520        } else if ((slideIndex - 3) % 4 === 0) {
17521          tx = -swiperSize;
17522          tz = 3 * swiperSize + swiperSize * 4 * round;
17523        }
17524        if (rtl) {
17525          tx = -tx;
17526        }
17527        if (!isHorizontal) {
17528          ty = tx;
17529          tx = 0;
17530        }
17531        const transform = `rotateX(${r(isHorizontal ? 0 : -slideAngle)}deg) rotateY(${r(isHorizontal ? slideAngle : 0)}deg) translate3d(${tx}px, ${ty}px, ${tz}px)`;
17532        if (progress <= 1 && progress > -1) {
17533          wrapperRotate = slideIndex * 90 + progress * 90;
17534          if (rtl) wrapperRotate = -slideIndex * 90 - progress * 90;
17535        }
17536        slideEl.style.transform = transform;
17537        if (params.slideShadows) {
17538          createSlideShadows(slideEl, progress, isHorizontal);
17539        }
17540      }
17541      wrapperEl.style.transformOrigin = `50% 50% -${swiperSize / 2}px`;
17542      wrapperEl.style['-webkit-transform-origin'] = `50% 50% -${swiperSize / 2}px`;
17543      if (params.shadow) {
17544        if (isHorizontal) {
17545          cubeShadowEl.style.transform = `translate3d(0px, ${swiperWidth / 2 + params.shadowOffset}px, ${-swiperWidth / 2}px) rotateX(89.99deg) rotateZ(0deg) scale(${params.shadowScale})`;
17546        } else {
17547          const shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90;
17548          const multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2);
17549          const scale1 = params.shadowScale;
17550          const scale2 = params.shadowScale / multiplier;
17551          const offset = params.shadowOffset;
17552          cubeShadowEl.style.transform = `scale3d(${scale1}, 1, ${scale2}) translate3d(0px, ${swiperHeight / 2 + offset}px, ${-swiperHeight / 2 / scale2}px) rotateX(-89.99deg)`;
17553        }
17554      }
17555      const zFactor = (browser.isSafari || browser.isWebView) && browser.needPerspectiveFix ? -swiperSize / 2 : 0;
17556      wrapperEl.style.transform = `translate3d(0px,0,${zFactor}px) rotateX(${r(swiper.isHorizontal() ? 0 : wrapperRotate)}deg) rotateY(${r(swiper.isHorizontal() ? -wrapperRotate : 0)}deg)`;
17557      wrapperEl.style.setProperty('--swiper-cube-translate-z', `${zFactor}px`);
17558    };
17559    const setTransition = duration => {
17560      const {
17561        el,
17562        slides
17563      } = swiper;
17564      slides.forEach(slideEl => {
17565        slideEl.style.transitionDuration = `${duration}ms`;
17566        slideEl.querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').forEach(subEl => {
17567          subEl.style.transitionDuration = `${duration}ms`;
17568        });
17569      });
17570      if (swiper.params.cubeEffect.shadow && !swiper.isHorizontal()) {
17571        const shadowEl = el.querySelector('.swiper-cube-shadow');
17572        if (shadowEl) shadowEl.style.transitionDuration = `${duration}ms`;
17573      }
17574    };
17575    effectInit({
17576      effect: 'cube',
17577      swiper,
17578      on,
17579      setTranslate,
17580      setTransition,
17581      recreateShadows,
17582      getEffectParams: () => swiper.params.cubeEffect,
17583      perspective: () => true,
17584      overwriteParams: () => ({
17585        slidesPerView: 1,
17586        slidesPerGroup: 1,
17587        watchSlidesProgress: true,
17588        resistanceRatio: 0,
17589        spaceBetween: 0,
17590        centeredSlides: false,
17591        virtualTranslate: true
17592      })
17593    });
17594  }
17595
17596  function createShadow(suffix, slideEl, side) {
17597    const shadowClass = `swiper-slide-shadow${side ? `-${side}` : ''}${suffix ? ` swiper-slide-shadow-${suffix}` : ''}`;
17598    const shadowContainer = getSlideTransformEl(slideEl);
17599    let shadowEl = shadowContainer.querySelector(`.${shadowClass.split(' ').join('.')}`);
17600    if (!shadowEl) {
17601      shadowEl = createElement('div', shadowClass.split(' '));
17602      shadowContainer.append(shadowEl);
17603    }
17604    return shadowEl;
17605  }
17606
17607  function EffectFlip({
17608    swiper,
17609    extendParams,
17610    on
17611  }) {
17612    extendParams({
17613      flipEffect: {
17614        slideShadows: true,
17615        limitRotation: true
17616      }
17617    });
17618    const createSlideShadows = (slideEl, progress) => {
17619      let shadowBefore = swiper.isHorizontal() ? slideEl.querySelector('.swiper-slide-shadow-left') : slideEl.querySelector('.swiper-slide-shadow-top');
17620      let shadowAfter = swiper.isHorizontal() ? slideEl.querySelector('.swiper-slide-shadow-right') : slideEl.querySelector('.swiper-slide-shadow-bottom');
17621      if (!shadowBefore) {
17622        shadowBefore = createShadow('flip', slideEl, swiper.isHorizontal() ? 'left' : 'top');
17623      }
17624      if (!shadowAfter) {
17625        shadowAfter = createShadow('flip', slideEl, swiper.isHorizontal() ? 'right' : 'bottom');
17626      }
17627      if (shadowBefore) shadowBefore.style.opacity = Math.max(-progress, 0);
17628      if (shadowAfter) shadowAfter.style.opacity = Math.max(progress, 0);
17629    };
17630    const recreateShadows = () => {
17631      // Set shadows
17632      swiper.params.flipEffect;
17633      swiper.slides.forEach(slideEl => {
17634        let progress = slideEl.progress;
17635        if (swiper.params.flipEffect.limitRotation) {
17636          progress = Math.max(Math.min(slideEl.progress, 1), -1);
17637        }
17638        createSlideShadows(slideEl, progress);
17639      });
17640    };
17641    const setTranslate = () => {
17642      const {
17643        slides,
17644        rtlTranslate: rtl
17645      } = swiper;
17646      const params = swiper.params.flipEffect;
17647      const rotateFix = getRotateFix(swiper);
17648      for (let i = 0; i < slides.length; i += 1) {
17649        const slideEl = slides[i];
17650        let progress = slideEl.progress;
17651        if (swiper.params.flipEffect.limitRotation) {
17652          progress = Math.max(Math.min(slideEl.progress, 1), -1);
17653        }
17654        const offset = slideEl.swiperSlideOffset;
17655        const rotate = -180 * progress;
17656        let rotateY = rotate;
17657        let rotateX = 0;
17658        let tx = swiper.params.cssMode ? -offset - swiper.translate : -offset;
17659        let ty = 0;
17660        if (!swiper.isHorizontal()) {
17661          ty = tx;
17662          tx = 0;
17663          rotateX = -rotateY;
17664          rotateY = 0;
17665        } else if (rtl) {
17666          rotateY = -rotateY;
17667        }
17668        slideEl.style.zIndex = -Math.abs(Math.round(progress)) + slides.length;
17669        if (params.slideShadows) {
17670          createSlideShadows(slideEl, progress);
17671        }
17672        const transform = `translate3d(${tx}px, ${ty}px, 0px) rotateX(${rotateFix(rotateX)}deg) rotateY(${rotateFix(rotateY)}deg)`;
17673        const targetEl = effectTarget(params, slideEl);
17674        targetEl.style.transform = transform;
17675      }
17676    };
17677    const setTransition = duration => {
17678      const transformElements = swiper.slides.map(slideEl => getSlideTransformEl(slideEl));
17679      transformElements.forEach(el => {
17680        el.style.transitionDuration = `${duration}ms`;
17681        el.querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').forEach(shadowEl => {
17682          shadowEl.style.transitionDuration = `${duration}ms`;
17683        });
17684      });
17685      effectVirtualTransitionEnd({
17686        swiper,
17687        duration,
17688        transformElements
17689      });
17690    };
17691    effectInit({
17692      effect: 'flip',
17693      swiper,
17694      on,
17695      setTranslate,
17696      setTransition,
17697      recreateShadows,
17698      getEffectParams: () => swiper.params.flipEffect,
17699      perspective: () => true,
17700      overwriteParams: () => ({
17701        slidesPerView: 1,
17702        slidesPerGroup: 1,
17703        watchSlidesProgress: true,
17704        spaceBetween: 0,
17705        virtualTranslate: !swiper.params.cssMode
17706      })
17707    });
17708  }
17709
17710  function EffectCoverflow({
17711    swiper,
17712    extendParams,
17713    on
17714  }) {
17715    extendParams({
17716      coverflowEffect: {
17717        rotate: 50,
17718        stretch: 0,
17719        depth: 100,
17720        scale: 1,
17721        modifier: 1,
17722        slideShadows: true
17723      }
17724    });
17725    const setTranslate = () => {
17726      const {
17727        width: swiperWidth,
17728        height: swiperHeight,
17729        slides,
17730        slidesSizesGrid
17731      } = swiper;
17732      const params = swiper.params.coverflowEffect;
17733      const isHorizontal = swiper.isHorizontal();
17734      const transform = swiper.translate;
17735      const center = isHorizontal ? -transform + swiperWidth / 2 : -transform + swiperHeight / 2;
17736      const rotate = isHorizontal ? params.rotate : -params.rotate;
17737      const translate = params.depth;
17738      const r = getRotateFix(swiper);
17739      // Each slide offset from center
17740      for (let i = 0, length = slides.length; i < length; i += 1) {
17741        const slideEl = slides[i];
17742        const slideSize = slidesSizesGrid[i];
17743        const slideOffset = slideEl.swiperSlideOffset;
17744        const centerOffset = (center - slideOffset - slideSize / 2) / slideSize;
17745        const offsetMultiplier = typeof params.modifier === 'function' ? params.modifier(centerOffset) : centerOffset * params.modifier;
17746        let rotateY = isHorizontal ? rotate * offsetMultiplier : 0;
17747        let rotateX = isHorizontal ? 0 : rotate * offsetMultiplier;
17748        // var rotateZ = 0
17749        let translateZ = -translate * Math.abs(offsetMultiplier);
17750        let stretch = params.stretch;
17751        // Allow percentage to make a relative stretch for responsive sliders
17752        if (typeof stretch === 'string' && stretch.indexOf('%') !== -1) {
17753          stretch = parseFloat(params.stretch) / 100 * slideSize;
17754        }
17755        let translateY = isHorizontal ? 0 : stretch * offsetMultiplier;
17756        let translateX = isHorizontal ? stretch * offsetMultiplier : 0;
17757        let scale = 1 - (1 - params.scale) * Math.abs(offsetMultiplier);
17758
17759        // Fix for ultra small values
17760        if (Math.abs(translateX) < 0.001) translateX = 0;
17761        if (Math.abs(translateY) < 0.001) translateY = 0;
17762        if (Math.abs(translateZ) < 0.001) translateZ = 0;
17763        if (Math.abs(rotateY) < 0.001) rotateY = 0;
17764        if (Math.abs(rotateX) < 0.001) rotateX = 0;
17765        if (Math.abs(scale) < 0.001) scale = 0;
17766        const slideTransform = `translate3d(${translateX}px,${translateY}px,${translateZ}px)  rotateX(${r(rotateX)}deg) rotateY(${r(rotateY)}deg) scale(${scale})`;
17767        const targetEl = effectTarget(params, slideEl);
17768        targetEl.style.transform = slideTransform;
17769        slideEl.style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;
17770        if (params.slideShadows) {
17771          // Set shadows
17772          let shadowBeforeEl = isHorizontal ? slideEl.querySelector('.swiper-slide-shadow-left') : slideEl.querySelector('.swiper-slide-shadow-top');
17773          let shadowAfterEl = isHorizontal ? slideEl.querySelector('.swiper-slide-shadow-right') : slideEl.querySelector('.swiper-slide-shadow-bottom');
17774          if (!shadowBeforeEl) {
17775            shadowBeforeEl = createShadow('coverflow', slideEl, isHorizontal ? 'left' : 'top');
17776          }
17777          if (!shadowAfterEl) {
17778            shadowAfterEl = createShadow('coverflow', slideEl, isHorizontal ? 'right' : 'bottom');
17779          }
17780          if (shadowBeforeEl) shadowBeforeEl.style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0;
17781          if (shadowAfterEl) shadowAfterEl.style.opacity = -offsetMultiplier > 0 ? -offsetMultiplier : 0;
17782        }
17783      }
17784    };
17785    const setTransition = duration => {
17786      const transformElements = swiper.slides.map(slideEl => getSlideTransformEl(slideEl));
17787      transformElements.forEach(el => {
17788        el.style.transitionDuration = `${duration}ms`;
17789        el.querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').forEach(shadowEl => {
17790          shadowEl.style.transitionDuration = `${duration}ms`;
17791        });
17792      });
17793    };
17794    effectInit({
17795      effect: 'coverflow',
17796      swiper,
17797      on,
17798      setTranslate,
17799      setTransition,
17800      perspective: () => true,
17801      overwriteParams: () => ({
17802        watchSlidesProgress: true
17803      })
17804    });
17805  }
17806
17807  function EffectCreative({
17808    swiper,
17809    extendParams,
17810    on
17811  }) {
17812    extendParams({
17813      creativeEffect: {
17814        limitProgress: 1,
17815        shadowPerProgress: false,
17816        progressMultiplier: 1,
17817        perspective: true,
17818        prev: {
17819          translate: [0, 0, 0],
17820          rotate: [0, 0, 0],
17821          opacity: 1,
17822          scale: 1
17823        },
17824        next: {
17825          translate: [0, 0, 0],
17826          rotate: [0, 0, 0],
17827          opacity: 1,
17828          scale: 1
17829        }
17830      }
17831    });
17832    const getTranslateValue = value => {
17833      if (typeof value === 'string') return value;
17834      return `${value}px`;
17835    };
17836    const setTranslate = () => {
17837      const {
17838        slides,
17839        wrapperEl,
17840        slidesSizesGrid
17841      } = swiper;
17842      const params = swiper.params.creativeEffect;
17843      const {
17844        progressMultiplier: multiplier
17845      } = params;
17846      const isCenteredSlides = swiper.params.centeredSlides;
17847      const rotateFix = getRotateFix(swiper);
17848      if (isCenteredSlides) {
17849        const margin = slidesSizesGrid[0] / 2 - swiper.params.slidesOffsetBefore || 0;
17850        wrapperEl.style.transform = `translateX(calc(50% - ${margin}px))`;
17851      }
17852      for (let i = 0; i < slides.length; i += 1) {
17853        const slideEl = slides[i];
17854        const slideProgress = slideEl.progress;
17855        const progress = Math.min(Math.max(slideEl.progress, -params.limitProgress), params.limitProgress);
17856        let originalProgress = progress;
17857        if (!isCenteredSlides) {
17858          originalProgress = Math.min(Math.max(slideEl.originalProgress, -params.limitProgress), params.limitProgress);
17859        }
17860        const offset = slideEl.swiperSlideOffset;
17861        const t = [swiper.params.cssMode ? -offset - swiper.translate : -offset, 0, 0];
17862        const r = [0, 0, 0];
17863        let custom = false;
17864        if (!swiper.isHorizontal()) {
17865          t[1] = t[0];
17866          t[0] = 0;
17867        }
17868        let data = {
17869          translate: [0, 0, 0],
17870          rotate: [0, 0, 0],
17871          scale: 1,
17872          opacity: 1
17873        };
17874        if (progress < 0) {
17875          data = params.next;
17876          custom = true;
17877        } else if (progress > 0) {
17878          data = params.prev;
17879          custom = true;
17880        }
17881        // set translate
17882        t.forEach((value, index) => {
17883          t[index] = `calc(${value}px + (${getTranslateValue(data.translate[index])} * ${Math.abs(progress * multiplier)}))`;
17884        });
17885        // set rotates
17886        r.forEach((value, index) => {
17887          let val = data.rotate[index] * Math.abs(progress * multiplier);
17888          r[index] = val;
17889        });
17890        slideEl.style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length;
17891        const translateString = t.join(', ');
17892        const rotateString = `rotateX(${rotateFix(r[0])}deg) rotateY(${rotateFix(r[1])}deg) rotateZ(${rotateFix(r[2])}deg)`;
17893        const scaleString = originalProgress < 0 ? `scale(${1 + (1 - data.scale) * originalProgress * multiplier})` : `scale(${1 - (1 - data.scale) * originalProgress * multiplier})`;
17894        const opacityString = originalProgress < 0 ? 1 + (1 - data.opacity) * originalProgress * multiplier : 1 - (1 - data.opacity) * originalProgress * multiplier;
17895        const transform = `translate3d(${translateString}) ${rotateString} ${scaleString}`;
17896
17897        // Set shadows
17898        if (custom && data.shadow || !custom) {
17899          let shadowEl = slideEl.querySelector('.swiper-slide-shadow');
17900          if (!shadowEl && data.shadow) {
17901            shadowEl = createShadow('creative', slideEl);
17902          }
17903          if (shadowEl) {
17904            const shadowOpacity = params.shadowPerProgress ? progress * (1 / params.limitProgress) : progress;
17905            shadowEl.style.opacity = Math.min(Math.max(Math.abs(shadowOpacity), 0), 1);
17906          }
17907        }
17908        const targetEl = effectTarget(params, slideEl);
17909        targetEl.style.transform = transform;
17910        targetEl.style.opacity = opacityString;
17911        if (data.origin) {
17912          targetEl.style.transformOrigin = data.origin;
17913        }
17914      }
17915    };
17916    const setTransition = duration => {
17917      const transformElements = swiper.slides.map(slideEl => getSlideTransformEl(slideEl));
17918      transformElements.forEach(el => {
17919        el.style.transitionDuration = `${duration}ms`;
17920        el.querySelectorAll('.swiper-slide-shadow').forEach(shadowEl => {
17921          shadowEl.style.transitionDuration = `${duration}ms`;
17922        });
17923      });
17924      effectVirtualTransitionEnd({
17925        swiper,
17926        duration,
17927        transformElements,
17928        allSlides: true
17929      });
17930    };
17931    effectInit({
17932      effect: 'creative',
17933      swiper,
17934      on,
17935      setTranslate,
17936      setTransition,
17937      perspective: () => swiper.params.creativeEffect.perspective,
17938      overwriteParams: () => ({
17939        watchSlidesProgress: true,
17940        virtualTranslate: !swiper.params.cssMode
17941      })
17942    });
17943  }
17944
17945  function EffectCards({
17946    swiper,
17947    extendParams,
17948    on
17949  }) {
17950    extendParams({
17951      cardsEffect: {
17952        slideShadows: true,
17953        rotate: true,
17954        perSlideRotate: 2,
17955        perSlideOffset: 8
17956      }
17957    });
17958    const setTranslate = () => {
17959      const {
17960        slides,
17961        activeIndex,
17962        rtlTranslate: rtl
17963      } = swiper;
17964      const params = swiper.params.cardsEffect;
17965      const {
17966        startTranslate,
17967        isTouched
17968      } = swiper.touchEventsData;
17969      const currentTranslate = rtl ? -swiper.translate : swiper.translate;
17970      for (let i = 0; i < slides.length; i += 1) {
17971        const slideEl = slides[i];
17972        const slideProgress = slideEl.progress;
17973        const progress = Math.min(Math.max(slideProgress, -4), 4);
17974        let offset = slideEl.swiperSlideOffset;
17975        if (swiper.params.centeredSlides && !swiper.params.cssMode) {
17976          swiper.wrapperEl.style.transform = `translateX(${swiper.minTranslate()}px)`;
17977        }
17978        if (swiper.params.centeredSlides && swiper.params.cssMode) {
17979          offset -= slides[0].swiperSlideOffset;
17980        }
17981        let tX = swiper.params.cssMode ? -offset - swiper.translate : -offset;
17982        let tY = 0;
17983        const tZ = -100 * Math.abs(progress);
17984        let scale = 1;
17985        let rotate = -params.perSlideRotate * progress;
17986        let tXAdd = params.perSlideOffset - Math.abs(progress) * 0.75;
17987        const slideIndex = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.from + i : i;
17988        const isSwipeToNext = (slideIndex === activeIndex || slideIndex === activeIndex - 1) && progress > 0 && progress < 1 && (isTouched || swiper.params.cssMode) && currentTranslate < startTranslate;
17989        const isSwipeToPrev = (slideIndex === activeIndex || slideIndex === activeIndex + 1) && progress < 0 && progress > -1 && (isTouched || swiper.params.cssMode) && currentTranslate > startTranslate;
17990        if (isSwipeToNext || isSwipeToPrev) {
17991          const subProgress = (1 - Math.abs((Math.abs(progress) - 0.5) / 0.5)) ** 0.5;
17992          rotate += -28 * progress * subProgress;
17993          scale += -0.5 * subProgress;
17994          tXAdd += 96 * subProgress;
17995          tY = `${(params.rotate || swiper.isHorizontal() ? -25 : 0) * subProgress * Math.abs(progress)}%`;
17996        }
17997        if (progress < 0) {
17998          // next
17999          tX = `calc(${tX}px ${rtl ? '-' : '+'} (${tXAdd * Math.abs(progress)}%))`;
18000        } else if (progress > 0) {
18001          // prev
18002          tX = `calc(${tX}px ${rtl ? '-' : '+'} (-${tXAdd * Math.abs(progress)}%))`;
18003        } else {
18004          tX = `${tX}px`;
18005        }
18006        if (!swiper.isHorizontal()) {
18007          const prevY = tY;
18008          tY = tX;
18009          tX = prevY;
18010        }
18011        const scaleString = progress < 0 ? `${1 + (1 - scale) * progress}` : `${1 - (1 - scale) * progress}`;
18012
18013        /* eslint-disable */
18014        const transform = `
18015        translate3d(${tX}, ${tY}, ${tZ}px)
18016        rotateZ(${params.rotate ? rtl ? -rotate : rotate : 0}deg)
18017        scale(${scaleString})
18018      `;
18019        /* eslint-enable */
18020
18021        if (params.slideShadows) {
18022          // Set shadows
18023          let shadowEl = slideEl.querySelector('.swiper-slide-shadow');
18024          if (!shadowEl) {
18025            shadowEl = createShadow('cards', slideEl);
18026          }
18027          if (shadowEl) shadowEl.style.opacity = Math.min(Math.max((Math.abs(progress) - 0.5) / 0.5, 0), 1);
18028        }
18029        slideEl.style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length;
18030        const targetEl = effectTarget(params, slideEl);
18031        targetEl.style.transform = transform;
18032      }
18033    };
18034    const setTransition = duration => {
18035      const transformElements = swiper.slides.map(slideEl => getSlideTransformEl(slideEl));
18036      transformElements.forEach(el => {
18037        el.style.transitionDuration = `${duration}ms`;
18038        el.querySelectorAll('.swiper-slide-shadow').forEach(shadowEl => {
18039          shadowEl.style.transitionDuration = `${duration}ms`;
18040        });
18041      });
18042      effectVirtualTransitionEnd({
18043        swiper,
18044        duration,
18045        transformElements
18046      });
18047    };
18048    effectInit({
18049      effect: 'cards',
18050      swiper,
18051      on,
18052      setTranslate,
18053      setTransition,
18054      perspective: () => true,
18055      overwriteParams: () => ({
18056        _loopSwapReset: false,
18057        watchSlidesProgress: true,
18058        loopAdditionalSlides: swiper.params.cardsEffect.rotate ? 3 : 2,
18059        centeredSlides: true,
18060        virtualTranslate: !swiper.params.cssMode
18061      })
18062    });
18063  }
18064
18065  /**
18066   * Swiper 12.0.3
18067   * Most modern mobile touch slider and framework with hardware accelerated transitions
18068   * https://swiperjs.com
18069   *
18070   * Copyright 2014-2025 Vladimir Kharlampidi
18071   *
18072   * Released under the MIT License
18073   *
18074   * Released on: October 21, 2025
18075   */
18076
18077
18078  // Swiper Class
18079  const modules = [Virtual, Keyboard, Mousewheel, Navigation, Pagination, Scrollbar, Parallax, Zoom, Controller, A11y, History, HashNavigation, Autoplay, Thumb, freeMode, Grid, Manipulation, EffectFade, EffectCube, EffectFlip, EffectCoverflow, EffectCreative, EffectCards];
18080  Swiper.use(modules);
18081
18082  return Swiper;
18083
18084})();
18085
18086(function () {
18087
18088  const hasGalleryBodyClass = !!(document.body && (
18089    document.body.classList.contains('Gallery') ||
18090    document.body.classList.contains('Body--Gallery') ||
18091    document.body.classList.contains('BodyGallery')
18092  ));
18093
18094  const galleries = document.querySelectorAll('.MediaGallery, .MediaGalleryFullWidth');
18095  if (!galleries.length) {
18096    return;
18097  }
18098  const adIds = [];
18099  const adSlots = new Map();
18100
18101  /*
18102   * Konstanten-Dokumentation
18103   *
18104   * Layout/Rendering:
18105   * - AD_VERTICAL_OFFSET_PERCENT: Vertikaler Offset zur Positionierung des Ads im Ad-Slide.
18106   * - DEFAULT_INITIAL_SLIDE_HEIGHT_PX: Fallback-Start-Minimalhoehe fuer Slider/Slides.
18107   * - DEFAULT_SLIDER_CONTAINER_MIN_HEIGHT_PX: Standard-Minimalhoehe fuer normale Galerien.
18108   * - DEFAULT_FULLWIDTH_SLIDER_CONTAINER_MIN_HEIGHT_PX: Standard-Minimalhoehe fuer Fullwidth-Galerien.
18109   * - AUTO_HEIGHT_TOLERANCE_PX: Toleranz, ab der eine AutoHeight-Neuberechnung noetig ist.
18110   *
18111   * Debug/Beobachtbarkeit:
18112   * - DEBUG_EVENT_LIMIT: Maximale Anzahl gespeicherter Debug-Events im Ringpuffer.
18113   * - EXTERNAL_SLOT_HISTORY_LIMIT: Maximale Anzahl Historieneintraege je externem Slot.
18114   *
18115   * Refresh-Regeln (intern/extern):
18116   * - MIN_REFRESH_INTERVAL_MS: Untergrenze fuer konfigurierbares Refresh-Intervall (>= 30s).
18117   * - DEFAULT_REFRESH_INTERVAL_MS: Default-Refresh-Intervall fuer zeitgesteuerte Pruefungen.
18118   * - DEFAULT_MIN_VIEWABLE_MS: Mindestdauer, die ein Slot sichtbar sein muss.
18119   * - DEFAULT_USER_IDLE_TIMEOUT_MS: Inaktivitaetsgrenze; danach wird Refresh pausiert.
18120   * - DEFAULT_ELIGIBILITY_CACHE_TTL_MS: Cache-Lebensdauer fuer Eligibility-Abfragen.
18121   * - SLOT_VIEWPORT_THRESHOLD: Sichtbarkeits-Schwelle fuer internen Gallery-Slot (0..1).
18122   * - EXTERNAL_SLOT_VIEWPORT_THRESHOLD: Sichtbarkeits-Schwelle fuer externe Slots (0..1).
18123   * - EXTERNAL_REFRESH_COOLDOWN_MS: Mindestabstand zwischen externen Refreshes (ausser adPos-Trigger).
18124   *
18125   * Externe Slots:
18126   * - EXTERNAL_REFRESH_SLOT_IDS: IDs der externen Werbeflaechen, die mitrefreshen sollen.
18127   *
18128   * Display/Targeting-Orchestrierung:
18129   * - REQUIRED_PAGE_TARGETING_KEYS: Muss-Targeting-Keys vor display(), sonst Warteschleife/Fallback.
18130   * - MAX_DISPLAY_WAIT_ATTEMPTS: Maximale Anzahl Warteversuche auf Targeting.
18131   * - DISPLAY_WAIT_INTERVAL_MS: Intervall zwischen den Warteversuchen.
18132   *
18133   * Debug-Helfer (window.*):
18134   * - __galleryDebug: Aktiviert Konsolen-Logs der Galerie-Debugmeldungen.
18135   * - __galleryDebugVisualRefresh: Visuelle Marker an externen Slots (Request/Render).
18136   * - __galleryExternalRefreshForceNewCorrelator: Erzwingt externen Refresh mit changeCorrelator=true.
18137   * - __galleryExternalSlotViewportThreshold: Optionaler Viewport-Threshold (0..1) fuer externe Slots.
18138   * - __galleryDebugPing(): Kurzer Lebenszeichen-Check (Galleries/Slots/pubadsReady).
18139   * - __galleryDebugEvents(): Liefert den aktuellen Event-Puffer als Array.
18140   * - __galleryDebugDumpEvents(): Schreibt kompletten Event-Puffer als Snapshot ins Log.
18141   * - __galleryDebugDumpAdFlow(): Loggt gefilterten Ad-Flow ohne Thumb/Virtual-Tracking-Rauschen.
18142   * - __galleryDebugDump(): Snapshot zu adIds, Slot-States und registrierten GPT-Slots.
18143   * - __galleryDebugRefresh(): Trigger fuer manuellen Refresh der internen Gallery-Slots.
18144   * - __galleryDebugTargetingDump(): Dump der aktuellen Slot-Targeting-Informationen.
18145   * - __galleryDebugExternalStats(): Snapshot inkl. Historie fuer externe Slots.
18146   */
18147
18148  const AD_VERTICAL_OFFSET_PERCENT = 0;
18149  const DEFAULT_INITIAL_SLIDE_HEIGHT_PX = 0;
18150  const DEFAULT_SLIDER_CONTAINER_MIN_HEIGHT_PX = 540;
18151  const DEFAULT_FULLWIDTH_SLIDER_CONTAINER_MIN_HEIGHT_PX = 940;
18152  const AUTO_HEIGHT_TOLERANCE_PX = 6;
18153  const slotTargetingState = new WeakMap();
18154  const debugEventBuffer = [];
18155  const DEBUG_EVENT_LIMIT = 250;
18156  const REQUIRED_PAGE_TARGETING_KEYS = ['kw_page_url'];
18157  const MAX_DISPLAY_WAIT_ATTEMPTS = 20;
18158  const DISPLAY_WAIT_INTERVAL_MS = 120;
18159  const MIN_REFRESH_INTERVAL_MS = 30000;
18160  const DEFAULT_REFRESH_INTERVAL_MS = 30000;
18161  const DEFAULT_MIN_VIEWABLE_MS = 3000;
18162  const DEFAULT_USER_IDLE_TIMEOUT_MS = 20000;
18163  const DEFAULT_ELIGIBILITY_CACHE_TTL_MS = 120000;
18164  const SLOT_VIEWPORT_THRESHOLD = 0.5;
18165  const EXTERNAL_SLOT_VIEWPORT_THRESHOLD = 0.2;
18166  const EXTERNAL_REFRESH_SLOT_IDS = [
18167    'renderSlot_Billboard',
18168    'renderSlot_Skyscraper-links',
18169    'renderSlot_Skyscraper-rechts',
18170  ];
18171  const EXTERNAL_REFRESH_COOLDOWN_MS = 1000;
18172  const EXTERNAL_SLOT_HISTORY_LIMIT = 20;
18173  const ACTIVE_AD_FALLBACK_RETRY_MS = 450;
18174  const AD_SLIDE_REENTRY_GUARD_MS = 900;
18175  let lastExternalRefreshTs = Date.now();
18176  let externalRefreshCount = 0;
18177
18178  function createExternalSlotStatsBucket() {
18179    return {
18180      refreshCallTriggered: 0,
18181      slotRequested: 0,
18182      slotResponseReceived: 0,
18183      slotRenderEnded: 0,
18184      lastRenderLineItemId: null,
18185      lastRenderCreativeId: null,
18186      lastRenderTs: null,
18187      history: [],
18188    };
18189  }
18190
18191  const externalSlotDebugStats = {
18192    totals: {
18193      refreshCallTriggered: 0,
18194      slotRequested: 0,
18195      slotResponseReceived: 0,
18196      slotRenderEnded: 0,
18197    },
18198    bySlot: EXTERNAL_REFRESH_SLOT_IDS.reduce(function (acc, slotId) {
18199      acc[slotId] = createExternalSlotStatsBucket();
18200      return acc;
18201    }, {}),
18202  };
18203
18204  function ensureExternalSlotStats(slotId) {
18205    if (!externalSlotDebugStats.bySlot[slotId]) {
18206      externalSlotDebugStats.bySlot[slotId] = createExternalSlotStatsBucket();
18207    }
18208    return externalSlotDebugStats.bySlot[slotId];
18209  }
18210
18211  function pushExternalSlotHistory(slotId, eventType, payload) {
18212    if (!slotId || !eventType) {
18213      return;
18214    }
18215
18216    const slotStats = ensureExternalSlotStats(slotId);
18217    slotStats.history.push(Object.assign({
18218      ts: new Date().toISOString(),
18219      event: eventType,
18220    }, payload || {}));
18221
18222    if (slotStats.history.length > EXTERNAL_SLOT_HISTORY_LIMIT) {
18223      slotStats.history.shift();
18224    }
18225  }
18226
18227  function flashExternalSlotDebugMarker(slotId, phase) {
18228    if (typeof window === 'undefined' || !window.__galleryDebugVisualRefresh) {
18229      return;
18230    }
18231
18232    const slotElement = document.getElementById(slotId);
18233    if (!slotElement) {
18234      return;
18235    }
18236
18237    const isRenderPhase = phase === 'render';
18238    const borderColor = isRenderPhase ? '#2e7d32' : '#c62828';
18239    const shadowColor = isRenderPhase ? 'rgba(46, 125, 50, 0.82)' : 'rgba(198, 40, 40, 0.72)';
18240    const holdMs = isRenderPhase ? 700 : 260;
18241    const transitionMs = isRenderPhase ? 180 : 120;
18242
18243    slotElement.__galleryDebugMarkerToken = (slotElement.__galleryDebugMarkerToken || 0) + 1;
18244    const markerToken = slotElement.__galleryDebugMarkerToken;
18245
18246    slotElement.style.transition = 'box-shadow ' + transitionMs + 'ms ease-out, outline-color ' + transitionMs + 'ms ease-out';
18247    slotElement.style.outline = '3px solid ' + borderColor;
18248    slotElement.style.boxShadow = '0 0 0 4px ' + shadowColor;
18249
18250    window.setTimeout(function () {
18251      if (!slotElement || !slotElement.style) {
18252        return;
18253      }
18254      if (slotElement.__galleryDebugMarkerToken !== markerToken) {
18255        return;
18256      }
18257      slotElement.style.outline = '';
18258      slotElement.style.boxShadow = '';
18259    }, holdMs);
18260  }
18261
18262  function incrementExternalSlotStat(slotId, key) {
18263    if (!slotId || !key) {
18264      return;
18265    }
18266
18267    if (externalSlotDebugStats.totals[key] === undefined) {
18268      externalSlotDebugStats.totals[key] = 0;
18269    }
18270    externalSlotDebugStats.totals[key] += 1;
18271
18272    const slotStats = ensureExternalSlotStats(slotId);
18273
18274    if (slotStats[key] === undefined) {
18275      slotStats[key] = 0;
18276    }
18277    slotStats[key] += 1;
18278  }
18279
18280  function parsePositiveInt(value, fallback) {
18281    const parsed = parseInt(value, 10);
18282    return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
18283  }
18284
18285  function getRefreshRuntimeConfig() {
18286    const cfg = (typeof window !== 'undefined' && window.__galleryAdRefreshConfig && typeof window.__galleryAdRefreshConfig === 'object')
18287      ? window.__galleryAdRefreshConfig
18288      : {};
18289
18290    const refreshIntervalMs = Math.max(
18291      MIN_REFRESH_INTERVAL_MS,
18292      parsePositiveInt(cfg.refreshIntervalMs, DEFAULT_REFRESH_INTERVAL_MS)
18293    );
18294
18295    return {
18296      refreshIntervalMs: refreshIntervalMs,
18297      minViewableMs: parsePositiveInt(cfg.minViewableMs, DEFAULT_MIN_VIEWABLE_MS),
18298      userIdleTimeoutMs: parsePositiveInt(cfg.userIdleTimeoutMs, DEFAULT_USER_IDLE_TIMEOUT_MS),
18299      eligibilityCacheTtlMs: parsePositiveInt(cfg.eligibilityCacheTtlMs, DEFAULT_ELIGIBILITY_CACHE_TTL_MS),
18300      refreshCheckIntervalMs: parsePositiveInt(cfg.refreshCheckIntervalMs, 1000),
18301      strictDifferentLineItem: cfg.strictDifferentLineItem !== false,
18302    };
18303  }
18304
18305  const refreshRuntimeConfig = getRefreshRuntimeConfig();
18306  let lastUserActivityTs = Date.now();
18307  let hasExplicitUserInteraction = false;
18308
18309  function markUserActivity() {
18310    lastUserActivityTs = Date.now();
18311  }
18312
18313  function isUserRecentlyActive() {
18314    return (Date.now() - lastUserActivityTs) <= refreshRuntimeConfig.userIdleTimeoutMs;
18315  }
18316
18317  function isDocumentVisible() {
18318    if (typeof document === 'undefined') {
18319      return true;
18320    }
18321    if (typeof document.visibilityState === 'string') {
18322      return document.visibilityState === 'visible';
18323    }
18324    return true;
18325  }
18326
18327  if (typeof window !== 'undefined') {
18328    ['pointerdown', 'pointermove', 'keydown', 'scroll', 'touchstart', 'wheel', 'focus'].forEach(function (eventName) {
18329      window.addEventListener(eventName, markUserActivity, { passive: true });
18330    });
18331    ['pointerdown', 'keydown', 'touchstart', 'wheel', 'mousedown', 'click'].forEach(function (eventName) {
18332      window.addEventListener(eventName, function () {
18333        hasExplicitUserInteraction = true;
18334      }, { passive: true });
18335    });
18336    document.addEventListener('visibilitychange', function () {
18337      if (isDocumentVisible()) {
18338        markUserActivity();
18339      }
18340    });
18341  }
18342
18343  function debugAdLog(message, meta) {
18344    debugEventBuffer.push({
18345      ts: new Date().toISOString(),
18346      message: message,
18347      meta: meta || {},
18348    });
18349    if (debugEventBuffer.length > DEBUG_EVENT_LIMIT) {
18350      debugEventBuffer.shift();
18351    }
18352
18353    const isGalleryDebugEnabled = typeof window !== 'undefined' && !!window.__galleryDebug;
18354    if (!isGalleryDebugEnabled || !window.console) {
18355      return;
18356    }
18357
18358    if (typeof window.console.log === 'function') {
18359      window.console.log('[GalleryAds] ' + message, meta || '');
18360      return;
18361    }
18362
18363    if (typeof window.console.info === 'function') {
18364      window.console.info('[GalleryAds] ' + message, meta || '');
18365    }
18366  }
18367
18368  function applySlotConfigTargeting(slotObj, targeting) {
18369    if (!slotObj || !targeting || typeof targeting !== 'object') {
18370      return;
18371    }
18372
18373    const previousTargeting = slotTargetingState.get(slotObj) || {};
18374    const mergedTargeting = Object.assign({}, previousTargeting, targeting);
18375    slotTargetingState.set(slotObj, mergedTargeting);
18376
18377    if (typeof slotObj.setConfig === 'function') {
18378      slotObj.setConfig({ targeting: mergedTargeting });
18379      return;
18380    }
18381
18382    if (typeof slotObj.setTargeting !== 'function') {
18383      return;
18384    }
18385
18386    Object.keys(targeting).forEach(function (key) {
18387      slotObj.setTargeting(key, targeting[key]);
18388    });
18389  }
18390
18391  function getStoredSlotTargetingSnapshot(slotObj) {
18392    const stored = slotTargetingState.get(slotObj) || {};
18393    return Object.assign({}, stored);
18394  }
18395
18396  function normalizeTargetingSnapshot(rawTargeting) {
18397    if (!rawTargeting || typeof rawTargeting !== 'object') {
18398      return {};
18399    }
18400
18401    function collectPrimitiveTargetingValues(inputValue, collector) {
18402      if (inputValue === null || typeof inputValue === 'undefined') {
18403        return;
18404      }
18405
18406      if (Array.isArray(inputValue)) {
18407        inputValue.forEach(function (entry) {
18408          collectPrimitiveTargetingValues(entry, collector);
18409        });
18410        return;
18411      }
18412
18413      if (typeof inputValue === 'object') {
18414        // GPT kann je nach API-Variante Objektstrukturen liefern (z. B. mit `value`).
18415        if (Object.prototype.hasOwnProperty.call(inputValue, 'value')) {
18416          collectPrimitiveTargetingValues(inputValue.value, collector);
18417          return;
18418        }
18419        return;
18420      }
18421
18422      if (typeof inputValue === 'function') {
18423        return;
18424      }
18425
18426      const normalized = String(inputValue);
18427      if (normalized.length > 0) {
18428        collector[normalized] = true;
18429      }
18430    }
18431
18432    function setNormalizedValue(target, key, value) {
18433      if (!key || typeof key !== 'string') {
18434        return;
18435      }
18436
18437      const valuesCollector = {};
18438      collectPrimitiveTargetingValues(value, valuesCollector);
18439      const normalizedValues = Object.keys(valuesCollector);
18440      if (normalizedValues.length === 0) {
18441        return;
18442      }
18443
18444      target[key] = normalizedValues;
18445    }
18446
18447    const normalized = {};
18448
18449    // GPT `getConfig('targeting')` kann als `{ targeting: {...} }` zurückkommen.
18450    if (
18451      Object.prototype.hasOwnProperty.call(rawTargeting, 'targeting') &&
18452      rawTargeting.targeting &&
18453      typeof rawTargeting.targeting === 'object' &&
18454      !Array.isArray(rawTargeting.targeting)
18455    ) {
18456      Object.keys(rawTargeting.targeting).forEach(function (nestedKey) {
18457        setNormalizedValue(normalized, nestedKey, rawTargeting.targeting[nestedKey]);
18458      });
18459      return normalized;
18460    }
18461
18462    Object.keys(rawTargeting).forEach(function (key) {
18463      setNormalizedValue(normalized, key, rawTargeting[key]);
18464    });
18465
18466    return normalized;
18467  }
18468
18469  function getSlotTargetingSnapshot(slotObj) {
18470    if (!slotObj) {
18471      return {};
18472    }
18473
18474    if (typeof slotObj.getConfig === 'function') {
18475      return normalizeTargetingSnapshot(slotObj.getConfig('targeting'));
18476    }
18477
18478    if (typeof slotObj.getTargetingKeys !== 'function' || typeof slotObj.getTargeting !== 'function') {
18479      return {};
18480    }
18481
18482    const targeting = {};
18483    slotObj.getTargetingKeys().forEach(function (key) {
18484      targeting[key] = slotObj.getTargeting(key);
18485    });
18486
18487    return normalizeTargetingSnapshot(targeting);
18488  }
18489
18490  function getPageTargetingSnapshot() {
18491    if (typeof googletag === 'undefined') {
18492      return {};
18493    }
18494
18495    if (typeof googletag.getConfig === 'function') {
18496      return normalizeTargetingSnapshot(googletag.getConfig('targeting'));
18497    }
18498
18499    if (!googletag.pubads || typeof googletag.pubads !== 'function') {
18500      return {};
18501    }
18502
18503    const pubads = googletag.pubads();
18504    if (!pubads || typeof pubads.getTargetingKeys !== 'function' || typeof pubads.getTargeting !== 'function') {
18505      return {};
18506    }
18507
18508    const pageTargeting = {};
18509    pubads.getTargetingKeys().forEach(function (key) {
18510      pageTargeting[key] = pubads.getTargeting(key);
18511    });
18512
18513    return normalizeTargetingSnapshot(pageTargeting);
18514  }
18515
18516  function getGalleryAdDatasetSnapshot(gallery) {
18517    if (!gallery || !gallery.dataset) {
18518      return {};
18519    }
18520
18521    const adGamIdRaw = typeof gallery.dataset.ad_gam_id === 'string' ? gallery.dataset.ad_gam_id : '';
18522    return {
18523      galleryId: gallery.id || null,
18524      adPosRaw: typeof gallery.dataset.adpos === 'string' ? gallery.dataset.adpos : null,
18525      adTargetingRaw: typeof gallery.dataset.ad_targeting === 'string' ? gallery.dataset.ad_targeting : null,
18526      hasAdGamId: adGamIdRaw.length > 0,
18527      adGamIdPreview: adGamIdRaw.slice(0, 180),
18528    };
18529  }
18530
18531  function mirrorPageTargetingToSlot(slotObj, keys) {
18532    if (!slotObj) {
18533      return;
18534    }
18535
18536    const pageTargeting = getPageTargetingSnapshot();
18537    const targetKeys = Array.isArray(keys) && keys.length > 0 ? keys : Object.keys(pageTargeting);
18538    const mirrored = {};
18539
18540    targetKeys.forEach(function (key) {
18541      const values = pageTargeting[key];
18542      if (!Array.isArray(values) || values.length === 0) {
18543        return;
18544      }
18545
18546      const normalized = values.filter(function (v) {
18547        return v !== null && typeof v !== 'undefined' && String(v).length > 0;
18548      }).map(function (v) {
18549        return String(v);
18550      });
18551
18552      if (normalized.length === 1) {
18553        mirrored[key] = normalized[0];
18554        return;
18555      }
18556
18557      if (normalized.length > 1) {
18558        mirrored[key] = normalized;
18559      }
18560    });
18561
18562    const mirroredKeys = Object.keys(mirrored);
18563    if (mirroredKeys.length === 0) {
18564      debugAdLog('Kein Page-Targeting zum Spiegeln vorhanden', {
18565        requestedKeys: targetKeys,
18566        availablePageKeys: Object.keys(pageTargeting),
18567      });
18568      return;
18569    }
18570
18571    applySlotConfigTargeting(slotObj, mirrored);
18572    debugAdLog('Page-Targeting auf Slot gespiegelt', {
18573      keys: mirroredKeys,
18574      values: mirrored,
18575    });
18576  }
18577
18578  function hasAllRequiredPageTargeting(keys) {
18579    if (!Array.isArray(keys) || keys.length === 0) {
18580      return true;
18581    }
18582
18583    const pageTargeting = getPageTargetingSnapshot();
18584    return keys.every(function (key) {
18585      const values = pageTargeting[key];
18586      return Array.isArray(values) && values.length > 0;
18587    });
18588  }
18589
18590  if (typeof window !== 'undefined') {
18591    window.__galleryDebugPing = function () {
18592      debugAdLog('Debug-Ping', {
18593        galleries: galleries.length,
18594        adIds: adIds.length,
18595        slots: adSlots.size,
18596        pubadsReady: !!googletag.pubadsReady,
18597      });
18598    };
18599
18600    window.__galleryDebugEvents = function () {
18601      return debugEventBuffer.slice();
18602    };
18603
18604    window.__galleryDebugDumpEvents = function () {
18605      debugAdLog('Debug-Eventbuffer Snapshot', {
18606        count: debugEventBuffer.length,
18607        events: debugEventBuffer.slice(),
18608      });
18609    };
18610
18611    window.__galleryDebugDumpAdFlow = function () {
18612      const adFlowEvents = debugEventBuffer.filter(function (entry) {
18613        return entry.message.indexOf('ThumbTrace') === -1 && entry.message.indexOf('Virtual-Tracking') === -1;
18614      });
18615
18616      debugAdLog('Debug-Ad-Flow Snapshot', {
18617        count: adFlowEvents.length,
18618        events: adFlowEvents,
18619      });
18620
18621      return adFlowEvents;
18622    };
18623  }
18624
18625  function normalizeTargetingValueForSlot(value) {
18626    if (value === null || typeof value === 'undefined') {
18627      return null;
18628    }
18629
18630    if (Array.isArray(value)) {
18631      const normalizedList = value.filter(function (v) {
18632        const valueType = typeof v;
18633        return v !== null && valueType !== 'undefined' && valueType !== 'object' && valueType !== 'function' && String(v).length > 0;
18634      }).map(function (v) {
18635        return String(v);
18636      });
18637
18638      return normalizedList.length > 0 ? normalizedList : null;
18639    }
18640
18641    const valueType = typeof value;
18642    if (valueType === 'object' || valueType === 'function') {
18643      return null;
18644    }
18645
18646    const normalizedValue = String(value);
18647    return normalizedValue.length > 0 ? normalizedValue : null;
18648  }
18649
18650  function applySlotTargeting(slotObj, adData) {
18651    if (!slotObj || (typeof slotObj.setConfig !== 'function' && typeof slotObj.setTargeting !== 'function') || !adData) {
18652      return;
18653    }
18654
18655    const targetingSources = [
18656      { name: 'targeting', data: adData.targeting },
18657      { name: 'gam_config.targeting', data: adData.gam_config && adData.gam_config.targeting },
18658    ];
18659
18660    const mergedTargeting = {};
18661    const sourceInfo = [];
18662    const droppedEntries = [];
18663
18664    targetingSources.forEach(function (source) {
18665      const targeting = source.data;
18666      if (!targeting || typeof targeting !== 'object') {
18667        sourceInfo.push({ source: source.name, present: false, keys: [] });
18668        return;
18669      }
18670
18671      const sourceKeys = Object.keys(targeting);
18672      sourceInfo.push({ source: source.name, present: sourceKeys.length > 0, keys: sourceKeys });
18673
18674      sourceKeys.forEach(function (key) {
18675        const value = targeting[key];
18676        const normalizedValue = normalizeTargetingValueForSlot(value);
18677        if (normalizedValue === null) {
18678          droppedEntries.push({
18679            key: key,
18680            source: source.name,
18681            type: Array.isArray(value) ? 'array' : typeof value,
18682          });
18683          return;
18684        }
18685
18686        mergedTargeting[key] = normalizedValue;
18687      });
18688    });
18689
18690    const appliedKeys = Object.keys(mergedTargeting);
18691    if (appliedKeys.length > 0) {
18692      applySlotConfigTargeting(slotObj, mergedTargeting);
18693    }
18694
18695    debugAdLog('Slot-Targeting ausgewertet', {
18696      path: adData.path || null,
18697      sourceInfo: sourceInfo,
18698      appliedKeys: appliedKeys,
18699      droppedEntries: droppedEntries,
18700    });
18701  }
18702
18703  function applyGalleryDatasetTargeting(slotObj, gallery) {
18704    if (!slotObj || (typeof slotObj.setConfig !== 'function' && typeof slotObj.setTargeting !== 'function') || !gallery || !gallery.dataset) {
18705      return;
18706    }
18707
18708    const adTargetingValue = typeof gallery.dataset.ad_targeting === 'string'
18709      ? gallery.dataset.ad_targeting.trim()
18710      : '';
18711
18712    if (!adTargetingValue) {
18713      return;
18714    }
18715
18716    applySlotConfigTargeting(slotObj, { kw: adTargetingValue });
18717
18718    debugAdLog('Gallery data-ad_targeting gesetzt', {
18719      galleryId: gallery.id || null,
18720      key: 'kw',
18721      value: adTargetingValue,
18722    });
18723  }
18724
18725  googletag.cmd.push(function () {
18726
18727    function getReferenceSlideHeight(gallery, targetAdSlide) {
18728      if (!gallery) {
18729        return 0;
18730      }
18731
18732      if (gallery.__lastImageSlideHeight && gallery.__lastImageSlideHeight > 0) {
18733        return gallery.__lastImageSlideHeight;
18734      }
18735
18736      const sliderContainer = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer');
18737      if (!sliderContainer) {
18738        return 0;
18739      }
18740
18741      const normalSlides = Array.from(sliderContainer.children).filter(function (slide) {
18742        return !slide.classList.contains('ad-slide');
18743      });
18744
18745      if (!normalSlides.length) {
18746        return targetAdSlide ? targetAdSlide.clientHeight : 0;
18747      }
18748
18749      const activeNormalSlide = normalSlides.find(function (slide) {
18750        return slide.classList.contains('swiper-slide-active');
18751      });
18752
18753      if (activeNormalSlide && activeNormalSlide.clientHeight > 0) {
18754        return activeNormalSlide.clientHeight;
18755      }
18756
18757      const maxHeight = normalSlides.reduce(function (acc, slide) {
18758        return Math.max(acc, slide.clientHeight || 0);
18759      }, 0);
18760
18761      return maxHeight;
18762    }
18763
18764    function rememberCurrentImageSlideHeight(gallery, swiperInstance) {
18765      if (!gallery || !swiperInstance || !swiperInstance.slides || typeof swiperInstance.activeIndex !== 'number') {
18766        return;
18767      }
18768
18769      const activeSlide = swiperInstance.slides[swiperInstance.activeIndex];
18770      if (!activeSlide || activeSlide.classList.contains('ad-slide')) {
18771        return;
18772      }
18773
18774      const measuredHeight = Math.max(
18775        activeSlide.offsetHeight || 0,
18776        activeSlide.scrollHeight || 0,
18777        Math.ceil(activeSlide.getBoundingClientRect ? activeSlide.getBoundingClientRect().height : 0)
18778      );
18779
18780      if (measuredHeight > 0) {
18781        gallery.__lastImageSlideHeight = measuredHeight;
18782      }
18783    }
18784
18785    function centerAdIframes(adContainer, targetAdSlide) {
18786      if (!adContainer) {
18787        return;
18788      }
18789
18790      let gallery = adContainer.closest('.MediaGallery, .MediaGalleryFullWidth');
18791      if (targetAdSlide) {
18792        gallery = targetAdSlide.closest('.MediaGallery, .MediaGalleryFullWidth');
18793      }
18794
18795      if (targetAdSlide) {
18796        // Kein Fremdwert von Bild-Slides erzwingen: Ad-Slide soll sich am Ad-Inhalt orientieren.
18797        targetAdSlide.style.minHeight = '0';
18798        targetAdSlide.style.height = 'auto';
18799
18800        targetAdSlide.style.display = 'flex';
18801        targetAdSlide.style.justifyContent = 'center';
18802        targetAdSlide.style.alignItems = 'center';
18803      }
18804
18805      adContainer.style.width = '100%';
18806      adContainer.style.height = '100%';
18807      adContainer.style.display = 'flex';
18808      adContainer.style.justifyContent = 'center';
18809      adContainer.style.alignItems = 'center';
18810      adContainer.style.textAlign = 'center';
18811      adContainer.style.minHeight = '0';
18812      adContainer.style.transform = 'translateY(' + AD_VERTICAL_OFFSET_PERCENT + '%)';
18813
18814      adContainer.querySelectorAll('iframe').forEach(function (iframe) {
18815        iframe.style.display = 'block';
18816        iframe.style.marginLeft = 'auto';
18817        iframe.style.marginRight = 'auto';
18818      });
18819
18820      if (targetAdSlide) {
18821        const firstIframe = adContainer.querySelector('iframe');
18822        const measuredHeight = firstIframe ? firstIframe.offsetHeight : adContainer.scrollHeight;
18823        const referenceHeight = getReferenceSlideHeight(gallery, targetAdSlide);
18824        const minHeight = Math.max(measuredHeight || 0, referenceHeight || 0
18824);
18825        if (minHeight > 0) {
18826          // Ensure vertical centering has enough available slide height.
18827          targetAdSlide.style.minHeight = minHeight + 'px';
18828        }
18829      }
18830
18831      if (!adContainer.__galleryAdObserver) {
18832        const observer = new MutationObserver(function () {
18833          adContainer.querySelectorAll('iframe').forEach(function (iframe) {
18834            iframe.style.display = 'block';
18835            iframe.style.marginLeft = 'auto';
18836            iframe.style.marginRight = 'auto';
18837          });
18838        });
18839
18840        observer.observe(adContainer, { childList: true, subtree: true });
18841        adContainer.__galleryAdObserver = observer;
18842      }
18843    }
18844
18845
18846    function removeAllAdMarkup(gallery) {
18847      const adElements = gallery.querySelectorAll('.ad-thumb, .ad-slide');
18848      adElements.forEach(function (el) {
18849        el.remove();
18850      });
18851
18852      debugAdLog('Ad-Markup entfernt', {
18853        galleryId: gallery.id || null,
18854        removedNodes: adElements.length,
18855      });
18856    }
18857
18858    function injectAdMarkup(slotInfo) {
18859      let adsAdded = 0;
18860      let insertedSlides = 0;
18861      const originalSlides = Array.from(slotInfo.mainWrapper.children).filter(function (slide) {
18862        return !slide.classList.contains('ad-slide');
18863      });
18864
18865      originalSlides.forEach(function (slide, index) {
18866        if ((index + 1) % slotInfo.adPos === 0) {
18867          const adSlide = document.createElement('div');
18868          adSlide.className = 'swiper-slide ad-slide MediaGallery_sliderImage';
18869          adSlide.style.height = 'auto';
18870          const insertAt = index + adsAdded + 1;
18871          slotInfo.mainWrapper.insertBefore(adSlide, slotInfo.mainWrapper.children[insertAt] || null);
18872          adsAdded++;
18873          insertedSlides++;
18874        }
18875      });
18876
18877      debugAdLog('Ad-Markup eingefuegt', {
18878        adId: slotInfo.adId,
18879        galleryId: slotInfo.gallery.id || null,
18880        insertedSlides: insertedSlides,
18881        insertedThumbs: 0,
18882      });
18883    }
18884
18885    function getImageIndexFromMainIndex(mainSlides, mainIndex) {
18886      let imageIndex = -1;
18887      for (let i = 0; i <= mainIndex; i++) {
18888        if (mainSlides[i] && !mainSlides[i].classList.contains('ad-slide')) {
18889          imageIndex++;
18890        }
18891      }
18892      return imageIndex;
18893    }
18894
18895    function getMainIndexFromImageIndex(mainSlides, imageIndex) {
18896      let currentImageIndex = -1;
18897      for (let i = 0; i < mainSlides.length; i++) {
18898        if (!mainSlides[i].classList.contains('ad-slide')) {
18899          currentImageIndex++;
18900          if (currentImageIndex === imageIndex) {
18901            return i;
18902          }
18903        }
18904      }
18905      return -1;
18906    }
18907
18908    function getThumbActiveClassIndex(gallery) {
18909      if (!gallery || !gallery.tSwiper || !gallery.tSwiper.slides) {
18910        return -1;
18911      }
18912
18913      for (let i = 0; i < gallery.tSwiper.slides.length; i++) {
18914        if (gallery.tSwiper.slides[i].classList.contains('swiper-slide-thumb-active')) {
18915          return i;
18916        }
18917      }
18918
18919      return -1;
18920    }
18921
18922    function traceThumbSync(gallery, stage, extra) {
18923      if (typeof window === 'undefined' || !window.__galleryDebug) {
18924        return;
18925      }
18926
18927      const mainSwiper = gallery && gallery.mSwiper;
18928      const mainActiveIndex = mainSwiper && typeof mainSwiper.activeIndex === 'number' ? mainSwiper.activeIndex : -1;
18929      const mainSlides = mainSwiper && mainSwiper.slides ? mainSwiper.slides : null;
18930      const imageIndex = mainSlides && mainActiveIndex >= 0 ? getImageIndexFromMainIndex(mainSlides, mainActiveIndex) : -1;
18931      const activeSlide = mainSlides && mainActiveIndex >= 0 ? mainSlides[mainActiveIndex] : null;
18932
18933      debugAdLog('ThumbTrace ' + stage, Object.assign({
18934        galleryId: gallery && gallery.id ? gallery.id : null,
18935        mainActiveIndex: mainActiveIndex,
18936        imageIndex: imageIndex,
18937        mainIsAd: !!(activeSlide && activeSlide.classList.contains('ad-slide')),
18938        thumbSwiperActiveIndex: gallery && gallery.tSwiper && typeof gallery.tSwiper.activeIndex === 'number' ? gallery.tSwiper.activeIndex : -1,
18939        thumbActiveClassIndex: getThumbActiveClassIndex(gallery),
18940        thumbSyncToken: gallery && gallery.__thumbSyncToken ? gallery.__thumbSyncToken : 0,
18941      }, extra || {}));
18942    }
18943
18944    function updateActiveThumbState(gallery, imageIndex) {
18945      if (!gallery || !gallery.tSwiper || !gallery.tSwiper.slides) {
18946        return;
18947      }
18948
18949      Array.from(gallery.tSwiper.slides).forEach(function (slide, idx) {
18950        const isActive = idx === imageIndex;
18951
18952        // Beide Klassen konsistent pflegen, da Theme-Styling auf swiper-slide-active basiert.
18953        slide.classList.toggle('swiper-slide-thumb-active', isActive);
18954        slide.classList.toggle('swiper-slide-active', isActive);
18955      });
18956
18957      traceThumbSync(gallery, 'updateActiveThumbState', { targetImageIndex: imageIndex });
18958    }
18959
18960    function clearActiveThumbState(gallery) {
18961      if (!gallery || !gallery.tSwiper || !gallery.tSwiper.slides) {
18962        return;
18963      }
18964
18965      Array.from(gallery.tSwiper.slides).forEach(function (slide) {
18966        slide.classList.remove('swiper-slide-thumb-active');
18967        slide.classList.remove('swiper-slide-active');
18968      });
18969
18970      traceThumbSync(gallery, 'clearActiveThumbState');
18971    }
18972
18973    function syncThumbSwiperToImageIndex(gallery, imageIndex) {
18974      if (!gallery || !gallery.tSwiper || typeof gallery.tSwiper.slideTo !== 'function') {
18975        return;
18976      }
18977
18978      if (!Number.isInteger(imageIndex) || imageIndex < 0) {
18979        return;
18980      }
18981
18982      traceThumbSync(gallery, 'syncThumbSwiperToImageIndex:start', { targetImageIndex: imageIndex });
18983
18984      // Ohne Animation synchronisieren, damit nach Ad-Slides kein Versatz entsteht.
18985      gallery.tSwiper.slideTo(imageIndex, 0);
18986      updateActiveThumbState(gallery, imageIndex);
18987
18988      // Schutz gegen stale RAF-Updates: nur der neueste Sync darf nachlaufen.
18989      gallery.__thumbSyncToken = (gallery.__thumbSyncToken || 0) + 1;
18990      const syncToken = gallery.__thumbSyncToken;
18991
18992      // Zweiter Tick: manche Swiper-Zustaende laufen nach dem ersten slideTo noch nach.
18993      if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') {
18994        window.requestAnimationFrame(function () {
18995          if (gallery.__thumbSyncToken !== syncToken) {
18996            traceThumbSync(gallery, 'syncThumbSwiperToImageIndex:raf-skip-stale', { targetImageIndex: imageIndex, syncToken: syncToken });
18997            return;
18998          }
18999
19000          gallery.tSwiper.slideTo(imageIndex, 0);
19001          updateActiveThumbState(gallery, imageIndex);
19002          traceThumbSync(gallery, 'syncThumbSwiperToImageIndex:raf-apply', { targetImageIndex: imageIndex, syncToken: syncToken });
19003        });
19004      }
19005
19006      traceThumbSync(gallery, 'syncThumbSwiperToImageIndex:end', { targetImageIndex: imageIndex, syncToken: syncToken });
19007    }
19008
19009    function syncThumbStateWithMainSwiper(gallery) {
19010      if (!gallery || !gallery.mSwiper || !gallery.tSwiper || !gallery.mSwiper.slides || typeof gallery.mSwiper.activeIndex !== 'number') {
19011        return;
19012      }
19013
19014      traceThumbSync(gallery, 'syncThumbStateWithMainSwiper:start');
19015
19016      const activeSlide = gallery.mSwiper.slides[gallery.mSwiper.activeIndex];
19017      if (!activeSlide) {
19018        return;
19019      }
19020
19021      if (activeSlide.classList.contains('ad-slide')) {
19022        clearActiveThumbState(gallery);
19023        traceThumbSync(gallery, 'syncThumbStateWithMainSwiper:active-ad');
19024        return;
19025      }
19026
19027      const imageIndex = getImageIndexFromMainIndex(gallery.mSwiper.slides, gallery.mSwiper.activeIndex);
19028      if (imageIndex >= 0) {
19029        updateActiveThumbState(gallery, imageIndex);
19030        syncThumbSwiperToImageIndex(gallery, imageIndex);
19031        traceThumbSync(gallery, 'syncThumbStateWithMainSwiper:active-image', { targetImageIndex: imageIndex });
19032      }
19033    }
19034
19035    function setGalleryAdNavigationState(gallery, activeSlide) {
19036      if (!gallery || !gallery.classList) {
19037        return;
19038      }
19039
19040      const isAdActive = !!(activeSlide && activeSlide.classList.contains('ad-slide'));
19041      gallery.classList.toggle('is-ad-active', isAdActive);
19042
19043      const overlays = gallery.querySelectorAll('.MediaGallery_slideLeft, .MediaGallery_slideRight, .MediaGalleryFullWidth_slideLeft, .MediaGalleryFullWidth_slideRight');
19044      if (!overlays.length) {
19045        return;
19046      }
19047
19048      overlays.forEach(function (overlayEl) {
19049        if (isAdActive) {
19050          // Schmale Rand-Klickzonen nur fuer Ad-Slides: Mitte bleibt fuer Ad-Klicks frei.
19051          overlayEl.style.width = '8%';
19052          overlayEl.style.pointerEvents = 'auto';
19053          return;
19054        }
19055
19056        // Fuer normale Bild-Slides wieder das CSS-Layout verwenden.
19057        overlayEl.style.width = '';
19058        overlayEl.style.pointerEvents = '';
19059      });
19060    }
19061
19062    function getActiveSlideHeight(swiperInstance) {
19063      if (!swiperInstance || !swiperInstance.slides || typeof swiperInstance.activeIndex !== 'number') {
19064        return 0;
19065      }
19066
19067      const activeSlide = swiperInstance.slides[swiperInstance.activeIndex];
19068      if (!activeSlide) {
19069        return 0;
19070      }
19071
19072      return Math.max(
19073        activeSlide.offsetHeight || 0,
19074        activeSlide.scrollHeight || 0,
19075        Math.ceil(activeSlide.getBoundingClientRect ? activeSlide.getBoundingClientRect().height : 0)
19076      );
19077    }
19078
19079    function shouldUpdateAutoHeight(gallery, swiperInstance, forceUpdate) {
19080      if (forceUpdate) {
19081        return true;
19082      }
19083
19084      const activeSlide = swiperInstance && swiperInstance.slides && typeof swiperInstance.activeIndex === 'number'
19085        ? swiperInstance.slides[swiperInstance.activeIndex]
19086        : null;
19087
19088      // Keep the previous image height while an ad slide is active to avoid small page jumps.
19089      if (activeSlide && activeSlide.classList.contains('ad-slide')) {
19090        return false;
19091      }
19092
19093      const activeSlideHeight = getActiveSlideHeight(swiperInstance);
19094      if (activeSlideHeight <= 0) {
19095        return false;
19096      }
19097
19098      // Solange die initiale Hoehe aktiv ist, nur updaten wenn sie sichtbar nicht passt.
19099      if (gallery && gallery.__initialSlideHeightActive) {
19100        const initialHeight = getInitialSlideHeightPx(gallery);
19101        if (initialHeight <= 0) {
19102          return true;
19103        }
19104        return Math.abs(activeSlideHeight - initialHeight) > AUTO_HEIGHT_TOLERANCE_PX;
19105      }
19106
19107      const wrapperHeight = swiperInstance && swiperInstance.wrapperEl ? swiperInstance.wrapperEl.offsetHeight : 0;
19108      if (wrapperHeight <= 0) {
19109        return true;
19110      }
19111
19112      return Math.abs(activeSlideHeight - wrapperHeight) > AUTO_HEIGHT_TOLERANCE_PX;
19113    }
19114
19115    function refreshSwiperAutoHeight(swiperInstance, gallery, forceUpdate) {
19116      if (!swiperInstance || typeof swiperInstance.updateAutoHeight !== 'function') {
19117        return;
19118      }
19119
19120      if (!shouldUpdateAutoHeight(gallery, swiperInstance, !!forceUpdate)) {
19121        return;
19122      }
19123
19124      swiperInstance.updateAutoHeight();
19125
19126      // Zweiter Tick fuer sichere Hoehen-Neuberechnung nach Reflow/Render.
19127      if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') {
19128        window.requestAnimationFrame(function () {
19129          if (shouldUpdateAutoHeight(gallery, swiperInstance, !!forceUpdate)) {
19130            swiperInstance.updateAutoHeight();
19131          }
19132        });
19133      }
19134    }
19135
19136    // Optional data attributes:
19137    // - data-initial-slide-height
19138    // - data-slider-container-min-height
19139    // Numeric values are interpreted as px, missing/invalid/'auto' fall back to auto behavior.
19140    function getInitialSlideHeightPx(gallery) {
19141      if (!gallery || !gallery.dataset) {
19142        return DEFAULT_INITIAL_SLIDE_HEIGHT_PX;
19143      }
19144
19145      const fromData = parseInt(gallery.dataset.initialSlideHeight, 10);
19146      return Number.isFinite(fromData) && fromData > 0 ? fromData : DEFAULT_INITIAL_SLIDE_HEIGHT_PX;
19147    }
19148
19149    function isFullWidthGallery(gallery) {
19150      return !!(gallery && gallery.classList && gallery.classList.contains('MediaGalleryFullWidth'));
19151    }
19152
19153    function getSliderContainerMinHeightPx(gallery) {
19154      if (!gallery || !gallery.dataset) {
19155        return DEFAULT_SLIDER_CONTAINER_MIN_HEIGHT_PX;
19156      }
19157
19158      const fromData = parseInt(gallery.dataset.sliderContainerMinHeight, 10);
19159      if (Number.isFinite(fromData) && fromData > 0) {
19160        return fromData;
19161      }
19162
19163      if (isFullWidthGallery(gallery)) {
19164        return DEFAULT_FULLWIDTH_SLIDER_CONTAINER_MIN_HEIGHT_PX;
19165      }
19166
19167      const sliderEl = gallery.querySelector('.MediaGallery_slider');
19168      const sliderWidth = sliderEl ? sliderEl.clientWidth : 0;
19169
19170      if (sliderWidth > 0) {
19171        // Adaptive Untergrenze fuer eingebettete, schmale Galerien (z. B. Artikelspalte).
19172        const adaptiveHeight = Math.round(sliderWidth * 0.62);
19173        return Math.max(220, Math.min(DEFAULT_SLIDER_CONTAINER_MIN_HEIGHT_PX, adaptiveHeight));
19174      }
19175
19176      return DEFAULT_SLIDER_CONTAINER_MIN_HEIGHT_PX;
19177    }
19178
19179    function toMinHeightCssValue(heightPx) {
19180      return Number.isFinite(heightPx) && heightPx > 0 ? heightPx + 'px' : 'auto';
19181    }
19182
19183    function applyInitialSlideHeight(gallery) {
19184      if (!gallery) {
19185        return;
19186      }
19187
19188      const slider = gallery.querySelector('.MediaGallery_slider, .MediaGalleryFullWidth_slider');
19189      const wrapper = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer');
19190      const initialHeight = getInitialSlideHeightPx(gallery);
19191
19192      if (slider) {
19193        slider.style.minHeight = toMinHeightCssValue(initialHeight);
19194      }
19195
19196      if (wrapper) {
19197        wrapper.style.minHeight = toMinHeightCssValue(initialHeight);
19198      }
19199
19200      gallery.__initialSlideHeightActive = true;
19201    }
19202
19203    function clearInitialSlideHeightIfReady(gallery, swiperInstance) {
19204      if (!gallery || !gallery.__initialSlideHeightActive) {
19205        return;
19206      }
19207
19208      if (!swiperInstance || !swiperInstance.wrapperEl || swiperInstance.wrapperEl.offsetHeight <= 0) {
19209        return;
19210      }
19211
19212      const slider = gallery.querySelector('.MediaGallery_slider, .MediaGalleryFullWidth_slider');
19213      const wrapper = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer');
19214
19215      if (slider) {
19216        slider.style.minHeight = '0';
19217      }
19218
19219      if (wrapper) {
19220        wrapper.style.minHeight = toMinHeightCssValue(getSliderContainerMinHeightPx(gallery));
19221      }
19222
19223      gallery.__initialSlideHeightActive = false;
19224    }
19225
19226    function normalizeGallerySlideHeights(gallery) {
19227      if (!gallery) {
19228        return;
19229      }
19230
19231      const slider = gallery.querySelector('.MediaGallery_slider, .MediaGalleryFullWidth_slider');
19232      const wrapper = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer');
19233
19234      if (slider) {
19235        slider.style.height = 'auto';
19236        if (!gallery.__initialSlideHeightActive) {
19237          slider.style.minHeight = '0';
19238        }
19239      }
19240
19241      if (!wrapper) {
19242        return;
19243      }
19244
19245      wrapper.style.height = 'auto';
19246      if (!gallery.__initialSlideHeightActive) {
19247        wrapper.style.minHeight = toMinHeightCssValue(getSliderContainerMinHeightPx(gallery));
19248      }
19249
19250      Array.from(wrapper.children).forEach(function (slide) {
19251        slide.style.height = 'auto';
19252      });
19253    }
19254
19255    function bindImageLoadAutoHeight(gallery) {
19256      if (!gallery) {
19257        return;
19258      }
19259
19260      gallery.querySelectorAll('.MediaGallery_sliderImage img, .MediaGalleryFullWidth_sliderImage img').forEach(function (img) {
19261        if (img.complete) {
19262          return;
19263        }
19264
19265        img.addEventListener('load', function () {
19266          refreshSwiperAutoHeight(gallery.mSwiper, gallery);
19267          clearInitialSlideHeightIfReady(gallery, gallery.mSwiper);
19268          scheduleDescriptionThumbOverlapCheck(gallery);
19269        }, { once: true });
19270      });
19271    }
19272
19273    function refreshActiveAdSlot(gallery, activeSlide) {
19274      if (!gallery || !activeSlide || !activeSlide.classList.contains('ad-slide')) {
19275        return;
19276      }
19277
19278      traceThumbSync(gallery, 'refreshActiveAdSlot:start');
19279
19280      const adDiv = gallery.querySelector('.ad-container');
19281      if (!adDiv || !adDiv.children[0]) {
19282        debugAdLog('Interner Gallery-Slot nicht refreshbar (ad-container fehlt)', {
19283          galleryId: gallery.id || null,
19284        });
19285        return;
19286      }
19287
19288      if (adDiv.parentNode !== activeSlide) {
19289        activeSlide.appendChild(adDiv);
19290      }
19291
19292      centerAdIframes(adDiv, activeSlide);
19293
19294      const slots = googletag.pubads().getSlots();
19295      const slotElementId = adDiv.children[0].id;
19296      const currentSlot = slots.find(function (s) {
19297        return s.getSlotElementId() === slotElementId;
19298      });
19299
19300      if (!currentSlot) {
19301        debugAdLog('Interner Gallery-Slot nicht refreshbar (Slotobjekt fehlt)', {
19302          galleryId: gallery.id || null,
19303          slotElementId: slotElementId,
19304        });
19305        return;
19306      }
19307
19308      const activeSlotInfo = adSlots.get(slotElementId);
19309      if (activeSlotInfo) {
19310        activeSlotInfo.targetAdSlide = activeSlide;
19311        const refreshState = getOrCreateRefreshState(activeSlotInfo);
19312        const nowTs = Date.now();
19313        if (refreshState.lastHandledAdSlideElement === activeSlide && (nowTs - refreshState.lastHandledAdSlideTs) < AD_SLIDE_REENTRY_GUARD_MS) {
19314          traceThumbSync(gallery, 'refreshActiveAdSlot:dedup-skip', { slotElementId: slotElementId });
19315          return;
19316        }
19317        refreshState.lastHandledAdSlideElement = activeSlide;
19318        refreshState.lastHandledAdSlideTs = nowTs;
19319        refreshState.lastAdSlideActivationTs = nowTs;
19320        refreshState.fallbackRefreshDone = false;
19321        if (refreshState.activeSlideFallbackTimerId) {
19322          window.clearTimeout(refreshState.activeSlideFallbackTimerId);
19323          refreshState.activeSlideFallbackTimerId = null;
19324        }
19325
19326        maybeRefreshSlot(activeSlotInfo, 'slideChangeTransitionEnd').catch(function (err) {
19327          debugAdLog('Refresh bei aktivem Ad-Slide fehlgeschlagen', {
19328            adId: activeSlotInfo.adId,
19329            message: err && err.message ? err.message : String(err),
19330          });
19331        });
19332
19333        if (hasExplicitUserInteraction) {
19334          const activationTs = refreshState.lastAdSlideActivationTs;
19335          refreshState.activeSlideFallbackTimerId = window.setTimeout(function () {
19336            refreshState.activeSlideFallbackTimerId = null;
19337
19338            if (!hasExplicitUserInteraction || !activeSlide.isConnected || !activeSlide.classList.contains('swiper-slide-active')) {
19339              return;
19340            }
19341            if (activeSlotInfo.targetAdSlide !== activeSlide || refreshState.pending || refreshState.fallbackRefreshDone) {
19342              return;
19343            }
19344
19345            const iframe = adDiv.querySelector('iframe');
19346            const hasNoVisibleIframe = !iframe || iframe.offsetWidth < 10 || iframe.offsetHeight < 10;
19347            const noRefreshSinceActivation = refreshState.lastRefreshTs < activationTs;
19348            if (!hasNoVisibleIframe && !noRefreshSinceActivation) {
19349              return;
19350            }
19351
19352            refreshState.fallbackRefreshDone = true;
19353            maybeRefreshSlot(activeSlotInfo, 'activeSlideFallback', { ignoreInterval: true }).catch(function (err) {
19354              debugAdLog('Fallback-Refresh bei aktivem Ad-Slide fehlgeschlagen', {
19355                adId: activeSlotInfo.adId,
19356                message: err && err.message ? err.message : String(err),
19357              });
19358            });
19359          }, ACTIVE_AD_FALLBACK_RETRY_MS);
19360        }
19361      }
19362
19363      traceThumbSync(gallery, 'refreshActiveAdSlot:evaluated', { slotElementId: slotElementId });
19364    }
19365
19366    function maybeRefreshExternalSlotsByAdPos(gallery, mainSwiper) {
19367      if (!gallery || !mainSwiper || !mainSwiper.slides || typeof mainSwiper.activeIndex !== 'number') {
19368        return;
19369      }
19370
19371      const adPos = parseInt(gallery.dataset.adpos, 10);
19372      if (!adPos || adPos < 1) {
19373        return;
19374      }
19375
19376      const imageIndex = getImageIndexFromMainIndex(mainSwiper.slides, mainSwiper.activeIndex);
19377      if (imageIndex < 0) {
19378        return;
19379      }
19380
19381      const imageCount = imageIndex + 1;
19382      const stepCount = mainSwiper.activeIndex + 1;
19383      const triggerEvery = adPos + 1;
19384
19385      // Wenn der User zurueckblaettert, Trigger-Freigabe fuer bereits erreichte Positionen zuruecksetzen.
19386      const lastSeenStepCount = Number.isInteger(gallery.__lastExternalRefreshSeenStepCount)
19387        ? gallery.__lastExternalRefreshSeenStepCount
19388        : null;
19389      if (lastSeenStepCount !== null && stepCount < lastSeenStepCount) {
19390        gallery.__lastExternalRefreshTriggerStepCount = null;
19391      }
19392      gallery.__lastExternalRefreshSeenStepCount = stepCount;
19393
19394      if ((stepCount % triggerEvery) !== 0) {
19395        return;
19396      }
19397
19398      // Pro Slide-Position nur ein Trigger, bis wieder unter diese Position zurueckgeblaettert wurde.
19399      if (gallery.__lastExternalRefreshTriggerStepCount === stepCount) {
19400        return;
19401      }
19402
19403      const triggerMarker = stepCount + ':' + mainSwiper.activeIndex;
19404
19405      debugAdLog('Externer Refresh via adPos-Trigger', {
19406        galleryId: gallery.id || null,
19407        adPos: adPos,
19408        triggerEvery: triggerEvery,
19409        imageCount: imageCount,
19410        mainActiveIndex: mainSwiper.activeIndex,
19411      });
19412
19413      const refreshExecuted = refreshExternalGalleryRelatedSlots('adPosTransition', {
19414        galleryId: gallery.id || null,
19415        imageCount: imageCount,
19416        stepCount: stepCount,
19417        mainActiveIndex: mainSwiper.activeIndex,
19418        triggerEvery: triggerEvery,
19419        triggerMarker: triggerMarker,
19420      });
19421      if (refreshExecuted) {
19422        gallery.__lastExternalRefreshTriggerStepCount = stepCount;
19423      }
19424    }
19425
19426    function applySliderContainerMinHeight(gallery) {
19427      if (!gallery) {
19428        return;
19429      }
19430
19431      const wrapper = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer');
19432      if (!wrapper) {
19433        return;
19434      }
19435
19436      wrapper.style.minHeight = toMinHeightCssValue(getSliderContainerMinHeightPx(gallery));
19437    }
19438
19439    function forceThumbnailContainerFullWidth(gallery) {
19440      if (!gallery) {
19441        return;
19442      }
19443
19444      const thumbWrapper = gallery.querySelector('.MediaGallery_thumbnailContainer');
19445      if (!thumbWrapper) {
19446        return;
19447      }
19448
19449      // Override legacy theme offsets (left: ~45%) via inline styles.
19450      thumbWrapper.style.left = '0';
19451      thumbWrapper.style.width = '100%';
19452      thumbWrapper.style.maxWidth = '100%';
19453      thumbWrapper.style.position = 'relative';
19454    }
19455
19456    function getActiveDescriptionElement(gallery) {
19457      if (!gallery) {
19458        return null;
19459      }
19460
19461      return gallery.querySelector(
19462        '.MediaGallery_sliderImage.swiper-slide-active .MediaGallery_imageDescription, ' +
19463        '.MediaGalleryFullWidth_sliderImage.swiper-slide-active .MediaGallery_imageDescription, ' +
19464        '.MediaGallery_imageDescription'
19465      );
19466    }
19467
19468    function preventDescriptionThumbOverlap(gallery) {
19469      if (!gallery) {
19470        return;
19471      }
19472
19473      const thumbsEl = gallery.querySelector('.MediaGallery_thumbnails');
19474      if (!thumbsEl) {
19475        return;
19476      }
19477
19478      const descriptionEl = getActiveDescriptionElement(gallery);
19479      if (!descriptionEl) {
19480        thumbsEl.style.marginTop = '';
19481        return;
19482      }
19483
19484      // Erst resetten, damit wiederholte Messungen keine Offsets aufaddieren.
19485      thumbsEl.style.marginTop = '';
19486
19487      const descriptionRect = descriptionEl.getBoundingClientRect();
19488      const thumbsRect = thumbsEl.getBoundingClientRect();
19489      const overlapPx = Math.ceil(descriptionRect.bottom - thumbsRect.top);
19490
19491      if (overlapPx > 0) {
19492        // Kleiner Puffer, damit Border/Line-Height nicht am Thumb klebt.
19493        thumbsEl.style.marginTop = (overlapPx + 8) + 'px';
19494      }
19495    }
19496
19497    function scheduleDescriptionThumbOverlapCheck(gallery) {
19498      if (!gallery) {
19499        return;
19500      }
19501
19502      if (gallery.__descThumbOverlapRaf && typeof window !== 'undefined' && typeof window.cancelAnimationFrame === 'function') {
19503        window.cancelAnimationFrame(gallery.__descThumbOverlapRaf);
19504      }
19505
19506      if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') {
19507        gallery.__descThumbOverlapRaf = window.requestAnimationFrame(function () {
19508          preventDescriptionThumbOverlap(gallery);
19509          gallery.__descThumbOverlapRaf = null;
19510        });
19511        return;
19512      }
19513
19514      preventDescriptionThumbOverlap(gallery);
19515    }
19516
19517    function bindDescriptionThumbOverlapGuard(gallery) {
19518      if (!gallery || gallery.__descThumbOverlapResizeBound) {
19519        return;
19520      }
19521
19522      if (typeof window !== 'undefined') {
19523        window.addEventListener('resize', function () {
19524          scheduleDescriptionThumbOverlapCheck(gallery);
19525        });
19526      }
19527
19528      gallery.__descThumbOverlapResizeBound = true;
19529    }
19530
19531    function buildTrackingUrl(gallery, activeSlide, activeIndex) {
19532      const baseUrl = (gallery && gallery.dataset && gallery.dataset.url) || (window.location.pathname + window.location.search);
19533      const hashFromSlide = activeSlide && activeSlide.getAttribute('data-hash');
19534      const hash = hashFromSlide || ('slide-' + (activeIndex + 1));
19535      return baseUrl.split('#')[0] + '#' + hash;
19536    }
19537
19538    function safeTrackerCall(label, fn) {
19539      try {
19540        fn();
19541      } catch (err) {
19542        debugAdLog('Tracking-Fehler in ' + label, {
19543          message: err && err.message ? err.message : String(err),
19544        });
19545      }
19546    }
19547
19548    function triggerVirtualPageTracking(gallery, activeSlide, activeIndex) {
19549      if (!gallery || !activeSlide) {
19550        return;
19551      }
19552
19553      // Ads nicht als virtuelle Seiten tracken, um externe Tracker-Fehler zu vermeiden.
19554      if (activeSlide.classList.contains('ad-slide')) {
19555        return;
19556      }
19557
19558      const url = buildTrackingUrl(gallery, activeSlide, activeIndex);
19559      const gtitle = (gallery && gallery.dataset && gallery.dataset.title) || document.title || '';
19560      const galId = (gallery && gallery.id) || null;
19561
19562      if (typeof window.dfv_iom_rpl === 'function') {
19563        safeTrackerCall('window.dfv_iom_rpl', function () {
19564          window.dfv_iom_rpl();
19565        });
19566      } else if (typeof dfv_iom_rpl === 'function') {
19567        safeTrackerCall('dfv_iom_rpl', function () {
19568          dfv_iom_rpl();
19569        });
19570      }
19571
19572      if (typeof window.dfv_ga_vpageview === 'function') {
19573        safeTrackerCall('window.dfv_ga_vpageview', function () {
19574          window.dfv_ga_vpageview(url, gtitle);
19575        });
19576      }
19577
19578      if (typeof window.sp_track_virtual_page_view === 'function') {
19579        safeTrackerCall('window.sp_track_virtual_page_view', function () {
19580          window.sp_track_virtual_page_view(galId, url, gtitle);
19581        });
19582      }
19583
19584      debugAdLog('Virtual-Tracking ausgeloest', {
19585        galId: galId,
19586        url: url,
19587        title: gtitle,
19588        mainIndex: activeIndex,
19589        isAd: !!(activeSlide && activeSlide.classList.contains('ad-slide')),
19590      });
19591    }
19592
19593    const refreshEligibilityCache = new Map();
19594
19595    function getRegisteredSlotById(slotId) {
19596      const slots = googletag.pubads().getSlots();
19597      return slots.find(function (slot) {
19598        return slot.getSlotElementId() === slotId;
19599      }) || null;
19600    }
19601
19602    function getVisibleRatio(element) {
19603      if (!element || typeof element.getBoundingClientRect !== 'function') {
19604        return 0;
19605      }
19606      const rect = element.getBoundingClientRect();
19607      if (!rect.width || !rect.height) {
19608        return 0;
19609      }
19610
19611      const viewportWidth = window.innerWidth || document.documentElement.clientWidth || 0;
19612      const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0;
19613      if (!viewportWidth || !viewportHeight) {
19614        return 0;
19615      }
19616
19617      const intersectionWidth = Math.max(0, Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0));
19618      const intersectionHeight = Math.max(0, Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0));
19619      const intersectionArea = intersectionWidth * intersectionHeight;
19620      const area = rect.width * rect.height;
19621      return area > 0 ? (intersectionArea / area) : 0;
19622    }
19623
19624    function isSlotInViewport(slotInfo) {
19625      if (!slotInfo || !slotInfo.gallery) {
19626        return false;
19627      }
19628      const galleryRatio = getVisibleRatio(slotInfo.gallery);
19629      if (galleryRatio < SLOT_VIEWPORT_THRESHOLD) {
19630        return false;
19631      }
19632
19633      const adContainer = slotInfo.gallery.querySelector('.ad-container');
19634      if (!adContainer) {
19635        return false;
19636      }
19637
19638      return getVisibleRatio(adContainer) >= SLOT_VIEWPORT_THRESHOLD;
19639    }
19640
19641    function getExternalSlotViewportThreshold() {
19642      if (typeof window === 'undefined') {
19643        return EXTERNAL_SLOT_VIEWPORT_THRESHOLD;
19644      }
19645
19646      const raw = Number(window.__galleryExternalSlotViewportThreshold);
19647      if (!Number.isFinite(raw)) {
19648        return EXTERNAL_SLOT_VIEWPORT_THRESHOLD;
19649      }
19650
19651      return Math.max(0, Math.min(1, raw));
19652    }
19653
19654    function isExternalSlotInViewport(slotId) {
19655      if (!slotId) {
19656        return false;
19657      }
19658
19659      const slotElement = document.getElementById(slotId);
19660      if (!slotElement) {
19661        return false;
19662      }
19663
19664      const visibleRatio = getVisibleRatio(slotElement);
19665      const threshold = getExternalSlotViewportThreshold();
19666      return visibleRatio >= threshold;
19667    }
19668
19669    function isExternalSlotRefreshEligible(slotId) {
19670      if (!slotId || typeof window === 'undefined') {
19671        return false;
19672      }
19673
19674      const eligibilityMap = window.__galleryAdRefreshEligibilityByAdUnitId;
19675      if (!eligibilityMap || typeof eligibilityMap !== 'object') {
19676        return false;
19677      }
19678
19679      const slotName = slotId.replace(/^renderSlot_/, '');
19680      const candidates = [slotName, slotId];
19681      for (let i = 0; i < candidates.length; i++) {
19682        const key = candidates[i];
19683        if (Object.prototype.hasOwnProperty.call(eligibilityMap, key)) {
19684          return eligibilityMap[key] === true;
19685        }
19686      }
19687
19688      return false;
19689    }
19690
19691    function getOrCreateRefreshState(slotInfo) {
19692      if (!slotInfo.refreshState) {
19693        slotInfo.refreshState = {
19694          renderedLineItemId: null,
19695          previousRenderedLineItemId: null,
19696          viewableSinceTs: 0,
19697          lastRefreshTs: Date.now(),
19698          pending: false,
19699          lastRefreshReason: null,
19700          refreshCount: 0,
19701          lastAdSlideActivationTs: 0,
19702          fallbackRefreshDone: false,
19703          activeSlideFallbackTimerId: null,
19704          lastHandledAdSlideElement: null,
19705          lastHandledAdSlideTs: 0,
19706        };
19707      }
19708      return slotInfo.refreshState;
19709    }
19710
19711    function resolveEligibilityFromAdData(slotInfo) {
19712      if (!slotInfo || !slotInfo.adData) {
19713        return null;
19714      }
19715
19716      if (typeof slotInfo.adData.refreshEligible === 'boolean') {
19717        return slotInfo.adData.refreshEligible;
19718      }
19719
19720      if (typeof slotInfo.adData.lineItemCount === 'number') {
19721        return slotInfo.adData.lineItemCount > 1;
19722      }
19723
19724      return null;
19725    }
19726
19727    function resolveEligibilityFromWindow(path, adUnitId) {
19728      if (typeof window === 'undefined') {
19729        return null;
19730      }
19731
19732      if (adUnitId && window.__galleryAdRefreshEligibilityByAdUnitId && typeof window.__galleryAdRefreshEligibilityByAdUnitId === 'object') {
19733        const mappedByAdUnit = window.__galleryAdRefreshEligibilityByAdUnitId[String(adUnitId)];
19734        if (typeof mappedByAdUnit === 'boolean') {
19735          return mappedByAdUnit;
19736        }
19737      }
19738
19739      if (!path) {
19740        return null;
19741      }
19742
19743      const rawMap = window.__galleryAdRefreshEligibilityByPath;
19744      if (!rawMap || typeof rawMap !== 'object') {
19745        return null;
19746      }
19747
19748      const value = rawMap[path];
19749      if (typeof value === 'boolean') {
19750        return value;
19751      }
19752      if (value && typeof value === 'object' && typeof value.refreshEligible === 'boolean') {
19753        return value.refreshEligible;
19754      }
19755
19756      return null;
19757    }
19758
19759    async function resolveSlotRefreshEligibility(slotInfo, slotObj) {
19760      const slotPath = slotObj && typeof slotObj.getAdUnitPath === 'function' ? slotObj.getAdUnitPath() : null;
19761      if (!slotPath) {
19762        return false;
19763      }
19764
19765      const nowTs = Date.now();
19766      const cached = refreshEligibilityCache.get(slotPath);
19767      if (cached && (nowTs - cached.ts) <= refreshRuntimeConfig.eligibilityCacheTtlMs) {
19768        return cached.value;
19769      }
19770
19771      let eligible = resolveEligibilityFromAdData(slotInfo);
19772      const slotAdUnitId = slotInfo && slotInfo.adData ? String(slotInfo.adData.adUnitId || '') : '';
19773      if (eligible === null) {
19774        eligible = resolveEligibilityFromWindow(slotPath, slotAdUnitId);
19775      }
19776
19777      if (eligible === null && typeof window !== 'undefined' && typeof window.__galleryAdRefreshEligibilityProvider === 'function') {
19778        try {
19779          const providerResult = await window.__galleryAdRefreshEligibilityProvider(slotPath);
19780          if (typeof providerResult === 'boolean') {
19781            eligible = providerResult;
19782          } else if (providerResult && typeof providerResult === 'object' && typeof providerResult.refreshEligible === 'boolean') {
19783            eligible = providerResult.refreshEligible;
19784          }
19785        } catch (err) {
19786          debugAdLog('Eligibility-Provider Fehler', {
19787            slotPath: slotPath,
19788            message: err && err.message ? err.message : String(err),
19789          });
19790        }
19791      }
19792
19793      if (eligible === null) {
19794        // Falls keine Datenquelle vorhanden ist, defensiv keinen Refresh ausfuehren.
19795        eligible = false;
19796      }
19797
19798      refreshEligibilityCache.set(slotPath, { value: !!eligible, ts: nowTs });
19799      return !!eligible;
19800    }
19801
19802    async function maybeRefreshSlot(slotInfo, reason, options) {
19803      if (!slotInfo || !slotInfo.injected) {
19804        return;
19805      }
19806
19807      // Legacy-Verhalten: Gallery-Slot nur beim Wechsel auf einen Ad-Slide refreshen.
19808      if (reason !== 'slideChangeTransitionEnd' && reason !== 'activeSlideFallback') {
19809        return;
19810      }
19811
19812      const refreshOptions = options || {};
19813      const refreshState = getOrCreateRefreshState(slotInfo);
19814      if (refreshState.pending) {
19815        return;
19816      }
19817
19818      const nowTs = Date.now();
19819      const ignoreInterval = !!refreshOptions.ignoreInterval;
19820      const intervalNotReached = (nowTs - refreshState.lastRefreshTs) < refreshRuntimeConfig.refreshIntervalMs;
19821      const canBypassInitialDelay = refreshState.refreshCount === 0 && hasExplicitUserInteraction;
19822      if (!ignoreInterval && intervalNotReached && !canBypassInitialDelay) {
19823        return;
19824      }
19825
19826      const slotObj = getRegisteredSlotById(slotInfo.adId);
19827      if (!slotObj) {
19828        return;
19829      }
19830
19831      refreshState.pending = true;
19832      refreshState.lastRefreshReason = reason;
19833      refreshState.lastRefreshTs = nowTs;
19834      refreshState.refreshCount += 1;
19835
19836      googletag.pubads().refresh([slotObj]);
19837      debugAdLog('Slot-Refresh ausgeloest', {
19838        adId: slotInfo.adId,
19839        reason: refreshState.lastRefreshReason,
19840        slotPath: typeof slotObj.getAdUnitPath === 'function' ? slotObj.getAdUnitPath() : null,
19841      });
19842    }
19843
19844    function evaluateAllSlotRefreshes(reason) {
19845      adSlots.forEach(function (slotInfo) {
19846        maybeRefreshSlot(slotInfo, reason).catch(function (err) {
19847          debugAdLog('Refresh-Pruefung fehlgeschlagen', {
19848            adId: slotInfo && slotInfo.adId ? slotInfo.adId : null,
19849            reason: reason,
19850            message: err && err.message ? err.message : String(err),
19851          });
19852        });
19853      });
19854    }
19855
19856    function refreshExternalGalleryRelatedSlots(reason, meta) {
19857      // Billboard/Skyscraper-Refreshes nur auf Gallerydetail-Seiten
19858      if (!hasGalleryBodyClass) {
19859        return false;
19860      }
19861
19862      const nowTs = Date.now();
19863      const elapsedSinceLastRefreshMs = nowTs - lastExternalRefreshTs;
19864      const isAdPosTransition = reason === 'adPosTransition';
19865      const canBypassInitialDelay = externalRefreshCount === 0 && hasExplicitUserInteraction;
19866      if (!isAdPosTransition && !canBypassInitialDelay && elapsedSinceLastRefreshMs < refreshRuntimeConfig.refreshIntervalMs) {
19867        debugAdLog('Externer Slot-Refresh wegen Initial-Intervall gesperrt', {
19868          reason: reason || null,
19869          elapsedSinceLastRefreshMs: elapsedSinceLastRefreshMs,
19870          minIntervalMs: refreshRuntimeConfig.refreshIntervalMs,
19871          externalRefreshCount: externalRefreshCount,
19872          hasExplicitUserInteraction: hasExplicitUserInteraction,
19873        });
19874        return false;
19875      }
19876
19877      const shouldApplyCooldown = reason !== 'adPosTransition';
19878      const forceNewCorrelator = typeof window !== 'undefined' && !!window.__galleryExternalRefreshForceNewCorrelator;
19879      if (shouldApplyCooldown && (nowTs - lastExternalRefreshTs) < EXTERNAL_REFRESH_COOLDOWN_MS) {
19880        debugAdLog('Externer Slot-Refresh wegen Cooldown uebersprungen', {
19881          reason: reason || null,
19882          cooldownMs: EXTERNAL_REFRESH_COOLDOWN_MS,
19883        });
19884        return false;
19885      }
19886
19887      if (typeof window === 'undefined' || typeof window.refreshAdSlot !== 'function') {
19888        debugAdLog('Externer Slot-Refresh nicht verfuegbar', {
19889          reason: reason || null,
19890          hasWindow: typeof window !== 'undefined',
19891          hasRefreshFn: typeof window !== 'undefined' && typeof window.refreshAdSlot === 'function',
19892        });
19893        return false;
19894      }
19895
19896      const attempted = [];
19897      let refreshedCount = 0;
19898      EXTERNAL_REFRESH_SLOT_IDS.forEach(function (slotId) {
19899        const slotObj = window.gamSlots && window.gamSlots[slotId] ? window.gamSlots[slotId] : null;
19900        const eligibilityAllowed = isExternalSlotRefreshEligible(slotId);
19901        const canRefresh = !!(slotObj && slotObj.allowRefresh && eligibilityAllowed);
19902         const inViewport = canRefresh ? isExternalSlotInViewport(slotId) : false;
19903         const visibleRatio = canRefresh ? getVisibleRatio(document.getElementById(slotId)) : 0;
19904
19905         attempted.push({
19906           slotId: slotId,
19907           hasSlot: !!slotObj,
19908           refreshEligible: eligibilityAllowed,
19909           allowRefresh: canRefresh,
19910           inViewport: inViewport,
19911           visibleRatio: Number(visibleRatio.toFixed(3)),
19912         });
19913
19914         if (!canRefresh || !inViewport) {
19915           if (!eligibilityAllowed) {
19916             pushExternalSlotHistory(slotId, 'refreshSkippedEligibilityFalse', {
19917               reason: reason || null,
19918               meta: meta || null,
19919             });
19920           } else if (canRefresh && !inViewport) {
19921             pushExternalSlotHistory(slotId, 'refreshSkippedNotInViewport', {
19922               reason: reason || null,
19923               visibleRatio: Number(visibleRatio.toFixed(3)),
19924               threshold: getExternalSlotViewportThreshold(),
19925               meta: meta || null,
19926             });
19927           }
19928           return;
19929         }
19930
19931         if (forceNewCorrelator && typeof googletag !== 'undefined' && googletag.pubads && typeof googletag.pubads === 'function') {
19932           googletag.pubads().refresh([slotObj], { changeCorrelator: true });
19933         } else {
19934           window.refreshAdSlot(slotId);
19935         }
19936         incrementExternalSlotStat(slotId, 'refreshCallTriggered');
19937         flashExternalSlotDebugMarker(slotId, 'request');
19938         pushExternalSlotHistory(slotId, 'refreshCallTriggered', {
19939           reason: reason || null,
19940           forceNewCorrelator: forceNewCorrelator,
19941           meta: meta || null,
19942         });
19943         refreshedCount += 1;
19944       });
19945
19946       if (refreshedCount < 1) {
19947         debugAdLog('Externer Slot-Refresh ohne refreshbare Slots uebersprungen', {
19948           reason: reason || null,
19949           attempted: attempted,
19950         });
19951         return false;
19952       }
19953
19954       lastExternalRefreshTs = nowTs;
19955       externalRefreshCount += 1;
19956       debugAdLog('Externer Slot-Refresh ausgefuehrt', {
19957         reason: reason || null,
19958         forceNewCorrelator: forceNewCorrelator,
19959         refreshedCount: refreshedCount,
19960         attempted: attempted,
19961       });
19962       return true;
19963     }
19964
19965     function maybeRefreshExternalSlotsByInterval() {
19966       const nowTs = Date.now();
19967       const elapsedSinceLastRefreshMs = nowTs - lastExternalRefreshTs;
19968
19969       if (elapsedSinceLastRefreshMs < refreshRuntimeConfig.refreshIntervalMs) {
19970         return;
19971       }
19972
19973       if (!isDocumentVisible()) {
19974         debugAdLog('Externer Intervall-Refresh ausgesetzt (Dokument nicht sichtbar)', {
19975           elapsedSinceLastRefreshMs: elapsedSinceLastRefreshMs,
19976           minIntervalMs: refreshRuntimeConfig.refreshIntervalMs,
19977         });
19978         return;
19979       }
19980
19981       if (!isUserRecentlyActive()) {
19982         debugAdLog('Externer Intervall-Refresh ausgesetzt (Nutzer inaktiv)', {
19983           elapsedSinceLastRefreshMs: elapsedSinceLastRefreshMs,
19984           minIntervalMs: refreshRuntimeConfig.refreshIntervalMs,
19985           userIdleTimeoutMs: refreshRuntimeConfig.userIdleTimeoutMs,
19986           inactiveForMs: nowTs - lastUserActivityTs,
19987         });
19988         return;
19989       }
19990
19991       refreshExternalGalleryRelatedSlots('autoInterval', {
19992         elapsedSinceLastRefreshMs: elapsedSinceLastRefreshMs,
19993         minIntervalMs: refreshRuntimeConfig.refreshIntervalMs,
19994       });
19995     }
19996
19997     function isExternalGalleryRelatedSlotId(slotId) {
19998       return EXTERNAL_REFRESH_SLOT_IDS.indexOf(slotId) !== -1;
19999     }
20000
20001     function logExternalSlotEvent(eventName, event) {
20002       if (!event || !event.slot || typeof event.slot.getSlotElementId !== 'function') {
20003         return;
20004       }
20005
20006       const slotId = event.slot.getSlotElementId();
20007       if (!isExternalGalleryRelatedSlotId(slotId)) {
20008         return;
20009       }
20010
20011       debugAdLog(eventName + ' (External)', {
20012         slotId: slotId,
20013         path: typeof event.slot.getAdUnitPath === 'function' ? event.slot.getAdUnitPath() : null,
20014         isEmpty: typeof event.isEmpty === 'boolean' ? event.isEmpty : null,
20015         size: event.size || null,
20016         lineItemId: typeof event.lineItemId === 'number' ? event.lineItemId : null,
20017         creativeId: typeof event.creativeId === 'number' ? event.creativeId : null,
20018       });
20019
20020       if (eventName === 'slotRequested') {
20021         incrementExternalSlotStat(slotId, 'slotRequested');
20022         pushExternalSlotHistory(slotId, 'slotRequested', {
20023           path: typeof event.slot.getAdUnitPath === 'function' ? event.slot.getAdUnitPath() : null,
20024         });
20025       } else if (eventName === 'slotResponseReceived') {
20026         incrementExternalSlotStat(slotId, 'slotResponseReceived');
20027         pushExternalSlotHistory(slotId, 'slotResponseReceived', {
20028           path: typeof event.slot.getAdUnitPath === 'function' ? event.slot.getAdUnitPath() : null,
20029         });
20030       } else if (eventName === 'slotRenderEnded') {
20031         incrementExternalSlotStat(slotId, 'slotRenderEnded');
20032         flashExternalSlotDebugMarker(slotId, 'render');
20033         const slotStats = ensureExternalSlotStats(slotId);
20034         slotStats.lastRenderLineItemId = typeof event.lineItemId === 'number' ? event.lineItemId : null;
20035         slotStats.lastRenderCreativeId = typeof event.creativeId === 'number' ? event.creativeId : null;
20036         slotStats.lastRenderTs = new Date().toISOString();
20037         pushExternalSlotHistory(slotId, 'slotRenderEnded', {
20038           isEmpty: typeof event.isEmpty === 'boolean' ? event.isEmpty : null,
20039           size: event.size || null,
20040           lineItemId: typeof event.lineItemId === 'number' ? event.lineItemId : null,
20041           creativeId: typeof event.creativeId === 'number' ? event.creativeId : null,
20042         });
20043       }
20044     }
20045
20046     googletag.pubads().addEventListener('slotRenderEnded', function(event) {
20047       const slotId = event.slot.getSlotElementId();
20048       const slotInfo = adSlots.get(slotId);
20049       if (!slotInfo) {
20050         logExternalSlotEvent('slotRenderEnded', event);
20051         return;
20052       }
20053
20054       debugAdLog('slotRenderEnded empfangen', {
20055         slotId: slotId,
20056         isEmpty: !!event.isEmpty,
20057         size: event.size || null,
20058         lineItemId: typeof event.lineItemId === 'number' ? event.lineItemId : null,
20059         creativeId: typeof event.creativeId === 'number' ? event.creativeId : null,
20060       });
20061
20062       const gallery = slotInfo.gallery;
20063       const refreshState = getOrCreateRefreshState(slotInfo);
20064       refreshState.pending = false;
20065       if (refreshState.activeSlideFallbackTimerId) {
20066         window.clearTimeout(refreshState.activeSlideFallbackTimerId);
20067         refreshState.activeSlideFallbackTimerId = null;
20068       }
20069       refreshState.previousRenderedLineItemId = refreshState.renderedLineItemId;
20070       refreshState.renderedLineItemId = typeof event.lineItemId === 'number' ? String(event.lineItemId) : null;
20071       if (!gallery) {
20072         return;
20073       }
20074
20075       if (event.isEmpty) {
20076         if (!slotInfo.injected) {
20077           debugAdLog('Leerer Initial-Slot, Ad-Markup wird nicht eingefuegt', {
20078             adId: slotInfo.adId,
20079             galleryId: gallery.id || null,
20080           });
20081         } else {
20082           debugAdLog('Leerer Refresh-Slot, Ad-Markup bleibt erhalten', {
20083             adId: slotInfo.adId,
20084             galleryId: gallery.id || null,
20085           });
20086         }
20087         if (gallery.mSwiper && typeof gallery.mSwiper.update === 'function') {
20088           gallery.mSwiper.update();
20089         }
20090         if (gallery.tSwiper && typeof gallery.tSwiper.update === 'function') {
20091           gallery.tSwiper.update();
20092         }
20093         scheduleDescriptionThumbOverlapCheck(gallery);
20094         return;
20095       }
20096
20097       let hasInjectedAdMarkup = false;
20098       if (!slotInfo.injected) {
20099         injectAdMarkup(slotInfo);
20100         slotInfo.injected = true;
20101         hasInjectedAdMarkup = true;
20102       }
20103
20104       normalizeGallerySlideHeights(gallery);
20105
20106       const adContainer = gallery.querySelector('#renderSlot-' + slotId);
20107       const targetAdSlide = slotInfo.targetAdSlide && slotInfo.targetAdSlide.isConnected
20108         ? slotInfo.targetAdSlide
20109         : slotInfo.mainWrapper.querySelector('.ad-slide');
20110
20111       if (adContainer && targetAdSlide && adContainer.parentNode !== targetAdSlide) {
20112         targetAdSlide.appendChild(adContainer);
20113         debugAdLog('Ad-Container in aktiven Ad-Slide verschoben', {
20114           adId: slotInfo.adId,
20115           galleryId: gallery.id || null,
20116         });
20117       }
20118
20119       centerAdIframes(adContainer, targetAdSlide);
20120
20121       if (isSlotInViewport(slotInfo) && !refreshState.viewableSinceTs) {
20122         refreshState.viewableSinceTs = Date.now();
20123       }
20124
20125       refreshSwiperAutoHeight(gallery.mSwiper, gallery);
20126
20127       if (hasInjectedAdMarkup && gallery.mSwiper && typeof gallery.mSwiper.update === 'function') {
20128         gallery.mSwiper.update();
20129       }
20130       if (hasInjectedAdMarkup && gallery.tSwiper && typeof gallery.tSwiper.update === 'function') {
20131         gallery.tSwiper.update();
20132       }
20133
20134       syncThumbStateWithMainSwiper(gallery);
20135       traceThumbSync(gallery, 'slotRenderEnded:after-sync', { slotId: slotId, isEmpty: !!event.isEmpty });
20136       scheduleDescriptionThumbOverlapCheck(gallery);
20137       evaluateAllSlotRefreshes('slotRenderEnded');
20138     });
20139
20140     googletag.pubads().addEventListener('slotRequested', function (event) {
20141       const slotId = event.slot.getSlotElementId();
20142       if (!adSlots.has(slotId)) {
20143         logExternalSlotEvent('slotRequested', event);
20144         return;
20145       }
20146
20147       debugAdLog('slotRequested (Gallery)', {
20148         slotId: slotId,
20149         path: typeof event.slot.getAdUnitPath === 'function' ? event.slot.getAdUnitPath() : null,
20150         slotTargetingFromCode: getStoredSlotTargetingSnapshot(event.slot),
20151         slotTargetingFromGpt: getSlotTargetingSnapshot(event.slot),
20152         pageTargeting: getPageTargetingSnapshot(),
20153       });
20154     });
20155
20156     googletag.pubads().addEventListener('slotResponseReceived', function (event) {
20157       const slotId = event.slot.getSlotElementId();
20158       if (!adSlots.has(slotId)) {
20159         logExternalSlotEvent('slotResponseReceived', event);
20160         return;
20161       }
20162
20163       debugAdLog('slotResponseReceived (Gallery)', {
20164         slotId: slotId,
20165         path: typeof event.slot.getAdUnitPath === 'function' ? event.slot.getAdUnitPath() : null,
20166       });
20167     });
20168
20169     googletag.pubads().addEventListener('impressionViewable', function (event) {
20170       const slotId = event.slot.getSlotElementId();
20171       const slotInfo = adSlots.get(slotId);
20172       if (!slotInfo) {
20173         return;
20174       }
20175
20176       const refreshState = getOrCreateRefreshState(slotInfo);
20177       if (!refreshState.viewableSinceTs) {
20178         refreshState.viewableSinceTs = Date.now();
20179       }
20180
20181       debugAdLog('impressionViewable empfangen', {
20182         slotId: slotId,
20183       });
20184
20185       evaluateAllSlotRefreshes('impressionViewable');
20186     });
20187
20188     galleries.forEach((gallery, wIndex) => {
20189       debugAdLog('Gallery-Ad-Konfiguration erkannt', getGalleryAdDatasetSnapshot(gallery));
20190
20191       const adPos = parseInt(gallery.dataset.adpos, 10);
20192       let adData = {};
20193
20194       if (!adPos || adPos < 1) {
20195         debugAdLog('Gallery ohne gueltige adPos uebersprungen', {
20196           galleryId: gallery.id || null,
20197           adPos: gallery.dataset.adpos,
20198         });
20199         return;
20200       }
20201
20202       try {
20203         adData = JSON.parse(gallery.dataset.ad_gam_id);
20204       } catch (e) {
20205         debugAdLog('Gallery mit ungueltiger ad_gam_id uebersprungen', {
20206           galleryId: gallery.id || null,
20207         });
20208         return;
20209       }
20210       if(!adData.path || !adData.sizes || adData.path.length < 1){
20211         debugAdLog('Gallery ohne vollstaendige Ad-Daten uebersprungen', {
20212           galleryId: gallery.id || null,
20213         });
20214         return;
20215       }
20216
20217
20218       const adId = `ad-id-${wIndex}`;
20219
20220       const mainWrapper = gallery.querySelector('.MediaGallery_sliderContainer, .MediaGalleryFullWidth_sliderContainer');
20221       if (!mainWrapper) {
20222         debugAdLog('Gallery ohne Slider-Container uebersprungen', {
20223           galleryId: gallery.id || null,
20224         });
20225         return;
20226       }
20227
20228       if (Math.floor(mainWrapper.children.length / adPos) < 1) {
20229         debugAdLog('Gallery hat zu wenige Slides fuer Ad-Position', {
20230           galleryId: gallery.id || null,
20231           slideCount: mainWrapper.children.length,
20232           adPos: adPos,
20233         });
20234         return;
20235       }
20236
20237       adIds.push(adId);
20238       const definedSlot = googletag.defineSlot(adData.path, adData.sizes, adId);
20239       if (!definedSlot) {
20240         debugAdLog('defineSlot lieferte kein Slot-Objekt, Gallery-Ad wird uebersprungen', {
20241           adId: adId,
20242           galleryId: gallery.id || null,
20243           path: adData.path || null,
20244           sizes: adData.sizes || null,
20245         });
20246         adIds.pop();
20247         return;
20248       }
20249
20250       const slotObj = definedSlot.addService(googletag.pubads());
20251       applySlotTargeting(slotObj, adData);
20252       mirrorPageTargetingToSlot(slotObj);
20253       applyGalleryDatasetTargeting(slotObj, gallery);
20254
20255       const mainThumbWrapper = gallery.querySelector('.MediaGallery_thumbnailContainer');
20256
20257       const staging = document.createElement('div');
20258       // GPT/Creatives koennen in display:none sporadisch nicht sauber initialisieren.
20259       // Deshalb offscreen parken statt komplett aus dem Render-Tree zu nehmen.
20260       staging.style.position = 'absolute';
20261       staging.style.left = '-10000px';
20262       staging.style.top = '0';
20263       staging.style.width = '1px';
20264       staging.style.height = '1px';
20265       staging.style.overflow = 'hidden';
20266       staging.style.pointerEvents = 'none';
20267       staging.innerHTML = `<div class="ad-container Ad" id="renderSlot-${adId}"><div id="${adId}"></div></div>`;
20268       gallery.appendChild(staging);
20269
20270       adSlots.set(adId, {
20271         adId: adId,
20272         gallery: gallery,
20273         adData: adData,
20274         mainWrapper: mainWrapper,
20275         mainThumbWrapper: mainThumbWrapper,
20276         adPos: adPos,
20277         staging: staging,
20278         injected: false,
20279         targetAdSlide: null,
20280         refreshState: {
20281           renderedLineItemId: null,
20282           previousRenderedLineItemId: null,
20283           viewableSinceTs: 0,
20284           lastRefreshTs: Date.now(),
20285           pending: false,
20286           lastRefreshReason: null,
20287           refreshCount: 0,
20288           lastAdSlideActivationTs: 0,
20289           fallbackRefreshDone: false,
20290           activeSlideFallbackTimerId: null,
20291           lastHandledAdSlideElement: null,
20292           lastHandledAdSlideTs: 0,
20293         },
20294       });
20295
20296       debugAdLog('Ad-Slot fuer Gallery registriert', {
20297         adId: adId,
20298         galleryId: gallery.id || null,
20299         adPos: adPos,
20300         slotTargetingFromCode: getStoredSlotTargetingSnapshot(slotObj),
20301         pageTargetingAtRegister: getPageTargetingSnapshot(),
20302       });
20303     });
20304
20305     function displayGallerySlots(waitAttempt) {
20306       const attempt = typeof waitAttempt === 'number' ? waitAttempt : 0;
20307       if (displayGallerySlots.executed) {
20308         return;
20309       }
20310
20311       if (!hasAllRequiredPageTargeting(REQUIRED_PAGE_TARGETING_KEYS) && attempt < MAX_DISPLAY_WAIT_ATTEMPTS) {
20312         debugAdLog('Display wartet auf required page-targeting', {
20313           attempt: attempt,
20314           maxAttempts: MAX_DISPLAY_WAIT_ATTEMPTS,
20315           requiredKeys: REQUIRED_PAGE_TARGETING_KEYS,
20316           pageTargetingNow: getPageTargetingSnapshot(),
20317         });
20318         window.setTimeout(function () {
20319           displayGallerySlots(attempt + 1);
20320         }
20320, DISPLAY_WAIT_INTERVAL_MS);
20321         return;
20322       }
20323
20324       if (!hasAllRequiredPageTargeting(REQUIRED_PAGE_TARGETING_KEYS) && attempt >= MAX_DISPLAY_WAIT_ATTEMPTS) {
20325         debugAdLog('Display-Fallback ohne vollstaendiges page-targeting', {
20326           attempts: attempt,
20327           requiredKeys: REQUIRED_PAGE_TARGETING_KEYS,
20328           pageTargetingNow: getPageTargetingSnapshot(),
20329         });
20330       }
20331
20332       displayGallerySlots.executed = true;
20333       adIds.forEach(function (id) {
20334         const slots = googletag.pubads().getSlots();
20335         const slot = slots.find(function (s) {
20336           return s.getSlotElementId() === id;
20337         });
20338
20339         if (slot) {
20340           mirrorPageTargetingToSlot(slot);
20341         }
20342
20343         debugAdLog('display() wird aufgerufen', {
20344           adId: id,
20345           hasSlotObject: !!slot,
20346           path: slot && typeof slot.getAdUnitPath === 'function' ? slot.getAdUnitPath() : null,
20347           slotTargetingFromCode: slot ? getStoredSlotTargetingSnapshot(slot) : {},
20348           pageTargetingBeforeDisplay: getPageTargetingSnapshot(),
20349         });
20350
20351         googletag.display(id);
20352
20353         debugAdLog('display() aufgerufen', {
20354           adId: id,
20355         });
20356       });
20357       debugAdLog('Gallery-Slots wurden ausgeloest', { count: adIds.length });
20358     }
20359
20360     if (typeof window !== 'undefined') {
20361       window.__galleryDebugDump = function () {
20362         const slotStates = [];
20363         adSlots.forEach(function (slotInfo, adId) {
20364           slotStates.push({
20365             adId: adId,
20366             injected: !!slotInfo.injected,
20367             hasTargetSlide: !!slotInfo.targetAdSlide,
20368             hasStaging: !!slotInfo.staging,
20369             adPos: slotInfo.adPos,
20370           });
20371         });
20372
20373         debugAdLog('Debug-Dump', {
20374           adIds: adIds.slice(),
20375           slotStates: slotStates,
20376           pubadsReady: !!googletag.pubadsReady,
20377           registeredSlots: googletag.pubads().getSlots().map(function (s) {
20378             return s.getSlotElementId();
20379           }),
20380         });
20381       };
20382
20383       window.__galleryDebugRefresh = function () {
20384         const refreshed = [];
20385         const slots = googletag.pubads().getSlots();
20386
20387         adIds.forEach(function (adId) {
20388           const slot = slots.find(function (s) {
20389             return s.getSlotElementId() === adId;
20390           });
20391           if (slot) {
20392             googletag.pubads().refresh([slot]);
20393             refreshed.push(adId);
20394           }
20395         });
20396
20397         debugAdLog('Debug-Refresh ausgefuehrt', {
20398           refreshedSlots: refreshed,
20399           requestedSlots: adIds.slice(),
20400         });
20401       };
20402
20403       window.__galleryDebugTargetingDump = function () {
20404         const slots = googletag.pubads().getSlots();
20405
20406         adIds.forEach(function (adId) {
20407           const slot = slots.find(function (s) {
20408             return s.getSlotElementId() === adId;
20409           });
20410
20411           if (!slot) {
20412             debugAdLog('Targeting-Dump: Slot nicht gefunden', { adId: adId });
20413             return;
20414           }
20415
20416           const targeting = getSlotTargetingSnapshot(slot);
20417           const keys = Object.keys(targeting);
20418
20419           debugAdLog('Targeting-Dump', {
20420             adId: adId,
20421             keys: keys,
20422             targeting: targeting,
20423           });
20424         });
20425       };
20426
20427       window.__galleryDebugExternalStats = function () {
20428         const snapshot = JSON.parse(JSON.stringify(externalSlotDebugStats));
20429         debugAdLog('External-Slot-Debug-Stats', snapshot);
20430         return snapshot;
20431       };
20432     }
20433
20434     if (googletag.pubadsReady) {
20435       debugAdLog('pubads bereits aktiv, display direkt', {});
20436       displayGallerySlots(0);
20437     } else if (document.readyState === 'loading') {
20438       document.addEventListener('DOMContentLoaded', function () {
20439         googletag.cmd.push(function () {
20440           debugAdLog('display nach DOMContentLoaded ausgefuehrt', {});
20441           displayGallerySlots(0);
20442         });
20443       }, { once: true });
20444     } else {
20445       googletag.cmd.push(function () {
20446         debugAdLog('display nach spaeterem GPT-Init ausgefuehrt', {});
20447         displayGallerySlots(0);
20448       });
20449     }
20450
20451     if (typeof window !== 'undefined' && adSlots.size > 0) {
20452       window.setInterval(function () {
20453         evaluateAllSlotRefreshes('interval');
20454         maybeRefreshExternalSlotsByInterval();
20455       }, refreshRuntimeConfig.refreshCheckIntervalMs);
20456     }
20457
20458
20459     galleries.forEach(function (gallery) {
20460       const thumbnailsEl = gallery.querySelector('.MediaGallery_thumbnails');
20461       const sliderEl = gallery.querySelector('.MediaGallery_slider, .MediaGalleryFullWidth_slider');
20462       const paginationEl = gallery.querySelector('.swiper-pagination');
20463
20464       forceThumbnailContainerFullWidth(gallery);
20465       bindDescriptionThumbOverlapGuard(gallery);
20466
20467       if (paginationEl) {
20468         paginationEl.style.display = 'none';
20469       }
20470
20471       if (!sliderEl) {
20472         return;
20473       }
20474
20475       if (thumbnailsEl) {
20476         gallery.tSwiper = new Swiper(thumbnailsEl, {
20477           slidesPerView: 'auto',
20478           centeredSlides: false,
20479           centeredSlidesBounds: false,
20480           centerInsufficientSlides: false,
20481           slideToClickedSlide: true,
20482           watchSlidesProgress: true,
20483           observer: true,
20484           observeParents: true,
20485           spaceBetween: 10
20486         });
20487
20488         gallery.tSwiper.on('tap', function () {
20489           if (!gallery.mSwiper || typeof this.clickedIndex !== 'number') {
20490             return;
20491           }
20492
20493           const clickedImageIndex = this.clickedIndex;
20494           const targetMainIndex = getMainIndexFromImageIndex(gallery.mSwiper.slides, clickedImageIndex);
20495           if (targetMainIndex >= 0) {
20496             const currentMainIndex = gallery.mSwiper.activeIndex;
20497             const currentImageIndex = getImageIndexFromMainIndex(gallery.mSwiper.slides, currentMainIndex);
20498             const adBeforeTargetMainIndex = targetMainIndex > 0 && gallery.mSwiper.slides[targetMainIndex - 1] && gallery.mSwiper.slides[targetMainIndex - 1].classList.contains('ad-slide')
20499               ? targetMainIndex - 1
20500               : -1;
20501             const adAfterTargetMainIndex = gallery.mSwiper.slides[targetMainIndex + 1] && gallery.mSwiper.slides[targetMainIndex + 1].classList.contains('ad-slide')
20502               ? targetMainIndex + 1
20503               : -1;
20504             const isForwardNavigation = clickedImageIndex > currentImageIndex;
20505             const isBackwardNavigation = clickedImageIndex < currentImageIndex;
20506
20507             if (isForwardNavigation && adBeforeTargetMainIndex >= 0 && currentMainIndex < adBeforeTargetMainIndex) {
20508               gallery.mSwiper.slideTo(adBeforeTargetMainIndex);
20509               return;
20510             }
20511
20512             if (isBackwardNavigation && adAfterTargetMainIndex >= 0 && currentMainIndex > adAfterTargetMainIndex) {
20513               gallery.mSwiper.slideTo(adAfterTargetMainIndex);
20514               return;
20515             }
20516
20517             gallery.mSwiper.slideTo(targetMainIndex);
20518             traceThumbSync(gallery, 'thumbTap:slideTo', { clickedImageIndex: clickedImageIndex, targetMainIndex: targetMainIndex });
20519           }
20520         });
20521       } else {
20522         gallery.tSwiper = null;
20523       }
20524
20525       const mainSwiperConfig = {
20526         loop: false,
20527         slidesPerView: 1,
20528         autoHeight: true,
20529         pagination: {
20530           el: '.swiper-pagination',
20531           clickable: true,
20532           centered: true,
20533         },
20534         navigation: {
20535           nextEl: '.swiper-button-next',
20536           prevEl: '.swiper-button-prev',
20537           addIcons: false
20538         },
20539         keyboard: {
20540           enabled: true,
20541           onlyInViewport: true,
20542         },
20543         centeredSlides: true,
20544         centeredSlidesBounds: true,
20545         observer: true,
20546         observeParents: true,
20547         observeSlideChildren: true,
20548         on: {
20549           init: function () {
20550             normalizeGallerySlideHeights(gallery);
20551             refreshSwiperAutoHeight(this, gallery);
20552             clearInitialSlideHeightIfReady(gallery, this);
20553             rememberCurrentImageSlideHeight(gallery, this);
20554             setGalleryAdNavigationState(gallery, this.slides && typeof this.activeIndex === 'number' ? this.slides[this.activeIndex] : null);
20555             scheduleDescriptionThumbOverlapCheck(gallery);
20556           },
20557           slideChange: function() {
20558             const activeIndex = this.activeIndex;
20559             const activeSlide = this.slides[this.activeIndex];
20560             if (!activeSlide) {
20561               return;
20562             }
20563
20564             setGalleryAdNavigationState(gallery, activeSlide);
20565
20566             traceThumbSync(gallery, 'slideChange:start');
20567
20568             refreshSwiperAutoHeight(this, gallery);
20569             clearInitialSlideHeightIfReady(gallery, this);
20570
20571             triggerVirtualPageTracking(gallery, activeSlide, activeIndex);
20572
20573             if (gallery.tSwiper && activeSlide && !activeSlide.classList.contains('ad-slide')) {
20574               rememberCurrentImageSlideHeight(gallery, this);
20575               const imageIndex = getImageIndexFromMainIndex(this.slides, this.activeIndex);
20576               if (imageIndex >= 0) {
20577                 updateActiveThumbState(gallery, imageIndex);
20578                 syncThumbSwiperToImageIndex(gallery, imageIndex);
20579                 traceThumbSync(gallery, 'slideChangeTransitionEnd:image-slide', { targetImageIndex: imageIndex });
20580               }
20581             }
20582
20583             maybeRefreshExternalSlotsByAdPos(gallery, this);
20584             refreshActiveAdSlot(gallery, activeSlide);
20585             traceThumbSync(gallery, 'slideChangeTransitionEnd:end');
20586             scheduleDescriptionThumbOverlapCheck(gallery);
20587           }
20588         }
20589       };
20590
20591       applyInitialSlideHeight(gallery);
20592       applySliderContainerMinHeight(gallery);
20593
20594       gallery.mSwiper = new Swiper(sliderEl, mainSwiperConfig);
20595
20596       setGalleryAdNavigationState(
20597         gallery,
20598         gallery.mSwiper && gallery.mSwiper.slides && typeof gallery.mSwiper.activeIndex === 'number'
20599           ? gallery.mSwiper.slides[gallery.mSwiper.activeIndex]
20600           : null
20601       );
20602
20603       normalizeGallerySlideHeights(gallery);
20604       bindImageLoadAutoHeight(gallery);
20605
20606       refreshSwiperAutoHeight(gallery.mSwiper, gallery);
20607       clearInitialSlideHeightIfReady(gallery, gallery.mSwiper);
20608       scheduleDescriptionThumbOverlapCheck(gallery);
20609
20610       if (gallery.tSwiper && gallery.mSwiper && gallery.mSwiper.slides && typeof gallery.mSwiper.activeIndex === 'number') {
20611         rememberCurrentImageSlideHeight(gallery, gallery.mSwiper);
20612         const initialImageIndex = getImageIndexFromMainIndex(gallery.mSwiper.slides, gallery.mSwiper.activeIndex);
20613         if (initialImageIndex >= 0) {
20614           updateActiveThumbState(gallery, initialImageIndex);
20615         }
20616       }
20617     });
20618
20619   });
20620})();
20621
20622
20623
20624
20625/* ----- DOCUMENT READY FUNCTION ------ */
20626
20627$(function() {
20628  
20629  if (!$("Body.BodyGallery").length ) {
20630    // Sticky Header nicht in Galerie-Detailseiten
20631
20632      $(window).on('scroll resize touchmove',function(){
20633        stickybegins = $(".SiteHeader").offset().top + $(".SiteHeader").height();
20634
20635        if($(this).scrollTop()>stickybegins && window.innerWidth>768){
20636          $('.SiteHeaderSticky').fadeIn();
20637        }else{
20638          $('.SiteHeaderSticky').fadeOut();
20639        }
20640      });
20641
20642
20643  }
20644
20645  
20646} );
20647 
20648

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.