imported>Dawning
Im Wiking It
imported>Dawning
Im Wiking It
Line 3: Line 3:
/* DRUID */
/* DRUID */
$(function () {
$(function () {
  $(".druid-main-images-label").off("click");
    $(".druid-main-images-label").off("click");
  $(".druid-main-images-label").click(function () {
    $(".druid-main-images-label").click(function () {
    var $parent = $(this).closest(".druid-container");
      var $parent = $(this).closest(".druid-container");
    $parent.find(".druid-toggleable").removeClass("focused");
      $parent.find(".druid-toggleable").removeClass("focused");
    var i = $(this).attr("data-druid");
      var i = $(this).attr("data-druid");
    $parent.find(".druid-toggleable[data-druid=" + i + "]").addClass("focused");
      $parent.find(".druid-toggleable[data-druid=" + i + "]").addClass("focused");
    });
 
    $(".druid-collapsible").off("click");
    $(".druid-collapsible").click(function () {
      var kind = $(this).attr("data-druid-section");
      $(this).toggleClass("druid-collapsible-collapsed");
      $(this)
        .closest(".druid-container")
        .find("[data-druid-section-row=" + kind + "]")
        .toggleClass("druid-collapsed");
    });
  });
  /* End DRUID */
 
  /* [[Template:Spoiler]] */
  $(function () {
      $('.spoiler-content')
      .off('click') // in case this code is loaded twice
      .on('click', function(e){
          $(this).toggleClass('show');
      }).find('a').on('click', function(e){
          e.stopPropagation();
      });
 
   });
   });
 
  /* End Template:Spoiler */
   $(".druid-collapsible").off("click");
 
  $(".druid-collapsible").click(function () {
 
    var kind = $(this).attr("data-druid-section");
  /* Link to imported modules from Lua code */
    $(this).toggleClass("druid-collapsible-collapsed");
   $(function() {
    $(this)
      var config = mw.config.get([
      .closest(".druid-container")
          'wgCanonicalNamespace',
      .find("[data-druid-section-row=" + kind + "]")
          'wgFormattedNamespaces'
       .toggleClass("druid-collapsed");
      ]);
      if (config.wgCanonicalNamespace !== 'Module') {
          return;
      }
      var localizedNamespace = config.wgFormattedNamespaces[828];
      $('.s1, .s2, .s').each(function() {
          var $this = $(this);
          var html = $this.html();
          var quote = html[0];
          var isLongStringQuote = quote === '[';
          var quoteRE = new RegExp('^\\' + quote + '|\\' + quote + '$', 'g');
          if (isLongStringQuote) {
              quoteRE = /^\[\[|\]\]$/g;
          }
          var name = html.replace(quoteRE, '');
          var isEnglishPrefix = name.startsWith('Module:');
          var isLocalizedPrefix = name.startsWith(localizedNamespace + ':');
          var isDevPrefix = name.startsWith('Dev:');
          if (isEnglishPrefix || isLocalizedPrefix || isDevPrefix) {
              var attrs = {
                  href: mw.util.getUrl(name)
              };
              if (isDevPrefix) {
                  attrs.href = 'https://commons.wiki.gg/wiki/Module:' + mw.util.wikiUrlencode(name.replace('Dev:', ''));
                  attrs.target = '_blank';
                  attrs.rel = 'noopener';
              }
              var link = mw.html.element('a', attrs, name);
              var str = quote + link + quote;
              if (isLongStringQuote) {
                  str = '[[' + link + ']]';
              }
              $this.html(str);
          }
       });
   });
   });
});
 
/* End DRUID */
  /* dynamic gif displayer ONLY TOUCH IF YOU KNOW WHAT YOU ARE DOING */
 
 
