/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ 		}
/******/ 	};
/******/
/******/ 	// define __esModule on exports
/******/ 	__webpack_require__.r = function(exports) {
/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 		}
/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
/******/ 	};
/******/
/******/ 	// create a fake namespace object
/******/ 	// mode & 1: value is a module id, require it
/******/ 	// mode & 2: merge all properties of value into the ns
/******/ 	// mode & 4: return value when already ns object
/******/ 	// mode & 8|1: behave like require
/******/ 	__webpack_require__.t = function(value, mode) {
/******/ 		if(mode & 1) value = __webpack_require__(value);
/******/ 		if(mode & 8) return value;
/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ 		var ns = Object.create(null);
/******/ 		__webpack_require__.r(ns);
/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ 		return ns;
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = "./src/js/edit/advanced-slider.js");
/******/ })
/************************************************************************/
/******/ ({

/***/ "./src/js/_shared/advanced-slider.js":
/*!*******************************************!*\
  !*** ./src/js/_shared/advanced-slider.js ***!
  \*******************************************/
/*! exports provided: ADVANCED_SLIDER_EASING_CURVES, toAlphabet, toRoman, escapeHtml, getPaginationType, getPaginationPosition, buildPaginationConfig, mountPaginationHost, swiperLoader */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ADVANCED_SLIDER_EASING_CURVES\", function() { return ADVANCED_SLIDER_EASING_CURVES; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"toAlphabet\", function() { return toAlphabet; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"toRoman\", function() { return toRoman; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"escapeHtml\", function() { return escapeHtml; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getPaginationType\", function() { return getPaginationType; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getPaginationPosition\", function() { return getPaginationPosition; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"buildPaginationConfig\", function() { return buildPaginationConfig; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mountPaginationHost\", function() { return mountPaginationHost; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"swiperLoader\", function() { return swiperLoader; });\n/**\n * EA Advanced Slider — shared helpers\n *\n * Imported by BOTH `src/js/view/advanced-slider.js` (frontend + editor\n * preview iframe) and `src/js/edit/advanced-slider.js` (Elementor editor\n * control-change handler). Phase 6 is gradually moving duplicated helpers\n * here; until that migration is complete, the view and edit entries will\n * still each contain their own copies of some helpers — extract one piece\n * at a time and verify the editor + frontend both still work before\n * lifting the next one.\n *\n * Webpack 4's entry globber only scans `src/js/view/*` and `src/js/edit/*`\n * (see webpack.config.js — `outputEntry()`), so files under `src/js/_shared/`\n * are never treated as entry points. They're inlined into any bundle that\n * imports them. Net cost: one copy each in view + edit's minified output,\n * but a SINGLE source of truth in this directory.\n *\n * Conventions:\n *   - Export only pure functions / constants with no closure dependencies\n *     on either bundle's runtime state.\n *   - Helpers that need jQuery should accept `$` as a parameter instead\n *     of relying on a closure (view JS has helpers at IIFE-top, edit JS\n *     re-creates them per call — neither contract carries here).\n *   - Keep editor-only behaviour (rAF token tracking, swiper.destroy\n *     teardown) in `edit/advanced-slider.js`. This file is shared, not\n *     editor-flavoured.\n */\n\n/* ─────────── Constants ─────────── */\n\n/**\n * Easing presets for the Advanced Slider's slide-transition timing.\n *\n * Both bundles read `$scope.attr('data-easing')` (set by PHP from the\n * `eael_advanced_slider_transition_easing` control) and look the preset\n * up in this map. The selected curve is written via\n * `setProperty('transition-timing-function', curve, 'important')` so it\n * beats the SCSS rule `transition-timing-function: var(--eael-as-easing)\n * !important` in the cascade. See applyTransitionEasing in either entry.\n */\nvar ADVANCED_SLIDER_EASING_CURVES = {\n  smooth: 'cubic-bezier(0.4, 0, 0.2, 1)',\n  snappy: 'cubic-bezier(0.7, 0, 0.3, 1)',\n  spring: 'cubic-bezier(0.22, 1, 0.36, 1)',\n  soft: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)'\n};\n\n/**\n * Valid pagination types the user can select in the\n * `eael_advanced_slider_pagination_type` control. Anything else (including\n * an unrecognised legacy value) is coerced to 'tick_bars' by\n * getPaginationType() so the slider never renders without pagination.\n *\n * Order: discrete (Swiper-pagination-module) types first, custom-DOM\n * types last. Not user-facing — getPaginationType() is the only consumer.\n */\nvar PAGINATION_TYPES = ['dots', 'dots_vertical', 'fraction', 'tick_bars', 'progress_bar', 'thumbnails', 'numbered_index'];\n\n/* ─────────── Pure helpers (no jQuery, no closure deps) ─────────── */\n\n/**\n * 0 → 'A', 1 → 'B', 2 → 'C', ...  — index-label generator for the\n * 'numbered_index' pagination type's 'alphabet' format.\n * Wraps at 25 → 'Z'; consumers should cap slide count or fall through to\n * the default 'number' format for sliders with > 26 slides.\n */\nvar toAlphabet = function toAlphabet(num) {\n  return String.fromCharCode(65 + num); // 0 → A, 1 → B, 2 → C ...\n};\n\n/**\n * 1 → 'I', 4 → 'IV', 5 → 'V', 9 → 'IX', 10 → 'X', etc. — Roman numeral\n * generator for the 'numbered_index' pagination type's 'roman' format.\n * Slide indices are 1-based by convention for this format.\n */\nvar toRoman = function toRoman(num) {\n  var map = [{\n    v: 1000,\n    s: 'M'\n  }, {\n    v: 900,\n    s: 'CM'\n  }, {\n    v: 500,\n    s: 'D'\n  }, {\n    v: 400,\n    s: 'CD'\n  }, {\n    v: 100,\n    s: 'C'\n  }, {\n    v: 90,\n    s: 'XC'\n  }, {\n    v: 50,\n    s: 'L'\n  }, {\n    v: 40,\n    s: 'XL'\n  }, {\n    v: 10,\n    s: 'X'\n  }, {\n    v: 9,\n    s: 'IX'\n  }, {\n    v: 5,\n    s: 'V'\n  }, {\n    v: 4,\n    s: 'IV'\n  }, {\n    v: 1,\n    s: 'I'\n  }];\n  var result = '';\n  map.forEach(function (o) {\n    while (num >= o.v) {\n      result += o.s;\n      num -= o.v;\n    }\n  });\n  return result;\n};\n\n/**\n * Minimal HTML-entity escape. Used when injecting user-controlled strings\n * (slide image URLs, alt text) into innerHTML / attribute values.\n *\n * NOT a substitute for proper PHP escaping at render time — this is a\n * client-side defence-in-depth for strings that came from Elementor's\n * model (already kses'd at save time) and need to survive a JS round-trip.\n */\nvar escapeHtml = function escapeHtml(str) {\n  if (str === null || str === undefined) return '';\n  return String(str).replace(/[&<>\"']/g, function (c) {\n    return {\n      '&': '&amp;',\n      '<': '&lt;',\n      '>': '&gt;',\n      '\"': '&quot;',\n      \"'\": '&#39;'\n    }[c];\n  });\n};\n\n/**\n * Resolve the active pagination type from saved settings.\n *\n * - 'none' → renders no pagination\n * - Any value in PAGINATION_TYPES → that exact value\n * - Anything else (including undefined) → fall through to 'tick_bars'\n *   (the default for fresh sliders so the user sees pagination immediately\n *   and can switch it off via the dropdown).\n */\nvar getPaginationType = function getPaginationType(options) {\n  if ((options === null || options === void 0 ? void 0 : options.pagination_type) === 'none') return 'none';\n  if (options !== null && options !== void 0 && options.pagination_type && PAGINATION_TYPES.indexOf(options.pagination_type) !== -1) {\n    return options.pagination_type;\n  }\n  return 'tick_bars';\n};\n\n/**\n * Resolve the active pagination position from saved settings.\n *\n * Dots Vertical is the one type whose position is structurally fixed\n * (right rail) — the position control is hidden in the editor for that\n * type but a saved slider could still carry a stale position value, so\n * we force-override here. Everything else falls through to the saved\n * value or 'bottom' as default.\n */\nvar getPaginationPosition = function getPaginationPosition(options) {\n  if (getPaginationType(options) === 'dots_vertical') return 'right_center';\n  return (options === null || options === void 0 ? void 0 : options.pagination_position) || 'bottom';\n};\n\n/**\n * Build the Swiper pagination config object for a given type.\n *\n * Returns null for types that don't use Swiper's pagination module —\n * 'progress_bar', 'thumbnails', 'numbered_index' all render via custom\n * DOM in their own build*Nav() helpers (those stay in the view/edit\n * entries because they wire in Swiper-instance event listeners and\n * editor-only state).\n *\n * NOTE: do NOT pass `verticalClass: ''` here. Modern Swiper calls\n * `classList.add(params.verticalClass)` which throws DOMTokenList.add:\n * \"The empty string is not a valid token\", aborting the entire\n * swiperInstancePromise chain. We let Swiper apply its default\n * `.swiper-pagination-vertical` class and override the visual position\n * via the SCSS rule\n *   `.eael-advanced-slider-vertical .swiper-pagination.swiper-pagination-vertical`.\n */\nvar buildPaginationConfig = function buildPaginationConfig(type, el) {\n  if (!el || type === 'none' || type === 'progress_bar' || type === 'thumbnails' || type === 'numbered_index') return null;\n  var base = {\n    el: el,\n    clickable: true\n  };\n  if (type === 'fraction') {\n    return Object.assign({}, base, {\n      type: 'fraction',\n      renderFraction: function renderFraction(currentClass, totalClass) {\n        return '<span class=\"' + currentClass + ' eael-as-fraction-current\"></span>' + '<span class=\"eael-as-fraction-sep\">/</span>' + '<span class=\"' + totalClass + ' eael-as-fraction-total\"></span>';\n      }\n    });\n  }\n  if (type === 'tick_bars') {\n    // Bullets (not custom) so each tick is a clickable button.\n    // CSS styles `.eael-as-tick-bar` as a vertical bar.\n    return Object.assign({}, base, {\n      type: 'bullets',\n      bulletClass: 'eael-as-tick-bar',\n      bulletActiveClass: 'is-active',\n      bulletElement: 'button'\n    });\n  }\n  // 'dots' and 'dots_vertical'\n  return Object.assign({}, base, {\n    type: 'bullets',\n    bulletClass: 'eael-as-bullet',\n    bulletActiveClass: 'eael-as-bullet-active',\n    bulletElement: 'button'\n  });\n};\n\n/* ─────────── jQuery-aware helpers ($ passed as parameter) ─────────── */\n\n/**\n * Create the pagination host element and append it to $scope (the outer\n * .eael-advanced-slider). Always mount OUTSIDE the .swiper child element so\n * 3D effects (cards / flip / coverflow) — which apply preserve-3d to the\n * .swiper container — don't drag pagination into their 3D context (where\n * it would inherit perspective transforms and render at unintended depth).\n *\n * Signature: ($scope, $inner, type, position, $) — note `$inner` is\n * currently unused inside the helper but kept on the signature for\n * symmetry with future variants that may need it (e.g. mounting inside\n * .swiper for specific types).\n */\nvar mountPaginationHost = function mountPaginationHost($scope, $inner, type, position, $) {\n  if (type === 'none') return null;\n  var typeClass = 'eael-as-pagination--type-' + type.replace(/_/g, '-');\n  var posClass = 'eael-as-pagination--position-' + position.replace(/_/g, '-');\n  var $host = $('<div class=\"eael-as-pagination ' + typeClass + ' ' + posClass + '\"></div>');\n  $scope.append($host);\n  return $host;\n};\n\n/* ─────────── Swiper loader ─────────── */\n\n/**\n * Internal: wrap synchronous `new Swiper(...)` in a Promise so the loader\n * always returns the same shape.\n */\nvar swiperPromise = function swiperPromise(swiperElement, swiperConfig) {\n  return new Promise(function (resolve) {\n    var swiperInstance = new Swiper(swiperElement, swiperConfig);\n    resolve(swiperInstance);\n  });\n};\n\n/**\n * Async Swiper bootstrapper. Returns a Promise<Swiper>.\n *\n * Two paths because Elementor lazy-loads Swiper:\n *   - If global `Swiper` (constructor) is already on window, use it\n *     directly via swiperPromise.\n *   - Otherwise use elementorFrontend.utils.swiper, which kicks off the\n *     async fetch and resolves once Swiper's bundle has loaded.\n *\n * `typeof Swiper === 'function'` covers the loaded-but-not-yet-instantiated\n * case; `typeof Swiper === 'undefined'` is the not-yet-loaded case (also\n * routed through the async loader, falling through here would throw a\n * ReferenceError).\n */\nvar swiperLoader = function swiperLoader(swiperElement, swiperConfig) {\n  if ('undefined' === typeof Swiper || 'function' === typeof Swiper) {\n    var asyncSwiper = elementorFrontend.utils.swiper;\n    return new asyncSwiper(swiperElement, swiperConfig).then(function (newSwiperInstance) {\n      return newSwiperInstance;\n    });\n  }\n  return swiperPromise(swiperElement, swiperConfig);\n};\n\n//# sourceURL=webpack:///./src/js/_shared/advanced-slider.js?");

/***/ }),

