(function () {
  'use strict';

  var CFG = (typeof window !== 'undefined' && window.misticeaseCfg)
    ? window.misticeaseCfg
    : { images: false, cdnHosts: [], playPng: '' };

  var L10N = CFG.i18n || {};

  var IMAGES_ENABLED = !(
    CFG.images === false ||
    CFG.images === 0 ||
    CFG.images === '0' ||
    CFG.images === '' ||
    CFG.images === 'off' ||
    CFG.images === null ||
    typeof CFG.images === 'undefined'
  );

  function i18n(key, fallback) {
    var value = L10N[key];
    return (typeof value === 'string' && value) ? value : fallback;
  }

  var mgr = (typeof window !== 'undefined') ? window.MisticEasePopupManager : null;

  var BASE = String(CFG.pluginUrl || '').trim();
  if (BASE && BASE.slice(-1) !== '/') BASE += '/';

  function createCloseIcon() {
    var img = document.createElement('img');
    img.src = BASE ? (BASE + 'img/close.png') : '';
    img.alt = '';
    img.decoding = 'async';
    img.width = 24;
    img.height = 24;
    return img;
  }

  function debounce(fn, wait) {
    var t;
    return function () {
      var ctx = this;
      var args = arguments;
      clearTimeout(t);
      t = setTimeout(function () {
        fn.apply(ctx, args);
      }, wait);
    };
  }

  function closestAnchor(el) {
    while (el && el !== document) {
      if (el.tagName && el.tagName.toLowerCase() === 'a') {
        return el;
      }
      el = el.parentNode;
    }
    return null;
  }

  function closestByClass(el, classes) {
    while (el && el !== document) {
      if (el.classList) {
        for (var i = 0; i < classes.length; i++) {
          if (el.classList.contains(classes[i])) {
            return el;
          }
        }
      }
      el = el.parentNode;
    }
    return null;
  }

  function getClampedPopupWidth(widthPx) {
    var viewportWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
    var viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);

    var sideMargin = 48;
    var topBottomMargin = 48;
    var popupPaddingX = 40; // 20px left + 20px right
    var popupPaddingY = 20; // 10px top + 10px bottom
    var aspect = 16 / 9;

    var maxByWidth = Math.max(320, viewportWidth - sideMargin);
    var maxByHeight = Math.max(
      320,
      Math.floor((viewportHeight - topBottomMargin - popupPaddingY) * aspect) + popupPaddingX
    );
    var maxAllowed = Math.min(maxByWidth, maxByHeight);

    if (!widthPx || widthPx < 1) {
      return maxAllowed;
    }

    return Math.min(widthPx, maxAllowed);
  }

  function fitVideoPopupToViewport(popup, iframe, requestedWidthPx) {
    var viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
    var popupPaddingX = 40; // 20px left + 20px right
    var clampedWidth = getClampedPopupWidth(requestedWidthPx);
    var frameWidth = Math.max(0, clampedWidth - popupPaddingX);
    var frameHeight = Math.round(frameWidth / (16 / 9));
    var maxFrameHeight = Math.max(180, viewportHeight - 48 - 20);

    if (frameHeight > maxFrameHeight) {
      frameHeight = maxFrameHeight;
      frameWidth = Math.round(frameHeight * (16 / 9));
      clampedWidth = frameWidth + popupPaddingX;
    }

    popup.style.maxWidth = clampedWidth + 'px';
    popup.style.width = clampedWidth + 'px';
    iframe.style.height = frameHeight + 'px';
  }

  var _lockCount = 0;
  var _scrollTop = 0;
  var _prevBodyStyle = null;

  function lockScroll() {
    _lockCount++;
    if (_lockCount > 1) {
      return;
    }

    var body = document.body;

    _prevBodyStyle = {
      position: body.style.position || '',
      top: body.style.top || '',
      width: body.style.width || '',
      overflow: body.style.overflow || ''
    };

    _scrollTop = (window.pageYOffset || document.documentElement.scrollTop || 0);

    body.style.position = 'fixed';
    body.style.top = (-_scrollTop) + 'px';
    body.style.width = '100%';
    body.style.overflow = 'hidden';
  }

  function unlockScroll() {
    if (_lockCount === 0) {
      return;
    }

    _lockCount--;
    if (_lockCount > 0) {
      return;
    }

    var body = document.body;

    if (_prevBodyStyle) {
      body.style.position = _prevBodyStyle.position;
      body.style.top = _prevBodyStyle.top;
      body.style.width = _prevBodyStyle.width;
      body.style.overflow = _prevBodyStyle.overflow;
    } else {
      body.style.position = '';
      body.style.top = '';
      body.style.width = '';
      body.style.overflow = '';
    }

    if (_scrollTop > 0) {
      window.scrollTo(0, _scrollTop);
    }

    _prevBodyStyle = null;
  }

  // =========================================
  // VIDEO (YouTube / Vimeo / Dailymotion)
  // =========================================
  function isActivationKey(e) {
    var key = e && (e.key || e.keyCode);
    return key === 'Enter' || key === ' ' || key === 'Spacebar' || key === 13 || key === 32;
  }

  function isValidVideoMeta(type, id) {
    type = String(type || '');
    id = String(id || '');

    if (!/^[A-Za-z0-9_-]{1,128}$/.test(id)) {
      return false;
    }

    return type === 'youtube' || type === 'vimeo' || type === 'dailymotion';
  }

  function buildEmbedUrl(type, id) {
    if (!isValidVideoMeta(type, id)) {
      return '';
    }

    if (type === 'youtube') {
      return 'https://www.youtube-nocookie.com/embed/' + id + '?autoplay=1&rel=0&modestbranding=1&playsinline=1';
    }
    if (type === 'vimeo') {
      return 'https://player.vimeo.com/video/' + id + '?autoplay=1';
    }
    if (type === 'dailymotion') {
      return 'https://www.dailymotion.com/embed/video/' + id + '?autoplay=1';
    }
    return '';
  }

  function createVideoWindow(url, widthPx, popupTitle) {
    var popup = document.createElement('div');
    popup.className = 'misticease-popup-content';
    popup.setAttribute('role', 'dialog');
    popup.setAttribute('aria-modal', 'true');

    var clampedWidth = getClampedPopupWidth(widthPx);
    popup.style.maxWidth = clampedWidth + 'px';
    popup.style.width = clampedWidth + 'px';

    var close = document.createElement('button');
    close.type = 'button';
    close.className = 'misticease-close';
    close.setAttribute('aria-label', i18n('closeVideo', 'Close video'));
    close.appendChild(createCloseIcon());

    var iframe = document.createElement('iframe');
    iframe.setAttribute('allowfullscreen', 'true');
    iframe.setAttribute('frameborder', '0');
    iframe.setAttribute('allow', 'autoplay; encrypted-media; picture-in-picture; fullscreen');
    iframe.setAttribute('referrerpolicy', 'strict-origin-when-cross-origin');
    iframe.setAttribute('title', i18n('embeddedVideo', 'Embedded video'));

    popup.appendChild(close);
    popup.appendChild(iframe);

    if (popupTitle) {
      var caption = document.createElement('div');
      caption.className = 'misticease-popup-caption';
      caption.textContent = popupTitle;
      popup.appendChild(caption);
    }

    document.body.appendChild(popup);

    function fit() {
      fitVideoPopupToViewport(popup, iframe, widthPx);
    }

    var debouncedFit = debounce(fit, 100);
    fit();
    window.addEventListener('resize', debouncedFit, false);

    iframe.src = url;

    return {
      el: popup,
      closeBtn: close,
      close: function () {
        window.removeEventListener('resize', debouncedFit, false);
        try {
          iframe.src = 'about:blank';
        } catch (_e) {}
        if (popup && popup.parentNode) {
          popup.parentNode.removeChild(popup);
        }
      }
    };
  }

  function openVideoPopup(url, widthPx, popupTitle) {
    if (mgr && typeof mgr.requestOpen === 'function') {
      mgr.requestOpen({
        owner: 'video',
        group: 'video',
        floatingControls: true,
        create: function () {
          return createVideoWindow(url, widthPx, popupTitle);
        }
      });
      return;
    }

    var olds = document.querySelectorAll('.misticease-popup-overlay');
    for (var i = 0; i < olds.length; i++) {
      if (olds[i].parentNode) {
        olds[i].parentNode.removeChild(olds[i]);
      }
    }

    var overlay = document.createElement('div');
    overlay.className = 'misticease-popup-overlay';
    overlay.setAttribute('role', 'dialog');
    overlay.setAttribute('aria-modal', 'true');

    var popup = document.createElement('div');
    popup.className = 'misticease-popup-content';

    var clampedWidth = getClampedPopupWidth(widthPx);
    popup.style.maxWidth = clampedWidth + 'px';
    popup.style.width = clampedWidth + 'px';

    var close = document.createElement('button');
    close.type = 'button';
    close.className = 'misticease-close';
    close.textContent = '×';
    close.setAttribute('aria-label', i18n('closeVideo', 'Close video'));

    var iframe = document.createElement('iframe');
    iframe.setAttribute('allowfullscreen', 'true');
    iframe.setAttribute('frameborder', '0');
    iframe.setAttribute('allow', 'autoplay; encrypted-media; picture-in-picture; fullscreen');
    iframe.setAttribute('referrerpolicy', 'strict-origin-when-cross-origin');
    iframe.setAttribute('title', i18n('embeddedVideo', 'Embedded video'));

    popup.appendChild(close);
    popup.appendChild(iframe);

    if (popupTitle) {
      var caption = document.createElement('div');
      caption.className = 'misticease-popup-caption';
      caption.textContent = popupTitle;
      popup.appendChild(caption);
    }

    overlay.appendChild(popup);
    document.body.appendChild(overlay);

    lockScroll();

    function fit() {
      fitVideoPopupToViewport(popup, iframe, widthPx);
    }

    var debouncedFit = debounce(fit, 100);
    fit();
    window.addEventListener('resize', debouncedFit, false);

    function cleanup() {
      window.removeEventListener('resize', debouncedFit, false);
      document.removeEventListener('keydown', esc, false);
      if (overlay && overlay.parentNode) {
        overlay.parentNode.removeChild(overlay);
      }
      unlockScroll();
    }

    function esc(e) {
      e = e || window.event;
      if (e.key === 'Escape' || e.keyCode === 27) {
        cleanup();
      }
    }

    close.addEventListener('click', cleanup, false);
    overlay.addEventListener('click', function (e) {
      if (e.target === overlay) {
        cleanup();
      }
    }, false);
    document.addEventListener('keydown', esc, false);

    iframe.src = url;
    close.focus();
  }

  // =========================================
  // IMAGES (Media Library anchors + /wp-content/ or CDN links)
  // =========================================
  var cdnAlt = '';
  if (typeof CFG.cdnHosts !== 'undefined' && CFG.cdnHosts && CFG.cdnHosts.length) {
    var esc = [];
    for (var h = 0; h < CFG.cdnHosts.length; h++) {
      var host = (CFG.cdnHosts[h] || '').toString().replace(/[.*+?^${}()|[\]\\]/g, '\\$&').trim();
      if (host) {
        esc.push(host);
      }
    }
    if (esc.length) {
      cdnAlt = '(?:' + esc.join('|') + ')';
    }
  }

  var IMG_EXT = '(?:jpe?g|png|gif|webp)(?:\\?.*)?$';
  var wpContentOnly = new RegExp('/wp-content/.+\\.' + IMG_EXT, 'i');
  var cdnOrWpContent = cdnAlt
    ? new RegExp('(?:/wp-content/|https?://' + cdnAlt + '/).+\\.' + IMG_EXT, 'i')
    : wpContentOnly;

  function collectGroup() {
    var anchors = document.getElementsByTagName('a');
    var group = [];

    for (var i = 0; i < anchors.length; i++) {
      var a = anchors[i];

      if (!a.classList || !a.classList.contains('misticease-img-popup')) {
        continue;
      }

      var href = a.getAttribute('href') || '';
      if (!href) {
        continue;
      }

      var abs = a.href || href;
      group.push({
        url: abs,
        element: a,
        popupWidth: parseInt(a.getAttribute('data-popup-width') || '0', 10) || 0,
        title: a.getAttribute('data-misticease-title') || ''
      });
    }

    return group;
  }

  function createImageWindow(index, group) {
    var VPCT = 0.9;
    var FRAME_PAD = 15;
    var TITLE_BAND = 28;
    var titleReserve = 0;

    var box = document.createElement('div');
    box.className = 'misticease-image-popup-box';
    box.setAttribute('role', 'dialog');
    box.setAttribute('aria-modal', 'true');
    box.setAttribute('aria-label', i18n('image', 'Image'));
    box.setAttribute('tabindex', '-1');

    box.style.position = 'fixed';
    box.style.display = 'flex';
    box.style.alignItems = 'center';
    box.style.justifyContent = 'center';
    box.style.boxSizing = 'border-box';
    box.style.padding = FRAME_PAD + 'px';
    box.style.background = '#000';

    var btn = document.createElement('button');
    btn.type = 'button';
    btn.className = 'misticease-image-close';
    btn.setAttribute('aria-label', i18n('closeImage', 'Close image'));
    btn.appendChild(createCloseIcon());

    var img = document.createElement('img');
    img.style.display = 'block';
    img.style.width = 'auto';
    img.style.height = 'auto';
    img.style.objectFit = 'contain';
    img.style.margin = '0 auto';

    var caption = document.createElement('div');
    caption.className = 'misticease-image-popup-title';
    caption.hidden = true;

    var portalWrap = null;
    var portalPrev = null;
    var portalNext = null;
    var portalObserver = null;
    var keyHandler = null;
    var hintTimer = null;
    var hoverOffTimer = null;

    function limitBox() {
      var vw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
      var vh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);

      var boxMaxW = Math.floor(vw * VPCT);
      var boxMaxH = Math.floor(vh * VPCT);
      var requested = group[index] && group[index].popupWidth ? group[index].popupWidth : 0;

      if (requested > 0) {
        boxMaxW = Math.min(boxMaxW, requested + FRAME_PAD * 2);
      }

      box.style.maxWidth = boxMaxW + 'px';
      box.style.maxHeight = boxMaxH + 'px';
      box.style.paddingTop = FRAME_PAD + 'px';
      box.style.paddingRight = FRAME_PAD + 'px';
      box.style.paddingBottom = (FRAME_PAD + titleReserve) + 'px';
      box.style.paddingLeft = FRAME_PAD + 'px';

      var innerW = Math.max(0, boxMaxW - FRAME_PAD * 2);
      var innerH = Math.max(0, boxMaxH - FRAME_PAD * 2 - titleReserve);

      img.style.maxWidth = innerW + 'px';
      img.style.maxHeight = innerH + 'px';
    }

    function positionPortal() {
      if (!portalPrev || !portalNext) {
        return;
      }

      var vpH = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
      var r = box.getBoundingClientRect();
      var y = (r.top || 0) + (r.height || 0) / 2;
      y = Math.max(40, Math.min(vpH - 40, y));

      portalPrev.style.top = y + 'px';
      portalNext.style.top = y + 'px';
    }

    function set() {
      img.src = group[index].url;
      if (group[index].title) {
        caption.textContent = group[index].title;
        caption.hidden = false;
        titleReserve = TITLE_BAND;
        if (box.classList) {
          box.classList.add('misticease-has-title');
        }
      } else {
        caption.textContent = '';
        caption.hidden = true;
        titleReserve = 0;
        if (box.classList) {
          box.classList.remove('misticease-has-title');
        }
      }
      limitBox();
      positionPortal();
    }

    function goPrev() {
      index = (index - 1 + group.length) % group.length;
      set();
    }

    function goNext() {
      index = (index + 1) % group.length;
      set();
    }

    function clearHoverOff() {
      if (hoverOffTimer) {
        clearTimeout(hoverOffTimer);
        hoverOffTimer = null;
      }
    }

    function scheduleHoverOff(ms) {
      clearHoverOff();
      hoverOffTimer = setTimeout(function () {
        try {
          box.className = box.className
            .replace(/\bhover-left\b/g, '')
            .replace(/\bhover-right\b/g, '')
            .replace(/\s{2,}/g, ' ')
            .trim();
        } catch (_e) {}
        hoverOffTimer = null;
      }, ms || 2500);
    }

    function reveal(side) {
      try {
        box.className = box.className.replace(/\breveal-left\b|\breveal-right\b/g, '');
        box.className += (side === 'left' ? ' reveal-left' : ' reveal-right');
      } catch (_e) {}

      if (hintTimer) {
        clearTimeout(hintTimer);
        hintTimer = null;
      }

      hintTimer = setTimeout(function () {
        try {
          box.className = box.className
            .replace(/\breveal-left\b|\breveal-right\b/g, '')
            .replace(/\s{2,}/g, ' ')
            .trim();
        } catch (_e) {}
        hintTimer = null;
      }, 1200);
    }

    function showHint(ms) {
      try {
        if (!/\bhinting\b/.test(box.className)) {
          box.className += ' hinting';
        }
      } catch (_e) {}

      if (hintTimer) {
        clearTimeout(hintTimer);
        hintTimer = null;
      }

      hintTimer = setTimeout(function () {
        try {
          box.className = box.className
            .replace(/\bhinting\b/g, '')
            .replace(/\s{2,}/g, ' ')
            .trim();
        } catch (_e) {}
        hintTimer = null;
      }, ms || 2500);
    }

    function setPortalBtn(btnEl, on) {
      if (!btnEl) {
        return;
      }
      btnEl.style.opacity = on ? '1' : '0';
      btnEl.style.pointerEvents = on ? 'auto' : 'none';
    }

    function syncPortal() {
      if (!portalPrev || !portalNext) {
        return;
      }

      positionPortal();
      limitBox();

      var cn = box.className || '';
      var showBoth = /\bhinting\b/.test(cn);
      var showPrev = showBoth || /\bhover-left\b/.test(cn) || /\breveal-left\b/.test(cn);
      var showNext = showBoth || /\bhover-right\b/.test(cn) || /\breveal-right\b/.test(cn);

      setPortalBtn(portalPrev, showPrev);
      setPortalBtn(portalNext, showNext);
    }

    set();

    box.appendChild(btn);
    box.appendChild(img);
    box.appendChild(caption);

    img.addEventListener('load', function () {
      limitBox();
      positionPortal();
    }, false);

    var onResize = function () {
      limitBox();
      positionPortal();
    };

    window.addEventListener('resize', onResize);
    window.addEventListener('orientationchange', onResize);

    if (group.length > 1) {
      var hitL = document.createElement('div');
      var hitR = document.createElement('div');

      hitL.className = 'misticease-hit misticease-hit-left';
      hitR.className = 'misticease-hit misticease-hit-right';

      hitL.addEventListener('mouseenter', function () {
        clearHoverOff();
        if (!/\bhover-left\b/.test(box.className)) {
          box.className += ' hover-left';
        }
      }, false);

      hitL.addEventListener('mouseleave', function () {
        scheduleHoverOff(2500);
      }, false);

      hitR.addEventListener('mouseenter', function () {
        clearHoverOff();
        if (!/\bhover-right\b/.test(box.className)) {
          box.className += ' hover-right';
        }
      }, false);

      hitR.addEventListener('mouseleave', function () {
        scheduleHoverOff(2500);
      }, false);

      hitL.addEventListener('click', function (e) {
        if (e && e.stopPropagation) {
          e.stopPropagation();
        }
        try {
          box.className = box.className
            .replace(/\bhover-left\b/g, '')
            .replace(/\bhover-right\b/g, '')
            .replace(/\s{2,}/g, ' ')
            .trim();
        } catch (_e) {}
        clearHoverOff();
        reveal('left');
        goPrev();
        scheduleHoverOff(1200);
      }, false);

      hitR.addEventListener('click', function (e) {
        if (e && e.stopPropagation) {
          e.stopPropagation();
        }
        try {
          box.className = box.className
            .replace(/\bhover-left\b/g, '')
            .replace(/\bhover-right\b/g, '')
            .replace(/\s{2,}/g, ' ')
            .trim();
        } catch (_e) {}
        clearHoverOff();
        reveal('right');
        goNext();
        scheduleHoverOff(1200);
      }, false);

      portalWrap = document.createElement('div');
      portalWrap.className = 'misticease-image-nav-portal';

      portalPrev = document.createElement('button');
      portalNext = document.createElement('button');

      portalPrev.type = 'button';
      portalNext.type = 'button';
      portalPrev.className = 'misticease-image-popup-nav-portal misticease-image-popup-prev';
      portalNext.className = 'misticease-image-popup-nav-portal misticease-image-popup-next';
      portalPrev.setAttribute('aria-label', i18n('previousImage', 'Previous image'));
      portalNext.setAttribute('aria-label', i18n('nextImage', 'Next image'));
      portalPrev.innerHTML = '&#10094;';
      portalNext.innerHTML = '&#10095;';

      portalWrap.appendChild(portalPrev);
      portalWrap.appendChild(portalNext);
      document.body.appendChild(portalWrap);

      portalObserver = new MutationObserver(function () {
        syncPortal();
      });
      portalObserver.observe(box, { attributes: true, attributeFilter: ['class'] });

      portalPrev.addEventListener('mouseenter', function () {
        clearHoverOff();
        if (!/\bhover-left\b/.test(box.className)) {
          box.className += ' hover-left';
        }
      }, false);

      portalPrev.addEventListener('mouseleave', function () {
        scheduleHoverOff(2500);
      }, false);

      portalNext.addEventListener('mouseenter', function () {
        clearHoverOff();
        if (!/\bhover-right\b/.test(box.className)) {
          box.className += ' hover-right';
        }
      }, false);

      portalNext.addEventListener('mouseleave', function () {
        scheduleHoverOff(2500);
      }, false);

      portalPrev.addEventListener('click', function (e) {
        if (e && e.stopPropagation) {
          e.stopPropagation();
        }
        goPrev();
        if (this && this.blur) {
          this.blur();
        }
      }, false);

      portalNext.addEventListener('click', function (e) {
        if (e && e.stopPropagation) {
          e.stopPropagation();
        }
        goNext();
        if (this && this.blur) {
          this.blur();
        }
      }, false);

      keyHandler = function (e) {
        e = e || window.event;
        var k = e.key || e.keyCode;
        if (k === 'ArrowLeft' || k === 37) {
          if (e.preventDefault) {
            e.preventDefault();
          }
          goPrev();
        }
        if (k === 'ArrowRight' || k === 39) {
          if (e.preventDefault) {
            e.preventDefault();
          }
          goNext();
        }
      };
      document.addEventListener('keydown', keyHandler, false);

      box.appendChild(hitL);
      box.appendChild(hitR);

      showHint(2500);
      syncPortal();

      box.addEventListener('pointerdown', function (e) {
        e = e || window.event;
        var t = e.target || e.srcElement;
        if (t === btn || t === hitL || t === hitR) {
          return;
        }
        showHint(2500);
      }, false);
    }

    document.body.appendChild(box);

    return {
      el: box,
      closeBtn: btn,
      close: function () {
        try {
          window.removeEventListener('resize', onResize);
          window.removeEventListener('orientationchange', onResize);
        } catch (_e) {}

        if (keyHandler) {
          document.removeEventListener('keydown', keyHandler, false);
        }
        if (hintTimer) {
          clearTimeout(hintTimer);
          hintTimer = null;
        }
        if (hoverOffTimer) {
          clearTimeout(hoverOffTimer);
          hoverOffTimer = null;
        }
        if (portalObserver) {
          try {
            portalObserver.disconnect();
          } catch (_e) {}
          portalObserver = null;
        }
        if (portalWrap && portalWrap.parentNode) {
          portalWrap.parentNode.removeChild(portalWrap);
        }
        if (box && box.parentNode) {
          box.parentNode.removeChild(box);
        }
      }
    };
  }

  function createImageNavPortal(box, onPrev, onNext) {
    var wrap = document.createElement('div');
    wrap.className = 'misticease-image-nav-portal';

    var prev = document.createElement('button');
    var next = document.createElement('button');

    prev.type = 'button';
    next.type = 'button';
    prev.className = 'misticease-image-popup-nav-portal misticease-image-popup-prev';
    next.className = 'misticease-image-popup-nav-portal misticease-image-popup-next';
    prev.setAttribute('aria-label', i18n('previousImage', 'Previous image'));
    next.setAttribute('aria-label', i18n('nextImage', 'Next image'));
    prev.innerHTML = '&#10094;';
    next.innerHTML = '&#10095;';

    wrap.appendChild(prev);
    wrap.appendChild(next);
    document.body.appendChild(wrap);

    var timer = null;

    function clearTimer() {
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
    }

    function setBtn(btnEl, on) {
      btnEl.style.opacity = on ? '1' : '0';
      btnEl.style.pointerEvents = on ? 'auto' : 'none';
    }

    function show() {
      setBtn(prev, true);
      setBtn(next, true);
    }

    function hide() {
      setBtn(prev, false);
      setBtn(next, false);
    }

    function scheduleHide(ms) {
      clearTimer();
      timer = setTimeout(function () {
        hide();
        timer = null;
      }, ms || 2500);
    }

    function onEnter() {
      clearTimer();
      show();
    }

    function onLeave() {
      scheduleHide(2500);
    }

    function onMove() {
      clearTimer();
      show();
    }

    if (box && box.addEventListener) {
      box.addEventListener('mouseenter', onEnter, false);
      box.addEventListener('mouseleave', onLeave, false);
      box.addEventListener('mousemove', onMove, false);
    }

    prev.addEventListener('mouseenter', onEnter, false);
    prev.addEventListener('mouseleave', onLeave, false);
    next.addEventListener('mouseenter', onEnter, false);
    next.addEventListener('mouseleave', onLeave, false);

    prev.addEventListener('click', function (e) {
      if (e && e.preventDefault) {
        e.preventDefault();
      }
      if (e && e.stopPropagation) {
        e.stopPropagation();
      }
      onPrev();
      show();
      scheduleHide(2500);
      if (this && this.blur) {
        this.blur();
      }
    }, false);

    next.addEventListener('click', function (e) {
      if (e && e.preventDefault) {
        e.preventDefault();
      }
      if (e && e.stopPropagation) {
        e.stopPropagation();
      }
      onNext();
      show();
      scheduleHide(2500);
      if (this && this.blur) {
        this.blur();
      }
    }, false);

    show();
    scheduleHide(2500);

    return {
      destroy: function () {
        clearTimer();
        try {
          if (box && box.removeEventListener) {
            box.removeEventListener('mouseenter', onEnter, false);
            box.removeEventListener('mouseleave', onLeave, false);
            box.removeEventListener('mousemove', onMove, false);
          }
        } catch (_e) {}
        if (wrap && wrap.parentNode) {
          wrap.parentNode.removeChild(wrap);
        }
      }
    };
  }

  function openImagePopup(index, group) {
    if (mgr && typeof mgr.requestOpen === 'function') {
      mgr.requestOpen({
        owner: 'image',
        group: 'image',
        floatingControls: true,
        create: function () {
          return createImageWindow(index, group);
        }
      });
      return;
    }

    var olds = document.querySelectorAll('.misticease-image-overlay');
    for (var z = 0; z < olds.length; z++) {
      if (olds[z].parentNode) {
        olds[z].parentNode.removeChild(olds[z]);
      }
    }

    var ov = document.createElement('div');
    ov.className = 'misticease-image-overlay';
    ov.setAttribute('role', 'dialog');
    ov.setAttribute('aria-modal', 'true');

    var box = document.createElement('div');
    box.className = 'misticease-image-popup-box';
    box.setAttribute('tabindex', '-1');

    var btn = document.createElement('button');
    btn.type = 'button';
    btn.className = 'misticease-image-close';
    btn.setAttribute('aria-label', i18n('closeImage', 'Close image'));
    btn.appendChild(createCloseIcon());

    var img = document.createElement('img');
    img.style.display = 'block';
    img.style.maxWidth = '100%';
    img.style.maxHeight = '100%';
    img.style.margin = '0 auto';

    function set() {
      img.src = group[index].url;
    }

    function goPrev() {
      index = (index - 1 + group.length) % group.length;
      set();
    }

    function goNext() {
      index = (index + 1) % group.length;
      set();
    }

    set();

    box.appendChild(btn);
    box.appendChild(img);
    ov.appendChild(box);
    document.body.appendChild(ov);

    lockScroll();

    var portal = null;
    var keyHandler = null;

    if (group.length > 1) {
      try {
        img.style.cursor = 'pointer';
        img.addEventListener('click', function (ev) {
          ev = ev || window.event;
          var r = img.getBoundingClientRect();
          var x = (ev.clientX || 0) - (r.left || 0);
          if (x < (r.width || 0) / 2) {
            goPrev();
          } else {
            goNext();
          }
        }, false);
      } catch (_e) {}

      portal = createImageNavPortal(box, goPrev, goNext);

      keyHandler = function (e) {
        e = e || window.event;
        var k = e.key || e.keyCode;
        if (k === 'ArrowLeft' || k === 37) {
          if (e.preventDefault) {
            e.preventDefault();
          }
          goPrev();
        }
        if (k === 'ArrowRight' || k === 39) {
          if (e.preventDefault) {
            e.preventDefault();
          }
          goNext();
        }
        if (k === 'Escape' || k === 27) {
          if (e.preventDefault) {
            e.preventDefault();
          }
          cleanup();
        }
      };
      document.addEventListener('keydown', keyHandler, false);
    } else {
      keyHandler = function (e) {
        e = e || window.event;
        var k = e.key || e.keyCode;
        if (k === 'Escape' || k === 27) {
          if (e.preventDefault) {
            e.preventDefault();
          }
          cleanup();
        }
      };
      document.addEventListener('keydown', keyHandler, false);
    }

    function cleanup() {
      if (keyHandler) {
        document.removeEventListener('keydown', keyHandler, false);
      }
      if (portal) {
        portal.destroy();
      }
      if (ov && ov.parentNode) {
        ov.parentNode.removeChild(ov);
      }
      unlockScroll();
    }

    ov.addEventListener('click', function (e) {
      if (e.target === ov) {
        cleanup();
      }
    }, false);

    btn.addEventListener('click', function () {
      cleanup();
    }, false);
  }

  // =========================================
  // Boot (event delegation for videos, global capture for images)
  // =========================================
  function setupVideosDelegation() {
    document.addEventListener('click', function (e) {
      e = e || window.event;
      var target = e.target || e.srcElement;

      var trigger = (target.closest && target.closest('.misticease-thumbnail, .misticease-n-link')) ||
        closestByClass(target, ['misticease-thumbnail', 'misticease-n-link']);

      if (!trigger) {
        return;
      }

      var id = trigger.getAttribute('data-video-id');
      var type = trigger.getAttribute('data-video-type');
      var url = buildEmbedUrl(type, id);

      if (!url) {
        return;
      }

      if (e.preventDefault) {
        e.preventDefault();
      } else {
        e.returnValue = false;
      }

      if (e.stopPropagation) {
        e.stopPropagation();
      } else {
        e.cancelBubble = true;
      }

      var w = parseInt(trigger.getAttribute('data-popup-width') || '0', 10) || 0;
      var popupTitle = trigger.getAttribute('data-misticease-title') || '';
      openVideoPopup(url, w, popupTitle);
    }, true);

    document.addEventListener('keydown', function (e) {
      e = e || window.event;

      if (!isActivationKey(e) || e.repeat) {
        return;
      }

      var target = e.target || e.srcElement;
      var trigger = (target.closest && target.closest('.misticease-thumbnail')) ||
        closestByClass(target, ['misticease-thumbnail']);

      if (!trigger) {
        return;
      }

      if (!buildEmbedUrl(trigger.getAttribute('data-video-type'), trigger.getAttribute('data-video-id'))) {
        return;
      }

      if (e.preventDefault) {
        e.preventDefault();
      } else {
        e.returnValue = false;
      }

      trigger.click();
    }, true);
  }

  function setupImagesDelegation() {
    if (!IMAGES_ENABLED) {
      return;
    }

    document.addEventListener('keydown', function (e) {
      e = e || window.event;

      if (!isActivationKey(e) || e.repeat) {
        return;
      }

      var target = e.target || e.srcElement;
      var a = target && target.closest ? target.closest('a.misticease-img-popup') : closestAnchor(target);

      if (!a || !a.classList || !a.classList.contains('misticease-img-popup')) {
        return;
      }

      if (e.preventDefault) {
        e.preventDefault();
      } else {
        e.returnValue = false;
      }

      a.click();
    }, true);

    document.addEventListener('click', function (e) {
      e = e || window.event;
      var target = e.target || e.srcElement;
      var a = target.closest ? target.closest('a') : closestAnchor(target);

      if (!a) {
        return;
      }

      if (!a.classList || !a.classList.contains('misticease-img-popup')) {
        return;
      }

      var group = collectGroup();
      var idx = -1;

      for (var i = 0; i < group.length; i++) {
        if (group[i].element === a) {
          idx = i;
          break;
        }
      }

      if (idx === -1) {
        return;
      }

      if (e.preventDefault) {
        e.preventDefault();
      } else {
        e.returnValue = false;
      }

      if (e.stopPropagation) {
        e.stopPropagation();
      } else {
        e.cancelBubble = true;
      }

      openImagePopup(idx, group);
    }, true);
  }

  function boot() {
    setupVideosDelegation();
    setupImagesDelegation();
  }

  if (document.readyState === 'complete' || document.readyState === 'interactive') {
    boot();
  } else {
    document.addEventListener('DOMContentLoaded', boot, false);
  }
})();