/* [[Template:Spoiler]] */
  (function() {
$(function () {
      'use strict';
$('.spoiler-content')
     
.off('click') // in case this code is loaded twice
      console.log('Dynamic GIF Displayer: Script loading...');
.on('click', function(e){
     
$(this).toggleClass('show');
      // Configuration
}).find('a').on('click', function(e){
      const CONFIG = {
e.stopPropagation();
          containerClass: 'dynamic-gif-container',
});
          displayClass: 'gif-display-area',
 
          autoExpand: true,
});
          expandDelay: 200,
/* End Template:Spoiler */
          collapseDelay: 1000
 
      };
 
     
/* Link to imported modules from Lua code */
      let expandTimer = null;
$(function() {
      let collapseTimer = null;
    var config = mw.config.get([
      let currentGif = null;
        'wgCanonicalNamespace',
     
        'wgFormattedNamespaces'
      function safeCreateError(message) {
    ]);
          const div = document.createElement('div');
    if (config.wgCanonicalNamespace !== 'Module') {
          div.className = 'gif-error';
        return;
          div.textContent = message;
    }
          return div;
    var localizedNamespace = config.wgFormattedNamespaces[828];
      }
    $('.s1, .s2, .s').each(function() {
     
        var $this = $(this);
      function safeCreatePlaceholder(message) {
        var html = $this.html();
          const div = document.createElement('div');
        var quote = html[0];
          div.className = 'gif-placeholder';
        var isLongStringQuote = quote === '[';
          div.textContent = message;
        var quoteRE = new RegExp('^\\' + quote + '|\\' + quote + '$', 'g');
          return div;
        if (isLongStringQuote) {
      }
            quoteRE = /^\[\[|\]\]$/g;
     
        }
      function init() {
        var name = html.replace(quoteRE, '');
          console.log('Dynamic GIF Displayer: Initializing...');
        var isEnglishPrefix = name.startsWith('Module:');
         
        var isLocalizedPrefix = name.startsWith(localizedNamespace + ':');
          const containers = document.querySelectorAll('.' + CONFIG.containerClass);
        var isDevPrefix = name.startsWith('Dev:');
          console.log('Dynamic GIF Displayer: Found', containers.length, 'containers');
        if (isEnglishPrefix || isLocalizedPrefix || isDevPrefix) {
         
            var attrs = {
          containers.forEach(container => {
                href: mw.util.getUrl(name)
              console.log('Dynamic GIF Displayer: Setting up container', container.id);
            };
              setupContainer(container);
            if (isDevPrefix) {
              attachTooltipListeners(container);
                attrs.href = 'https://commons.wiki.gg/wiki/Module:' + mw.util.wikiUrlencode(name.replace('Dev:', ''));
          });
                attrs.target = '_blank';
      }
                attrs.rel = 'noopener';
     
            }
      function setupContainer(container) {
            var link = mw.html.element('a', attrs, name);
          const displayArea = container.querySelector('.' + CONFIG.displayClass);
            var str = quote + link + quote;
          if (!displayArea) {
            if (isLongStringQuote) {
              console.error('Dynamic GIF Displayer: No display area found');
                str = '[[' + link + ']]';
              return;
            }
          }
            $this.html(str);
         
        }
          displayArea.addEventListener('mouseenter', () => {
    });
              clearTimeout(collapseTimer);
});
          });
 
         
/* dynamic gif displayer ONLY TOUCH IF YOU KNOW WHAT YOU ARE DOING */
          displayArea.addEventListener('mouseleave', () => {
 
              scheduleCollapse(container);
(function() {
          });
    'use strict';
      }
   
     
    console.log('Dynamic GIF Displayer: Script loading...');
      function attachTooltipListeners(container) {
   
          console.log('Dynamic GIF Displayer: Attaching tooltip listeners...');
    // Configuration
         
    const CONFIG = {
          const gifMap = buildGifMap(container);
        containerClass: 'dynamic-gif-container',
          console.log('Dynamic GIF Displayer: GIF map', gifMap);
        displayClass: 'gif-display-area',
         
        autoExpand: true,
          const tooltips = document.querySelectorAll('.advanced-tooltip');
        expandDelay: 200,
          console.log('Dynamic GIF Displayer: Found', tooltips.length, 'tooltips');
        collapseDelay: 1000
         
    };
          tooltips.forEach((tooltip) => {
   
              const skillTitle = tooltip.querySelector('.skill-title');
    let expandTimer = null;
              if (!skillTitle) return;
    let collapseTimer = null;
             
    let currentGif = null;
              const skillName = skillTitle.textContent.trim();
   
              const gifUrl = gifMap[skillName];
    function safeCreateError(message) {
             
        const div = document.createElement('div');
              console.log('Dynamic GIF Displayer: Processing tooltip:', skillName, 'GIF:', gifUrl);
        div.className = 'gif-error';
             
        div.textContent = message;
              if (gifUrl) {
        return div;
                  // Remove old listeners if they exist
    }
                  if (tooltip._gifHoverHandler) {
   
                      tooltip.removeEventListener('mouseenter', tooltip._gifHoverHandler);
    function safeCreatePlaceholder(message) {
                  }
        const div = document.createElement('div');
                  if (tooltip._gifLeaveHandler) {
        div.className = 'gif-placeholder';
                      tooltip.removeEventListener('mouseleave', tooltip._gifLeaveHandler);
        div.textContent = message;
                  }
        return div;
                 
    }
                  tooltip._gifHoverHandler = () => handleTooltipHover(container, gifUrl, skillName);
   
                  tooltip._gifLeaveHandler = () => scheduleCollapse(container);
    function init() {
                 
        console.log('Dynamic GIF Displayer: Initializing...');
                  tooltip.addEventListener('mouseenter', tooltip._gifHoverHandler);
       
                  tooltip.addEventListener('mouseleave', tooltip._gifLeaveHandler);
        const containers = document.querySelectorAll('.' + CONFIG.containerClass);
                 
        console.log('Dynamic GIF Displayer: Found', containers.length, 'containers');
                  console.log('Dynamic GIF Displayer: Attached listeners to', skillName);
       
              }
        containers.forEach(container => {
          });
            console.log('Dynamic GIF Displayer: Setting up container', container.id);
      }
            setupContainer(container);
     
            attachTooltipListeners(container);
      function buildGifMap(container) {
        });
          const gifMap = {};
    }
          const listData = container.getAttribute('data-gif-list');
   
         
    function setupContainer(container) {
          if (!listData) {
        const displayArea = container.querySelector('.' + CONFIG.displayClass);
              console.error('Dynamic GIF Displayer: No data-gif-list attribute found');
        if (!displayArea) {
              return gifMap;
            console.error('Dynamic GIF Displayer: No display area found');
          }
            return;
         
        }
          console.log('Dynamic GIF Displayer: Raw list data:', listData);
       
         
        displayArea.addEventListener('mouseenter', () => {
          const entries = listData.split(';').filter(e => e.trim());
            clearTimeout(collapseTimer);
          console.log('Dynamic GIF Displayer: Found', entries.length, 'entries');
        });
         
       
          entries.forEach(entry => {
        displayArea.addEventListener('mouseleave', () => {
              const parts = entry.split(':');
            scheduleCollapse(container);
              if (parts.length >= 2) {
        });
                  const skillName = parts[0].trim();
    }
                  const gifFile = parts.slice(1).join(':').trim();
   
                 
    function attachTooltipListeners(container) {
                  if (skillName && gifFile) {
        console.log('Dynamic GIF Displayer: Attaching tooltip listeners...');
                      let gifUrl;
       
                      if (typeof mw !== 'undefined' && mw.config) {
        const gifMap = buildGifMap(container);
                          const scriptPath = mw.config.get('wgScriptPath') || '';
        console.log('Dynamic GIF Displayer: GIF map', gifMap);
                          gifUrl = scriptPath + '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
       
                      } else {
        const tooltips = document.querySelectorAll('.advanced-tooltip');
                          gifUrl = '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
        console.log('Dynamic GIF Displayer: Found', tooltips.length, 'tooltips');
                      }
       
                     
        tooltips.forEach((tooltip) => {
                      gifMap[skillName] = gifUrl;
            const skillTitle = tooltip.querySelector('.skill-title');
                      console.log('Dynamic GIF Displayer: Mapped "' + skillName + '" to', gifUrl);
            if (!skillTitle) return;
                  }
           
              }
            const skillName = skillTitle.textContent.trim();
          });
            const gifUrl = gifMap[skillName];
         
           
          return gifMap;
            console.log('Dynamic GIF Displayer: Processing tooltip:', skillName, 'GIF:', gifUrl);
      }
           
     
            if (gifUrl) {
                tooltip.removeEventListener('mouseenter', tooltip._gifHoverHandler);
                tooltip.removeEventListener('mouseleave', tooltip._gifLeaveHandler);
               
                tooltip._gifHoverHandler = () => handleTooltipHover(container, gifUrl, skillName);
                tooltip._gifLeaveHandler = () => scheduleCollapse(container);
               
                tooltip.addEventListener('mouseenter', tooltip._gifHoverHandler);
                tooltip.addEventListener('mouseleave', tooltip._gifLeaveHandler);
               
                console.log('Dynamic GIF Displayer: Attached listeners to', skillName);
            }
        });
    }
   
    function buildGifMap(container) {
        const gifMap = {};
        const listData = container.getAttribute('data-gif-list');
       
        if (!listData) {
            console.error('Dynamic GIF Displayer: No data-gif-list attribute found');
            return gifMap;
        }
       
        console.log('Dynamic GIF Displayer: Raw list data:', listData);
       
        const entries = listData.split(';').filter(e => e.trim());
        console.log('Dynamic GIF Displayer: Found', entries.length, 'entries');
       
        entries.forEach(entry => {
            const parts = entry.split(':');
            if (parts.length >= 2) {
                const skillName = parts[0].trim();
                const gifFile = parts.slice(1).join(':').trim();
               
                if (skillName && gifFile) {
                    let gifUrl;
                    if (typeof mw !== 'undefined' && mw.config) {
                        const scriptPath = mw.config.get('wgScriptPath') || '';
                        gifUrl = scriptPath + '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
                    } else {
                        gifUrl = '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
                    }
                   
                    gifMap[skillName] = gifUrl;
                    console.log('Dynamic GIF Displayer: Mapped "' + skillName + '" to', gifUrl);
                }
            }
        });
       
        return gifMap;
    }
   
     function handleTooltipHover(container, gifUrl, skillName) {
     function handleTooltipHover(container, gifUrl, skillName) {
         console.log('Dynamic GIF Displayer: Hovering', skillName);
         console.log('Dynamic GIF Displayer: Hovering', skillName);
Line 218: Line 223:
         clearTimeout(expandTimer);
         clearTimeout(expandTimer);
          
          
        // Immediate response for fast hovers
         expandTimer = setTimeout(() => {
         expandTimer = setTimeout(() => {
             showGif(container, gifUrl, skillName);
             // Check if already showing this GIF to prevent redundant loads
            if (currentGif !== gifUrl) {
                showGif(container, gifUrl, skillName);
            }
         }, CONFIG.expandDelay);
         }, CONFIG.expandDelay);
     }
     }
 
 
     function showGif(container, gifUrl, skillName) {
     function showGif(container, gifUrl, skillName) {
         console.log('Dynamic GIF Displayer: Showing GIF for', skillName, gifUrl);
         console.log('Dynamic GIF Displayer: Showing GIF for', skillName, gifUrl);
Line 236: Line 245:
         }
         }
          
          
         if (currentGif !== gifUrl) {
         // Always update, even if same GIF (ensures display is correct)
            const imgContainer = displayArea.querySelector('.gif-image-container');
        const imgContainer = displayArea.querySelector('.gif-image-container');
            const caption = displayArea.querySelector('.gif-caption');
        const caption = displayArea.querySelector('.gif-caption');
              
       
             if (imgContainer) {
        if (imgContainer) {
             // Only reload if different GIF
             if (currentGif !== gifUrl) {
                 const placeholder = imgContainer.querySelector('.gif-placeholder');
                 const placeholder = imgContainer.querySelector('.gif-placeholder');
                 if (placeholder) {
                 if (placeholder) {
Line 250: Line 261:
                  
                  
                 const gifFilename = gifUrl.split('/').pop();
                 const gifFilename = gifUrl.split('/').pop();
                 if (gifFilename.toLowerCase() === 'blank' || gifFilename.toLowerCase() === 'blank.gif') {
                const decodedFilename = decodeURIComponent(gifFilename);
               
                 if (decodedFilename.toLowerCase() === 'blank' || decodedFilename.toLowerCase() === 'blank.gif') {
                     imgContainer.innerHTML = '';
                     imgContainer.innerHTML = '';
                     imgContainer.appendChild(safeCreatePlaceholder('This node does not require a GIF due to its simplicity.'));
                     imgContainer.appendChild(safeCreatePlaceholder('This node does not require a GIF due to its simplicity.'));
                     imgContainer.classList.remove('loading');
                     imgContainer.classList.remove('loading');
                    currentGif = gifUrl;
                 } else {
                 } else {
                    // Cancel any existing image loads
                    const existingImg = imgContainer.querySelector('img');
                    if (existingImg && existingImg.src !== gifUrl) {
                        existingImg.onload = null;
                        existingImg.onerror = null;
                    }
                   
                     imgContainer.classList.add('loading');
                     imgContainer.classList.add('loading');
                      
                      
Line 261: Line 282:
                     img.alt = skillName;
                     img.alt = skillName;
                     img.style.maxHeight = gifSize + 'px';
                     img.style.maxHeight = gifSize + 'px';
                   
                    // Store reference for cancellation check
                    const loadingGif = gifUrl;
                      
                      
                     img.onload = () => {
                     img.onload = () => {
                         imgContainer.innerHTML = '';
                         // Only update if this is still the desired GIF
                        imgContainer.appendChild(img);
                        if (currentGif === loadingGif || currentGif === null) {
                        imgContainer.classList.remove('loading');
                            imgContainer.innerHTML = '';
                        console.log('Dynamic GIF Displayer: GIF loaded successfully');
                            imgContainer.appendChild(img);
                            imgContainer.classList.remove('loading');
                            currentGif = gifUrl;
                            console.log('Dynamic GIF Displayer: GIF loaded successfully');
                        }
                     };
                     };
                      
                      
                     img.onerror = () => {
                     img.onerror = () => {
                         imgContainer.innerHTML = '';
                         if (currentGif === loadingGif || currentGif === null) {
                        imgContainer.appendChild(safeCreateError('GIF not found: ' + gifUrl));
                            imgContainer.innerHTML = '';
                        imgContainer.classList.remove('loading');
                            imgContainer.appendChild(safeCreateError('GIF not found: ' + decodedFilename));
                        console.error('Dynamic GIF Displayer: Failed to load GIF', gifUrl);
                            imgContainer.classList.remove('loading');
                            currentGif = gifUrl;
                            console.error('Dynamic GIF Displayer: Failed to load GIF', gifUrl);
                        }
                     };
                     };
                 }
                 }
             }
             }
           
            if (caption) {
                caption.textContent = skillName;
                caption.style.display = 'block';
            }
           
            currentGif = gifUrl;
        }
    }
   
    function scheduleCollapse(container) {
        // Keep the most recent GIF displayed instead of clearing it
        // GIF will only change when a different skill node is hovered
        clearTimeout(collapseTimer);
        console.log('Dynamic GIF Displayer: Keeping current GIF displayed');
    }
   
    window.toggleGifDisplay = function(containerId) {
        console.log('Dynamic GIF Displayer: Toggle clicked for', containerId);
        const container = document.getElementById(containerId);
        if (!container) {
            console.error('Dynamic GIF Displayer: Container not found', containerId);
            return;
         }
         }
          
          
        clearTimeout(collapseTimer);
         if (caption) {
       
             caption.textContent = skillName;
         if (container.style.display === 'none') {
             caption.style.display = 'block';
             container.style.display = 'block';
        } else {
             container.style.display = 'none';
         }
         }
       
        // Only clear the GIF when manually toggling the display off
        if (container.style.display === 'none') {
            const displayArea = container.querySelector('.' + CONFIG.displayClass);
            if (displayArea) {
                const imgContainer = displayArea.querySelector('.gif-image-container');
                const caption = displayArea.querySelector('.gif-caption');
               
                if (imgContainer) {
                    imgContainer.innerHTML = '';
                    imgContainer.appendChild(safeCreatePlaceholder('Hover over a skill node to see its demonstration'));
                    imgContainer.style.height = '';
                    imgContainer.style.minHeight = '';
                }
               
                if (caption) {
                    caption.textContent = '';
                    caption.style.display = 'none';
                }
            }
           
            container.classList.remove('expanded');
            currentGif = null;
        }
    };
   
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
   
    window.addEventListener('load', init);
   
    if (typeof mw !== 'undefined' && mw.hook) {
        mw.hook('wikipage.content').add(init);
     }
     }
   
     
    const observer = new MutationObserver(function(mutations) {
      function scheduleCollapse(container) {
        let shouldReinit = false;
          // Keep the most recent GIF displayed instead of clearing it
        mutations.forEach(function(mutation) {
          // GIF will only change when a different skill node is hovered
            if (mutation.addedNodes.length) {
          clearTimeout(collapseTimer);
                mutation.addedNodes.forEach(function(node) {
          console.log('Dynamic GIF Displayer: Keeping current GIF displayed');
                    if (node.nodeType === 1 && (
      }
                        node.classList && node.classList.contains('advanced-tooltip') ||
     
                        node.querySelector && node.querySelector('.advanced-tooltip')
      window.toggleGifDisplay = function(containerId) {
                    )) {
          console.log('Dynamic GIF Displayer: Toggle clicked for', containerId);
                        shouldReinit = true;
          const container = document.getElementById(containerId);
                    }
          if (!container) {
                });
              console.error('Dynamic GIF Displayer: Container not found', containerId);
            }
              return;
        });
          }
        if (shouldReinit) {
         
            console.log('Dynamic GIF Displayer: Content changed, reinitializing...');
          clearTimeout(collapseTimer);
            setTimeout(init, 100);
         
        }
          if (container.style.display === 'none') {
    });
              container.style.display = 'block';
   
          } else {
    observer.observe(document.body, {
              container.style.display = 'none';
        childList: true,
          }
        subtree: true
         
    });
          // Only clear the GIF when manually toggling the display off
   
          if (container.style.display === 'none') {
    console.log('Dynamic GIF Displayer: Script loaded');
              const displayArea = container.querySelector('.' + CONFIG.displayClass);
              if (displayArea) {
                  const imgContainer = displayArea.querySelector('.gif-image-container');
                  const caption = displayArea.querySelector('.gif-caption');
                 
                  if (imgContainer) {
                      imgContainer.innerHTML = '';
                      imgContainer.appendChild(safeCreatePlaceholder('Hover over a skill node to see its demonstration'));
                      imgContainer.style.height = '';
                      imgContainer.style.minHeight = '';
                  }
                 
                  if (caption) {
                      caption.textContent = '';
                      caption.style.display = 'none';
                  }
              }
             
              container.classList.remove('expanded');
              currentGif = null;
          }
      };
     
      if (document.readyState === 'loading') {
          document.addEventListener('DOMContentLoaded', init);
      } else {
          init();
      }
     
      window.addEventListener('load', init);
     
      if (typeof mw !== 'undefined' && mw.hook) {
          mw.hook('wikipage.content').add(init);
      }
     
      const observer = new MutationObserver(function(mutations) {
          let shouldReinit = false;
          mutations.forEach(function(mutation) {
              if (mutation.addedNodes.length) {
                  mutation.addedNodes.forEach(function(node) {
                      if (node.nodeType === 1 && (
                          node.classList && node.classList.contains('advanced-tooltip') ||
                          node.querySelector && node.querySelector('.advanced-tooltip')
                      )) {
                          shouldReinit = true;
                      }
                  });
              }
          });
          if (shouldReinit) {
              console.log('Dynamic GIF Displayer: Content changed, reinitializing...');
              setTimeout(init, 100);
          }
      });
     
      observer.observe(document.body, {
          childList: true,
          subtree: true
      });
     
      console.log('Dynamic GIF Displayer: Script loaded');
})();
})();


 
/* Make mp-links clickable anywhere in the box */
(function() {
(function() {
     'use strict';
     'use strict';
      
      
    console.log('Tab GIF Display: Script loading...');
     function initMpLinksClick() {
   
         const mpLinkItems = document.querySelectorAll('.mp-links > ul > li');
    // Configuration
    const CONFIG = {
        containerClass: 'tab-gif-container',
        displayClass: 'tab-gif-display-area',
        tabsClass: 'tab-gif-tabs',
        tabClass: 'tab-gif-tab',
        activeTabClass: 'tab-gif-active'
    };
   
    let currentContainers = new Map();
    let initAttempts = 0;
    const MAX_INIT_ATTEMPTS = 5;
   
     function safeCreateError(message) {
         const div = document.createElement('div');
        div.className = 'gif-error';
        div.textContent = message;
        return div;
    }
   
    function safeCreatePlaceholder(message) {
        const div = document.createElement('div');
        div.className = 'gif-placeholder';
        div.textContent = message;
        return div;
    }
   
    function init() {
        initAttempts++;
        console.log('Tab GIF Display: Initializing... (attempt ' + initAttempts + ')');
       
        const containers = document.querySelectorAll('.' + CONFIG.containerClass);
        console.log('Tab GIF Display: Found', containers.length, 'containers');
       
        if (containers.length === 0 && initAttempts < MAX_INIT_ATTEMPTS) {
            console.log('Tab GIF Display: No containers found yet, will retry...');
            setTimeout(init, 500);
            return;
        }
          
          
         let setupCount = 0;
         mpLinkItems.forEach(item => {
        containers.forEach(container => {
             // Remove any existing click handler
             const containerId = container.id;
             if (item._clickHandlerAttached) return;
             console.log('Tab GIF Display: Checking container', containerId);
              
              
             if (!currentContainers.has(containerId)) {
             item.addEventListener('click', function(e) {
                 console.log('Tab GIF Display: Setting up NEW container', containerId);
                 // Find the first anchor tag in this li
                 const success = setupContainer(container);
                 const link = this.querySelector('a');
                 if (success) {
                 if (link && e.target !== link) {
                     currentContainers.set(containerId, container);
                     // Trigger a click on the link
                    setupCount++;
                    link.click();
                 }
                 }
            } else {
                console.log('Tab GIF Display: Container already initialized', containerId);
            }
        });
       
        console.log('Tab GIF Display: Successfully set up', setupCount, 'containers');
    }
   
    function setupContainer(container) {
        console.log('Tab GIF Display: setupContainer called for', container.id);
       
        const gifMap = buildGifMap(container);
        console.log('Tab GIF Display: GIF map built', gifMap);
       
        if (Object.keys(gifMap).length === 0) {
            console.error('Tab GIF Display: No GIFs found for container', container.id);
            const displayArea = container.querySelector('.' + CONFIG.displayClass);
            if (displayArea) {
                const imgContainer = displayArea.querySelector('.gif-image-container');
                if (imgContainer) {
                    imgContainer.innerHTML = '';
                    imgContainer.appendChild(safeCreateError('No GIFs configured. Check your list parameter.'));
                }
            }
            return false;
        }
       
        createTabs(container, gifMap);
       
        // Display the first GIF by default
        const firstTabName = Object.keys(gifMap)[0];
        console.log('Tab GIF Display: Showing first tab:', firstTabName);
        showGif(container, gifMap[firstTabName], firstTabName);
       
        return true;
    }
   
    function buildGifMap(container) {
        const gifMap = {};
        const listData = container.getAttribute('data-gif-list');
       
        console.log('Tab GIF Display: Building map for container', container.id);
        console.log('Tab GIF Display: data-gif-list attribute:', listData);
       
        if (!listData) {
            console.error('Tab GIF Display: No data-gif-list attribute found on', container.id);
            return gifMap;
        }
       
        if (listData.trim() === '') {
            console.error('Tab GIF Display: data-gif-list is empty on', container.id);
            return gifMap;
        }
       
        const entries = listData.split(';').filter(e => e.trim());
        console.log('Tab GIF Display: Found', entries.length, 'entries in list');
       
        entries.forEach((entry, index) => {
            console.log('Tab GIF Display: Processing entry', index, ':', entry);
            const parts = entry.split(':');
           
            if (parts.length < 2) {
                console.warn('Tab GIF Display: Invalid entry format (no colon):', entry);
                return;
            }
           
            const tabName = parts[0].trim();
            const gifFile = parts.slice(1).join(':').trim();
           
            console.log('Tab GIF Display: Parsed - Tab:', tabName, 'File:', gifFile);
           
            if (!tabName) {
                console.warn('Tab GIF Display: Empty tab name in entry:', entry);
                return;
            }
           
            if (!gifFile) {
                console.warn('Tab GIF Display: Empty gif file in entry:', entry);
                return;
            }
           
            let gifUrl;
            if (typeof mw !== 'undefined' && mw.config) {
                const scriptPath = mw.config.get('wgScriptPath') || '';
                gifUrl = scriptPath + '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
            } else {
                gifUrl = '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
            }
           
            gifMap[tabName] = gifUrl;
            console.log('Tab GIF Display: Mapped "' + tabName + '" to', gifUrl);
        });
       
        console.log('Tab GIF Display: Final map has', Object.keys(gifMap).length, 'entries');
        return gifMap;
    }
   
    function createTabs(container, gifMap) {
        const tabsContainer = container.querySelector('.' + CONFIG.tabsClass);
        if (!tabsContainer) {
            console.error('Tab GIF Display: No tabs container found in', container.id);
            return;
        }
       
        console.log('Tab GIF Display: Creating tabs in', container.id);
       
        tabsContainer.innerHTML = '';
       
        let isFirst = true;
        let tabCount = 0;
       
        Object.keys(gifMap).forEach(tabName => {
            const tab = document.createElement('button');
            tab.className = CONFIG.tabClass;
            tab.textContent = tabName;
            tab.setAttribute('data-tab-name', tabName);
            tab.type = 'button';
           
            if (isFirst) {
                tab.classList.add(CONFIG.activeTabClass);
                isFirst = false;
            }
           
            tab.addEventListener('click', () => {
                console.log('Tab GIF Display: Tab clicked:', tabName);
                handleTabClick(container, gifMap, tabName);
             });
             });
              
              
             tabsContainer.appendChild(tab);
             item._clickHandlerAttached = true;
            tabCount++;
            console.log('Tab GIF Display: Created tab button for', tabName);
        });
       
        console.log('Tab GIF Display: Created', tabCount, 'tabs total');
    }
   
    function handleTabClick(container, gifMap, tabName) {
        console.log('Tab GIF Display: Handling tab click for', tabName);
       
        const tabs = container.querySelectorAll('.' + CONFIG.tabClass);
        tabs.forEach(tab => {
            if (tab.getAttribute('data-tab-name') === tabName) {
                tab.classList.add(CONFIG.activeTabClass);
            } else {
                tab.classList.remove(CONFIG.activeTabClass);
            }
         });
         });
       
        const gifUrl = gifMap[tabName];
        showGif(container, gifUrl, tabName);
     }
     }
      
      
     function showGif(container, gifUrl, tabName) {
     // Initialize on page load
        console.log('Tab GIF Display: Showing GIF for', tabName, '-', gifUrl);
       
        const displayArea = container.querySelector('.' + CONFIG.displayClass);
        if (!displayArea) {
            console.error('Tab GIF Display: No display area found');
            return;
        }
       
        const rawSize = container.getAttribute('data-gif-size') || '400';
        const gifSize = rawSize.replace(/[^0-9]/g, '') || '400';
       
        const imgContainer = displayArea.querySelector('.gif-image-container');
        const caption = displayArea.querySelector('.gif-caption');
       
        if (imgContainer) {
            const placeholder = imgContainer.querySelector('.gif-placeholder');
            if (placeholder) {
                placeholder.remove();
            }
           
            imgContainer.style.height = gifSize + 'px';
            imgContainer.style.minHeight = gifSize + 'px';
           
            const gifFilename = gifUrl.split('/').pop();
            const decodedFilename = decodeURIComponent(gifFilename);
           
            if (decodedFilename.toLowerCase() === 'blank' || decodedFilename.toLowerCase() === 'blank.gif') {
                imgContainer.innerHTML = '';
                imgContainer.appendChild(safeCreatePlaceholder('No GIF available for this tab.'));
                imgContainer.classList.remove('loading');
            } else {
                const oldImg = imgContainer.querySelector('img');
               
                const img = document.createElement('img');
                img.src = gifUrl;
                img.alt = tabName;
                img.style.maxHeight = gifSize + 'px';
                img.style.opacity = '0';
                img.style.position = 'absolute';
                img.style.transition = 'opacity 0.2s ease';
               
                img.onload = () => {
                    if (oldImg) {
                        oldImg.style.transition = 'opacity 0.15s ease';
                        oldImg.style.opacity = '0';
                        setTimeout(() => {
                            imgContainer.innerHTML = '';
                            img.style.position = 'relative';
                            img.style.opacity = '1';
                            imgContainer.appendChild(img);
                            imgContainer.classList.remove('loading');
                        }, 150);
                    } else {
                        imgContainer.innerHTML = '';
                        img.style.position = 'relative';
                        img.style.opacity = '1';
                        imgContainer.appendChild(img);
                        imgContainer.classList.remove('loading');
                    }
                    console.log('Tab GIF Display: GIF loaded successfully');
                };
               
                img.onerror = () => {
                    imgContainer.innerHTML = '';
                    imgContainer.appendChild(safeCreateError('GIF not found: ' + decodedFilename));
                    imgContainer.classList.remove('loading');
                    console.error('Tab GIF Display: Failed to load GIF', gifUrl);
                };
               
                if (!oldImg) {
                    imgContainer.appendChild(img);
                    imgContainer.classList.add('loading');
                }
            }
        }
       
        if (caption) {
            caption.textContent = tabName;
            caption.style.display = 'block';
        }
    }
   
    window.toggleTabGifDisplay = function(containerId) {
        console.log('Tab GIF Display: Toggle clicked for', containerId);
        const container = document.getElementById(containerId);
        if (!container) {
            console.error('Tab GIF Display: Container not found', containerId);
            return;
        }
       
        if (container.style.display === 'none') {
            container.style.display = 'block';
        } else {
            container.style.display = 'none';
        }
    };
   
     if (document.readyState === 'loading') {
     if (document.readyState === 'loading') {
         document.addEventListener('DOMContentLoaded', init);
         document.addEventListener('DOMContentLoaded', initMpLinksClick);
     } else {
     } else {
         init();
         initMpLinksClick();
     }
     }
      
      
     window.addEventListener('load', init);
    // Reinitialize when content changes
     window.addEventListener('load', initMpLinksClick);
      
      
     if (typeof mw !== 'undefined' && mw.hook) {
     if (typeof mw !== 'undefined' && mw.hook) {
         mw.hook('wikipage.content').add(init);
         mw.hook('wikipage.content').add(initMpLinksClick);
     }
     }
      
      
    // Watch for DOM changes
     const observer = new MutationObserver(function(mutations) {
     const observer = new MutationObserver(function(mutations) {
         let shouldReinit = false;
         let shouldReinit = false;
Line 701: Line 449:
                 mutation.addedNodes.forEach(function(node) {
                 mutation.addedNodes.forEach(function(node) {
                     if (node.nodeType === 1 && (
                     if (node.nodeType === 1 && (
                         node.classList && node.classList.contains(CONFIG.containerClass) ||
                         node.classList && node.classList.contains('mp-links') ||
                         node.querySelector && node.querySelector('.' + CONFIG.containerClass)
                         node.querySelector && node.querySelector('.mp-links')
                     )) {
                     )) {
                         shouldReinit = true;
                         shouldReinit = true;
Line 710: Line 458:
         });
         });
         if (shouldReinit) {
         if (shouldReinit) {
            console.log('Tab GIF Display: Content changed, reinitializing...');
             setTimeout(initMpLinksClick, 100);
             setTimeout(init, 100);
         }
         }
     });
     });
Line 719: Line 466:
         subtree: true
         subtree: true
     });
     });
   
    console.log('Tab GIF Display: Script loaded and ready');
})();
})();