/***/ "./src/js/edit/advanced-slider.js":
/*!****************************************!*\
  !*** ./src/js/edit/advanced-slider.js ***!
  \****************************************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../_shared/advanced-slider.js */ \"./src/js/_shared/advanced-slider.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n/**\n * EA Advanced Slider — editor handler\n * Wrapped in an IIFE so AdvancedSliderHandler is module-local and cannot collide\n * with the same identifier in src/js/view/advanced-slider.js.\n */\n\n(function () {\n  var AdvancedSliderHandler = function AdvancedSliderHandler($scope, $) {\n    var editorState = window.__eaelAdvancedSliderEditorState || (window.__eaelAdvancedSliderEditorState = {\n      queued: false,\n      inProgress: false,\n      lastRunAt: 0,\n      changeListenerBound: false\n    });\n    editorState.sliderSettings = editorState.sliderSettings || {};\n    // Per-slider state — keyed by Elementor element ID. Tracks the active\n    // Swiper instance (Phase 5.1) and any in-flight requestAnimationFrame\n    // tokens (Phase 5.2) so teardownSlider() can shut both down before\n    // the next init pass rebuilds the DOM (Phase 5.3).\n    editorState.sliders = editorState.sliders || new Map();\n\n    /* Phase 5.3 — clean up the previous slider before re-init.\n        Before this commit, every signature-changing control flip\n       (direction, effect, items-per-slide…) caused initAdvancedSlider to\n       container.empty() and rebuild — but the OLD Swiper instance kept\n       its autoplay timer, transitionEnd listeners, and rAF loops\n       running against the now-detached DOM. After ~3-4 control changes\n       the editor preview accumulated enough stale handlers to feel\n       sluggish and intermittently render wrong slide widths or skip\n       slides on the first interaction. Cowork's earlier attempt at\n       this teardown went wrong by ALSO invalidating the settings\n       cache + clearing the Map entry, which caused the next init\n       to read partial state. This version is deliberately minimal:\n       destroy + cancelAnimationFrame, then null the swiper field.\n       The Map key + rafTokens Set are preserved so Phase 5.1/5.2's\n       stash logic writes back into the same slot on next init. */\n    var teardownSlider = function teardownSlider(elementId) {\n      if (!elementId) return;\n      var entry = editorState.sliders.get(elementId);\n      if (!entry) return;\n      if (entry.swiper && !entry.swiper.destroyed && typeof entry.swiper.destroy === 'function') {\n        try {\n          /* (deleteInstance=true, cleanStyles=false) — kill the\n             instance reference, the autoplay timer, and all event\n             listeners, but SKIP Swiper's per-slide inline-style\n             stripping. That scrub walks every slide and removes\n             transform/width/transition styles + swiper-slide-active\n             / -duplicate / -prev / -next classes; on an 18-slide\n             looped slider it's ~50ms of layout-thrashing work.\n              The follow-up items.detach() + container.empty() in\n             initAdvancedSlider discards the entire subtree anyway,\n             so cleanStyles=true is double work. Flipping to false\n             was specifically what cleared the items-per-slide /\n             item-gap drag lag in QA. */\n          entry.swiper.destroy(true, false);\n        } catch (e) {\n          /* destroy() can throw on partially-initialized instances\n             (e.g. a previous init promise hadn't resolved yet when\n             the next control change fired). Best-effort only —\n             swallow and continue so the rebuild isn't blocked. */\n        }\n      }\n      if (entry.rafTokens && typeof entry.rafTokens.forEach === 'function') {\n        entry.rafTokens.forEach(function (token) {\n          return cancelAnimationFrame(token);\n        });\n        entry.rafTokens.clear();\n      }\n      /* Disconnect the viewport-autoplay observer (see initSwiperSlider's\n         autoplay block) before the DOM is rebuilt, so observers don't leak\n         across re-inits and keep referencing detached slider wrappers. */\n      if (entry.autoplayObserver && typeof entry.autoplayObserver.disconnect === 'function') {\n        entry.autoplayObserver.disconnect();\n        entry.autoplayObserver = null;\n      }\n      entry.swiper = null;\n    };\n    // 250ms debounce — gives Elementor's CSS injection time to settle and\n    // batches multiple control changes (e.g. dragging a slider) into one\n    // re-init pass instead of running every frame.\n    var INIT_DEBOUNCE_MS = 250;\n\n    /* toAlphabet, toRoman imported from ../_shared/advanced-slider.js (Phase 6.1). */\n\n    var buildSettingsSignature = function buildSettingsSignature(settings) {\n      return JSON.stringify({\n        effect: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_effect,\n        direction: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_direction,\n        manualScrolling: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_manual_scrolling,\n        marquee: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_effect_marquee,\n        indicator: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_indicator,\n        indicatorType: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_indicator_type,\n        navigationArrows: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_navigation_arrows,\n        // New pagination contract — re-init editor when any of these change.\n        paginationType: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_pagination_type,\n        paginationPosition: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_pagination_position,\n        centeredSlides: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_centered_slides,\n        indexFormat: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_index_format,\n        autoHeight: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_auto_height,\n        height3d: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_3d_height,\n        showNavigation: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_enable_navigation,\n        loop: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_loop,\n        speed: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_speed,\n        speedMarquee: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_speed_marquee,\n        transitionEasing: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_transition_easing,\n        autoplay: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_autoplay,\n        autoplaySpeed: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_autoplay_speed,\n        items: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_per_view,\n        gap: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_item_gap,\n        gapMarquee: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_item_gap_marquee,\n        enableBackground: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_enable_background,\n        coverflowRotation: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_coverflow_rotation,\n        pauseOnHover: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_pause_on_hover,\n        pauseOnHoverMarquee: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_pause_on_hover_marquee,\n        height: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_height,\n        navigationIconLeft: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_navigation_icon_left,\n        navigationIconRight: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_navigation_icon_right\n      });\n    };\n\n    /* Pagination helpers (getPaginationType, getPaginationPosition,\n       escapeHtml, buildPaginationConfig) and the editor's mountPaginationHost\n       are imported from ../_shared/advanced-slider.js (Phase 6.1). */\n    /* Detect a slide's representative image (img > bg-image url > null). */\n    var detectSlideImage = function detectSlideImage($slide) {\n      var imgSrc = $slide.find('img').first().attr('src') || '';\n      if (!imgSrc) {\n        var $bgEl = $slide.find('[style*=\"background-image\"]').first();\n        if ($bgEl.length) {\n          var m = ($bgEl.attr('style') || '').match(/background-image\\s*:\\s*url\\(['\"]?([^'\"\\)]+)/);\n          if (m) imgSrc = m[1];\n        }\n      }\n      return imgSrc;\n    };\n\n    /* Thumbnails sub-Swiper builder (auto-detects per-slide image).\n       In the EDITOR, Elementor renders slide content asynchronously, so\n       images often aren't in the DOM when this builder first runs.\n       We schedule retry passes to swap numbered placeholders for actual\n       images as they appear. */\n    var buildThumbnailsNav = function buildThumbnailsNav($scope, $slides, options) {\n      var position = ((options === null || options === void 0 ? void 0 : options.pagination_position) || 'bottom').replace(/_/g, '-');\n      var $host = $('<div class=\"eael-as-thumbnails eael-as-thumbnails--position-' + position + '\"></div>');\n      var $thumbsSwiper = $('<div class=\"swiper eael-as-thumbnails-swiper\"></div>');\n      var $thumbsWrapper = $('<div class=\"swiper-wrapper\"></div>');\n      var slideElements = $slides.toArray();\n      slideElements.forEach(function (slideEl, i) {\n        var imgSrc = detectSlideImage($(slideEl));\n        var inner = imgSrc ? '<img src=\"' + Object(_shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"escapeHtml\"])(imgSrc) + '\" alt=\"\" data-eael-as-thumb-detected=\"1\">' : '<span class=\"eael-as-thumb-num\" data-idx=\"' + i + '\">' + (i + 1) + '</span>';\n        $thumbsWrapper.append('<div class=\"swiper-slide eael-as-thumb\">' + inner + '</div>');\n      });\n      $thumbsSwiper.append($thumbsWrapper);\n      $host.append($thumbsSwiper);\n      $scope.append($host);\n\n      // Retry up to 6 times over ~3 seconds to upgrade number placeholders\n      // to actual images as Elementor renders slide content async.\n      var retries = 6;\n      var retryTimer = setInterval(function () {\n        var $needs = $host.find('.eael-as-thumb-num');\n        if (!$needs.length) {\n          clearInterval(retryTimer);\n          return;\n        }\n        $needs.each(function () {\n          var idx = parseInt(this.getAttribute('data-idx'), 10);\n          if (isNaN(idx) || !slideElements[idx]) return;\n          var imgSrc = detectSlideImage($(slideElements[idx]));\n          if (imgSrc) {\n            $(this).replaceWith('<img src=\"' + Object(_shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"escapeHtml\"])(imgSrc) + '\" alt=\"\" data-eael-as-thumb-detected=\"1\">');\n          }\n        });\n        retries--;\n        if (retries <= 0) clearInterval(retryTimer);\n      }, 500);\n      return {\n        $host: $host,\n        getThumbsSwiper: function getThumbsSwiper() {\n          return new Swiper($thumbsSwiper[0], {\n            slidesPerView: 'auto',\n            spaceBetween: 8,\n            centerInsufficientSlides: true,\n            watchSlidesProgress: true,\n            slideToClickedSlide: true\n          });\n        }\n      };\n    };\n\n    /* Auto-fit height for 3D effects (cards / flip / coverflow). */\n    var autoFitHeight = function autoFitHeight($scope, swiper) {\n      var $swiperEl = $scope.children('.swiper').first();\n      if (!$swiperEl.length) return;\n      var $slides = $swiperEl.find('> .swiper-wrapper > .swiper-slide');\n      if (!$slides.length) return;\n      var measure = function measure() {\n        var slidesPrev = [];\n        $slides.each(function () {\n          slidesPrev.push(this.style.height);\n        });\n        $slides.css('height', 'auto');\n        $swiperEl.css('height', 'auto');\n        $swiperEl[0].offsetHeight; // reflow\n        var maxH = 0;\n        $slides.each(function () {\n          var h = this.scrollHeight;\n          if (h > maxH) maxH = h;\n        });\n        $slides.each(function (i) {\n          this.style.height = slidesPrev[i] || '';\n        });\n        if (maxH > 0) $swiperEl.css('height', maxH + 'px');\n        if (swiper && typeof swiper.update === 'function') swiper.update();\n      };\n      measure();\n      var imgTimer;\n      var debouncedMeasure = function debouncedMeasure() {\n        clearTimeout(imgTimer);\n        imgTimer = setTimeout(measure, 150);\n      };\n      $scope.find('img').each(function () {\n        if (!this.complete) this.addEventListener('load', debouncedMeasure, {\n          once: true\n        });\n      });\n    };\n\n    /* Time-based Autoplay Progress Bar (matches demo V3). */\n    var buildProgressBarNav = function buildProgressBarNav($scope, options, trackRaf) {\n      var position = ((options === null || options === void 0 ? void 0 : options.pagination_position) || 'bottom').replace(/_/g, '-');\n      /* re-centered pause/play SVGs — see view JS for the full rationale.\n         Pause bars now sit symmetrically inside the 24-unit viewBox; play\n         triangle is shifted right of geometric center so the optical center\n         lands in the middle of the round button. SVG sizing comes from CSS. */\n      var $host = $('<div class=\"eael-as-pagination eael-as-pagination--type-progress-bar eael-as-pagination--position-' + position + '\">' + '<button type=\"button\" class=\"eael-as-pb-toggle\" aria-label=\"Pause autoplay\">' + '<svg class=\"eael-as-pb-pause\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><rect x=\"7\" y=\"5\" width=\"3.5\" height=\"14\" rx=\"1\"/><rect x=\"13.5\" y=\"5\" width=\"3.5\" height=\"14\" rx=\"1\"/></svg>' + '<svg class=\"eael-as-pb-play\" viewBox=\"0 0 24 24\" fill=\"currentColor\" style=\"display:none\" aria-hidden=\"true\"><path d=\"M7.5 5.2v13.6c0 .8.9 1.3 1.6.9l11-6.8c.6-.4.6-1.4 0-1.8l-11-6.8c-.7-.4-1.6 0-1.6.9z\"/></svg>' + '</button>' + '<div class=\"eael-as-pb-track\"><div class=\"eael-as-pb-fill\"></div></div>' + '<div class=\"eael-as-pb-counter\"><strong class=\"eael-as-pb-current\">01</strong><span class=\"eael-as-pb-sep\">/</span><span class=\"eael-as-pb-total\">01</span></div>' + '</div>');\n      $scope.append($host);\n      return {\n        $host: $host,\n        attach: function attach(swiper) {\n          if (!swiper) return;\n          var $fill = $host.find('.eael-as-pb-fill');\n          var $current = $host.find('.eael-as-pb-current');\n          var $total = $host.find('.eael-as-pb-total');\n          var $toggle = $host.find('.eael-as-pb-toggle');\n          var $iconPause = $host.find('.eael-as-pb-pause');\n          var $iconPlay = $host.find('.eael-as-pb-play');\n          var totalSlides = swiper.slides.length - (swiper.params.loop ? 2 * swiper.loopedSlides : 0);\n          var safeTotal = Math.max(1, totalSlides);\n          $total.text(String(safeTotal).padStart(2, '0'));\n          $current.text(String((swiper.realIndex || 0) + 1).padStart(2, '0'));\n          /* Fill animation works for ANY effect, not just fade.\n             Mirror of view JS — see that file for the rationale. */\n          var autoplayEnabled = !!(swiper.params.autoplay && (swiper.params.autoplay.delay || swiper.params.autoplay === true));\n          var delay = (options === null || options === void 0 ? void 0 : options.autoplay_speed) || swiper.params.autoplay && swiper.params.autoplay.delay || 3000;\n          /* A slide is on screen for `delay` + `speed` (Swiper autoplay\n             waitForTransition:true). Span the full cycle so the fill\n             completes as the next slide settles, not at `delay`. Mirror\n             of view JS. */\n          var transitionSpeed = swiper.params.speed || 0;\n          var cycle = delay + transitionSpeed;\n          var startTime = performance.now();\n          var paused = !autoplayEnabled;\n          if (autoplayEnabled && swiper.autoplay && !swiper.autoplay.running) {\n            try {\n              swiper.autoplay.start();\n            } catch (e) {}\n          }\n          var setPausedUI = function setPausedUI(isPaused) {\n            paused = isPaused;\n            $iconPause.css('display', isPaused ? 'none' : '');\n            $iconPlay.css('display', isPaused ? '' : 'none');\n            $toggle.attr('aria-label', isPaused ? 'Resume autoplay' : 'Pause autoplay');\n          };\n          setPausedUI(paused);\n          $toggle.on('click', function () {\n            if (paused) {\n              startTime = performance.now();\n              if (swiper.autoplay) swiper.autoplay.start();\n              setPausedUI(false);\n            } else {\n              if (swiper.autoplay) swiper.autoplay.stop();\n              setPausedUI(true);\n            }\n          });\n          swiper.on('slideChange', function () {\n            startTime = performance.now();\n            $current.text(String((swiper.realIndex || 0) + 1).padStart(2, '0'));\n            $fill.css('width', '0%');\n          });\n          swiper.on('autoplayStart', function () {\n            return setPausedUI(false);\n          });\n          swiper.on('autoplayStop', function () {\n            return setPausedUI(true);\n          });\n          swiper.on('autoplayPause', function () {\n            return setPausedUI(true);\n          });\n          swiper.on('autoplayResume', function () {\n            return setPausedUI(false);\n          });\n          var _tick = function tick() {\n            if (!paused) {\n              var _elapsed = performance.now() - startTime;\n              var pct = Math.min(100, _elapsed / cycle * 100);\n              $fill.css('width', pct + '%');\n            }\n            var token = requestAnimationFrame(_tick);\n            if (trackRaf) trackRaf(token);\n          };\n          _tick();\n        }\n      };\n    };\n\n    /* Numbered/Alphabet/Roman index rail builder. */\n    var buildNumberedIndexNav = function buildNumberedIndexNav($scope, $slides, options) {\n      var format = (options === null || options === void 0 ? void 0 : options.index_format) || 'number';\n      var cls = 'eael-as-pagination eael-as-pagination--type-numbered-index eael-as-pagination--position-' + ((options === null || options === void 0 ? void 0 : options.pagination_position) || 'bottom').replace(/_/g, '-');\n      var $host = $('<nav class=\"' + cls + '\" aria-label=\"Slider navigation\"></nav>');\n      $slides.each(function (i) {\n        var label;\n        if (format === 'alphabet') label = String.fromCharCode(65 + i);else if (format === 'roman') {\n          var map = [[10, 'X'], [9, 'IX'], [5, 'V'], [4, 'IV'], [1, 'I']];\n          var n = i + 1,\n            s = '';\n          map.forEach(function (_ref) {\n            var _ref2 = _slicedToArray(_ref, 2),\n              v = _ref2[0],\n              sym = _ref2[1];\n            while (n >= v) {\n              s += sym;\n              n -= v;\n            }\n          });\n          label = s;\n        } else label = String(i + 1).padStart(2, '0');\n        $host.append('<button type=\"button\" class=\"eael-as-index-item' + (i === 0 ? ' is-active' : '') + '\" data-index=\"' + i + '\">' + '<span class=\"eael-as-index-label\">' + label + '</span>' + '<span class=\"eael-as-index-bar\" aria-hidden=\"true\"></span>' + '</button>');\n      });\n      $scope.append($host);\n      return {\n        $host: $host,\n        onSlideChange: function onSlideChange(idx) {\n          $host.find('.eael-as-index-item').removeClass('is-active');\n          $host.find('.eael-as-index-item[data-index=\"' + idx + '\"]').addClass('is-active');\n        },\n        bindClicks: function bindClicks(swiper) {\n          $host.on('click', '.eael-as-index-item', function () {\n            var idx = parseInt($(this).attr('data-index'), 10);\n            if (!isNaN(idx)) swiper.slideTo(idx);\n          });\n        }\n      };\n    };\n    var getIconTag = function getIconTag(icon) {\n      if (!icon) return '';\n      if (typeof icon === 'string') {\n        return \"<i class=\\\"\".concat(icon, \"\\\"></i>\");\n      }\n      if (icon.library === 'svg') {\n        if (icon.value && icon.value.url) {\n          return \"<img src=\\\"\".concat(icon.value.url, \"\\\" />\");\n        }\n      } else {\n        if (icon.value) {\n          return \"<i class=\\\"\".concat(icon.value, \"\\\"></i>\");\n        }\n      }\n      return '';\n    };\n\n    /* swiperLoader imported from ../_shared/advanced-slider.js (Phase 6.1). */\n\n    var initVerticalSlider = function initVerticalSlider($scope, options, $, settings) {\n      /* Manual-scroll vertical uses native CSS scroll-snap (NOT Swiper).\n         initAdvancedSlider built a mode-agnostic .swiper > .swiper-wrapper\n         hull around the items; in manual-scroll mode that hull is dead\n         weight AND breaks the SCSS rules — the scroll-snap selectors all\n         target .eael-advanced-slider-inner, which until this commit never\n         got attached because the original code looked at $scope > .swiper-\n         wrapper (one level too shallow) and silently no-op'd.\n          Flatten: lift each slide out of .swiper > .swiper-wrapper into a\n         fresh .eael-advanced-slider-inner that lives directly under $scope,\n         strip .swiper-slide (irrelevant outside Swiper), tag with\n         .eael-advanced-slider-slide so the scroll-snap-align rule binds. */\n      var $swiperEl = $scope.children('.swiper').first();\n      var $swiperWrap = $swiperEl.children('.swiper-wrapper').first();\n      var $inner;\n      var $slides;\n      if ($swiperWrap.length) {\n        $inner = $('<div class=\"eael-advanced-slider-inner\"></div>');\n        $slides = $swiperWrap.children('.swiper-slide');\n        $slides.each(function () {\n          $(this).removeClass('swiper-slide').addClass('eael-advanced-slider-slide');\n          $inner.append(this);\n        });\n        $swiperEl.remove();\n        $scope.append($inner);\n      } else {\n        // Legacy / re-init path: structure may already be flattened.\n        $inner = $scope.children('.eael-advanced-slider-inner').first();\n        if (!$inner.length) {\n          $inner = $('<div class=\"eael-advanced-slider-inner\"></div>');\n          $scope.append($inner);\n        }\n        $slides = $inner.children();\n        $slides.addClass('eael-advanced-slider-slide');\n      }\n      if ('yes' === (options === null || options === void 0 ? void 0 : options.indicator)) {\n        var $indicator = $('<ul id=\"eael-advanced-slider-' + $scope.attr('id') + '\" class=\"eael-as-indicator\"></ul>');\n        var mode = (options === null || options === void 0 ? void 0 : options.indicator_type) || '';\n        $slides.each(function (i) {\n          $(this).attr('data-index', i);\n          var label = mode === 'alphabet' ? Object(_shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"toAlphabet\"])(i) : mode === 'roman' ? Object(_shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"toRoman\"])(i + 1) : i + 1;\n          $indicator.append(\"<li class=\\\"eael-as-indicator-index\\\" data-index=\\\"\".concat(i, \"\\\">\").concat(label, \"</li>\"));\n        });\n        $scope.append($indicator);\n      }\n      var $indicators = $scope.find('.eael-as-indicator-index');\n      function update(entries) {\n        entries.forEach(function (entry) {\n          var i = $(entry.target).data('index');\n          $indicators.eq(i).toggleClass('expand', entry.isIntersecting);\n        });\n      }\n      function detect(slide) {\n        var options = {\n          threshold: 0.2\n        };\n        var io = new IntersectionObserver(update, options);\n        io.observe(slide);\n      }\n      $slides.each(function () {\n        detect(this);\n      });\n    };\n    var initMarqueeSlider = function initMarqueeSlider($scope, options, $) {\n      var $track = $scope.find('> .eael-as-track');\n      if (!$track.length) {\n        $track = $scope.find('> .swiper-wrapper');\n        $track.addClass('eael-as-track');\n        $track.removeClass('swiper-wrapper');\n      }\n      if (options !== null && options !== void 0 && options.gap) {\n        $track.css('gap', (options === null || options === void 0 ? void 0 : options.gap) + 'px');\n      }\n      var duplicateTrackContent = function duplicateTrackContent() {\n        var $originalChildren = $track.children().clone(true);\n        if (!$originalChildren.length) {\n          return;\n        }\n        for (var i = 0; i < 4; i++) {\n          $track.append($originalChildren.clone(true));\n        }\n      };\n      setTimeout(duplicateTrackContent, 500);\n      // duplicateTrackContent();\n\n      var SPEED_PX_PER_SEC = (options === null || options === void 0 ? void 0 : options.speed) || 50;\n      function setDuration() {\n        // let totalWidth = $track[0].scrollWidth / 2;\n        var duration = SPEED_PX_PER_SEC / 20;\n        $track.css('--duration', duration + 's');\n      }\n      setDuration();\n      $(window).on('resize', setDuration);\n      if ('yes' === (options === null || options === void 0 ? void 0 : options.pauseOnHover)) {\n        $track.on('mouseenter', function () {\n          $(this).css('animation-play-state', 'paused');\n        });\n        $track.on('mouseleave', function () {\n          $(this).css('animation-play-state', 'running');\n        });\n      }\n      function syncHeight() {\n        var childHeights = $track.children().map(function () {\n          return $(this).outerHeight(true);\n        }).get();\n        if (childHeights.length) {\n          var maxHeight = Math.max.apply(Math, _toConsumableArray(childHeights));\n          if (maxHeight) {\n            $scope.css('height', maxHeight);\n          }\n        }\n      }\n      syncHeight();\n      setTimeout(syncHeight, 50);\n      $(window).on('resize', syncHeight);\n    };\n    var initSwiperSlider = function initSwiperSlider($scope, options, $) {\n      // After the editor restructure, $scope is the outer .eael-advanced-slider\n      // and the actual Swiper container is a .swiper child of it. Fall back to\n      // $scope itself if the structure is legacy (no inner .swiper found).\n      var $inner = $scope.children('.swiper').first();\n      if (!$inner.length) $inner = $scope;\n      // Phase 5.2 — rAF token capture (passive). Tokens accumulate into the\n      // per-slider stash so Phase 5.3 can cancelAnimationFrame() on them\n      // during teardown. Lazy-init the Set so tokens written before the\n      // Swiper promise resolves still land in the right entry.\n      /* Key the per-slider stash by the RAW Elementor element id so it\n         matches the key teardownSlider() and the soft-update fast-path use\n         (model.attributes.id, e.g. \"aaaa111\"). $scope here is the built\n         .eael-advanced-slider whose DOM id is \"eael-advanced-slider-<id>\";\n         stashing under that prefixed id meant teardownSlider(\"<id>\") never\n         found the instance — old Swipers (autoplay timers, listeners) were\n         never destroyed on rebuild, and the soft-update path couldn't locate\n         the live Swiper. Strip the prefix so all three agree on one key. */\n      var elementId = $scope.attr('data-id') || ($scope.attr('id') || '').replace('eael-advanced-slider-', '') || null;\n      var trackRaf = function trackRaf(token) {\n        if (!elementId || !token) return token;\n        var entry = editorState.sliders.get(elementId);\n        if (!entry) {\n          entry = {};\n          editorState.sliders.set(elementId, entry);\n        }\n        entry.rafTokens = entry.rafTokens || new Set();\n        entry.rafTokens.add(token);\n        return token;\n      };\n      var sliderDirection = (options === null || options === void 0 ? void 0 : options.direction) || 'horizontal';\n      var isCardsEffect = (options === null || options === void 0 ? void 0 : options.effect) === 'cards';\n      var isFadeEffect = (options === null || options === void 0 ? void 0 : options.effect) === 'fade';\n      var isFlipEffect = (options === null || options === void 0 ? void 0 : options.effect) === 'flip';\n      /* Fade & Flip are single-slide effects — Swiper shows ONE slide at a\n         time and sizes it to the FULL container width. Mirror the frontend\n         (view JS) and force slidesPerView:1 / spaceBetween:0 for them.\n          Without this the editor fell through to \"Items Per Slide\" (default 3),\n         so each flip/fade slide was sized to ~1/3 of the container. With\n         Swiper's flip effect (virtualTranslate) the active slide then rendered\n         blank at 1/3 width, and the auto-fit pass measured a near-zero slide\n         height → the whole slider collapsed the moment the effect was changed.\n         The frontend never hit this because it already forces perView 1, which\n         is why the breakage was editor-only (and most visible in Firefox). */\n      var isSingleSlideEffect = isFadeEffect || isFlipEffect;\n      var isNavigationEnabled = (options === null || options === void 0 ? void 0 : options.showNavigation) === 'yes' || typeof (options === null || options === void 0 ? void 0 : options.showNavigation) === 'undefined' && 'yes' === (options === null || options === void 0 ? void 0 : options.navigation_arrows);\n      var slidesPerViewValue = isCardsEffect ? 'auto' : isSingleSlideEffect ? 1 : (options === null || options === void 0 ? void 0 : options.items) || 3;\n      var spaceBetweenValue = isCardsEffect ? (options === null || options === void 0 ? void 0 : options.gap) || 0 : isSingleSlideEffect ? 0 : (options === null || options === void 0 ? void 0 : options.gap) || 10;\n      if ('yes' === (options === null || options === void 0 ? void 0 : options.navigation_arrows) && 'fade' !== (options === null || options === void 0 ? void 0 : options.effect) && isNavigationEnabled) {\n        var leftIconHtml = options.navigation_icon_left || '';\n        var rightIconHtml = options.navigation_icon_right || '';\n        if ($inner.find('.swiper-button-next').length === 0) {\n          var content = rightIconHtml ? rightIconHtml : '';\n          var className = rightIconHtml ? 'swiper-button-next eael-as-nav-icon' : 'swiper-button-next';\n          $inner.append(\"<div class=\\\"\".concat(className, \"\\\" aria-label=\\\"Next\\\">\").concat(content, \"</div>\"));\n        }\n        if ($inner.find('.swiper-button-prev').length === 0) {\n          var _content = leftIconHtml ? leftIconHtml : '';\n          var _className = leftIconHtml ? 'swiper-button-prev eael-as-nav-icon' : 'swiper-button-prev';\n          $inner.append(\"<div class=\\\"\".concat(_className, \"\\\" aria-label=\\\"Previous\\\">\").concat(_content, \"</div>\"));\n        }\n      }\n\n      /* ──────── Pagination (new contract) ──────── */\n      var paginationType = Object(_shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"getPaginationType\"])(options);\n      var paginationPosition = Object(_shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"getPaginationPosition\"])(options);\n      var $paginationEl = null;\n      var thumbnailsNav = null;\n      var numberedIndexNav = null;\n      var progressBarNav = null;\n      $scope.addClass('eael-as-pag-' + paginationType.replace(/_/g, '-')).addClass('eael-as-pos-' + paginationPosition.replace(/_/g, '-'));\n      var $slidesForNav = $inner.find('.swiper-wrapper > .swiper-slide');\n      // Note: progress_bar is allowed on fade effect (matches demo V3 — fade hero with progress).\n      if (paginationType === 'progress_bar') {\n        progressBarNav = buildProgressBarNav($scope, options, trackRaf);\n      } else if ('fade' !== (options === null || options === void 0 ? void 0 : options.effect)) {\n        if (paginationType === 'thumbnails') {\n          thumbnailsNav = buildThumbnailsNav($scope, $slidesForNav, options);\n        } else if (paginationType === 'numbered_index') {\n          numberedIndexNav = buildNumberedIndexNav($scope, $slidesForNav, options);\n        } else if (paginationType !== 'none' && isNavigationEnabled) {\n          // Gate on isNavigationEnabled (master Enable toggle), NOT\n          // canShowNavigation. canShowNavigation also excludes vertical\n          // direction — correct for left/right ARROWS, but dots / tick\n          // bars / fraction render fine on a vertical slider. Using the\n          // arrow gate here hid the navigation style for vertical slide\n          // in the editor while the frontend still showed it.\n          $paginationEl = Object(_shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"mountPaginationHost\"])($scope, $inner, paginationType, paginationPosition, $);\n        }\n      }\n\n      // \"Inline with arrows\": co-locate prev-arrow + pagination + next-arrow\n      // in a single flex row. Arrows mount in $inner and the pagination host\n      // in $scope, so without this they live in different parents and the\n      // position collapses to look identical to \"bottom\". Mirrors view JS.\n      if (paginationPosition === 'inline_with_arrows' && 'yes' === (options === null || options === void 0 ? void 0 : options.navigation_arrows)) {\n        var $pagHost = $scope.find('.eael-as-pagination--position-inline-with-arrows').first();\n        var $prevArrow = $inner.find('> .swiper-button-prev').first();\n        var $nextArrow = $inner.find('> .swiper-button-next').first();\n        if ($pagHost.length && $prevArrow.length && $nextArrow.length) {\n          // Tag the row with the pagination type so CSS can give wide-rail\n          // types (progress bar) a definite width instead of shrink-wrapping.\n          var $inlineRow = $('<div class=\"eael-as-inline-row eael-as-inline-row--' + paginationType.replace(/_/g, '-') + '\"></div>');\n          $inlineRow.append($prevArrow).append($pagHost).append($nextArrow);\n          // Append to $scope (outer, overflow:visible) — NOT $inner\n          // (.swiper, overflow:hidden for slide/fade), which clips the row.\n          $scope.append($inlineRow);\n        }\n      }\n\n      /* Autoplay in the editor preview mirrors the frontend so the user can\n         see the configured autoplay/loop behaviour while building — earlier\n         builds held the editor static, but QA flagged \"autoplay not working\n         in editor\" as a regression vs user expectation. Read the same flags\n         the view JS reads. pauseOnHover is honoured here too so hovering the\n         preview to edit a slide doesn't fight the auto-advance. */\n      var isAutoplayEnabled = (options === null || options === void 0 ? void 0 : options.autoplay) === 'yes' || (options === null || options === void 0 ? void 0 : options.autoplay) === true;\n      var shouldPauseOnHover = isAutoplayEnabled && (options === null || options === void 0 ? void 0 : options.pauseOnHover) === 'yes';\n\n      // Honor centered_slides toggle on horizontal slide effect.\n      var isCenteredSlides = isCardsEffect || 'yes' === (options === null || options === void 0 ? void 0 : options.centered_slides) && (options === null || options === void 0 ? void 0 : options.effect) === 'slide' && sliderDirection === 'horizontal';\n\n      // Slide-count guard for loop — see view JS comment for the full\n      // rationale. Loop is only safe with MORE real slides than are visible\n      // at once; below that, Swiper's clones run out and it snaps backward\n      // to the first slide (reverse jump) or shows a blank slide — the\n      // latter especially visible in the editor where `observer` re-clones\n      // on Elementor DOM mutations. The old `>= 2 * slidesPerView` guard was\n      // too strict and silently dropped loop on common configs.\n      var realSlideCount = $inner.find('.swiper-wrapper > .swiper-slide').length;\n      var numericSPV = slidesPerViewValue === 'auto' ? 1 : parseInt(slidesPerViewValue, 10) || 1;\n      var wantsLoop = !!(options !== null && options !== void 0 && options.loop);\n      var safeLoop = wantsLoop && realSlideCount > numericSPV;\n      var swiperOptions = {\n        effect: (options === null || options === void 0 ? void 0 : options.effect) || 'slide',\n        slidesPerView: slidesPerViewValue,\n        slidesPerGroup: 1,\n        spaceBetween: spaceBetweenValue,\n        grabCursor: false,\n        loop: safeLoop,\n        // Clone the FULL slide set on each side — documented cure for\n        // Swiper 8's loop artifacts (reverse-jump teleport + blank\n        // trailing slide). With a full buffer the cycle never reaches an\n        // un-cloned edge. See view JS comment for the full rationale.\n        loopedSlides: safeLoop ? realSlideCount : undefined,\n        speed: (options === null || options === void 0 ? void 0 : options.speed) || 300,\n        direction: sliderDirection,\n        centeredSlides: isCenteredSlides,\n        autoHeight: isCardsEffect && sliderDirection === 'vertical',\n        // Keep false — watchOverflow:true makes Swiper add\n        // swiper-button-lock / swiper-pagination-lock and hide nav +\n        // pagination when slidesPerView >= slide count. Slide effect's\n        // perView comes from \"Items Per Slide\" (default 2), so few-slide\n        // sliders lost their navigation style in the editor preview.\n        watchOverflow: false,\n        observer: true,\n        observeParents: true,\n        navigation: {\n          // Search $scope, not $inner (.swiper): the inline_with_arrows\n          // reparent moves the arrows into the row under $scope, so a\n          // .swiper-scoped lookup would resolve to undefined.\n          nextEl: $scope.find('.swiper-button-next')[0],\n          prevEl: $scope.find('.swiper-button-prev')[0]\n        }\n      };\n      var paginationConfig = $paginationEl ? Object(_shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"buildPaginationConfig\"])(paginationType, $paginationEl[0]) : null;\n      if (paginationConfig) {\n        swiperOptions.pagination = paginationConfig;\n      }\n      if (thumbnailsNav) {\n        try {\n          swiperOptions.thumbs = {\n            swiper: thumbnailsNav.getThumbsSwiper()\n          };\n        } catch (e) {/* swiper modules not ready */}\n      }\n      if (isCardsEffect && sliderDirection === 'vertical') {\n        swiperOptions.slidesPerView = 1;\n        swiperOptions.slidesPerGroup = 1;\n        swiperOptions.centeredSlides = true;\n        swiperOptions.spaceBetween = 0;\n        swiperOptions.autoHeight = true;\n        swiperOptions.watchOverflow = false;\n        swiperOptions.resizeObserver = true;\n        swiperOptions.observer = true;\n        swiperOptions.observeParents = true;\n      }\n      if (isAutoplayEnabled) {\n        swiperOptions.autoplay = _objectSpread({\n          delay: (options === null || options === void 0 ? void 0 : options.autoplay_speed) || 3000,\n          disableOnInteraction: false\n        }, shouldPauseOnHover ? {\n          pauseOnMouseEnter: true\n        } : {});\n      }\n      if ('coverflow' === (options === null || options === void 0 ? void 0 : options.effect)) {\n        // V4 reference defaults: rotation 35°, depth 200, stretch 0, modifier 1.\n        swiperOptions.coverflowEffect = {\n          rotate: typeof (options === null || options === void 0 ? void 0 : options.coverflow_rotation) === 'number' ? options.coverflow_rotation : 35,\n          depth: typeof (options === null || options === void 0 ? void 0 : options.coverflow_depth) === 'number' ? options.coverflow_depth : 200,\n          stretch: typeof (options === null || options === void 0 ? void 0 : options.coverflow_stretch) === 'number' ? options.coverflow_stretch : 0,\n          modifier: 1,\n          slideShadows: (options === null || options === void 0 ? void 0 : options.enable_background) !== false\n        };\n      }\n      if ('cards' === (options === null || options === void 0 ? void 0 : options.effect)) {\n        swiperOptions.cardsEffect = {\n          slideShadows: (options === null || options === void 0 ? void 0 : options.enable_background) !== false,\n          perSlideOffset: 9,\n          // matches reference demo (V5 stacked cards)\n          perSlideRotate: 2.4\n        };\n        // Cards overflow:visible so rotated edges show; let CSS handle clipping per slide.\n        $inner.css('overflow', 'visible');\n      } else if ('flip' === (options === null || options === void 0 ? void 0 : options.effect)) {\n        swiperOptions.flipEffect = {\n          slideShadows: (options === null || options === void 0 ? void 0 : options.enable_background) !== false,\n          limitRotation: true\n        };\n        $inner.css('overflow', 'visible');\n      }\n      var swiperInstancePromise = Object(_shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"swiperLoader\"])($inner[0], swiperOptions);\n\n      // Phase 5.1 — stash the Swiper instance per-slider so future\n      // sub-commits can tear it down before re-init. Write-only at this\n      // commit (no reads, no destroy). Keyed by the Elementor element ID\n      // so multiple sliders on a page don't collide.\n      swiperInstancePromise.then(function (swiper) {\n        if (!swiper || !elementId) return;\n        var prevEntry = editorState.sliders.get(elementId) || {};\n        editorState.sliders.set(elementId, Object.assign(prevEntry, {\n          swiper: swiper\n        }));\n      });\n\n      /**\n       * slidesPerView visual override — CSS-variable approach (mirror of view JS).\n       * Writes Swiper's calculated slide size to a CSS custom property on the\n       * wrapper once per Swiper resize/breakpoint event. The companion rule in\n       * advanced-slider.scss applies the variable to every slide with !important\n       * and specificity high enough to beat Elementor's per-widget max-width\n       * injection. ~1 DOM op per event regardless of slide count.\n       */\n      var applySlideSizeVariable = function applySlideSizeVariable(swiper) {\n        if (!swiper || !swiper.slidesSizesGrid || !swiper.slidesSizesGrid[0]) return;\n        var effect = swiper.params.effect;\n        if (effect === 'cards' || effect === 'flip') return;\n        var size = swiper.slidesSizesGrid[0];\n        // Feedback-loop guard — see view JS for full rationale.\n        if (size > 5000) return;\n        var isVertical = swiper.params.direction === 'vertical';\n        var wrapper = swiper.el && swiper.el.closest ? swiper.el.closest('.eael-advanced-slider') || swiper.el : swiper.el;\n        if (!wrapper) return;\n        if (isVertical) {\n          wrapper.style.setProperty('--eael-as-slide-h', size + 'px');\n        } else {\n          wrapper.style.setProperty('--eael-as-slide-w', size + 'px');\n        }\n      };\n      swiperInstancePromise.then(function (swiper) {\n        if (!swiper) return;\n        applySlideSizeVariable(swiper);\n        swiper.on('resize', function () {\n          return applySlideSizeVariable(swiper);\n        });\n        swiper.on('slidesUpdated', function () {\n          return applySlideSizeVariable(swiper);\n        });\n        swiper.on('breakpoint', function () {\n          return applySlideSizeVariable(swiper);\n        });\n        /* vertical mode needs an extra update() pulse after Elementor's\n           CSS selectors have been injected. On the FIRST direction-toggle to\n           vertical, .swiper height jumps from \"auto\" to \"70vh\" via CSS but\n           Swiper has already cached slide heights against the previous\n           (auto, near-zero) container size. Without this, the editor renders\n           a blank slider until the next resize event. The two-tick approach\n           (rAF + setTimeout) covers both the immediate CSS settle and any\n           late paint. */\n        if (swiper.params.direction === 'vertical') {\n          var refresh = function refresh() {\n            if (!swiper.destroyed) {\n              if (typeof swiper.updateSize === 'function') swiper.updateSize();\n              if (typeof swiper.updateSlides === 'function') swiper.updateSlides();\n              if (typeof swiper.update === 'function') swiper.update();\n              applySlideSizeVariable(swiper);\n            }\n          };\n          trackRaf(requestAnimationFrame(refresh));\n          setTimeout(refresh, 120);\n        }\n      });\n\n      /**\n       * Transition Easing — inline timing-function write on every transition.\n       * Mirror of view JS. See that file for the full rationale on why CSS\n       * alone wasn't reliable.\n       */\n      /* ADVANCED_SLIDER_EASING_CURVES is imported from\n         ../_shared/advanced-slider.js (Phase 6.0 — first extraction). */\n      var applyTransitionEasing = function applyTransitionEasing(swiper) {\n        var preset = $scope.attr('data-easing') || 'spring';\n        var curve = _shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"ADVANCED_SLIDER_EASING_CURVES\"][preset] || _shared_advanced_slider_js__WEBPACK_IMPORTED_MODULE_0__[\"ADVANCED_SLIDER_EASING_CURVES\"].spring;\n        // setProperty with 'important' flag — see view JS comment for rationale.\n        if (swiper.wrapperEl) {\n          swiper.wrapperEl.style.setProperty('transition-timing-function', curve, 'important');\n        }\n        if (swiper.slides && swiper.slides.length) {\n          for (var i = 0; i < swiper.slides.length; i++) {\n            if (swiper.slides[i]) {\n              swiper.slides[i].style.setProperty('transition-timing-function', curve, 'important');\n            }\n          }\n        }\n      };\n      swiperInstancePromise.then(function (swiper) {\n        if (!swiper) return;\n        applyTransitionEasing(swiper);\n        swiper.on('setTransition', function () {\n          return applyTransitionEasing(swiper);\n        });\n      });\n      if (['cards', 'flip', 'coverflow'].indexOf(options === null || options === void 0 ? void 0 : options.effect) !== -1 && (options === null || options === void 0 ? void 0 : options.auto_height) === 'yes') {\n        swiperInstancePromise.then(function (swiper) {\n          if (!swiper) return;\n          setTimeout(function () {\n            return autoFitHeight($scope, swiper);\n          }, 50);\n        });\n      }\n      if (numberedIndexNav) {\n        swiperInstancePromise.then(function (swiper) {\n          if (!swiper) return;\n          numberedIndexNav.bindClicks(swiper);\n          swiper.on('slideChange', function () {\n            return numberedIndexNav.onSlideChange(swiper.realIndex);\n          });\n        });\n      }\n      if (progressBarNav) {\n        swiperInstancePromise.then(function (swiper) {\n          if (!swiper) return;\n          progressBarNav.attach(swiper);\n        });\n      }\n      if (isAutoplayEnabled) {\n        swiperInstancePromise.then(function (swiper) {\n          if (!(swiper !== null && swiper !== void 0 && swiper.autoplay)) return;\n\n          /* PERF (editor lag, worst in Firefox) — the editor renders every\n             slider on the page at once. Swiper autoplay advances on a\n             setTimeout, which browsers do NOT throttle for off-screen\n             elements, so each autoplaying slider keeps firing transitions\n             even while scrolled out of view. Every transition runs the\n             setTransition easing pass (an inline write to each slide, loop\n             clones included) plus a style/layout recalc, so 3-4 stacked\n             sliders animating in the background churn the main thread\n             continuously while the user edits a panel. Firefox feels this\n             hardest because it composites the 3D card/coverflow decks far\n             less cheaply than Chrome.\n              Fix: only autoplay a slider while it is actually inside the\n             editor viewport. Visible sliders still animate (preserves the\n             \"autoplay works in the editor preview\" expectation); off-screen\n             ones stay paused until scrolled into view, so at most the one\n             or two sliders the user is looking at ever run. Front-end\n             behaviour is untouched — this lives only in the editor handler.\n             pauseOnHover (below) and the progress-bar UI both listen to\n             Swiper's autoplayStart/Stop events, so they stay in sync when\n             the observer toggles autoplay. The observer is stashed on the\n             per-slider entry so teardownSlider() disconnects it on rebuild. */\n          var startAutoplay = function startAutoplay() {\n            if (!swiper.destroyed && swiper.autoplay && !swiper.autoplay.running) {\n              try {\n                swiper.autoplay.start();\n              } catch (e) {}\n            }\n          };\n          var stopAutoplay = function stopAutoplay() {\n            if (!swiper.destroyed && swiper.autoplay && swiper.autoplay.running) {\n              try {\n                swiper.autoplay.stop();\n              } catch (e) {}\n            }\n          };\n          var targetEl = $scope[0];\n          if (typeof IntersectionObserver === 'function' && targetEl) {\n            var io = new IntersectionObserver(function (entries) {\n              entries.forEach(function (e) {\n                if (e.isIntersecting) {\n                  startAutoplay();\n                } else {\n                  stopAutoplay();\n                }\n              });\n            }, {\n              threshold: 0\n            });\n            io.observe(targetEl);\n            if (elementId) {\n              var entry = editorState.sliders.get(elementId);\n              if (!entry) {\n                entry = {};\n                editorState.sliders.set(elementId, entry);\n              }\n              entry.autoplayObserver = io;\n            }\n          } else {\n            // No IntersectionObserver support — keep the previous always-on behaviour.\n            startAutoplay();\n          }\n        });\n      }\n      if (shouldPauseOnHover) {\n        swiperInstancePromise.then(function (swiper) {\n          if (!(swiper !== null && swiper !== void 0 && swiper.autoplay)) {\n            return;\n          }\n          var stopAutoplay = function stopAutoplay() {\n            return swiper.autoplay.stop();\n          };\n          var startAutoplay = function startAutoplay() {\n            return swiper.autoplay.start();\n          };\n          $inner.on('mouseenter.eael-advanced-slider', stopAutoplay);\n          $inner.on('mouseleave.eael-advanced-slider', startAutoplay);\n        });\n      }\n      if (isCardsEffect && sliderDirection === 'vertical') {\n        swiperInstancePromise.then(function (swiper) {\n          if (!swiper) {\n            return;\n          }\n          $inner.find('.swiper-slide').css('width', '100%');\n          $inner.find('.swiper-wrapper').css('align-items', 'stretch');\n          var syncHeight = function syncHeight() {\n            if (typeof swiper.updateAutoHeight === 'function') {\n              swiper.updateAutoHeight(0);\n            }\n            if (typeof swiper.update === 'function') {\n              swiper.update();\n            }\n          };\n          syncHeight();\n          setTimeout(syncHeight, 50);\n        });\n      }\n    };\n    function initAdvancedSlider(model) {\n      var _model$attributes, _model$attributes2, _settings$eael_advanc, _settings$eael_advanc2, _settings$eael_advanc3, _settings$eael_advanc4, _settings$eael_advanc5, _settings$eael_advanc6, _settings$eael_advanc7, _items;\n      var settings = model === null || model === void 0 || (_model$attributes = model.attributes) === null || _model$attributes === void 0 || (_model$attributes = _model$attributes.settings) === null || _model$attributes === void 0 ? void 0 : _model$attributes.attributes;\n      if ('yes' !== (settings === null || settings === void 0 ? void 0 : settings.eael_enable_advanced_slider)) {\n        return;\n      }\n      var elementId = model === null || model === void 0 || (_model$attributes2 = model.attributes) === null || _model$attributes2 === void 0 ? void 0 : _model$attributes2.id;\n      if (!elementId) {\n        return;\n      }\n      var element = $(\".elementor-element-\".concat(elementId));\n      var sliderWrapperExists = element.hasClass('eael-advanced-slider-wrapper');\n      /* DOM-intact check. Elementor rebuilds a container's .e-con-inner from\n         the model whenever a child widget renders asynchronously — video\n         oembed resolving, text-editor TinyMCE boot, icon library swap, etc.\n         That rebuild wipes the .swiper structure we injected and drops the\n         slides back into .e-con-inner, so the slider silently un-inits and\n         renders stacked. Image widgets render synchronously and never trigger\n         this, which is why image sliders looked fine while video/text/icon\n         ones didn't. When our injected DOM is gone we MUST rebuild even\n         though the settings signature is unchanged — so the cache skip below\n         is gated on the slider DOM still being present, not just on the\n         wrapper class (which survives Elementor's inner rebuild). */\n      var sliderDomIntact = element.find('.eael-advanced-slider, .eael-advanced-slider-inner, .eael-as-track').length > 0;\n      var signature = buildSettingsSignature(settings);\n      var cached = editorState.sliderSettings[elementId];\n      if (sliderWrapperExists && sliderDomIntact && (cached === null || cached === void 0 ? void 0 : cached.signature) === signature) {\n        return;\n      }\n      editorState.sliderSettings[elementId] = {\n        signature: signature\n      };\n      var isMarquee = (settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_effect_marquee) === 'yes' && 'slide' === settings.eael_advanced_slider_effect;\n\n      // Vertical direction is only supported for the Slide effect — see\n      // PHP register_main_settings_controls and before_render. Normalize\n      // here so editor preview matches frontend for any legacy/saved\n      // sliders that have vertical+non-slide combinations.\n      var effectForOptions = settings.eael_advanced_slider_effect || 'slide';\n      var rawDirection = settings.eael_advanced_slider_direction || 'horizontal';\n      var normalizedDirection = 'slide' === effectForOptions ? rawDirection : 'horizontal';\n      var options = {\n        effect: effectForOptions,\n        direction: normalizedDirection,\n        manualScrolling: settings.eael_advanced_slider_manual_scrolling || 'no',\n        marquee: settings.eael_advanced_slider_effect_marquee || 'no',\n        indicator: settings.eael_advanced_slider_indicator || 'no',\n        indicator_type: settings.eael_advanced_slider_indicator_type || 'number',\n        navigation_arrows: settings.eael_advanced_slider_navigation_arrows || 'no',\n        loop: settings.eael_advanced_slider_loop === 'yes',\n        speed: isMarquee ? ((_settings$eael_advanc = settings.eael_advanced_slider_speed_marquee) === null || _settings$eael_advanc === void 0 ? void 0 : _settings$eael_advanc.size) || 50 : ((_settings$eael_advanc2 = settings.eael_advanced_slider_speed) === null || _settings$eael_advanc2 === void 0 ? void 0 : _settings$eael_advanc2.size) || 300,\n        autoplay: settings.eael_advanced_slider_autoplay === 'yes',\n        autoplay_speed: ((_settings$eael_advanc3 = settings.eael_advanced_slider_autoplay_speed) === null || _settings$eael_advanc3 === void 0 ? void 0 : _settings$eael_advanc3.size) || 3000,\n        items: ((_settings$eael_advanc4 = settings.eael_advanced_slider_per_view) === null || _settings$eael_advanc4 === void 0 ? void 0 : _settings$eael_advanc4.size) || 3,\n        gap: isMarquee ? ((_settings$eael_advanc5 = settings.eael_advanced_slider_item_gap_marquee) === null || _settings$eael_advanc5 === void 0 ? void 0 : _settings$eael_advanc5.size) || 10 : ((_settings$eael_advanc6 = settings.eael_advanced_slider_item_gap) === null || _settings$eael_advanc6 === void 0 ? void 0 : _settings$eael_advanc6.size) || 10,\n        enable_background: settings.eael_advanced_slider_enable_background === 'yes',\n        coverflow_rotation: ((_settings$eael_advanc7 = settings.eael_advanced_slider_coverflow_rotation) === null || _settings$eael_advanc7 === void 0 ? void 0 : _settings$eael_advanc7.size) || 100,\n        pauseOnHover: isMarquee ? settings.eael_advanced_slider_pause_on_hover_marquee === 'yes' ? 'yes' : 'no' : settings.eael_advanced_slider_pause_on_hover === 'yes' ? 'yes' : 'no',\n        navigation_icon_left: getIconTag(settings.eael_advanced_slider_navigation_icon_left),\n        navigation_icon_right: getIconTag(settings.eael_advanced_slider_navigation_icon_right),\n        showNavigation: settings === null || settings === void 0 ? void 0 : settings.eael_advanced_slider_enable_navigation,\n        // New pagination contract — read from settings, fall through to default.\n        pagination_type: settings.eael_advanced_slider_pagination_type || 'tick_bars',\n        pagination_position: settings.eael_advanced_slider_pagination_position || 'bottom',\n        centered_slides: settings.eael_advanced_slider_centered_slides || 'no',\n        index_format: settings.eael_advanced_slider_index_format || 'number',\n        // Switcher returns 'yes' when on, '' when off. Default is 'yes'.\n        auto_height: settings.eael_advanced_slider_auto_height === '' || settings.eael_advanced_slider_auto_height === 'no' ? 'no' : 'yes'\n      };\n      var sliderDirection = options.direction;\n      var isCardsEffect = options.effect === 'cards';\n      var isEditorMarquee = options.effect === 'slide' && options.direction === 'horizontal' && options.marquee === 'yes';\n      if (element.hasClass('e-con--column')) {\n        element.css('--flex-direction', 'row');\n      }\n      var container = element.find(' > .e-con-inner');\n      if (!container.length) {\n        container = element.find(' > .elementor-container, > .elementor-column-wrap > .elementor-widget-wrap, > .elementor-widget-wrap');\n      }\n      if (!container.length) {\n        container = element;\n      }\n\n      // Search for items. If already wrapped, look inside the wrapper.\n      // `.e-con` catches nested Elementor flex containers used as slides\n      // (4.x renders them with this class instead of `.e-child`).\n      var items = container.find(' > .e-child, > .elementor-column, > .elementor-widget, > .e-con');\n      if (!items.length && container.find('.eael-advanced-slider').length) {\n        // Re-init path: real slides now live nested in .swiper-wrapper, so\n        // the direct-child selector above finds nothing and we fall back to\n        // collecting the already-built slides. This MUST stay scoped to the\n        // MAIN slider wrapper only, via child combinators:\n        //   .eael-advanced-slider > .swiper > .swiper-wrapper > .swiper-slide\n        //   .eael-advanced-slider > .eael-as-track > *   (marquee)\n        // A loose descendant selector (`.eael-advanced-slider .swiper-slide`)\n        // also swept in the THUMBNAILS pagination rail — each thumb is a\n        // `<div class=\"swiper-slide eael-as-thumb\">` nested under\n        // .eael-as-thumbnails — AND Swiper's loop clones. Those got\n        // re-collected as real content slides, the rebuilt slider re-cloned\n        // the larger set, and the thumbnail rail regenerated from it, so the\n        // slide + thumbnail count compounded (~×2–×3) on every control change\n        // (3 → 12 → 30 …). The child-combinator scope reaches only the real\n        // content slides; `:not(.swiper-slide-duplicate)` drops the loop clones.\n        // Editor-only: re-init only fires on control changes.\n        items = container.find('.eael-advanced-slider > .swiper > .swiper-wrapper > .swiper-slide:not(.swiper-slide-duplicate), .eael-advanced-slider > .eael-as-track > *');\n      }\n      if (!((_items = items) !== null && _items !== void 0 && _items.length)) return;\n\n      /* Phase 5.3 — tear down the previous Swiper instance (and cancel\n         any rAFs from the progress-bar tick or vertical refresh pulse)\n         BEFORE the DOM is rebuilt. Order matters: destroy first while\n         the old DOM is still attached so Swiper's cleanup of inline\n         styles / event listeners has something to bind against; THEN\n         detach + empty + rebuild. */\n      teardownSlider(elementId);\n\n      /* Detach BEFORE remove(). Previously we let .remove() destroy the\n         old .eael-advanced-slider wrapper, which silently stripped jQuery\n         data and event handlers from every descendant — including the slide\n         elements we still hold references to in `items`. The slides came\n         back attached but with their state wiped, which manifested as\n         \"sometimes the slider goes blank or reverts to the default\" the\n         moment any signature-affecting control changed (direction, effect,\n         items per slide, etc.) AFTER the first init. detach() preserves\n         data + events on the items so the new init can re-mount them. */\n      items.detach();\n\n      // Clean up previous slider after items have been safely detached.\n      container.find('.eael-advanced-slider, .eael-as-indicator').remove();\n      element.addClass('eael-advanced-slider-wrapper');\n      var shapeTop = container.find(' > .elementor-shape.elementor-shape-top');\n      var shapeBottom = container.find(' > .elementor-shape.elementor-shape-bottom');\n      var overlay = container.find(' > .elementor-element-overlay');\n      var sliderHTML = $('<div id=\"eael-advanced-slider-' + elementId + '\" class=\"eael-advanced-slider\"></div>');\n      sliderHTML.addClass('eael-advanced-slider-' + options.direction);\n      sliderHTML.addClass('eael-advanced-slider-' + options.effect);\n      /* Auto-fit marker. On 3D effects (cards/flip/coverflow) the SCSS card\n         chrome carries a 360px min-height floor for the demo \"card\" presence.\n         When Auto-fit Slide Height is ON (default) that floor fights the\n         auto-fit measure pass — every slide is forced ≥360px so the\n         container never hugs shorter content, leaving a tall empty box. This\n         class lets the SCSS drop the floor when auto-fit is on so the slider\n         sizes to content; the floor still applies when auto-fit is off. */\n      if (['cards', 'flip', 'coverflow'].indexOf(options.effect) !== -1 && options.auto_height === 'yes') {\n        sliderHTML.addClass('eael-as-auto-height');\n      }\n      /* data-easing drives the CSS variable --eael-as-easing for slide\n         transition timing. PHP selectors target [data-easing=\"...\"] and set\n         the variable; .swiper-wrapper's transition-timing-function reads it. */\n      sliderHTML.attr('data-easing', settings.eael_advanced_slider_transition_easing || 'spring');\n\n      /* The .eael-advanced-slider-vertical class drives the vertical SCSS\n         block (height:70vh, overflow:hidden, scroll-snap). It must ONLY be\n         added when the slider is actually a vertical manual-scroll slider —\n         the same gate used for initVerticalSlider() below. Previously this\n         keyed on manualScrolling alone, so a HORIZONTAL slider whose saved\n         data still carried a leftover `manual_scrolling = yes` (e.g. after\n         switching direction back to horizontal) got the vertical class while\n         a normal Swiper was initialized. The 70vh vertical height then\n         applied to a short horizontal slider, producing a tall blank area\n         below it — the \"blank screen at the end of the slider section\". */\n      if (options.effect === 'slide' && options.direction === 'vertical' && options.manualScrolling === 'yes') {\n        sliderHTML.addClass('eael-advanced-slider-vertical');\n      }\n      var swiperWrapper;\n      var $sliderInner; // The .swiper element that Swiper actually inits on\n      if (isEditorMarquee) {\n        sliderHTML.addClass('eael-advanced-slider-marquee');\n        swiperWrapper = $('<div class=\"eael-as-track\"></div>');\n        sliderHTML.append(swiperWrapper);\n        $sliderInner = sliderHTML; // marquee has no separate inner\n      } else {\n        // Wrap the .swiper element as a CHILD of .eael-advanced-slider so the outer\n        // wrapper isn't itself a Swiper container. This is critical for 3D effects\n        // (cards / flip / coverflow): Swiper applies preserve-3d on its own container,\n        // and any sibling DOM (like our pagination) needs to live OUTSIDE that 3D\n        // context — i.e. as a child of the outer .eael-advanced-slider, not inside .swiper.\n        $sliderInner = $('<div class=\"swiper\"></div>');\n        swiperWrapper = $('<div class=\"swiper-wrapper\"></div>');\n        $sliderInner.append(swiperWrapper);\n        sliderHTML.append($sliderInner);\n      }\n      items.each(function () {\n        if (isEditorMarquee) {\n          $(this).removeClass('swiper-slide');\n        } else {\n          $(this).addClass('swiper-slide');\n        }\n        swiperWrapper.append(this);\n      });\n      container.empty();\n      if (overlay.length) {\n        container.append(overlay);\n      }\n      if (shapeTop.length) {\n        container.append(shapeTop);\n      }\n      if (shapeBottom.length) {\n        container.append(shapeBottom);\n      }\n      container.append(sliderHTML);\n      container.css('height', 'auto');\n      if (options.effect === 'slide' && options.direction === 'vertical' && options.manualScrolling === 'yes') {\n        initVerticalSlider(sliderHTML, options, $, settings);\n      } else if (isEditorMarquee) {\n        initMarqueeSlider(sliderHTML, options, $);\n      } else {\n        initSwiperSlider(sliderHTML, options, $);\n      }\n      if (sliderDirection === 'vertical') {\n        if (isCardsEffect) {\n          $(sliderHTML).css('height', 'auto');\n          container.css('height', 'auto');\n        } else {\n          /* stop hardcoding inline height here. The PHP control\n             eael_advanced_slider_height now applies via correctly-scoped\n             {{WRAPPER}} .eael-advanced-slider-vertical selectors and the\n             user's chosen value (default 70vh) is the single source of\n             truth — both in editor and on frontend. We only nudge the\n             container off any leftover explicit height from a previous\n             horizontal init so the CSS rule wins. */\n          $(sliderHTML).css('height', '');\n          container.css('height', '');\n        }\n      }\n    }\n    /**\n     * Walk the editor's model tree and init any container that is a Section\n     * Slider. Recurses into ALL non-widget containers (sections, columns,\n     * containers) so deeply-nested sliders are picked up. Widgets are leaves\n     * and never need walking.\n     *\n     * Performance notes:\n     *  - Iterative DFS with an explicit stack avoids deep recursion overhead\n     *    on pages with many nested containers.\n     *  - For each slider model, initAdvancedSlider's signature check is the\n     *    main perf gate — it skips work when nothing relevant changed.\n     */\n    function getAdvancedSliderSettings(models) {\n      if (!models || !Array.isArray(models) || !models.length) return;\n      var stack = [models];\n      while (stack.length) {\n        var current = stack.pop();\n        if (!Array.isArray(current)) continue;\n        for (var i = 0; i < current.length; i++) {\n          var _model$attributes3, _model$attributes4;\n          var model = current[i];\n          if (!model || !model.attributes) continue;\n          if (model.attributes.elType === 'widget') continue;\n          if ('yes' === (model === null || model === void 0 || (_model$attributes3 = model.attributes) === null || _model$attributes3 === void 0 || (_model$attributes3 = _model$attributes3.settings) === null || _model$attributes3 === void 0 || (_model$attributes3 = _model$attributes3.attributes) === null || _model$attributes3 === void 0 ? void 0 : _model$attributes3.eael_enable_advanced_slider)) {\n            initAdvancedSlider(model);\n          }\n          var children = (_model$attributes4 = model.attributes) === null || _model$attributes4 === void 0 || (_model$attributes4 = _model$attributes4.elements) === null || _model$attributes4 === void 0 ? void 0 : _model$attributes4.models;\n          if (children && children.length) stack.push(children);\n        }\n      }\n    }\n    var runInit = function runInit() {\n      if (editorState.inProgress) {\n        return;\n      }\n      editorState.inProgress = true;\n      editorState.lastRunAt = Date.now();\n      try {\n        var _window$elementor;\n        getAdvancedSliderSettings((_window$elementor = window.elementor) === null || _window$elementor === void 0 || (_window$elementor = _window$elementor.elements) === null || _window$elementor === void 0 ? void 0 : _window$elementor.models);\n      } finally {\n        editorState.inProgress = false;\n      }\n    };\n    if (editorState.queued) {\n      return;\n    }\n    var elapsed = Date.now() - editorState.lastRunAt;\n    var delay = elapsed >= INIT_DEBOUNCE_MS ? 0 : INIT_DEBOUNCE_MS - elapsed;\n    editorState.queued = true;\n    window.setTimeout(function () {\n      editorState.queued = false;\n      runInit();\n    }, delay);\n  };\n  jQuery(window).on(\"elementor/frontend/init\", function () {\n    var _window$elementor2;\n    if (eael.elementStatusCheck('eaelAdvancedSliderEditor')) {\n      return false;\n    }\n    elementorFrontend.hooks.addAction(\"frontend/element_ready/section\", AdvancedSliderHandler);\n    elementorFrontend.hooks.addAction(\"frontend/element_ready/container\", AdvancedSliderHandler);\n    elementorFrontend.hooks.addAction(\"frontend/element_ready/column\", AdvancedSliderHandler);\n\n    /* Re-init when a child widget (re)renders inside a slider. Elementor fires\n       this for the INITIAL render of widgets dropped into a slider container\n       AND for every async re-render afterwards (video oembed resolving,\n       text-editor TinyMCE boot, icon swaps). Without it the slider only\n       (re)builds on a slider control change, so a container whose slides are\n       async-rendering widgets stays stacked after Elementor rebuilds the\n       container DOM. AdvancedSliderHandler ignores its $scope arg here and just\n       schedules a single debounced tree walk; the per-slider signature +\n       DOM-intact guard in initAdvancedSlider keeps already-built, still-intact\n       sliders from rebuilding, so these extra calls coalesce into cheap\n       no-ops. Moving slides into .swiper-wrapper doesn't re-render the widget\n       views, so this can't feed back into an init loop. */\n    elementorFrontend.hooks.addAction(\"frontend/element_ready/widget\", AdvancedSliderHandler);\n    var editorState = window.__eaelAdvancedSliderEditorState || (window.__eaelAdvancedSliderEditorState = {\n      queued: false,\n      inProgress: false,\n      lastRunAt: 0,\n      changeListenerBound: false\n    });\n    if (!editorState.changeListenerBound && (_window$elementor2 = window.elementor) !== null && _window$elementor2 !== void 0 && (_window$elementor2 = _window$elementor2.channels) !== null && _window$elementor2 !== void 0 && _window$elementor2.editor) {\n      editorState.changeListenerBound = true;\n\n      // PERF: Pre-built skip list. These controls drive only CSS via\n      // Elementor's selector-based injection — they never need to trigger\n      // a slider re-init. Skipping them at the change-listener level\n      // avoids even calling AdvancedSliderHandler / scheduling a debounced\n      // runInit, which is the cheapest possible no-op.\n      var CSS_ONLY_CONTROLS = new Set(['eael_advanced_slider_swiper_arrow_size', 'eael_advanced_slider_swiper_arrow_color', 'eael_advanced_slider_swiper_arrow_color_hover', 'eael_advanced_slider_swiper_dot_size', 'eael_advanced_slider_swiper_dot_color', 'eael_advanced_slider_swiper_dot_active_color', 'eael_advanced_slider_dots_border_radius', 'eael_advanced_slider_dots_gap', 'eael_advanced_slider_pagination_color', 'eael_advanced_slider_pagination_active_color', 'eael_advanced_slider_tickbars_height', 'eael_advanced_slider_tickbars_active_height', 'eael_advanced_slider_tickbars_gap', 'eael_advanced_slider_progressbar_height', 'eael_advanced_slider_progressbar_max_width', 'eael_advanced_slider_indicator_color', 'eael_advanced_slider_indicator_bar_width', 'eael_advanced_slider_indicator_bar_color', 'eael_advanced_slider_3d_height', 'eael_advanced_slider_height', 'eael_advanced_slider_background_color']);\n      // Strip Elementor's responsive device suffix to find the base control name.\n      // CRITICAL: do NOT skip every name ending in _tablet / _mobile / etc. —\n      // some responsive controls (Items Per Slide, Item Gap) DO need to\n      // trigger a re-render. Only skip if the BASE name is in CSS_ONLY.\n      var DEVICE_SUFFIX_RE = /^(.+?)(_tablet|_mobile|_widescreen|_laptop|_mobile_extra|_tablet_extra)$/;\n      var isCssOnlyControl = function isCssOnlyControl(name) {\n        if (CSS_ONLY_CONTROLS.has(name)) return true;\n        if (name.indexOf('_typography') !== -1) return true;\n        var m = name.match(DEVICE_SUFFIX_RE);\n        return !!(m && CSS_ONLY_CONTROLS.has(m[1]));\n      };\n      elementor.channels.editor.on('change', function (controlView) {\n        var _controlView$model;\n        var controlName = controlView === null || controlView === void 0 || (_controlView$model = controlView.model) === null || _controlView$model === void 0 ? void 0 : _controlView$model.get('name');\n        if (!controlName) return;\n        if ('eael_enable_advanced_slider' !== controlName && !controlName.startsWith('eael_advanced_slider_') && 'content_width' !== controlName && 'direction' !== controlName && 'flex_direction' !== controlName) {\n          return;\n        }\n\n        // Skip CSS-only controls — Elementor handles them via selectors.\n        if (isCssOnlyControl(controlName)) return;\n\n        // PERF: Don't clear the cache. The signature check inside\n        // initAdvancedSlider detects which sliders actually changed.\n        // CSS-only fields aren't in the signature so they never trigger\n        // expensive DOM rebuilds anyway — but the early-skip above\n        // saves the entire AdvancedSliderHandler call too.\n        AdvancedSliderHandler(null, jQuery);\n      });\n    }\n\n    // Sync button — explicit \"Refresh Preview\" trigger. Forces a full\n    // re-render by invalidating the cache and running the handler again.\n    // This is the EA Parallax-style escape hatch for cases where the\n    // slider DOM gets out of sync (e.g. thumbnails not picking up images\n    // because the slide DOM rendered after our init pass).\n    jQuery(document).on('click', '.eael-as-sync-btn', function (e) {\n      e.preventDefault();\n      var editorState = window.__eaelAdvancedSliderEditorState;\n      if (editorState) editorState.sliderSettings = {};\n      AdvancedSliderHandler(null, jQuery);\n    });\n  });\n})();\n\n//# sourceURL=webpack:///./src/js/edit/advanced-slider.js?");

/***/ })

/******/ });