(function () {
(function() {
    const images = [
      'use strict';
        'url(/wiki/Special:Redirect/file/Site-background-image.jpg)',
     
        'url(/wiki/Special:Redirect/file/Site-background-image2.jpg)',
      console.log('Tab GIF Display: Script loading...');
        'url(/wiki/Special:Redirect/file/Site-background-image3.jpg)',
     
    ];
      // Configuration
 
      const CONFIG = {
    // Pick deterministic daily seed
          containerClass: 'tab-gif-container',
    const day = new Date().getDate();
          displayClass: 'tab-gif-display-area',
 
          tabsClass: 'tab-gif-tabs',
    // Deterministic shuffle using day as seed
          tabClass: 'tab-gif-tab',
    function seededRandom(seed) {
          activeTabClass: 'tab-gif-active'
        return Math.abs(Math.sin(seed)) % 1;
      };
    }
     
 
      let currentContainers = new Map();
    const pick1 = Math.floor(seededRandom(day) * images.length);
      let initAttempts = 0;
    let pick2 = Math.floor(seededRandom(day + 1) * images.length);
      const MAX_INIT_ATTEMPTS = 5;
 
     
    if (pick2 === pick1) pick2 = (pick2 + 1) % images.length;
      function safeCreateError(message) {
 
          const div = document.createElement('div');
    document.body.style.backgroundImage = images[pick1];
          div.className = 'gif-error';
 
          div.textContent = message;
    const footer = document.querySelector('.mw-footer');
          return div;
    if (footer) footer.style.backgroundImage = images[pick2];
      }
})();
     
      function safeCreatePlaceholder(message) {
          const div = document.createElement('div');
          div.className = 'gif-placeholder';
          div.textContent = message;
          return div;
      }
     
      function init() {
          initAttempts++;
          console.log('Tab GIF Display: Initializing... (attempt ' + initAttempts + ')');
         
          const containers = document.querySelectorAll('.' + CONFIG.containerClass);
          console.log('Tab GIF Display: Found', containers.length, 'containers');
         
          if (containers.length === 0 && initAttempts < MAX_INIT_ATTEMPTS) {
              console.log('Tab GIF Display: No containers found yet, will retry...');
              setTimeout(init, 500);
              return;
          }
         
          let setupCount = 0;
          containers.forEach(container => {
              const containerId = container.id;
              console.log('Tab GIF Display: Checking container', containerId);
             
              if (!currentContainers.has(containerId)) {
                  console.log('Tab GIF Display: Setting up NEW container', containerId);
                  const success = setupContainer(container);
                  if (success) {
                      currentContainers.set(containerId, container);
                      setupCount++;
                  }
              } else {
                  console.log('Tab GIF Display: Container already initialized', containerId);
              }
          });
         
          console.log('Tab GIF Display: Successfully set up', setupCount, 'containers');
      }
     
      function setupContainer(container) {
          console.log('Tab GIF Display: setupContainer called for', container.id);
         
          const gifMap = buildGifMap(container);
          console.log('Tab GIF Display: GIF map built', gifMap);
         
          if (Object.keys(gifMap).length === 0) {
              console.error('Tab GIF Display: No GIFs found for container', container.id);
              const displayArea = container.querySelector('.' + CONFIG.displayClass);
              if (displayArea) {
                  const imgContainer = displayArea.querySelector('.gif-image-container');
                  if (imgContainer) {
                      imgContainer.innerHTML = '';
                      imgContainer.appendChild(safeCreateError('No GIFs configured. Check your list parameter.'));
                  }
              }
              return false;
          }
         
          createTabs(container, gifMap);
         
          // Display the first GIF by default
          const firstTabName = Object.keys(gifMap)[0];
          console.log('Tab GIF Display: Showing first tab:', firstTabName);
          showGif(container, gifMap[firstTabName], firstTabName);
         
          return true;
      }
     
      function buildGifMap(container) {
          const gifMap = {};
          const listData = container.getAttribute('data-gif-list');
         
          console.log('Tab GIF Display: Building map for container', container.id);
          console.log('Tab GIF Display: data-gif-list attribute:', listData);
         
          if (!listData) {
              console.error('Tab GIF Display: No data-gif-list attribute found on', container.id);
              return gifMap;
          }
         
          if (listData.trim() === '') {
              console.error('Tab GIF Display: data-gif-list is empty on', container.id);
              return gifMap;
          }
         
          const entries = listData.split(';').filter(e => e.trim());
          console.log('Tab GIF Display: Found', entries.length, 'entries in list');
         
          entries.forEach((entry, index) => {
              console.log('Tab GIF Display: Processing entry', index, ':', entry);
              const parts = entry.split(':');
             
              if (parts.length < 2) {
                  console.warn('Tab GIF Display: Invalid entry format (no colon):', entry);
                  return;
              }
             
              const tabName = parts[0].trim();
              const gifFile = parts.slice(1).join(':').trim();
             
              console.log('Tab GIF Display: Parsed - Tab:', tabName, 'File:', gifFile);
             
              if (!tabName) {
                  console.warn('Tab GIF Display: Empty tab name in entry:', entry);
                  return;
              }
             
              if (!gifFile) {
                  console.warn('Tab GIF Display: Empty gif file in entry:', entry);
                  return;
              }
             
              let gifUrl;
              if (typeof mw !== 'undefined' && mw.config) {
                  const scriptPath = mw.config.get('wgScriptPath') || '';
                  gifUrl = scriptPath + '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
              } else {
                  gifUrl = '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
              }
             
              gifMap[tabName] = gifUrl;
              console.log('Tab GIF Display: Mapped "' + tabName + '" to', gifUrl);
          });
         
          console.log('Tab GIF Display: Final map has', Object.keys(gifMap).length, 'entries');
          return gifMap;
      }
     
      function createTabs(container, gifMap) {
          const tabsContainer = container.querySelector('.' + CONFIG.tabsClass);
          if (!tabsContainer) {
              console.error('Tab GIF Display: No tabs container found in', container.id);
              return;
          }
         
          console.log('Tab GIF Display: Creating tabs in', container.id);
         
          tabsContainer.innerHTML = '';
         
          let isFirst = true;
          let tabCount = 0;
         
          Object.keys(gifMap).forEach(tabName => {
              const tab = document.createElement('button');
              tab.className = CONFIG.tabClass;
              tab.textContent = tabName;
              tab.setAttribute('data-tab-name', tabName);
              tab.type = 'button';
             
              if (isFirst) {
                  tab.classList.add(CONFIG.activeTabClass);
                  isFirst = false;
              }
             
              tab.addEventListener('click', () => {
                  console.log('Tab GIF Display: Tab clicked:', tabName);
                  handleTabClick(container, gifMap, tabName);
              });
             
              tabsContainer.appendChild(tab);
              tabCount++;
              console.log('Tab GIF Display: Created tab button for', tabName);
          });
         
          console.log('Tab GIF Display: Created', tabCount, 'tabs total');
      }
     
      function handleTabClick(container, gifMap, tabName) {
          console.log('Tab GIF Display: Handling tab click for', tabName);
         
          const tabs = container.querySelectorAll('.' + CONFIG.tabClass);
          tabs.forEach(tab => {
              if (tab.getAttribute('data-tab-name') === tabName) {
                  tab.classList.add(CONFIG.activeTabClass);
              } else {
                  tab.classList.remove(CONFIG.activeTabClass);
              }
          });
         
          const gifUrl = gifMap[tabName];
          showGif(container, gifUrl, tabName);
      }
     
      function showGif(container, gifUrl, tabName) {
          console.log('Tab GIF Display: Showing GIF for', tabName, '-', gifUrl);
         
          const displayArea = container.querySelector('.' + CONFIG.displayClass);
          if (!displayArea) {
              console.error('Tab GIF Display: No display area found');
              return;
          }
         
          const rawSize = container.getAttribute('data-gif-size') || '400';
          const gifSize = rawSize.replace(/[^0-9]/g, '') || '400';
         
          const imgContainer = displayArea.querySelector('.gif-image-container');
          const caption = displayArea.querySelector('.gif-caption');
         
          if (imgContainer) {
              const placeholder = imgContainer.querySelector('.gif-placeholder');
              if (placeholder) {
                  placeholder.remove();
              }
             
              imgContainer.style.height = gifSize + 'px';
              imgContainer.style.minHeight = gifSize + 'px';
             
              const gifFilename = gifUrl.split('/').pop();
              const decodedFilename = decodeURIComponent(gifFilename);
             
              if (decodedFilename.toLowerCase() === 'blank' || decodedFilename.toLowerCase() === 'blank.gif') {
                  imgContainer.innerHTML = '';
                  imgContainer.appendChild(safeCreatePlaceholder('No GIF available for this tab.'));
                  imgContainer.classList.remove('loading');
              } else {
                  const oldImg = imgContainer.querySelector('img');
                 
                  const img = document.createElement('img');
                  img.src = gifUrl;
                  img.alt = tabName;
                  img.style.maxHeight = gifSize + 'px';
                  img.style.opacity = '0';
                  img.style.position = 'absolute';
                  img.style.transition = 'opacity 0.2s ease';
                 
                  img.onload = () => {
                      if (oldImg) {
                          oldImg.style.transition = 'opacity 0.15s ease';
                          oldImg.style.opacity = '0';
                          setTimeout(() => {
                              imgContainer.innerHTML = '';
                              img.style.position = 'relative';
                              img.style.opacity = '1';
                              imgContainer.appendChild(img);
                              imgContainer.classList.remove('loading');
                          }, 150);
                      } else {
                          imgContainer.innerHTML = '';
                          img.style.position = 'relative';
                          img.style.opacity = '1';
                          imgContainer.appendChild(img);
                          imgContainer.classList.remove('loading');
                      }
                      console.log('Tab GIF Display: GIF loaded successfully');
                  };
                 
                  img.onerror = () => {
                      imgContainer.innerHTML = '';
                      imgContainer.appendChild(safeCreateError('GIF not found: ' + decodedFilename));
                      imgContainer.classList.remove('loading');
                      console.error('Tab GIF Display: Failed to load GIF', gifUrl);
                  };
                 
                  if (!oldImg) {
                      imgContainer.appendChild(img);
                      imgContainer.classList.add('loading');
                  }
              }
          }
         
          if (caption) {
              caption.textContent = tabName;
              caption.style.display = 'block';
          }
      }
     
      window.toggleTabGifDisplay = function(containerId) {
          console.log('Tab GIF Display: Toggle clicked for', containerId);
          const container = document.getElementById(containerId);
          if (!container) {
              console.error('Tab GIF Display: Container not found', containerId);
              return;
          }
         
          if (container.style.display === 'none') {
              container.style.display = 'block';
          } else {
              container.style.display = 'none';
          }
      };
     
      if (document.readyState === 'loading') {
          document.addEventListener('DOMContentLoaded', init);
      } else {
          init();
      }
     
      window.addEventListener('load', init);
     
      if (typeof mw !== 'undefined' && mw.hook) {
          mw.hook('wikipage.content').add(init);
      }
     
      const observer = new MutationObserver(function(mutations) {
          let shouldReinit = false;
          mutations.forEach(function(mutation) {
              if (mutation.addedNodes.length) {
                  mutation.addedNodes.forEach(function(node) {
                      if (node.nodeType === 1 && (
                          node.classList && node.classList.contains(CONFIG.containerClass) ||
                          node.querySelector && node.querySelector('.' + CONFIG.containerClass)
                      )) {
                          shouldReinit = true;
                      }
                  });
              }
          });
          if (shouldReinit) {
              console.log('Tab GIF Display: Content changed, reinitializing...');
              setTimeout(init, 100);
          }
      });
     
      observer.observe(document.body, {
          childList: true,
          subtree: true
      });
     
      console.log('Tab GIF Display: Script loaded and ready');
  })();
 
  (function () {
      const images = [
          'url(/wiki/Special:Redirect/file/Site-background-image.jpg)',
          'url(/wiki/Special:Redirect/file/Site-background-image2.jpg)',
          'url(/wiki/Special:Redirect/file/Site-background-image3.jpg)',
      ];
 
      // Pick deterministic daily seed
      const day = new Date().getDate();
 
      // Deterministic shuffle using day as seed
      function seededRandom(seed) {
          return Math.abs(Math.sin(seed)) % 1;
      }
 
      const pick1 = Math.floor(seededRandom(day) * images.length);
      let pick2 = Math.floor(seededRandom(day + 1) * images.length);
 
      if (pick2 === pick1) pick2 = (pick2 + 1) % images.length;
 
      document.body.style.backgroundImage = images[pick1];
 
      const footer = document.querySelector('.mw-footer');
      if (footer) footer.style.backgroundImage = images[pick2];
  })();

Revision as of 16:52, 10 November 2025

/* Any JavaScript here will be loaded for all users on every page load. */

/* DRUID */
$(function () {
    $(".druid-main-images-label").off("click");
    $(".druid-main-images-label").click(function () {
      var $parent = $(this).closest(".druid-container");
      $parent.find(".druid-toggleable").removeClass("focused");
      var i = $(this).attr("data-druid");
      $parent.find(".druid-toggleable[data-druid=" + i + "]").addClass("focused");
    });
  
    $(".druid-collapsible").off("click");
    $(".druid-collapsible").click(function () {
      var kind = $(this).attr("data-druid-section");
      $(this).toggleClass("druid-collapsible-collapsed");
      $(this)
        .closest(".druid-container")
        .find("[data-druid-section-row=" + kind + "]")
        .toggleClass("druid-collapsed");
    });
  });
  /* End DRUID */
  
  /* [[Template:Spoiler]] */
  $(function () {
      $('.spoiler-content')
      .off('click') // in case this code is loaded twice
      .on('click', function(e){
          $(this).toggleClass('show');
      }).find('a').on('click', function(e){
          e.stopPropagation();
      });
  
  });
  /* End Template:Spoiler */
  
  
  /* Link to imported modules from Lua code */
  $(function() {
      var config = mw.config.get([
          'wgCanonicalNamespace',
          'wgFormattedNamespaces'
      ]);
      if (config.wgCanonicalNamespace !== 'Module') {
          return;
      }
      var localizedNamespace = config.wgFormattedNamespaces[828];
      $('.s1, .s2, .s').each(function() {
          var $this = $(this);
          var html = $this.html();
          var quote = html[0];
          var isLongStringQuote = quote === '[';
          var quoteRE = new RegExp('^\\' + quote + '|\\' + quote + '$', 'g');
          if (isLongStringQuote) {
              quoteRE = /^\[\[|\]\]$/g;
          }
          var name = html.replace(quoteRE, '');
          var isEnglishPrefix = name.startsWith('Module:');
          var isLocalizedPrefix = name.startsWith(localizedNamespace + ':');
          var isDevPrefix = name.startsWith('Dev:');
          if (isEnglishPrefix || isLocalizedPrefix || isDevPrefix) {
              var attrs = {
                  href: mw.util.getUrl(name)
              };
              if (isDevPrefix) {
                  attrs.href = 'https://commons.wiki.gg/wiki/Module:' + mw.util.wikiUrlencode(name.replace('Dev:', ''));
                  attrs.target = '_blank';
                  attrs.rel = 'noopener';
              }
              var link = mw.html.element('a', attrs, name);
              var str = quote + link + quote;
              if (isLongStringQuote) {
                  str = '[[' + link + ']]';
              }
              $this.html(str);
          }
      });
  });
  
  /* dynamic gif displayer ONLY TOUCH IF YOU KNOW WHAT YOU ARE DOING */
  
  (function() {
      'use strict';
      
      console.log('Dynamic GIF Displayer: Script loading...');
      
      // Configuration
      const CONFIG = {
          containerClass: 'dynamic-gif-container',
          displayClass: 'gif-display-area',
          autoExpand: true,
          expandDelay: 200,
          collapseDelay: 1000
      };
      
      let expandTimer = null;
      let collapseTimer = null;
      let currentGif = null;
      
      function safeCreateError(message) {
          const div = document.createElement('div');
          div.className = 'gif-error';
          div.textContent = message;
          return div;
      }
      
      function safeCreatePlaceholder(message) {
          const div = document.createElement('div');
          div.className = 'gif-placeholder';
          div.textContent = message;
          return div;
      }
      
      function init() {
          console.log('Dynamic GIF Displayer: Initializing...');
          
          const containers = document.querySelectorAll('.' + CONFIG.containerClass);
          console.log('Dynamic GIF Displayer: Found', containers.length, 'containers');
          
          containers.forEach(container => {
              console.log('Dynamic GIF Displayer: Setting up container', container.id);
              setupContainer(container);
              attachTooltipListeners(container);
          });
      }
      
      function setupContainer(container) {
          const displayArea = container.querySelector('.' + CONFIG.displayClass);
          if (!displayArea) {
              console.error('Dynamic GIF Displayer: No display area found');
              return;
          }
          
          displayArea.addEventListener('mouseenter', () => {
              clearTimeout(collapseTimer);
          });
          
          displayArea.addEventListener('mouseleave', () => {
              scheduleCollapse(container);
          });
      }
      
      function attachTooltipListeners(container) {
          console.log('Dynamic GIF Displayer: Attaching tooltip listeners...');
          
          const gifMap = buildGifMap(container);
          console.log('Dynamic GIF Displayer: GIF map', gifMap);
          
          const tooltips = document.querySelectorAll('.advanced-tooltip');
          console.log('Dynamic GIF Displayer: Found', tooltips.length, 'tooltips');
          
          tooltips.forEach((tooltip) => {
              const skillTitle = tooltip.querySelector('.skill-title');
              if (!skillTitle) return;
              
              const skillName = skillTitle.textContent.trim();
              const gifUrl = gifMap[skillName];
              
              console.log('Dynamic GIF Displayer: Processing tooltip:', skillName, 'GIF:', gifUrl);
              
              if (gifUrl) {
                  // Remove old listeners if they exist
                  if (tooltip._gifHoverHandler) {
                      tooltip.removeEventListener('mouseenter', tooltip._gifHoverHandler);
                  }
                  if (tooltip._gifLeaveHandler) {
                      tooltip.removeEventListener('mouseleave', tooltip._gifLeaveHandler);
                  }
                  
                  tooltip._gifHoverHandler = () => handleTooltipHover(container, gifUrl, skillName);
                  tooltip._gifLeaveHandler = () => scheduleCollapse(container);
                  
                  tooltip.addEventListener('mouseenter', tooltip._gifHoverHandler);
                  tooltip.addEventListener('mouseleave', tooltip._gifLeaveHandler);
                  
                  console.log('Dynamic GIF Displayer: Attached listeners to', skillName);
              }
          });
      }
      
      function buildGifMap(container) {
          const gifMap = {};
          const listData = container.getAttribute('data-gif-list');
          
          if (!listData) {
              console.error('Dynamic GIF Displayer: No data-gif-list attribute found');
              return gifMap;
          }
          
          console.log('Dynamic GIF Displayer: Raw list data:', listData);
          
          const entries = listData.split(';').filter(e => e.trim());
          console.log('Dynamic GIF Displayer: Found', entries.length, 'entries');
          
          entries.forEach(entry => {
              const parts = entry.split(':');
              if (parts.length >= 2) {
                  const skillName = parts[0].trim();
                  const gifFile = parts.slice(1).join(':').trim();
                  
                  if (skillName && gifFile) {
                      let gifUrl;
                      if (typeof mw !== 'undefined' && mw.config) {
                          const scriptPath = mw.config.get('wgScriptPath') || '';
                          gifUrl = scriptPath + '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
                      } else {
                          gifUrl = '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
                      }
                      
                      gifMap[skillName] = gifUrl;
                      console.log('Dynamic GIF Displayer: Mapped "' + skillName + '" to', gifUrl);
                  }
              }
          });
          
          return gifMap;
      }
      
    function handleTooltipHover(container, gifUrl, skillName) {
        console.log('Dynamic GIF Displayer: Hovering', skillName);
        clearTimeout(collapseTimer);
        clearTimeout(expandTimer);
        
        // Immediate response for fast hovers
        expandTimer = setTimeout(() => {
            // Check if already showing this GIF to prevent redundant loads
            if (currentGif !== gifUrl) {
                showGif(container, gifUrl, skillName);
            }
        }, CONFIG.expandDelay);
    }
  
    function showGif(container, gifUrl, skillName) {
        console.log('Dynamic GIF Displayer: Showing GIF for', skillName, gifUrl);
        
        const displayArea = container.querySelector('.' + CONFIG.displayClass);
        if (!displayArea) return;
        
        const gifSize = container.getAttribute('data-gif-size') || '400';
        
        if (!container.classList.contains('expanded')) {
            container.classList.add('expanded');
            console.log('Dynamic GIF Displayer: Expanded container');
        }
        
        // Always update, even if same GIF (ensures display is correct)
        const imgContainer = displayArea.querySelector('.gif-image-container');
        const caption = displayArea.querySelector('.gif-caption');
        
        if (imgContainer) {
            // Only reload if different GIF
            if (currentGif !== gifUrl) {
                const placeholder = imgContainer.querySelector('.gif-placeholder');
                if (placeholder) {
                    placeholder.remove();
                }
                
                imgContainer.style.height = gifSize + 'px';
                imgContainer.style.minHeight = gifSize + 'px';
                
                const gifFilename = gifUrl.split('/').pop();
                const decodedFilename = decodeURIComponent(gifFilename);
                
                if (decodedFilename.toLowerCase() === 'blank' || decodedFilename.toLowerCase() === 'blank.gif') {
                    imgContainer.innerHTML = '';
                    imgContainer.appendChild(safeCreatePlaceholder('This node does not require a GIF due to its simplicity.'));
                    imgContainer.classList.remove('loading');
                    currentGif = gifUrl;
                } else {
                    // Cancel any existing image loads
                    const existingImg = imgContainer.querySelector('img');
                    if (existingImg && existingImg.src !== gifUrl) {
                        existingImg.onload = null;
                        existingImg.onerror = null;
                    }
                    
                    imgContainer.classList.add('loading');
                    
                    const img = document.createElement('img');
                    img.src = gifUrl;
                    img.alt = skillName;
                    img.style.maxHeight = gifSize + 'px';
                    
                    // Store reference for cancellation check
                    const loadingGif = gifUrl;
                    
                    img.onload = () => {
                        // Only update if this is still the desired GIF
                        if (currentGif === loadingGif || currentGif === null) {
                            imgContainer.innerHTML = '';
                            imgContainer.appendChild(img);
                            imgContainer.classList.remove('loading');
                            currentGif = gifUrl;
                            console.log('Dynamic GIF Displayer: GIF loaded successfully');
                        }
                    };
                    
                    img.onerror = () => {
                        if (currentGif === loadingGif || currentGif === null) {
                            imgContainer.innerHTML = '';
                            imgContainer.appendChild(safeCreateError('GIF not found: ' + decodedFilename));
                            imgContainer.classList.remove('loading');
                            currentGif = gifUrl;
                            console.error('Dynamic GIF Displayer: Failed to load GIF', gifUrl);
                        }
                    };
                }
            }
        }
        
        if (caption) {
            caption.textContent = skillName;
            caption.style.display = 'block';
        }
    }
      
      function scheduleCollapse(container) {
          // Keep the most recent GIF displayed instead of clearing it
          // GIF will only change when a different skill node is hovered
          clearTimeout(collapseTimer);
          console.log('Dynamic GIF Displayer: Keeping current GIF displayed');
      }
      
      window.toggleGifDisplay = function(containerId) {
          console.log('Dynamic GIF Displayer: Toggle clicked for', containerId);
          const container = document.getElementById(containerId);
          if (!container) {
              console.error('Dynamic GIF Displayer: Container not found', containerId);
              return;
          }
          
          clearTimeout(collapseTimer);
          
          if (container.style.display === 'none') {
              container.style.display = 'block';
          } else {
              container.style.display = 'none';
          }
          
          // Only clear the GIF when manually toggling the display off
          if (container.style.display === 'none') {
              const displayArea = container.querySelector('.' + CONFIG.displayClass);
              if (displayArea) {
                  const imgContainer = displayArea.querySelector('.gif-image-container');
                  const caption = displayArea.querySelector('.gif-caption');
                  
                  if (imgContainer) {
                      imgContainer.innerHTML = '';
                      imgContainer.appendChild(safeCreatePlaceholder('Hover over a skill node to see its demonstration'));
                      imgContainer.style.height = '';
                      imgContainer.style.minHeight = '';
                  }
                  
                  if (caption) {
                      caption.textContent = '';
                      caption.style.display = 'none';
                  }
              }
              
              container.classList.remove('expanded');
              currentGif = null;
          }
      };
      
      if (document.readyState === 'loading') {
          document.addEventListener('DOMContentLoaded', init);
      } else {
          init();
      }
      
      window.addEventListener('load', init);
      
      if (typeof mw !== 'undefined' && mw.hook) {
          mw.hook('wikipage.content').add(init);
      }
      
      const observer = new MutationObserver(function(mutations) {
          let shouldReinit = false;
          mutations.forEach(function(mutation) {
              if (mutation.addedNodes.length) {
                  mutation.addedNodes.forEach(function(node) {
                      if (node.nodeType === 1 && (
                          node.classList && node.classList.contains('advanced-tooltip') ||
                          node.querySelector && node.querySelector('.advanced-tooltip')
                      )) {
                          shouldReinit = true;
                      }
                  });
              }
          });
          if (shouldReinit) {
              console.log('Dynamic GIF Displayer: Content changed, reinitializing...');
              setTimeout(init, 100);
          }
      });
      
      observer.observe(document.body, {
          childList: true,
          subtree: true
      });
      
      console.log('Dynamic GIF Displayer: Script loaded');
})();

/* Make mp-links clickable anywhere in the box */
(function() {
    'use strict';
    
    function initMpLinksClick() {
        const mpLinkItems = document.querySelectorAll('.mp-links > ul > li');
        
        mpLinkItems.forEach(item => {
            // Remove any existing click handler
            if (item._clickHandlerAttached) return;
            
            item.addEventListener('click', function(e) {
                // Find the first anchor tag in this li
                const link = this.querySelector('a');
                if (link && e.target !== link) {
                    // Trigger a click on the link
                    link.click();
                }
            });
            
            item._clickHandlerAttached = true;
        });
    }
    
    // Initialize on page load
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initMpLinksClick);
    } else {
        initMpLinksClick();
    }
    
    // Reinitialize when content changes
    window.addEventListener('load', initMpLinksClick);
    
    if (typeof mw !== 'undefined' && mw.hook) {
        mw.hook('wikipage.content').add(initMpLinksClick);
    }
    
    // Watch for DOM changes
    const observer = new MutationObserver(function(mutations) {
        let shouldReinit = false;
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes.length) {
                mutation.addedNodes.forEach(function(node) {
                    if (node.nodeType === 1 && (
                        node.classList && node.classList.contains('mp-links') ||
                        node.querySelector && node.querySelector('.mp-links')
                    )) {
                        shouldReinit = true;
                    }
                });
            }
        });
        if (shouldReinit) {
            setTimeout(initMpLinksClick, 100);
        }
    });
    
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
})();

(function() {
      'use strict';
      
      console.log('Tab GIF Display: Script loading...');
      
      // Configuration
      const CONFIG = {
          containerClass: 'tab-gif-container',
          displayClass: 'tab-gif-display-area',
          tabsClass: 'tab-gif-tabs',
          tabClass: 'tab-gif-tab',
          activeTabClass: 'tab-gif-active'
      };
      
      let currentContainers = new Map();
      let initAttempts = 0;
      const MAX_INIT_ATTEMPTS = 5;
      
      function safeCreateError(message) {
          const div = document.createElement('div');
          div.className = 'gif-error';
          div.textContent = message;
          return div;
      }
      
      function safeCreatePlaceholder(message) {
          const div = document.createElement('div');
          div.className = 'gif-placeholder';
          div.textContent = message;
          return div;
      }
      
      function init() {
          initAttempts++;
          console.log('Tab GIF Display: Initializing... (attempt ' + initAttempts + ')');
          
          const containers = document.querySelectorAll('.' + CONFIG.containerClass);
          console.log('Tab GIF Display: Found', containers.length, 'containers');
          
          if (containers.length === 0 && initAttempts < MAX_INIT_ATTEMPTS) {
              console.log('Tab GIF Display: No containers found yet, will retry...');
              setTimeout(init, 500);
              return;
          }
          
          let setupCount = 0;
          containers.forEach(container => {
              const containerId = container.id;
              console.log('Tab GIF Display: Checking container', containerId);
              
              if (!currentContainers.has(containerId)) {
                  console.log('Tab GIF Display: Setting up NEW container', containerId);
                  const success = setupContainer(container);
                  if (success) {
                      currentContainers.set(containerId, container);
                      setupCount++;
                  }
              } else {
                  console.log('Tab GIF Display: Container already initialized', containerId);
              }
          });
          
          console.log('Tab GIF Display: Successfully set up', setupCount, 'containers');
      }
      
      function setupContainer(container) {
          console.log('Tab GIF Display: setupContainer called for', container.id);
          
          const gifMap = buildGifMap(container);
          console.log('Tab GIF Display: GIF map built', gifMap);
          
          if (Object.keys(gifMap).length === 0) {
              console.error('Tab GIF Display: No GIFs found for container', container.id);
              const displayArea = container.querySelector('.' + CONFIG.displayClass);
              if (displayArea) {
                  const imgContainer = displayArea.querySelector('.gif-image-container');
                  if (imgContainer) {
                      imgContainer.innerHTML = '';
                      imgContainer.appendChild(safeCreateError('No GIFs configured. Check your list parameter.'));
                  }
              }
              return false;
          }
          
          createTabs(container, gifMap);
          
          // Display the first GIF by default
          const firstTabName = Object.keys(gifMap)[0];
          console.log('Tab GIF Display: Showing first tab:', firstTabName);
          showGif(container, gifMap[firstTabName], firstTabName);
          
          return true;
      }
      
      function buildGifMap(container) {
          const gifMap = {};
          const listData = container.getAttribute('data-gif-list');
          
          console.log('Tab GIF Display: Building map for container', container.id);
          console.log('Tab GIF Display: data-gif-list attribute:', listData);
          
          if (!listData) {
              console.error('Tab GIF Display: No data-gif-list attribute found on', container.id);
              return gifMap;
          }
          
          if (listData.trim() === '') {
              console.error('Tab GIF Display: data-gif-list is empty on', container.id);
              return gifMap;
          }
          
          const entries = listData.split(';').filter(e => e.trim());
          console.log('Tab GIF Display: Found', entries.length, 'entries in list');
          
          entries.forEach((entry, index) => {
              console.log('Tab GIF Display: Processing entry', index, ':', entry);
              const parts = entry.split(':');
              
              if (parts.length < 2) {
                  console.warn('Tab GIF Display: Invalid entry format (no colon):', entry);
                  return;
              }
              
              const tabName = parts[0].trim();
              const gifFile = parts.slice(1).join(':').trim();
              
              console.log('Tab GIF Display: Parsed - Tab:', tabName, 'File:', gifFile);
              
              if (!tabName) {
                  console.warn('Tab GIF Display: Empty tab name in entry:', entry);
                  return;
              }
              
              if (!gifFile) {
                  console.warn('Tab GIF Display: Empty gif file in entry:', entry);
                  return;
              }
              
              let gifUrl;
              if (typeof mw !== 'undefined' && mw.config) {
                  const scriptPath = mw.config.get('wgScriptPath') || '';
                  gifUrl = scriptPath + '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
              } else {
                  gifUrl = '/index.php?title=Special:Redirect/file/' + encodeURIComponent(gifFile);
              }
              
              gifMap[tabName] = gifUrl;
              console.log('Tab GIF Display: Mapped "' + tabName + '" to', gifUrl);
          });
          
          console.log('Tab GIF Display: Final map has', Object.keys(gifMap).length, 'entries');
          return gifMap;
      }
      
      function createTabs(container, gifMap) {
          const tabsContainer = container.querySelector('.' + CONFIG.tabsClass);
          if (!tabsContainer) {
              console.error('Tab GIF Display: No tabs container found in', container.id);
              return;
          }
          
          console.log('Tab GIF Display: Creating tabs in', container.id);
          
          tabsContainer.innerHTML = '';
          
          let isFirst = true;
          let tabCount = 0;
          
          Object.keys(gifMap).forEach(tabName => {
              const tab = document.createElement('button');
              tab.className = CONFIG.tabClass;
              tab.textContent = tabName;
              tab.setAttribute('data-tab-name', tabName);
              tab.type = 'button';
              
              if (isFirst) {
                  tab.classList.add(CONFIG.activeTabClass);
                  isFirst = false;
              }
              
              tab.addEventListener('click', () => {
                  console.log('Tab GIF Display: Tab clicked:', tabName);
                  handleTabClick(container, gifMap, tabName);
              });
              
              tabsContainer.appendChild(tab);
              tabCount++;
              console.log('Tab GIF Display: Created tab button for', tabName);
          });
          
          console.log('Tab GIF Display: Created', tabCount, 'tabs total');
      }
      
      function handleTabClick(container, gifMap, tabName) {
          console.log('Tab GIF Display: Handling tab click for', tabName);
          
          const tabs = container.querySelectorAll('.' + CONFIG.tabClass);
          tabs.forEach(tab => {
              if (tab.getAttribute('data-tab-name') === tabName) {
                  tab.classList.add(CONFIG.activeTabClass);
              } else {
                  tab.classList.remove(CONFIG.activeTabClass);
              }
          });
          
          const gifUrl = gifMap[tabName];
          showGif(container, gifUrl, tabName);
      }
      
      function showGif(container, gifUrl, tabName) {
          console.log('Tab GIF Display: Showing GIF for', tabName, '-', gifUrl);
          
          const displayArea = container.querySelector('.' + CONFIG.displayClass);
          if (!displayArea) {
              console.error('Tab GIF Display: No display area found');
              return;
          }
          
          const rawSize = container.getAttribute('data-gif-size') || '400';
          const gifSize = rawSize.replace(/[^0-9]/g, '') || '400';
          
          const imgContainer = displayArea.querySelector('.gif-image-container');
          const caption = displayArea.querySelector('.gif-caption');
          
          if (imgContainer) {
              const placeholder = imgContainer.querySelector('.gif-placeholder');
              if (placeholder) {
                  placeholder.remove();
              }
              
              imgContainer.style.height = gifSize + 'px';
              imgContainer.style.minHeight = gifSize + 'px';
              
              const gifFilename = gifUrl.split('/').pop();
              const decodedFilename = decodeURIComponent(gifFilename);
              
              if (decodedFilename.toLowerCase() === 'blank' || decodedFilename.toLowerCase() === 'blank.gif') {
                  imgContainer.innerHTML = '';
                  imgContainer.appendChild(safeCreatePlaceholder('No GIF available for this tab.'));
                  imgContainer.classList.remove('loading');
              } else {
                  const oldImg = imgContainer.querySelector('img');
                  
                  const img = document.createElement('img');
                  img.src = gifUrl;
                  img.alt = tabName;
                  img.style.maxHeight = gifSize + 'px';
                  img.style.opacity = '0';
                  img.style.position = 'absolute';
                  img.style.transition = 'opacity 0.2s ease';
                  
                  img.onload = () => {
                      if (oldImg) {
                          oldImg.style.transition = 'opacity 0.15s ease';
                          oldImg.style.opacity = '0';
                          setTimeout(() => {
                              imgContainer.innerHTML = '';
                              img.style.position = 'relative';
                              img.style.opacity = '1';
                              imgContainer.appendChild(img);
                              imgContainer.classList.remove('loading');
                          }, 150);
                      } else {
                          imgContainer.innerHTML = '';
                          img.style.position = 'relative';
                          img.style.opacity = '1';
                          imgContainer.appendChild(img);
                          imgContainer.classList.remove('loading');
                      }
                      console.log('Tab GIF Display: GIF loaded successfully');
                  };
                  
                  img.onerror = () => {
                      imgContainer.innerHTML = '';
                      imgContainer.appendChild(safeCreateError('GIF not found: ' + decodedFilename));
                      imgContainer.classList.remove('loading');
                      console.error('Tab GIF Display: Failed to load GIF', gifUrl);
                  };
                  
                  if (!oldImg) {
                      imgContainer.appendChild(img);
                      imgContainer.classList.add('loading');
                  }
              }
          }
          
          if (caption) {
              caption.textContent = tabName;
              caption.style.display = 'block';
          }
      }
      
      window.toggleTabGifDisplay = function(containerId) {
          console.log('Tab GIF Display: Toggle clicked for', containerId);
          const container = document.getElementById(containerId);
          if (!container) {
              console.error('Tab GIF Display: Container not found', containerId);
              return;
          }
          
          if (container.style.display === 'none') {
              container.style.display = 'block';
          } else {
              container.style.display = 'none';
          }
      };
      
      if (document.readyState === 'loading') {
          document.addEventListener('DOMContentLoaded', init);
      } else {
          init();
      }
      
      window.addEventListener('load', init);
      
      if (typeof mw !== 'undefined' && mw.hook) {
          mw.hook('wikipage.content').add(init);
      }
      
      const observer = new MutationObserver(function(mutations) {
          let shouldReinit = false;
          mutations.forEach(function(mutation) {
              if (mutation.addedNodes.length) {
                  mutation.addedNodes.forEach(function(node) {
                      if (node.nodeType === 1 && (
                          node.classList && node.classList.contains(CONFIG.containerClass) ||
                          node.querySelector && node.querySelector('.' + CONFIG.containerClass)
                      )) {
                          shouldReinit = true;
                      }
                  });
              }
          });
          if (shouldReinit) {
              console.log('Tab GIF Display: Content changed, reinitializing...');
              setTimeout(init, 100);
          }
      });
      
      observer.observe(document.body, {
          childList: true,
          subtree: true
      });
      
      console.log('Tab GIF Display: Script loaded and ready');
  })();
  
  (function () {
      const images = [
          'url(/wiki/Special:Redirect/file/Site-background-image.jpg)',
          'url(/wiki/Special:Redirect/file/Site-background-image2.jpg)',
          'url(/wiki/Special:Redirect/file/Site-background-image3.jpg)',
      ];
  
      // Pick deterministic daily seed
      const day = new Date().getDate();
  
      // Deterministic shuffle using day as seed
      function seededRandom(seed) {
          return Math.abs(Math.sin(seed)) % 1;
      }
  
      const pick1 = Math.floor(seededRandom(day) * images.length);
      let pick2 = Math.floor(seededRandom(day + 1) * images.length);
  
      if (pick2 === pick1) pick2 = (pick2 + 1) % images.length;
  
      document.body.style.backgroundImage = images[pick1];
  
      const footer = document.querySelector('.mw-footer');
      if (footer) footer.style.backgroundImage = images[pick2];
  })();