MediaWiki:Common.js: Difference between revisions

Undo revision 5755 by Chandrashekars (talk)
Tag: Undo
Undo revision 6527 by Vaishnavi (talk)
Tag: Undo
 
(33 intermediate revisions by 2 users not shown)
Line 1: Line 1:
/* MediaWiki:Common.js — grantha.io  (v7)
/* MediaWiki:Common.js */
*
* Changes vs v6:
*  1. BUG FIX: Main IIFE was never properly closed — About link block was
*    pasted inside it without the closing }() ); which broke the module
*    boundary and killed the by-Author toggle. Each block is now its
*    own self-contained IIFE.
*  2. TOC: "Beginning" link removed.
*  3. TOC: Heading label → "विषयसूची".
*  4. TOC: मूल / उल्लेख nav links injected at top of TOC panel.
*  5. TOC: All subsections expanded by default.
*  6. TOC: Only the active item is bold; all others are normal weight.
*  7. About link URL derived from wgArticlePath — works under any
*    sub-path install (e.g. /My_wiki/). Points to "My_wiki:About".
*  8. TOC customisations skipped on Main_Page and About pages.
*  9. Uses Vector's native TOC with IntersectionObserver-based active highlight.
*/


( function () {
(function () {


  var LS_SCRIPT_KEY = 'grantha_reader_script';
    var LS_SCRIPT_KEY = 'grantha_reader_script';
  var currentScript = 'deva';
    var currentScript = 'deva';


  // ── IAST transliteration ────────────────────────────────────────
    function devanagariToTamil(text) {
  function devanagariToIAST( text ) {
        var CONSONANTS = {
    var CONSONANTS = {
            'क': '', 'ख': '', 'ग': '', 'घ': '', 'ङ': '',
      'क':'k','ख':'kh','ग':'g','घ':'gh','ङ':'',
            'च': '', 'छ': '', 'ज': '', 'झ': '', 'ञ': '',
      'च':'c','छ':'ch','ज':'j','झ':'jh','ञ':'ñ',
            'ट': '', 'ठ': '', 'ड': '', 'ढ': '', 'ण': '',
      'ट':'','ठ':'ṭh','ड':'','ढ':'ḍh','ण':'',
            'त': '', 'थ': '', 'द': '', 'ध': '', 'न': '',
      'त':'t','थ':'th','द':'d','ध':'dh','न':'n',
            'प': '', 'फ': '', 'ब': '', 'भ': '', 'म': '',
      'प':'p','फ':'ph','ब':'b','भ':'bh','म':'m',
            'य': '', 'र': '', 'ल': '', 'ळ': '', 'व': '',
      'य':'y','र':'r','ल':'l','ळ':'','व':'v',
            'श': '', 'ष': '', 'स': '', 'ह': ''
      'श':'ś','ष':'','स':'s','ह':'h'
        };
    };
        var DIACRITICS = {
    var DIACRITICS = {
            'ा': '', 'ि': 'ி', 'ी': '', 'ु': '', 'ू': '',
      'ा':'ā','ि':'i','ी':'ī','ु':'u','ू':'ū',
            'े': '', 'ै': '', 'ो': '', 'ौ': ''
      'ृ':'ṛ','ॄ':'ṝ','े':'e','ै':'ai','ो':'o','ौ':'au'
        };
    };
        var VOWELS = {
    var VOWELS = {
            'अ': '', 'आ': '', 'इ': '', 'ई': '', 'उ': '', 'ऊ': '',
      'अ':'a','आ':'ā','इ':'i','ई':'ī','उ':'u','ऊ':'ū',
            'ए': '', 'ऐ': '', 'ओ': '', 'औ': '', 'ऽ': 'ऽ'
      'ऋ':'ṛ','ॠ':'ṝ','ए':'e','ऐ':'ai','ओ':'o','औ':'au','ऽ':"'"
        };
    };
        var MISC = {
    var MISC = {
            'ं':'ம்', 'ः':':', 'ँ':'ம்', 'ॐ':'',
      'ं':'','ः':'','ँ':'','ॐ':'oṃ',
            '०': '0', '१': '1', '२': '2', '३': '3', '४': '4',
      '०':'0','१':'1','२':'2','३':'3','४':'4',
            '५': '5', '६': '6', '७': '7', '८': '8', '९': '9'
      '५':'5','६':'6','७':'7','८':'8','९':'9'
        };
    };
        var HALANTA = '्';
    var HALANTA = '्';
        var chars = Array.from(text), result = '', i = 0;
    var chars = Array.from( text );
        while (i < chars.length) {
    var result = '';
            var ch = chars[i], next = chars[i + 1];
    var i = 0;
            if (CONSONANTS[ch]) {
    while ( i < chars.length ) {
                var base = CONSONANTS[ch];
      var ch   = chars[ i ];
                if (next === HALANTA) { result += base + '்'; i += 2; }
      var next = chars[ i + 1 ];
                else if (next === 'ृ') { result += base + '்ரி'; i += 2; }
      if ( CONSONANTS[ ch ] ) {
                else if (next === '') { result += base + '்ரீ'; i += 2; }
        var base = CONSONANTS[ ch ];
                else if (DIACRITICS[next]) { result += base + DIACRITICS[next]; i += 2; }
        if ( next === HALANTA )         { result += base;               i += 2; }
                else { result += base; i++; }  // inherent 'a'
        else if ( DIACRITICS[ next ] )   { result += base + DIACRITICS[ next ]; i += 2; }
            }
        else if ( next === '' || next === '' ) { result += base + 'a' + MISC[ next ]; i += 2; }
            else if (ch === 'ऋ') { result += 'ரி'; i++; }
        else                             { result += base + 'a';         i++;   }
            else if (ch === 'ॠ') { result += 'ரீ'; i++; }
      } else if ( VOWELS[ ch ] )         { result += VOWELS[ ch ];       i++; }
            else if (VOWELS[ch]) { result += VOWELS[ch]; i++; }
      else if ( DIACRITICS[ ch ] )       { result += DIACRITICS[ ch ];   i++; }
            else if (MISC[ch]) { result += MISC[ch]; i++; }
      else if ( MISC[ ch ] )             { result += MISC[ ch ];         i++; }
            else { result += ch; i++; }
      else                               { result += ch;                 i++; }
        }
        return result;
     }
     }
    return result;
  }


  // ── Character maps for Kannada / Tamil ─────────────────────────
    function devanagariToIAST(text) {
  var SCRIPT_MAP = {
        var CONSONANTS = {
    kn: {
            'क': 'k', 'ख': 'kh', 'ग': 'g', 'घ': 'gh', 'ङ': '',
      'अ':'ಅ','आ':'ಆ','इ':'ಇ','ई':'ಈ','उ':'ಉ','ऊ':'ಊ','ऋ':'ಋ',
            'च': 'c', 'छ': 'ch', 'ज': 'j', 'झ': 'jh', 'ञ': 'ñ',
      'ए':'ಏ','ऐ':'ಐ','ओ':'ಓ','औ':'ಔ','ऽ':'ಽ',
            'ट': '', 'ठ': 'ṭh', 'ड': '', 'ढ': 'ḍh', 'ण': '',
      'क':'','ख':'','ग':'','घ':'','ङ':'',
            'त': 't', 'थ': 'th', 'द': 'd', 'ध': 'dh', 'न': 'n',
      'च':'','छ':'','ज':'','झ':'','ञ':'',
            'प': 'p', 'फ': 'ph', 'ब': 'b', 'भ': 'bh', 'म': 'm',
      'ट':'','ठ':'','ड':'','ढ':'','ण':'',
            'य': 'y', 'र': 'r', 'ल': 'l', 'ळ': 'ḷ', 'व': 'v',
      'त':'','थ':'','द':'','ध':'','न':'',
            'श': 'ś', 'ष': '', 'स': 's', 'ह': 'h'
      'प':'','फ':'','ब':'','भ':'','म':'',
        };
      'य':'','र':'','ल':'','व':'',
        var DIACRITICS = {
      'श':'','ष':'','स':'','ह':'',
            'ा': 'ā', 'ि': 'i', 'ी': 'ī', 'ु': 'u', 'ू': 'ū',
      'ा':'','ि':'ಿ','ी':'','ु':'','ू':'',
            'ृ': '', '': '', '': 'e', '': 'ai', '': 'o', '': 'au'
      'ृ':'','':'','':'','':'','':'',
        };
      'ं':'ಂ','ः':'ಃ','्':'',
        var VOWELS = {
      '०':'೦','१':'೧','२':'೨','३':'೩','४':'೪',
            'अ': 'a', 'आ': 'ā', 'इ': 'i', 'ई': 'ī', 'उ': 'u', 'ऊ': 'ū',
      '५':'೫','६':'೬','७':'೭','८':'೮','९':'೯'
            'ऋ': '', 'ॠ': '', 'ए': 'e', 'ऐ': 'ai', 'ओ': 'o', 'औ': 'au', '': "'"
    },
        };
    ta: {
        var MISC = {
      'अ':'','आ':'','इ':'','ई':'','उ':'','ऊ':'',
            '': '', '': '', '': '', '': 'oṃ',
      'ऋ':'ரு','ॠ':'ரூ',
            '': '0', '': '1', '': '2', '': '3', '': '4',
      'ए':'','ऐ':'','ओ':'','औ':'',
            '': '5', '': '6', '': '7', '': '8', '': '9'
      '':'','ख':'','':'','':'','':'',
        };
      '':'','':'','':'','':'','':'',
        var HALANTA = '';
      '':'','':'','':'','':'','':'',
        var chars = Array.from(text), result = '', i = 0;
      'त':'த','थ':'த','द':'த','ध':'த','न':'ந',
        while (i < chars.length) {
      'प':'ப','फ':'ப','ब':'ப','भ':'ப','म':'ம',
            var ch = chars[i], next = chars[i + 1];
      'य':'ய','र':'ர','ல':'ல','ळ':'ழ','व':'வ',
            if (CONSONANTS[ch]) {
      'श':'ஶ','ष':'ஷ','स':'ஸ','ह':'ஹ',
                var base = CONSONANTS[ch];
      'ा':'ா','ि':'ி','ी':'ீ','ு':'ு','ू':'ூ',
                if (next === HALANTA) { result += base; i += 2; }
      'ृ':'ு','ॄ':'ூ',
                else if (DIACRITICS[next]) { result += base + DIACRITICS[next]; i += 2; }
      'े':'ே','ை':'ை','ो':'ோ','ौ':'ௌ',
                else if (next === 'ं' || next === 'ः') { result += base + 'a' + MISC[next]; i += 2; }
      'ं':'ம்','ः':':','':'ம்','्':'்','ॐ':'ௐ','ऽ':'ௗ',
                else { result += base + 'a'; i++; }
      '०':'0','१':'1','२':'2','३':'3','४':'4',
            }
      '५':'5','६':'6','७':'7','८':'8','९':'9'
            else if (VOWELS[ch]) { result += VOWELS[ch]; i++; }
            else if (DIACRITICS[ch]) { result += DIACRITICS[ch]; i++; }
            else if (MISC[ch]) { result += MISC[ch]; i++; }
            else { result += ch; i++; }
        }
        return result;
     }
     }
  };


  var PRE = [
    var SCRIPT_MAP = {
    [ /ङ्क/g, 'ंक' ], [ /ङ्ख/g, 'ंख' ], [ /ङ्ग/g, 'ंग' ], [ /ङ्घ/g, 'ंघ' ],
        kn: {
    [ /ञ्च/g, 'ंच' ], [ /ञ्ज/g, 'ंज' ], [ /ण्ट/g, 'ंट' ], [ /ण्ड/g, 'ंड' ],
            'अ': 'ಅ', 'आ': 'ಆ', 'इ': 'ಇ', 'ई': 'ಈ', 'उ': 'ಉ', 'ऊ': 'ಊ', 'ऋ': 'ಋ', 'ॠ': 'ೠ',
    [ /न्त/g, 'ंत' ], [ /न्द/g, 'ंद' ], [ /म्ब/g, 'ंब' ], [ /म्भ/g, 'ंभ' ]
            'ए': 'ಏ', 'ऐ': 'ಐ', 'ओ': 'ಓ', 'औ': 'ಔ', 'ऽ': 'ಽ',
  ];
            'क': 'ಕ', 'ख': 'ಖ', 'ग': 'ಗ', 'घ': 'ಘ', 'ङ': 'ಙ',
            'च': 'ಚ', 'छ': 'ಛ', 'ज': 'ಜ', 'झ': 'ಝ', 'ञ': 'ಞ',
            'ट': 'ಟ', 'ठ': 'ಠ', 'ड': 'ಡ', 'ढ': 'ಢ', 'ण': 'ಣ',
            'त': 'ತ', 'थ': 'ಥ', 'द': 'ದ', 'ध': 'ಧ', 'न': 'ನ',
            'प': 'ಪ', 'फ': 'ಫ', 'ब': 'ಬ', 'भ': 'ಭ', 'म': 'ಮ',
            'य': 'ಯ', 'र': 'ರ', 'ल': 'ಲ', 'ळ': 'ಳ', 'व': 'ವ',
            'श': 'ಶ', 'ष': 'ಷ', 'स': 'ಸ', 'ह': 'ಹ',
            'ा': 'ಾ', 'ि': 'ಿ', 'ी': 'ೀ', 'ु': 'ು', 'ू': 'ೂ',
            'ृ': 'ೃ', 'ॄ': 'ೄ', 'े': 'ೇ', 'ै': 'ೈ', 'ो': 'ೋ', 'ौ': 'ೌ',
            'ं': 'ಂ', 'ः': 'ಃ', '्': '್', 'ँ': 'ಁ',
            '०': '೦', '१': '೧', '२': '೨', '३': '೩', '४': '೪',
            '५': '೫', '६': '೬', '७': '೭', '८': '೮', '९': '೯'
        },
        te: {
            'अ': 'అ', 'आ': 'ఆ', 'इ': 'ఇ', 'ई': 'ఈ', 'उ': 'ఉ', 'ऊ': 'ఊ', 'ऋ': 'ఋ', 'ॠ': 'ౠ',
            'ए': 'ఏ', 'ऐ': 'ఐ', 'ओ': 'ఓ', 'औ': 'ఔ', 'ऽ': 'ఽ',
            'क': 'క', 'ख': 'ఖ', 'ग': 'గ', 'घ': 'ఘ', 'ङ': 'ఙ',
            'च': 'చ', 'छ': 'ఛ', 'ज': 'జ', 'झ': 'ఝ', 'ञ': 'ఞ',
            'ट': 'ట', 'ठ': 'ఠ', 'ड': 'డ', 'ढ': 'ఢ', 'ण': 'ణ',
            'त': 'త', 'थ': 'థ', 'द': 'ద', 'ध': 'ధ', 'न': 'న',
            'प': 'ప', 'फ': 'ఫ', 'ब': 'బ', 'भ': 'భ', 'म': 'మ',
            'य': 'య', 'र': 'ర', 'ल': 'ల', 'ळ': 'ళ', 'व': 'వ',
            'श': 'శ', 'ष': 'ష', 'स': 'స', 'ह': 'హ',
            'ा': 'ా', 'ि': 'ి', 'ी': 'ీ', 'ु': 'ు', 'ू': 'ూ',
            'ृ': 'ృ', 'ॄ': 'ౄ', 'े': 'ే', 'ै': 'ై', 'ो': 'ో', 'ौ': 'ౌ',
            'ं': 'ం', 'ः': 'ః', '्': '్', 'ँ': 'ఁ',
            '०': '౦', '१': '౧', '२': '౨', '३': '౩', '४': '౪',
            '५': '౫', '६': '౬', '७': '౭', '८': '౮', '९': '౯'
        }
    };


  function transliterateText( text, script ) {
     var PRE = [
     if ( script === 'en' ) return devanagariToIAST( text );
        [/ङ्क/g, 'ंक'], [/ङ्ख/g, 'ंख'], [/ङ्ग/g, 'ंग'], [/ङ्घ/g, 'ंघ'],
    var map = SCRIPT_MAP[ script ];
        [/ञ्च/g, 'ंच'], [/ञ्ज/g, 'ंज'], [/ण्ट/g, 'ंट'], [/ण्ड/g, 'ंड'],
    if ( !map ) return text;
        [/न्त/g, 'ंत'], [/न्द/g, 'ंद'], [/म्ब/g, 'ंब'], [/म्भ/g, 'ंभ']
    var t = text;
     ];
    PRE.forEach( function ( p ) { t = t.replace( p[ 0 ], p[ 1 ] ); } );
    return Array.from( t ).map( function ( ch ) {
      return map[ ch ] !== undefined ? map[ ch ] : ch;
     } ).join( '' );
  }


  // ── Tag all transliteratable text nodes once per page ───────────
    function transliterateText(text, script) {
  var translatableSpans = [];
        if (script === 'en') return devanagariToIAST(text);
 
        if (script === 'ta') return devanagariToTamil(text);
  function tagTextNodes() {
         var map = SCRIPT_MAP[script];
    var content = document.querySelector( '.mw-parser-output' );
         if (!map) return text;
    if ( content ) {
         var t = text;
      var walker = document.createTreeWalker( content, NodeFilter.SHOW_TEXT );
         PRE.forEach(function (p) { t = t.replace(p[0], p[1]); });
      var nodes  = [];
         return Array.from(t).map(function (ch) {
      while ( walker.nextNode() ) nodes.push( walker.currentNode );
            return map[ch] !== undefined ? map[ch] : ch;
 
         }).join('');
      nodes.forEach( function ( node ) {
         var p = node.parentNode;
         if ( !p ) return;
         if ( p.hasAttribute && p.hasAttribute( 'data-deva' ) ) return;
         if ( p.closest ) {
          if ( p.closest( '.gr-controls' )    ) return;
          if ( p.closest( '.mw-editsection' ) ) return;
          // #gr-toc-doc-nav buttons manage their own data-deva spans in makeBtn
        }
        var orig = node.textContent;
         if ( !orig.trim() ) return;
        var span = document.createElement( 'span' );
        span.setAttribute( 'data-deva', orig );
        span.textContent = orig;
         p.replaceChild( span, node );
        translatableSpans.push( span );
      } );
     }
     }


     document.querySelectorAll( '.vector-toc .vector-toc-text' ).forEach( function ( span ) {
     var translatableSpans = [];
      if ( span.hasAttribute( 'data-deva' ) ) return;
      var orig = span.textContent;
      if ( !orig.trim() ) return;
      span.setAttribute( 'data-deva', orig );
      translatableSpans.push( span );
    } );
  }


  // ── Apply a script to all tagged spans ─────────────────────────
     function tagTextNodes() {
  function applyScript( script ) {
        var content = document.querySelector('.mw-parser-output');
    currentScript = script;
        if (content) {
     translatableSpans.forEach( function ( span ) {
            var walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT);
      if ( !span.parentNode ) return;
            var nodes = [];
      var orig = span.getAttribute( 'data-deva' );
            while (walker.nextNode()) nodes.push(walker.currentNode);
      if ( !orig ) return;
            nodes.forEach(function (node) {
      span.textContent = ( script === 'deva' )
                var p = node.parentNode;
        ? orig
                if (!p) return;
        : transliterateText( orig, script );
                if (p.hasAttribute && p.hasAttribute('data-deva')) return;
    } );
                if (p.closest) {
  }
                    if (p.closest('.gr-controls')) return;
 
                    if (p.closest('.mw-editsection')) return;
  // ── Pages where sidebar TOC should not be modified ──────────────
                }
  function _isNoTocPage() {
                var orig = node.textContent;
    var pn = ( window.mw && mw.config && mw.config.get( 'wgPageName' ) ) || '';
                if (!orig.trim()) return;
    return pn === 'Main_Page' || /^[A-Za-z0-9_]+:About$/.test( pn );
                var span = document.createElement('span');
  }
                span.setAttribute('data-deva', orig);
 
                span.textContent = orig;
  // ── TOC: rename "Contents" → "विषयसूची" ────────────────────────
                p.replaceChild(span, node);
function renameTocTitle() {
                translatableSpans.push(span);
  if ( _isNoTocPage() ) return;
            });
 
  var toc = document.querySelector('.vector-toc');
  if ( !toc ) return;
 
  var titleEl =
    toc.querySelector('.vector-toc-title') ||
    toc.querySelector('.vector-pinnable-header-label');
 
  if ( !titleEl ) return;
 
  var LABEL = 'विषयसूची';
 
  /* If already inserted, just refresh text */
  var span = titleEl.querySelector('.gr-toc-title');
 
  if ( !span ) {
    titleEl.innerHTML = '';
 
    span = document.createElement('span');
    span.className = 'gr-toc-title';
    span.setAttribute('data-deva', LABEL);
 
    titleEl.appendChild(span);
    translatableSpans.push(span);   // uses your internal array
  }
 
  span.textContent =
    currentScript === 'deva'
      ? LABEL
      : transliterateText(LABEL, currentScript);
}
  // ── TOC: Remove the "Beginning" / top-of-page link ─────────────
  function removeTocBeginning() {
    if ( _isNoTocPage() ) return;
    var toc = document.querySelector( '.vector-toc' );
    if ( !toc ) return;
    // Try the dedicated id first (Vector 2022)
    var el = toc.querySelector( '#vector-toc-beginning' );
    if ( !el ) {
      // Fallback: first list-item whose link has no # anchor = the "Beginning" entry
      var items = toc.querySelectorAll( '.vector-toc-list-item' );
      for ( var i = 0; i < items.length; i++ ) {
        var a = items[ i ].querySelector( 'a' );
        if ( a ) {
          var href = a.getAttribute( 'href' ) || '';
          if ( href.indexOf( '#' ) === -1 ) { el = items[ i ]; break; }
         }
         }
      }
        document.querySelectorAll('.vector-toc .vector-toc-text').forEach(function (span) {
            if (span.hasAttribute('data-deva')) return;
            var orig = span.textContent;
            if (!orig.trim()) return;
            span.setAttribute('data-deva', orig);
            translatableSpans.push(span);
        });
     }
     }
    if ( el && el.parentNode ) el.parentNode.removeChild( el );
  }


  // ── TOC: Expand all collapsed subsections on load ───────────────
    function applyScript(script) {
  function expandTocSections() {
        currentScript = script;
    if ( _isNoTocPage() ) return;
        translatableSpans.forEach(function (span) {
    var toc = document.querySelector( '.vector-toc' );
            if (!span.parentNode) return;
    if ( !toc ) return;
            var orig = span.getAttribute('data-deva');
    toc.querySelectorAll( '.vector-toc-list-item-collapsed' ).forEach( function ( li ) {
            if (!orig) return;
      li.classList.remove( 'vector-toc-list-item-collapsed' );
            span.textContent = (script === 'deva')
    } );
                ? orig
  }
                : transliterateText(orig, script);
 
        });
  // ── TOC: Inject मूल / उल्लेख nav links ─────────────────────────
  function injectTocDocNav() {
    if ( _isNoTocPage() ) return;
    var toc = document.querySelector( '.vector-toc' );
    if ( !toc ) return;
    if ( document.getElementById( 'gr-toc-doc-nav' ) ) return;
 
    var artPath  = ( window.mw && mw.config && mw.config.get( 'wgArticlePath' ) ) || '/wiki/$1';
    var pageTitle = ( window.mw && mw.config && mw.config.get( 'wgPageName'  ) ) || '';
 
    var teekaPage  = document.querySelector( '.gr-teeka-page' );
    var primarySlug = teekaPage ? ( teekaPage.getAttribute( 'data-primary' ) || '' ) : '';
    var docSlug    = teekaPage ? ( teekaPage.getAttribute( 'data-slug'    ) || '' ) : '';
 
    if ( !primarySlug ) {
      primarySlug = pageTitle.split( '/' )[ 0 ];
      docSlug    = primarySlug;
     }
     }
    if ( !primarySlug ) return;


     function wikiUrl( slug ) {
     function _isNoTocPage() {
      if ( window.mw && mw.util && mw.util.getUrl ) return mw.util.getUrl( slug );
        var pn = (window.mw && mw.config && mw.config.get('wgPageName')) || '';
      return artPath.replace( '$1', encodeURIComponent( slug ).replace( /%2F/g, '/' ) );
        return pn === 'Main_Page' || /^[A-Za-z0-9_]+:About$/.test(pn);
     }
     }


     var moolaUrl  = wikiUrl( primarySlug );
     function renameTocTitle() {
    var ullekhaUrl = wikiUrl( primarySlug + '/Ullekha' );
        if (_isNoTocPage()) return;
 
        var toc = document.querySelector('.vector-toc');
    var docTitleEl  = document.querySelector( '.gr-doc-title' );
        if (!toc) return;
    var hasMoolaPage  = docTitleEl && docTitleEl.getAttribute( 'data-has-moola' )   === '1';
        var titleEl = toc.querySelector('.vector-toc-title') || toc.querySelector('.vector-pinnable-header-label');
    var hasUllekhaPage = docTitleEl && docTitleEl.getAttribute( 'data-has-ullekha' ) === '1';
        if (!titleEl) return;
 
        var LABEL = 'विषयसूची';
    var moolaPageUrl = wikiUrl( primarySlug + '/Moola' );
        var span = titleEl.querySelector('.gr-toc-title');
 
        if (!span) {
    var showMoolaPage  = !teekaPage && hasMoolaPage;
            titleEl.innerHTML = '';
    var showMoolaBack  = !!teekaPage;
            span = document.createElement('span');
    var showUllekha    = hasUllekhaPage || !!teekaPage;
            span.className = 'gr-toc-title';
 
            span.setAttribute('data-deva', LABEL);
    if ( !showMoolaPage && !showMoolaBack && !showUllekha ) return;
            titleEl.appendChild(span);
 
            translatableSpans.push(span);
    var nav = document.createElement( 'div' );
        }
    nav.id = 'gr-toc-doc-nav';
        span.textContent = currentScript === 'deva' ? LABEL : transliterateText(LABEL, currentScript);
    nav.setAttribute( 'class', 'toc-main-links');
 
    // ── CHANGE: makeBtn now wraps label in a data-deva span so
    // transliteration (script switching) applies to button text.
    function makeBtn( href, label ) {
      var a = document.createElement( 'a' );
      a.href = href;
      a.setAttribute( 'class', 'toc-main-link-item');
      var lspan = document.createElement( 'span' );
      lspan.setAttribute( 'data-deva', label );
      lspan.textContent = ( currentScript && currentScript !== 'deva' )
        ? transliterateText( label, currentScript )
        : label;
      translatableSpans.push( lspan );
      a.appendChild( lspan );
      a.addEventListener( 'mouseover', function () { this.style.opacity = '0.72'; } );
      a.addEventListener( 'mouseout', function () { this.style.opacity = '1';    } );
      return a;
     }
     }


     if ( showMoolaPage ) nav.appendChild( makeBtn( moolaPageUrl, 'मूलम्' ) );
     function removeTocBeginning() {
    if ( showMoolaBack ) nav.appendChild( makeBtn( moolaUrl,    'मूल' ) );
        if (_isNoTocPage()) return;
    if ( showUllekha  ) nav.appendChild( makeBtn( ullekhaUrl,  'उल्लेख') );
        var toc = document.querySelector('.vector-toc');
 
        if (!toc) return;
    var tocContents = toc.querySelector( '.vector-toc-contents' );
        var el = toc.querySelector('#vector-toc-beginning');
    if ( tocContents ) toc.insertBefore( nav, tocContents );
        if (!el) {
    else              toc.appendChild( nav );
            var items = toc.querySelectorAll('.vector-toc-list-item');
  }
            for (var i = 0; i < items.length; i++) {
 
                var a = items[i].querySelector('a');
  // ── TOC active-item highlight ────────────────────────────────────
                if (a) {
  function watchTocActive() {
                    var href = a.getAttribute('href') || '';
    if ( _isNoTocPage() ) return;
                    if (href.indexOf('#') === -1) { el = items[i]; break; }
    var toc = document.querySelector( '.vector-toc' );
                }
    if ( !toc ) return;
            }
    if ( !window.MutationObserver ) return;
        }
 
        if (el && el.parentNode) el.parentNode.removeChild(el);
    if ( toc._grObserved ) {
      toc.querySelectorAll( '.vector-toc-list-item' ).forEach( attachHighlight );
      return;
     }
     }
    toc._grObserved = true;


    var ACTIVE_COLOR = '#f57c00';
     function expandTocSections() {
 
        if (_isNoTocPage()) return;
     function setActive( li, on ) {
        var toc = document.querySelector('.vector-toc');
      var link = li.querySelector( '.vector-toc-link' ) || li.querySelector( 'a' );
        if (!toc) return;
      if ( !link ) return;
        toc.querySelectorAll('.vector-toc-list-item-collapsed').forEach(function (li) {
      var hasActiveChild = !!li.querySelector(
            li.classList.remove('vector-toc-list-item-collapsed');
        '.vector-toc-list-item .vector-toc-list-item-active'
         });
      );
      var shouldHighlight = on && !hasActiveChild;
      if ( shouldHighlight ) {
        link.style.setProperty( 'color',      ACTIVE_COLOR, 'important' );
        link.style.setProperty( 'font-weight', '700',        'important' );
        link.querySelectorAll( '*' ).forEach( function ( el ) {
          el.style.setProperty( 'color',      ACTIVE_COLOR, 'important' );
          el.style.setProperty( 'font-weight', '700',        'important' );
        } );
      } else {
        link.style.removeProperty( 'color' );
        link.style.setProperty( 'font-weight', '400', 'important' );
        link.querySelectorAll( '*' ).forEach( function ( el ) {
          el.style.removeProperty( 'color' );
          el.style.setProperty( 'font-weight', '400', 'important' );
         } );
      }
     }
     }


     function normaliseAll() {
     function injectTocDocNav() {
      toc.querySelectorAll( '.vector-toc-list-item' ).forEach( function ( li ) {
        if (_isNoTocPage()) return;
         setActive( li, li.classList.contains( 'vector-toc-list-item-active' ) );
        var toc = document.querySelector('.vector-toc');
      } );
        if (!toc) return;
        if (document.getElementById('gr-toc-doc-nav')) return;
        var artPath = (window.mw && mw.config && mw.config.get('wgArticlePath')) || '/wiki/$1';
        var pageTitle = (window.mw && mw.config && mw.config.get('wgPageName')) || '';
        var teekaPage = document.querySelector('.gr-teeka-page');
        var primarySlug = teekaPage ? (teekaPage.getAttribute('data-primary') || '') : '';
        if (!primarySlug) { primarySlug = pageTitle.split('/')[0]; }
        if (!primarySlug) return;
        function wikiUrl(slug) {
            if (window.mw && mw.util && mw.util.getUrl) return mw.util.getUrl(slug);
            return artPath.replace('$1', encodeURIComponent(slug).replace(/%2F/g, '/'));
        }
        var docTitleEl = document.querySelector('.gr-doc-title');
        var hasMoolaPage = docTitleEl && docTitleEl.getAttribute('data-has-moola') === '1';
        var hasUllekhaPage = docTitleEl && docTitleEl.getAttribute('data-has-ullekha') === '1';
        var showMoolaPage = !teekaPage && hasMoolaPage;
        var showMoolaBack = !!teekaPage;
        var showUllekha = hasUllekhaPage || !!teekaPage;
        if (!showMoolaPage && !showMoolaBack && !showUllekha) return;
        var nav = document.createElement('div');
        nav.id = 'gr-toc-doc-nav';
        nav.setAttribute('class', 'toc-main-links');
         function makeBtn(href, label) {
            var a = document.createElement('a');
            a.href = href;
            a.setAttribute('class', 'toc-main-link-item');
            var lspan = document.createElement('span');
            lspan.setAttribute('data-deva', label);
            lspan.textContent = (currentScript && currentScript !== 'deva') ? transliterateText(label, currentScript) : label;
            translatableSpans.push(lspan);
            a.appendChild(lspan);
            a.addEventListener('mouseover', function () { this.style.opacity = '0.72'; });
            a.addEventListener('mouseout', function () { this.style.opacity = '1'; });
            return a;
        }
        if (showMoolaPage) nav.appendChild(makeBtn(wikiUrl(primarySlug + '/Moola'), 'मूलम्'));
        if (showMoolaBack) nav.appendChild(makeBtn(wikiUrl(primarySlug), 'मूल'));
        if (showUllekha) nav.appendChild(makeBtn(wikiUrl(primarySlug + '/Ullekha'), 'उल्लेख'));
        var tocContents = toc.querySelector('.vector-toc-contents');
        if (tocContents) toc.insertBefore(nav, tocContents);
        else toc.appendChild(nav);
     }
     }


     function attachHighlight( li ) {
     var _headingObserver = null;
      if ( li._grHighlightAttached ) return;
      li._grHighlightAttached = true;
      liObs.observe( li, { attributes: true, attributeFilter: [ 'class' ] } );
      setActive( li, li.classList.contains( 'vector-toc-list-item-active' ) );
    }


     var liObs = new MutationObserver( function ( mutations ) {
     function attachHeadingObserver() {
      mutations.forEach( function ( m ) {
        if (_isNoTocPage()) return;
         if ( m.attributeName !== 'class' ) return;
        if (_headingObserver) return;
         var li    = m.target;
        if (!window.IntersectionObserver) return;
         var active = li.classList.contains( 'vector-toc-list-item-active' );
        var ACTIVE_COLOR = '#f57c00';
        setActive( li, active );
        var _activeId = null;
 
        var content = document.querySelector('.mw-parser-output');
         if ( active ) {
        if (!content) return;
          var anc = li.parentNode;
        var headings = Array.from(content.querySelectorAll('h1[id],h2[id],h3[id],h4[id],h5[id],h6[id]'));
          while ( anc && anc !== document.body ) {
         if (!headings.length) return;
             if ( anc.classList &&
        var toc = document.querySelector('.vector-toc');
                anc.classList.contains( 'vector-toc-list-item' ) &&
        if (!toc) return;
                anc.classList.contains( 'vector-toc-list-item-collapsed' ) ) {
         function getTocLink(id) { return toc.querySelector('a[href="#' + CSS.escape(id) + '"]'); }
              anc.classList.remove( 'vector-toc-list-item-collapsed' );
         function getTocLi(id) { var a = getTocLink(id); return a ? a.closest('.vector-toc-list-item') : null; }
        function clearActive() {
            toc.querySelectorAll('.vector-toc-list-item').forEach(function (li) {
                li.classList.remove('vector-toc-list-item-active');
                var lnk = li.querySelector('.vector-toc-link');
                if (!lnk) return;
                lnk.style.removeProperty('color');
                lnk.style.setProperty('font-weight', '400', 'important');
                lnk.querySelectorAll('*').forEach(function (el) { el.style.removeProperty('color'); el.style.setProperty('font-weight', '400', 'important'); });
            });
        }
         function setActive(id) {
            if (_activeId === id) return;
            _activeId = id;
            clearActive();
            if (!id) return;
            var li = getTocLi(id);
             if (!li) return;
            li.classList.add('vector-toc-list-item-active');
            var hasActiveChild = !!li.querySelector('.vector-toc-list-item .vector-toc-list-item-active');
            if (!hasActiveChild) {
                var lnk = li.querySelector('.vector-toc-link');
                if (lnk) {
                    lnk.style.setProperty('color', ACTIVE_COLOR, 'important');
                    lnk.style.setProperty('font-weight', '700', 'important');
                    lnk.querySelectorAll('*').forEach(function (el) { el.style.setProperty('color', ACTIVE_COLOR, 'important'); el.style.setProperty('font-weight', '700', 'important'); });
                }
            }
            var anc = li.parentNode;
            while (anc && anc !== toc) {
                if (anc.classList) anc.classList.remove('vector-toc-list-item-collapsed');
                if (anc.tagName === 'UL' || anc.tagName === 'LI') anc.style.removeProperty('display');
                anc = anc.parentNode;
             }
             }
             anc = anc.parentNode;
             var sticky = document.querySelector('.vector-sticky-pinned-container');
          }
             var scrollEl = sticky || toc;
 
             if (scrollEl.scrollHeight > scrollEl.clientHeight) {
          var container = document.querySelector( '.vector-sticky-pinned-container' );
                var lr = li.getBoundingClientRect();
          if ( container ) {
                var cr = scrollEl.getBoundingClientRect();
             var vis = container.offsetHeight > 0 &&
                if (lr.top < cr.top + 8 || lr.bottom > cr.bottom - 8) {
                      container.offsetParent !== null &&
                    scrollEl.scrollTop += lr.top - cr.top - scrollEl.clientHeight / 2 + li.offsetHeight / 2;
                      window.getComputedStyle( container ).display !== 'none' &&
                      window.getComputedStyle( container ).visibility !== 'hidden';
             if ( vis ) {
              var lr = li.getBoundingClientRect();
              var cr = container.getBoundingClientRect();
              if ( lr.top < cr.top + 4 || lr.bottom > cr.bottom - 4 ) {
                var sh = null, node = li.parentNode;
                while ( node && node !== document.body ) {
                  var ov = window.getComputedStyle( node ).overflowY;
                  if ( ( ov === 'auto' || ov === 'scroll' ) &&
                      node.scrollHeight > node.clientHeight ) { sh = node; break; }
                  node = node.parentNode;
                }
                if ( !sh && container.scrollHeight > container.clientHeight ) sh = container;
                if ( sh ) {
                  var hr  = sh.getBoundingClientRect();
                  var top = lr.top - hr.top + sh.scrollTop;
                  sh.scrollTop = Math.max( 0, top - sh.clientHeight / 2 + li.offsetHeight / 2 );
                 }
                 }
              }
             }
             }
          }
         }
         }
      } );
        var _visible = new Set();
    } );
        _headingObserver = new IntersectionObserver(function (entries) {
 
            entries.forEach(function (entry) {
    var structObs = new MutationObserver( function ( mutations ) {
                if (entry.isIntersecting) _visible.add(entry.target.id);
      mutations.forEach( function ( m ) {
                else _visible.delete(entry.target.id);
        if ( m.type !== 'childList' ) return;
            });
        m.addedNodes.forEach( function ( n ) {
            var topId = null, topY = Infinity;
          if ( n.nodeType !== 1 ) return;
            _visible.forEach(function (id) {
          if ( n.classList && n.classList.contains( 'vector-toc-list-item' ) ) attachHighlight( n );
                var el = document.getElementById(id);
          if ( n.querySelectorAll ) n.querySelectorAll( '.vector-toc-list-item' ).forEach( attachHighlight );
                if (el) { var y = el.getBoundingClientRect().top; if (y >= 0 && y < topY) { topY = y; topId = id; } }
          var newSpans = [];
            });
          if ( n.classList && n.classList.contains( 'vector-toc-text' ) ) newSpans.push( n );
            if (!topId) {
          if ( n.querySelectorAll ) n.querySelectorAll( '.vector-toc-text' ).forEach( function ( s ) { newSpans.push( s ); } );
                var bestY = -Infinity;
          newSpans.forEach( function ( span ) {
                headings.forEach(function (h) { var y = h.getBoundingClientRect().top; if (y < 0 && y > bestY) { bestY = y; topId = h.id; } });
            if ( span.hasAttribute( 'data-deva' ) ) return;
            }
            var orig = span.textContent;
            setActive(topId || null);
            if ( !orig.trim() ) return;
        }, { rootMargin: '-60px 0px -65% 0px', threshold: 0 });
            span.setAttribute( 'data-deva', orig );
        headings.forEach(function (h) { _headingObserver.observe(h); });
            if ( currentScript !== 'deva' ) span.textContent = transliterateText( orig, currentScript );
            translatableSpans.push( span );
          } );
        } );
      } );
    } );
 
    toc.querySelectorAll( '.vector-toc-list-item' ).forEach( attachHighlight );
    structObs.observe( toc, { childList: true, subtree: true } );
 
    setTimeout( function () {
      normaliseAll();
      var active = toc.querySelector( '.vector-toc-list-item-active' );
      if ( active ) setActive( active, true );
    }, 300 );
  }
 
  // ── TOC: Use Vector's native TOC, add highlight + expand + rename ──────
  // Drops the custom TOC builder entirely. Vector builds the correct TOC
  // from page headings (== Chapter ==, === Section ===). We just:
  //  1. Rename "Contents" → "विषयसूची"
  //  2. Expand all collapsed sections
  //  3. Remove the "Beginning" top link
  //  4. Inject मूल/उल्लेख nav
  //  5. Add reliable IntersectionObserver active-highlight on headings
 
  function setupToc() {
    if ( _isNoTocPage() ) return;
    var toc = document.querySelector( '.vector-toc' );
    if ( !toc ) return;
 
    removeTocBeginning();
    renameTocTitle();
    expandTocSections();
    injectTocDocNav();
    attachHeadingObserver();
  }
 
  // ── IntersectionObserver on actual heading elements ──────────────
  // Watches the real == Heading == elements in the page body.
  // Much more reliable than watching gr-toc-anchor spans.
  var _headingObserver = null;
 
  function attachHeadingObserver() {
    if ( _isNoTocPage() ) return;
    if ( _headingObserver ) return;  // only attach once
    if ( !window.IntersectionObserver ) {
      watchTocActive();               // fallback for old browsers
      return;
     }
     }


     var ACTIVE_COLOR = '#f57c00';
     function setupToc() {
    var _activeId    = null;
        if (_isNoTocPage()) return;
 
        var toc = document.querySelector('.vector-toc');
    // Collect all headings that have an id (Vector gives them ids)
        if (!toc) return;
    var content  = document.querySelector( '.mw-parser-output' );
        removeTocBeginning();
    if ( !content ) return;
        renameTocTitle();
    var headings = Array.from(
        expandTocSections();
      content.querySelectorAll( 'h1[id],h2[id],h3[id],h4[id],h5[id],h6[id]' )
        injectTocDocNav();
    );
        attachHeadingObserver();
    if ( !headings.length ) return;
 
    var toc = document.querySelector( '.vector-toc' );
    if ( !toc ) return;
 
    function getTocLink( id ) {
      // Vector renders TOC links as href="#id"
      return toc.querySelector( 'a[href="#' + CSS.escape( id ) + '"]' );
     }
     }


     function getTocLi( id ) {
     function init() {
      var a = getTocLink( id );
        var HIDE_IDS = ['vector-appearance', 'vector-appearance-pinned-container', 'vector-appearance-unpinned-container'];
      return a ? a.closest( '.vector-toc-list-item' ) : null;
         function removeHiddenEls() {
    }
            HIDE_IDS.forEach(function (id) { var el = document.getElementById(id); if (el && el.parentNode) el.parentNode.removeChild(el); });
 
            var pt = document.getElementById('vector-page-tools') || document.querySelector('.vector-page-tools-pinned-container');
    function clearActive() {
            if (pt) pt.querySelectorAll('[aria-controls="vector-appearance"]').forEach(function (el) { if (el.parentNode) el.parentNode.removeChild(el); });
      toc.querySelectorAll( '.vector-toc-list-item-active' ).forEach( function ( li ) {
        li.classList.remove( 'vector-toc-list-item-active' );
         var lnk = li.querySelector( '.vector-toc-link' );
        if ( !lnk ) return;
        lnk.style.removeProperty( 'color' );
        lnk.style.setProperty( 'font-weight', '400', 'important' );
        lnk.querySelectorAll( '*' ).forEach( function ( el ) {
          el.style.removeProperty( 'color' );
          el.style.setProperty( 'font-weight', '400', 'important' );
        } );
      } );
    }
 
    function setActive( id ) {
      if ( _activeId === id ) return;
      _activeId = id;
      clearActive();
      if ( !id ) return;
 
      var li = getTocLi( id );
      if ( !li ) return;
 
      li.classList.add( 'vector-toc-list-item-active' );
 
      // Highlight only the innermost active item
      var hasActiveChild = !!li.querySelector(
        '.vector-toc-list-item .vector-toc-list-item-active'
      );
      if ( !hasActiveChild ) {
        var lnk = li.querySelector( '.vector-toc-link' );
        if ( lnk ) {
          lnk.style.setProperty( 'color',      ACTIVE_COLOR, 'important' );
          lnk.style.setProperty( 'font-weight', '700',        'important' );
          lnk.querySelectorAll( '*' ).forEach( function ( el ) {
            el.style.setProperty( 'color',      ACTIVE_COLOR, 'important' );
            el.style.setProperty( 'font-weight', '700',        'important' );
          } );
         }
         }
      }
        removeHiddenEls();
 
        (function detectTeekaMode() {
      // Expand collapsed ancestors
            var tp = document.querySelector('.gr-teeka-page');
      var anc = li.parentNode;
            if (!tp) return;
      while ( anc && anc !== toc ) {
            var primary = tp.getAttribute('data-primary') || '';
        if ( anc.classList && anc.classList.contains( 'vector-toc-list-item-collapsed' ) ) {
            var artPath = (window.mw && mw.config.get('wgArticlePath')) || '/wiki/$1';
          anc.classList.remove( 'vector-toc-list-item-collapsed' );
            var mainUrl = artPath.replace('$1', primary);
            var refParam = window.location.search.match(/[?&]ref=([01])/);
            if (refParam) { document.body.classList.add(refParam[1] === '1' ? 'gr-ref-mode' : 'gr-standalone'); return; }
            var ref = document.referrer || '';
            document.body.classList.add((ref && primary && ref.indexOf(mainUrl) !== -1) ? 'gr-ref-mode' : 'gr-standalone');
        }());
        if (window.MutationObserver) {
            var hideObs = new MutationObserver(function (mutations) {
                var dirty = false;
                mutations.forEach(function (m) { if (m.addedNodes.length) dirty = true; });
                if (dirty) removeHiddenEls();
            });
            hideObs.observe(document.body, { childList: true, subtree: false });
            setTimeout(function () { hideObs.disconnect(); }, 6000);
         }
         }
         anc = anc.parentNode;
         var content = document.querySelector('.mw-parser-output');
      }
        var alreadyTagged = content && content.querySelector('[data-deva]');
 
        if (!alreadyTagged) { translatableSpans = []; tagTextNodes(); }
      // Scroll TOC item into view within sidebar
         else {
      var sticky = document.querySelector( '.vector-sticky-pinned-container' );
            document.querySelectorAll('.vector-toc .vector-toc-text:not([data-deva])').forEach(function (span) {
      var scrollEl = sticky || toc;
                var orig = span.textContent; if (!orig.trim()) return;
      if ( scrollEl.scrollHeight > scrollEl.clientHeight ) {
                span.setAttribute('data-deva', orig); translatableSpans.push(span);
        var lr = li.getBoundingClientRect();
            });
         var cr = scrollEl.getBoundingClientRect();
        if ( lr.top < cr.top + 8 || lr.bottom > cr.bottom - 8 ) {
          scrollEl.scrollTop += lr.top - cr.top - scrollEl.clientHeight / 2 + li.offsetHeight / 2;
         }
         }
      }
        var saved = (function () { try { return localStorage.getItem(LS_SCRIPT_KEY); } catch (e) { return null; } }());
        if (saved && saved !== 'deva') { applyScript(saved); } else { currentScript = 'deva'; }
        setTimeout(setupToc, 200);
     }
     }


     // Track which headings are visible
     window.addEventListener('gr-script-change', function (e) {
    var _visible = new Set();
        var script = e && e.detail && e.detail.script;
        if (script) applyScript(script);
    });


     _headingObserver = new IntersectionObserver( function ( entries ) {
     window.addEventListener('gr-new-content', function (e) {
      entries.forEach( function ( entry ) {
        var container = e && e.detail && e.detail.container;
        if ( entry.isIntersecting ) {
        if (!container) return;
          _visible.add( entry.target.id );
        var walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT);
        } else {
        var nodes = [];
          _visible.delete( entry.target.id );
        while (walker.nextNode()) nodes.push(walker.currentNode);
         }
        nodes.forEach(function (node) {
      } );
            var p = node.parentNode;
            if (!p || (p.hasAttribute && p.hasAttribute('data-deva'))) return;
            var orig = node.textContent;
            if (!orig.trim()) return;
            var span = document.createElement('span');
            span.setAttribute('data-deva', orig);
            span.textContent = currentScript !== 'deva' ? transliterateText(orig, currentScript) : orig;
            p.replaceChild(span, node);
            translatableSpans.push(span);
         });
    });


      // Pick the topmost visible heading
    try {
      var topId = null;
        var _grBC = new BroadcastChannel('gr-script');
      var topY  = Infinity;
        _grBC.onmessage = function (e) {
      _visible.forEach( function ( id ) {
            var script = e && e.data && e.data.script;
        var el = document.getElementById( id );
            if (script) { currentScript = script; var sel = document.querySelector('.gr-script-sel'); if (sel) sel.value = script; applyScript(script); }
        if ( el ) {
         };
          var y = el.getBoundingClientRect().top;
    } catch (e) { }
          if ( y >= 0 && y < topY ) { topY = y; topId = id; }
         }
      } );


      // Nothing visible: find the last heading scrolled past (above viewport)
    if (window.mw) {
      if ( !topId ) {
        mw.hook('wikipage.content').add(function () {
        var bestY = -Infinity;
            setTimeout(function () {
        headings.forEach( function ( h ) {
                var content = document.querySelector('.mw-parser-output');
          var y = h.getBoundingClientRect().top;
                var alreadyTagged = content && content.querySelector('[data-deva]');
          if ( y < 0 && y > bestY ) { bestY = y; topId = h.id; }
                if (!alreadyTagged) { translatableSpans = []; tagTextNodes(); }
         } );
                else {
      }
                    document.querySelectorAll('.vector-toc .vector-toc-text:not([data-deva])').forEach(function (span) {
                        var orig = span.textContent; if (!orig.trim()) return;
                        span.setAttribute('data-deva', orig); translatableSpans.push(span);
                    });
                }
                if (currentScript !== 'deva') applyScript(currentScript);
                setupToc();
            }, 150);
         });
    }


      setActive( topId || null );
    if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); }
    }, {
     else { init(); }
      // Fire when heading enters/leaves the top 30% of the viewport
      rootMargin: '-60px 0px -65% 0px',
      threshold: 0
     } );


    headings.forEach( function ( h ) { _headingObserver.observe( h ); } );
}());  /* ← end of main IIFE */
   }


  // ── Init ────────────────────────────────────────────────────────
  function init() {
    var HIDE_IDS = [
      'vector-appearance',
      'vector-appearance-pinned-container',
      'vector-appearance-unpinned-container'
    ];
    function removeHiddenEls() {
      HIDE_IDS.forEach( function ( id ) {
        var el = document.getElementById( id );
        if ( el && el.parentNode ) el.parentNode.removeChild( el );
      } );
      var pt = document.getElementById( 'vector-page-tools' ) ||
              document.querySelector( '.vector-page-tools-pinned-container' );
      if ( pt ) {
        pt.querySelectorAll( '[aria-controls="vector-appearance"]' )
          .forEach( function ( el ) { if ( el.parentNode ) el.parentNode.removeChild( el ); } );
      }
    }
    removeHiddenEls();


    ( function detectTeekaMode() {
// ── Inject "Help" and "About" links into the header ─────────────────
      var tp = document.querySelector( '.gr-teeka-page' );
(function () {
      if ( !tp ) return;
    function wikiHref(title) {
      var primary = tp.getAttribute( 'data-primary' ) || '';
        if (window.mw && mw.util && mw.util.getUrl) return mw.util.getUrl(title);
      var artPath = ( window.mw && mw.config.get( 'wgArticlePath' ) ) || '/wiki/$1';
        var ap = (window.mw && mw.config && mw.config.get('wgArticlePath')) || '/wiki/$1';
      var mainUrl = artPath.replace( '$1', primary );
        return ap.replace('$1', title);
      var refParam = window.location.search.match( /[?&]ref=([01])/ );
      if ( refParam ) {
        document.body.classList.add( refParam[1] === '1' ? 'gr-ref-mode' : 'gr-standalone' );
        return;
      }
      var ref = document.referrer || '';
      document.body.classList.add(
        ( ref && primary && ref.indexOf( mainUrl ) !== -1 ) ? 'gr-ref-mode' : 'gr-standalone'
      );
    }() );
 
    if ( window.MutationObserver ) {
      var hideObs = new MutationObserver( function ( mutations ) {
        var dirty = false;
        mutations.forEach( function ( m ) { if ( m.addedNodes.length ) dirty = true; } );
        if ( dirty ) removeHiddenEls();
      } );
      hideObs.observe( document.body, { childList: true, subtree: false } );
      setTimeout( function () { hideObs.disconnect(); }, 6000 );
     }
     }
 
     var linkStyle = ['color:rgba(255,255,255,0.88)', 'font-size:0.88em', 'font-family:system-ui,sans-serif', 'font-weight:500', 'text-decoration:none', 'padding:4px 10px', 'border-radius:4px', 'margin-right:4px', 'transition:color 0.15s,background 0.15s', 'white-space:nowrap'].join(';');
     var content      = document.querySelector( '.mw-parser-output' );
     function makeHeaderLink(id, href, label) {
    var alreadyTagged = content && content.querySelector( '[data-deva]' );
        var a = document.createElement('a');
     if ( !alreadyTagged ) {
        a.id = id; a.href = href; a.textContent = label; a.style.cssText = linkStyle;
      translatableSpans = [];
        a.addEventListener('mouseover', function () { this.style.color = '#fff'; this.style.background = 'rgba(255,255,255,0.12)'; });
      tagTextNodes();
         a.addEventListener('mouseout', function () { this.style.color = 'rgba(255,255,255,0.88)'; this.style.background = 'transparent'; });
    } else {
        return a;
      document.querySelectorAll( '.vector-toc .vector-toc-text:not([data-deva])' ).forEach( function ( span ) {
        var orig = span.textContent;
        if ( !orig.trim() ) return;
         span.setAttribute( 'data-deva', orig );
        translatableSpans.push( span );
      } );
     }
     }
    function injectHeaderLinks() {
        if (document.getElementById('gr-about-link')) return;
        var headerEnd = document.querySelector('.vector-header-end') || document.querySelector('#vector-user-links') || document.querySelector('.mw-header');
        if (!headerEnd) return;
        var helpLink = makeHeaderLink('gr-help-link', wikiHref('My_wiki:Help'), 'Help');
        var aboutLink = makeHeaderLink('gr-about-link', wikiHref('My_wiki:About'), 'About');


    var saved = ( function () {
        var userName = window.mw ? mw.config.get('wgUserName') : null;
      try { return localStorage.getItem( LS_SCRIPT_KEY ); } catch ( e ) { return null; }
        var isAnon = !userName || (window.mw && mw.config.get('wgUserId') === null);
    }() );
    if ( saved && saved !== 'deva' ) { applyScript( saved ); }
    else { currentScript = 'deva'; }


    // Vector 2022 defers TOC render — retry at 300ms and 800ms
        // Build the trailing auth element (Login link for anon, dropdown for logged-in)
    // Use a single short delay so Vector has rendered the TOC
        var authEl = null;
    setTimeout( setupToc, 200 );
        if (isAnon) {
  }
            if (!document.getElementById('gr-header-login')) {
 
                authEl = makeHeaderLink('gr-header-login', wikiHref('Special:UserLogin'), 'Login');
  // ── React to toolbar script-change events ──────────────────────
            }
  window.addEventListener( 'gr-script-change', function ( e ) {
        } else if (!document.getElementById('gr-header-user')) {
    var script = e && e.detail && e.detail.script;
            authEl = buildHeaderUserDropdown(userName);
    if ( script ) applyScript( script );
        }
  } );


  // ── React to gr-new-content (siteNav panel rendered new items) ──
        var ul = document.querySelector('.vector-user-links') || document.querySelector('#pt-userpage');
  // Tag any new text nodes added by the documents panel
         if (ul && ul.parentNode === headerEnd) {
  window.addEventListener( 'gr-new-content', function ( e ) {
            if (authEl) headerEnd.insertBefore(authEl, ul);
    var container = e && e.detail && e.detail.container;
            headerEnd.insertBefore(aboutLink, authEl || ul);
    if ( !container ) return;
            headerEnd.insertBefore(helpLink, aboutLink);
    var walker = document.createTreeWalker( container, NodeFilter.SHOW_TEXT );
    var nodes = [];
    while ( walker.nextNode() ) nodes.push( walker.currentNode );
    nodes.forEach( function ( node ) {
      var p = node.parentNode;
      if ( !p || ( p.hasAttribute && p.hasAttribute( 'data-deva' ) ) ) return;
      var orig = node.textContent;
      if ( !orig.trim() ) return;
      var span = document.createElement( 'span' );
      span.setAttribute( 'data-deva', orig );
      span.textContent = currentScript !== 'deva' ? transliterateText( orig, currentScript ) : orig;
      p.replaceChild( span, node );
      translatableSpans.push( span );
    } );
  } );
 
  // ── React to script changes from OTHER tabs (BroadcastChannel) ──
  try {
    var _grBC = new BroadcastChannel( 'gr-script' );
    _grBC.onmessage = function ( e ) {
      var script = e && e.data && e.data.script;
      if ( script ) {
        currentScript = script;
        var sel = document.querySelector( '.gr-script-sel' );
         if ( sel ) sel.value = script;
        applyScript( script );
      }
    };
  } catch ( e ) {}
 
  // ── MediaWiki SPA-style navigation ──────────────────────────────
  if ( window.mw ) {
    mw.hook( 'wikipage.content' ).add( function () {
      setTimeout( function () {
        var content      = document.querySelector( '.mw-parser-output' );
        var alreadyTagged = content && content.querySelector( '[data-deva]' );
        if ( !alreadyTagged ) {
          translatableSpans = [];
          tagTextNodes();
         } else {
         } else {
          document.querySelectorAll( '.vector-toc .vector-toc-text:not([data-deva])' ).forEach( function ( span ) {
            headerEnd.appendChild(helpLink);
            var orig = span.textContent;
             headerEnd.appendChild(aboutLink);
             if ( !orig.trim() ) return;
             if (authEl) headerEnd.appendChild(authEl);
             span.setAttribute( 'data-deva', orig );
            translatableSpans.push( span );
          } );
         }
         }
        if ( currentScript !== 'deva' ) applyScript( currentScript );
     }
        setupToc();
      }, 150 );
     } );
  }


  if ( document.readyState === 'loading' ) {
    function buildHeaderUserDropdown(userName) {
    document.addEventListener( 'DOMContentLoaded', init );
        var wrap = document.createElement('div');
  } else {
        wrap.id = 'gr-header-user';
    init();
        wrap.style.cssText = 'position:relative;display:inline-block;margin-right:4px;';
  }


}() );   /* ← end of main IIFE */
        var trigger = document.createElement('button');
        trigger.id = 'gr-header-user-trigger';
        trigger.type = 'button';
        trigger.setAttribute('aria-haspopup', 'true');
        trigger.setAttribute('aria-expanded', 'false');
        trigger.style.cssText = [
            'display:inline-flex', 'align-items:center', 'gap:5px',
            'color:rgba(255,255,255,0.88)', 'font-size:0.88em',
            'font-family:system-ui,sans-serif', 'font-weight:500',
            'background:transparent', 'border:none', 'cursor:pointer',
            'padding:4px 10px', 'border-radius:4px', 'white-space:nowrap',
            'transition:color 0.15s,background 0.15s'
        ].join(';');
        trigger.innerHTML =
            '<span>' + userName.replace(/</g, '&lt;') + '</span>' +
            '<span id="gr-header-caret" style="font-size:0.8em;transition:transform 0.2s;">\u25be</span>';
        trigger.addEventListener('mouseover', function () { this.style.color = '#fff'; this.style.background = 'rgba(255,255,255,0.12)'; });
        trigger.addEventListener('mouseout', function () { if (menu.style.display === 'none') { this.style.color = 'rgba(255,255,255,0.88)'; this.style.background = 'transparent'; } });


        var menu = document.createElement('div');
        menu.id = 'gr-header-user-menu';
        menu.setAttribute('role', 'menu');
        menu.style.cssText = [
            'display:none', 'position:absolute', 'top:100%', 'right:0', 'margin-top:4px',
            'min-width:150px', 'background:#fff', 'border-radius:6px',
            'box-shadow:0 4px 16px rgba(0,0,0,0.18)', 'overflow:hidden', 'z-index:1000'
        ].join(';');


// ── Inject "Help" and "About" links into the header ─────────────────
        var itemStyle = 'display:block;padding:10px 16px;font-size:0.9em;color:#2c1810;text-decoration:none;font-family:system-ui,sans-serif;background:#fff;';
( function () {
        function makeMenuItem(href, label, id) {
  function wikiHref( title ) {
            var a = document.createElement('a');
    if ( window.mw && mw.util && mw.util.getUrl ) return mw.util.getUrl( title );
            a.href = href; a.setAttribute('role', 'menuitem');
    var ap = ( window.mw && mw.config && mw.config.get( 'wgArticlePath' ) ) || '/wiki/$1';
            a.textContent = label; a.style.cssText = itemStyle;
    return ap.replace( '$1', title );
            if (id) a.id = id;
  }
            a.addEventListener('mouseover', function () { this.style.background = '#f5efe9'; });
            a.addEventListener('mouseout', function () { this.style.background = '#fff'; });
            return a;
        }


  var linkStyle = [
        menu.appendChild(makeMenuItem(wikiHref('Special:Profile'), 'Profile'));
    'color:rgba(255,255,255,0.88)', 'font-size:0.88em',
        menu.appendChild(makeMenuItem('#', 'Log out', 'gr-header-logout'));
    'font-family:system-ui,sans-serif', 'font-weight:500',
    'text-decoration:none', 'padding:4px 10px', 'border-radius:4px',
    'margin-right:4px', 'transition:color 0.15s,background 0.15s',
    'white-space:nowrap',
  ].join( ';' );


  function makeHeaderLink( id, href, label ) {
        function setOpen(open) {
    var a = document.createElement( 'a' );
            menu.style.display = open ? 'block' : 'none';
    a.id = id; a.href = href; a.textContent = label;
            trigger.setAttribute('aria-expanded', open ? 'true' : 'false');
    a.style.cssText = linkStyle;
            var caret = document.getElementById('gr-header-caret');
    a.addEventListener( 'mouseover', function () {
            if (caret) caret.style.transform = open ? 'rotate(180deg)' : '';
      this.style.color = '#fff'; this.style.background = 'rgba(255,255,255,0.12)';
            if (open) { trigger.style.color = '#fff'; trigger.style.background = 'rgba(255,255,255,0.12)'; }
    } );
            else { trigger.style.color = 'rgba(255,255,255,0.88)'; trigger.style.background = 'transparent'; }
    a.addEventListener( 'mouseout', function () {
        }
      this.style.color = 'rgba(255,255,255,0.88)'; this.style.background = 'transparent';
    } );
    return a;
  }


  function injectHeaderLinks() {
        trigger.addEventListener('click', function (e) {
    if ( document.getElementById( 'gr-about-link' ) ) return;
            e.stopPropagation();
            setOpen(menu.style.display === 'none');
        });
        document.addEventListener('click', function (e) {
            if (!wrap.contains(e.target)) setOpen(false);
        });


    var headerEnd = document.querySelector( '.vector-header-end' ) ||
        // Logout: POST with CSRF token (same approach as the desktop dropdown)
                    document.querySelector( '#vector-user-links' ) ||
        menu.querySelector('#gr-header-logout').addEventListener('click', function (e) {
                    document.querySelector( '.mw-header' );
            e.preventDefault();
    if ( !headerEnd ) return;
            if (window.mw && mw.user && mw.user.tokens) {
 
                var t = mw.user.tokens.get('csrfToken');
    var helpLink  = makeHeaderLink( 'gr-help-link',  wikiHref( 'My_wiki:Help' ), 'Help' );
                if (t) {
    var aboutLink = makeHeaderLink( 'gr-about-link', wikiHref( 'My_wiki:About' ), 'About' );
                    var script = (mw.util && mw.util.wikiScript) ? mw.util.wikiScript() : '/index.php';
                    var form = document.createElement('form');
                    form.method = 'post';
                    form.action = script + '?title=Special:UserLogout';
                    form.style.display = 'none';
                    form.innerHTML =
                        '<input type="hidden" name="wpEditToken" value="' + String(t).replace(/"/g, '&quot;') + '">' +
                        '<input type="hidden" name="title" value="Special:UserLogout">' +
                        '<input type="hidden" name="returnto" value="Main Page">';
                    document.body.appendChild(form);
                    form.submit();
                    return;
                }
            }
            if (window.mw && mw.Api) {
                new mw.Api().postWithToken('csrf', { action: 'logout' })
                    .done(function () { location.href = '/Main_Page'; })
                    .fail(function () { location.href = '/index.php?title=Special:UserLogout'; });
            } else {
                location.href = '/index.php?title=Special:UserLogout';
            }
        });


    var ul = document.querySelector( '.vector-user-links' ) ||
        wrap.appendChild(trigger);
            document.querySelector( '#pt-userpage' );
        wrap.appendChild(menu);
    if ( ul && ul.parentNode === headerEnd ) {
        return wrap;
      headerEnd.insertBefore( aboutLink, ul );
      headerEnd.insertBefore( helpLink,  aboutLink );
    } else {
      headerEnd.appendChild( helpLink );
      headerEnd.appendChild( aboutLink );
     }
     }
  }
    if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', injectHeaderLinks);
 
    else injectHeaderLinks();
  if ( document.readyState === 'loading' ) document.addEventListener( 'DOMContentLoaded', injectHeaderLinks );
}());
  else injectHeaderLinks();
}() );




// ── Main page: by-Grantha / by-Author toggle ──────────────────────
// ── Main page: by-Grantha / by-Author toggle ──────────────────────
( function () {
(function () {
  function grHomeView( v ) {
    function grHomeView(v) {
    var gView = document.getElementById( 'gr-view-grantha' );
        var gView = document.getElementById('gr-view-grantha');
    var aView = document.getElementById( 'gr-view-author' );
        var aView = document.getElementById('gr-view-author');
    var gBtn = document.getElementById( 'gr-toggle-grantha' );
        var gBtn = document.getElementById('gr-toggle-grantha');
    var aBtn = document.getElementById( 'gr-toggle-author' );
        var aBtn = document.getElementById('gr-toggle-author');
    if ( !gView || !aView || !gBtn || !aBtn ) return;
        if (!gView || !aView || !gBtn || !aBtn) return;
    gView.style.display = ( v === 'grantha' ) ? '' : 'none';
        gView.style.display = (v === 'grantha') ? '' : 'none';
    aView.style.display = ( v === 'author' ) ? '' : 'none';
        aView.style.display = (v === 'author') ? '' : 'none';
    gBtn.className = 'gr-toggle-btn' + ( v === 'grantha' ? ' gr-toggle-active' : '' );
        gBtn.className = 'gr-toggle-btn' + (v === 'grantha' ? ' gr-toggle-active' : '');
    aBtn.className = 'gr-toggle-btn' + ( v === 'author' ? ' gr-toggle-active' : '' );
        aBtn.className = 'gr-toggle-btn' + (v === 'author' ? ' gr-toggle-active' : '');
    try { localStorage.setItem( 'gr_home_view', v ); } catch ( e ) {}
        try { localStorage.setItem('gr_home_view', v); } catch (e) { }
  }
     }
 
}());
  function initHomeToggle() {
    var gBtn = document.getElementById( 'gr-toggle-grantha' );
    var aBtn = document.getElementById( 'gr-toggle-author' );
    if ( !gBtn || !aBtn ) return;
    gBtn.addEventListener( 'click', function () { grHomeView( 'grantha' ); } );
    aBtn.addEventListener( 'click', function () { grHomeView( 'author' );  } );
    [ gBtn, aBtn ].forEach( function ( btn ) {
      btn.addEventListener( 'keydown', function ( e ) {
        if ( e.key === 'Enter' || e.key === ' ' ) btn.click();
      } );
    } );
    var saved;
    try { saved = localStorage.getItem( 'gr_home_view' ); } catch ( e ) {}
     if ( saved === 'author' ) grHomeView( 'author' );
  }
 
  if ( document.readyState === 'loading' ) document.addEventListener( 'DOMContentLoaded', initHomeToggle );
  else initHomeToggle();
}() );




// ── Ullekha reference link handler ─────────────────────────────────
// ── Ullekha reference link handler ─────────────────────────────────
( function () {
(function () {
 
    function highlightOnArrival() {
  function highlightOnArrival() {
        var search = window.location.search;
    var search = window.location.search;
        if (!search) return;
    if ( !search ) return;
        var m = search.match(/[?&]hlUllekha=([^&]+)/);
    var m = search.match( /[?&]hlUllekha=([^&]+)/ );
        if (!m) return;
    if ( !m ) return;
        var needle;
    var needle;
        try { needle = decodeURIComponent(m[1]); } catch (e) { return; }
    try { needle = decodeURIComponent( m[ 1 ] ); } catch ( e ) { return; }
        if (!needle || needle.length < 4) return;
    if ( !needle || needle.length < 4 ) return;
        function doHighlight() {
 
            var content = document.querySelector('.mw-parser-output');
    // Wait for tagTextNodes() to finish wrapping text in data-deva spans,
            if (!content) return;
    // then search those spans rather than raw text nodes.
            var snippet = needle.slice(0, 40);
    function doHighlight() {
            var found = false;
      var content = document.querySelector( '.mw-parser-output' );
            var spans = content.querySelectorAll('[data-deva]');
      if ( !content ) return;
            for (var i = 0; i < spans.length && !found; i++) {
 
                var spanEl = spans[i];
      var snippet = needle.slice( 0, 40 );
                var orig = spanEl.getAttribute('data-deva') || '';
      var found   = false;
                if (orig.indexOf(snippet) === -1) continue;
 
                var idx = orig.indexOf(snippet);
      // Search data-deva spans first (post-tagTextNodes state)
                var hlText = orig.slice(idx, Math.min(idx + needle.length, orig.length));
      var spans = content.querySelectorAll( '[data-deva]' );
                var mark = document.createElement('mark');
      for ( var i = 0; i < spans.length && !found; i++ ) {
                mark.className = 'gr-ullekha-highlight';
        var spanEl = spans[ i ];
                mark.style.cssText = 'background:#fff176;border-radius:2px;padding:0 2px;';
        var orig   = spanEl.getAttribute( 'data-deva' ) || '';
                mark.textContent = hlText;
        if ( orig.indexOf( snippet ) === -1 ) continue;
                var parent = spanEl.parentNode;
 
                if (!parent) continue;
        // Replace the span with: text-before + <mark> + text-after
                var before = document.createTextNode(orig.slice(0, idx));
        var idx   = orig.indexOf( snippet );
                var after = document.createTextNode(orig.slice(idx + hlText.length));
        var hlText = orig.slice( idx, Math.min( idx + needle.length, orig.length ) );
                parent.insertBefore(before, spanEl); parent.insertBefore(mark, spanEl); parent.insertBefore(after, spanEl); parent.removeChild(spanEl);
        var mark   = document.createElement( 'mark' );
                setTimeout(function () { mark.scrollIntoView({ behavior: 'smooth', block: 'center' }); }, 100);
        mark.className = 'gr-ullekha-highlight';
                found = true;
        mark.style.cssText = 'background:#fff176;border-radius:2px;padding:0 2px;';
            }
        mark.textContent   = hlText;
            if (!found) {
 
                var walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT);
        var parent = spanEl.parentNode;
                while (walker.nextNode() && !found) {
        if ( !parent ) continue;
                    var node = walker.currentNode;
 
                    var txt = node.textContent || '';
        var before = document.createTextNode( orig.slice( 0, idx ) );
                    if (txt.indexOf(snippet) === -1) continue;
        var after = document.createTextNode( orig.slice( idx + hlText.length ) );
                    var idx2 = txt.indexOf(snippet);
        parent.insertBefore( before, spanEl );
                    var mark2 = document.createElement('mark');
        parent.insertBefore( mark,   spanEl );
                    mark2.className = 'gr-ullekha-highlight';
        parent.insertBefore( after, spanEl );
                    mark2.style.cssText = 'background:#fff176;border-radius:2px;padding:0 2px;';
        parent.removeChild( spanEl );
                    mark2.textContent = txt.slice(idx2, Math.min(idx2 + needle.length, txt.length));
 
                    var p = node.parentNode;
        setTimeout( function () {
                    p.insertBefore(document.createTextNode(txt.slice(0, idx2)), node);
          mark.scrollIntoView( { behavior: 'smooth', block: 'center' } );
                    p.insertBefore(mark2, node);
        }, 100 );
                    p.insertBefore(document.createTextNode(txt.slice(idx2 + mark2.textContent.length)), node);
        found = true;
                    p.removeChild(node);
      }
                    setTimeout(function () { mark2.scrollIntoView({ behavior: 'smooth', block: 'center' }); }, 100);
 
                    found = true;
      // Fallback: raw text nodes (before tagTextNodes runs)
                }
      if ( !found ) {
            }
        var walker = document.createTreeWalker( content, NodeFilter.SHOW_TEXT );
        while ( walker.nextNode() && !found ) {
          var node = walker.currentNode;
          var txt = node.textContent || '';
          if ( txt.indexOf( snippet ) === -1 ) continue;
          var idx2   = txt.indexOf( snippet );
          var mark2 = document.createElement( 'mark' );
          mark2.className   = 'gr-ullekha-highlight';
          mark2.style.cssText = 'background:#fff176;border-radius:2px;padding:0 2px;';
          mark2.textContent = txt.slice( idx2, Math.min( idx2 + needle.length, txt.length ) );
          var p = node.parentNode;
          p.insertBefore( document.createTextNode( txt.slice( 0, idx2 ) ), node );
          p.insertBefore( mark2, node );
          p.insertBefore( document.createTextNode( txt.slice( idx2 + mark2.textContent.length ) ), node );
          p.removeChild( node );
          setTimeout( function () {
            mark2.scrollIntoView( { behavior: 'smooth', block: 'center' } );
          }, 100 );
          found = true;
         }
         }
      }
        doHighlight();
     }
     }
    function wireUllekhaLinks() {
        document.querySelectorAll('.gr-ullekha-ref-link').forEach(function (wrap) {
            var anchor = wrap.getAttribute('data-anchor') || '';
            var hl = wrap.getAttribute('data-hl') || '';
            var a = wrap.querySelector('a');
            if (!a) return;
            var base = a.href.split('#')[0];
            var encoded = encodeURIComponent(hl);
            a.href = base + (hl ? '?hlUllekha=' + encoded : '') + (anchor ? '#' + anchor : '');
        });
    }
    if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function () { highlightOnArrival(); wireUllekhaLinks(); }); }
    else { highlightOnArrival(); wireUllekhaLinks(); }
}());


    // Delay to let tagTextNodes() and MW rendering finish
/* ── Search result highlight ──────────────────────────────────── */
    setTimeout( doHighlight, 600 );
/* EXACT REPLACEMENT for the search highlight IIFE in MediaWiki:Common.js.
  }
  * Only changes from the original working version:
 
  * - Mobile bar: full-width terracotta bottom bar instead of floating pill
  function wireUllekhaLinks() {
  *  - showDismissBar: guard added (if !count return) to prevent empty bar
    document.querySelectorAll( '.gr-ullekha-ref-link' ).forEach( function ( wrap ) {
* Everything else (storeQueryForLink, applyHighlight, wrapMatches) is
      var anchor = wrap.getAttribute( 'data-anchor' ) || '';
* identical to the version that was working.
      var hl    = wrap.getAttribute( 'data-hl' )    || '';
*/
      var a = wrap.querySelector( 'a' );
(function () {
      if ( !a ) return;
 
      var base = a.href.split( '#' )[ 0 ];
      var encoded = encodeURIComponent( hl );
      a.href = base + ( hl ? '?hlUllekha=' + encoded : '' )
                    + ( anchor ? '#' + anchor : '' );
    } );
  }
 
  if ( document.readyState === 'loading' ) {
    document.addEventListener( 'DOMContentLoaded', function () {
      highlightOnArrival();
      wireUllekhaLinks();
    } );
  } else {
    highlightOnArrival();
    wireUllekhaLinks();
  }
}() );/* ── Search result highlight highlight query term on arrival ──
  * When user clicks a search result, we pass the query in the URL
  * hash as #gr-search:QUERY or read it from sessionStorage.
  * On page load we find all matching text nodes and wrap them.
  * ─────────────────────────────────────────────────────────────── */
( function () {
 
  /* ── Step 1: When leaving via a search result link,
    store the query in sessionStorage ── */
  function storeQueryForLink( url, query ) {
    try {
      /* Store just the pathname so protocol/host differences don't break matching */
      var a = document.createElement( 'a' );
      a.href = url;
      sessionStorage.setItem( 'gr_search_hl', JSON.stringify({
        query:    query,
        pathname: a.pathname  // e.g. "/Brahmasutra"
      }) );
    } catch(e) {}
  }
 
  /* ── Step 2: On page load, check if we arrived from a search result ── */
  function applyHighlight() {
    var stored;
    try {
      stored = JSON.parse( sessionStorage.getItem( 'gr_search_hl' ) || 'null' );
    } catch(e) { return; }
    if ( !stored || !stored.query ) return;


     /* Check pathname matches — lenient comparison */
     function storeQueryForLink(url, query) {
    var currentPath = window.location.pathname;
        try {
    var storedPath  = stored.pathname || '';
            var a = document.createElement('a');
    /* Normalize: remove trailing slash, decode */
            a.href = url;
    function normPath(p) { return decodeURIComponent(p).replace(/\/+$/, ''); }
            sessionStorage.setItem('gr_search_hl', JSON.stringify({
    if ( storedPath && normPath(storedPath) !== normPath(currentPath) ) {
                query: query,
      /* Different page — clear and bail */
                pathname: a.pathname
      try { sessionStorage.removeItem( 'gr_search_hl' ); } catch(e) {}
            }));
      return;
        } catch (e) { }
     }
     }


     var query = stored.query.trim();
     function applyHighlight() {
    if ( !query ) return;
        var stored;
        try {
            stored = JSON.parse(sessionStorage.getItem('gr_search_hl') || 'null');
        } catch (e) { return; }
        if (!stored || !stored.query) return;


    /* Clear so refreshing doesn't re-highlight */
        var currentPath = window.location.pathname;
    try { sessionStorage.removeItem( 'gr_search_hl' ); } catch(e) {}
        var storedPath = stored.pathname || '';


    /* Wait for content + Common.js tagTextNodes to finish rendering */
        function normPath(p) { return decodeURIComponent(p).replace(/\/+$/, ''); }
    var delays = [400, 900, 1500];
        if (storedPath && normPath(storedPath) !== normPath(currentPath)) {
    delays.forEach( function(ms) {
            try { sessionStorage.removeItem('gr_search_hl'); } catch (e) { }
      setTimeout( function () {
            return;
        /* Only run if not already highlighted */
        if ( !document.querySelector( '.gr-search-hl' ) ) {
          highlightText( query );
         }
         }
      }, ms );
    } );
  }


  /* ── Core: walk text nodes and wrap matches ── */
        var query = stored.query.trim();
  function highlightText( query ) {
        if (!query) return;
    var content = document.querySelector( '#mw-content-text .mw-parser-output' );
    if ( !content ) return;


    /* Normalise query — strip quotes, split on spaces */
        try { sessionStorage.removeItem('gr_search_hl'); } catch (e) { }
    var raw = query.replace( /^"|"$/g, '' ).trim();
    if ( !raw ) return;


    /* Build regex — escape special chars, match whole query first,
        var delays = [0, 200, 600];
      fall back to individual words */
        delays.forEach(function (ms) {
    var patterns = [];
            setTimeout(function () {
    /* Full phrase */
                if (document.querySelector('.gr-search-hl')) return;
    patterns.push( escapeRegex( raw ) );
                highlightText(query);
    /* Individual words (min 2 chars) */
            }, ms);
    raw.split( /\s+/ ).forEach( function(w) {
        });
      if ( w.length >= 2 ) patterns.push( escapeRegex( w ) );
    } );
 
    var matched = false;
    for ( var pi = 0; pi < patterns.length; pi++ ) {
      var re;
      try { re = new RegExp( '(' + patterns[pi] + ')', 'gi' ); }
      catch(e) { continue; }
 
      var count = wrapMatches( content, re );
      if ( count > 0 ) { matched = true; break; }
     }
     }


     if ( !matched ) return;
     function highlightText(query) {
        var content = document.querySelector('#mw-content-text .mw-parser-output');
        if (!content) return;


    /* Scroll to first highlight */
        var raw = query.replace(/^"|"$/g, '').trim();
    var first = document.querySelector( '.gr-search-hl' );
         if (!raw) return;
    if ( first ) {
      first.scrollIntoView({ behavior: 'smooth', block: 'center' });
      /* Pulse animation */
      first.classList.add( 'gr-search-hl-pulse' );
      setTimeout( function() {
         first.classList.remove( 'gr-search-hl-pulse' );
      }, 2000 );
    }


    /* Show dismiss button */
        var patterns = [];
    showDismissBar( query );
        patterns.push(escapeRegex(raw));
  }
        raw.split(/\s+/).forEach(function (w) {
            if (w.length >= 2) patterns.push(escapeRegex(w));
        });


  function escapeRegex( s ) {
        var matched = false;
    return s.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' );
        for (var pi = 0; pi < patterns.length; pi++) {
  }
            var re;
 
            try { re = new RegExp('(' + patterns[pi] + ')', 'gi'); }
  function wrapMatches( root, re ) {
            catch (e) { continue; }
    var count = 0;
            var count = wrapMatches(content, re);
    var walker = document.createTreeWalker(
            if (count > 0) { matched = true; break; }
      root, NodeFilter.SHOW_TEXT, {
        acceptNode: function( node ) {
          /* Skip inside script, style, our own highlights */
          var p = node.parentElement;
          if ( !p ) return NodeFilter.FILTER_REJECT;
          var tag = p.tagName.toUpperCase();
          if ( tag === 'SCRIPT' || tag === 'STYLE' || tag === 'NOSCRIPT' ) return NodeFilter.FILTER_REJECT;
          if ( p.classList.contains( 'gr-search-hl' ) ) return NodeFilter.FILTER_REJECT;
          return NodeFilter.FILTER_ACCEPT;
         }
         }
      }, false
    );


    var nodes = [];
        if (!matched) return;
    var node;
    while ( ( node = walker.nextNode() ) ) nodes.push( node );


    nodes.forEach( function( textNode ) {
        var first = document.querySelector('.gr-search-hl');
      var val = textNode.nodeValue;
        if (first) {
      if ( !re.test( val ) ) return;
            first.scrollIntoView({ behavior: 'smooth', block: 'center' });
      re.lastIndex = 0;
            first.classList.add('gr-search-hl-pulse');
 
            setTimeout(function () { first.classList.remove('gr-search-hl-pulse'); }, 2000);
      var frag = document.createDocumentFragment();
      var last = 0;
      var m;
      while ( ( m = re.exec( val ) ) !== null ) {
        if ( m.index > last ) {
          frag.appendChild( document.createTextNode( val.slice( last, m.index ) ) );
         }
         }
        var span = document.createElement( 'span' );
        span.className = 'gr-search-hl';
        span.textContent = m[0];
        frag.appendChild( span );
        last = m.index + m[0].length;
        count++;
      }
      if ( last < val.length ) {
        frag.appendChild( document.createTextNode( val.slice( last ) ) );
      }
      textNode.parentNode.replaceChild( frag, textNode );
    } );


    return count;
        showDismissBar(query);
  }
     }
 
  /* ── Dismiss bar ── */
  function showDismissBar( query ) {
    var isMob = window.innerWidth < 768;
    var bar = document.createElement( 'div' );
     bar.id = 'gr-hl-bar';


     /* On mobile: float as a pill near top to avoid bottom bar conflicts.
     function escapeRegex(s) {
      On desktop: sit at bottom. */
         return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    if ( isMob ) {
      bar.style.cssText = [
        'position:fixed',
        'top:calc(var(--gr-header-height,56px) + var(--gr-toc-top,52px) + 8px)',
        'left:50%', 'transform:translateX(-50%)',
        'z-index:10200',
        'background:#b5451b', 'color:#fff',
        'padding:8px 14px',
        'border-radius:24px',
        'display:flex', 'align-items:center', 'gap:8px',
         'font-family:system-ui,sans-serif', 'font-size:13px',
        'box-shadow:0 3px 12px rgba(0,0,0,0.25)',
        'white-space:nowrap',
        'max-width:calc(100vw - 32px)'
      ].join(';');
    } else {
      bar.style.cssText = [
        'position:fixed', 'bottom:0', 'left:0', 'right:0', 'z-index:10200',
        'background:#b5451b', 'color:#fff', 'padding:10px 16px',
        'display:flex', 'align-items:center', 'justify-content:space-between',
        'font-family:system-ui,sans-serif', 'font-size:14px',
        'box-shadow:0 -2px 8px rgba(0,0,0,0.2)'
      ].join(';');
     }
     }


     var count = document.querySelectorAll( '.gr-search-hl' ).length;
     function wrapMatches(root, re) {
 
         var count = 0;
    if ( isMob ) {
         var walker = document.createTreeWalker(
      /* Mobile: compact pill — just count + prev/next + dismiss */
            root, NodeFilter.SHOW_TEXT, {
      bar.innerHTML =
            acceptNode: function (node) {
         '<span style="flex-shrink:0">🔍 ' + count + '</span>' +
                var p = node.parentElement;
        '<button id="gr-hl-prev" style="background:rgba(255,255,255,0.2);border:none;color:#fff;min-width:36px;height:36px;border-radius:50%;cursor:pointer;font-size:16px;display:flex;align-items:center;justify-content:center;">↑</button>' +
                if (!p) return NodeFilter.FILTER_REJECT;
         '<button id="gr-hl-next" style="background:rgba(255,255,255,0.2);border:none;color:#fff;min-width:36px;height:36px;border-radius:50%;cursor:pointer;font-size:16px;display:flex;align-items:center;justify-content:center;">↓</button>' +
                var tag = p.tagName.toUpperCase();
        '<button id="gr-hl-dismiss" style="background:rgba(255,255,255,0.15);border:none;color:#fff;min-width:36px;height:36px;border-radius:50%;cursor:pointer;font-size:16px;display:flex;align-items:center;justify-content:center;">✕</button>';
                if (tag === 'SCRIPT' || tag === 'STYLE' || tag === 'NOSCRIPT') return NodeFilter.FILTER_REJECT;
    } else {
                if (p.classList.contains('gr-search-hl')) return NodeFilter.FILTER_REJECT;
      /* Desktop: full bar */
                return NodeFilter.FILTER_ACCEPT;
      var nav = document.createElement( 'div' );
            }
      nav.style.cssText = 'display:flex;align-items:center;gap:12px;';
         }, false
      nav.innerHTML =
        );
        '<span>🔍 <strong>' + escHtml(query) + '</strong> — ' + count + ' match' + (count===1?'':'es') + '</span>' +
        '<button id="gr-hl-prev" style="background:rgba(255,255,255,0.2);border:none;color:#fff;padding:4px 10px;border-radius:4px;cursor:pointer;font-size:13px;min-height:32px;">↑ Prev</button>' +
         '<button id="gr-hl-next" style="background:rgba(255,255,255,0.2);border:none;color:#fff;padding:4px 10px;border-radius:4px;cursor:pointer;font-size:13px;min-height:32px;">↓ Next</button>';
      bar.appendChild( nav );
    }


    var dismiss = isMob
        var nodes = [];
      ? bar.querySelector( '#gr-hl-dismiss' )
        var node;
      : ( function() {
        while ((node = walker.nextNode())) nodes.push(node);
          var b = document.createElement( 'button' );
          b.textContent = '✕ Clear';
          b.id = 'gr-hl-dismiss';
          b.style.cssText = 'background:rgba(255,255,255,0.15);border:none;color:#fff;padding:4px 12px;border-radius:4px;cursor:pointer;font-size:13px;min-height:32px;';
          bar.appendChild( b );
          return b;
        }() );


    dismiss.onclick = function () {
        nodes.forEach(function (textNode) {
      clearHighlights();
            var val = textNode.nodeValue;
      bar.remove();
            if (!re.test(val)) return;
    };
            re.lastIndex = 0;


    document.body.appendChild( bar );
            var frag = document.createDocumentFragment();
            var last = 0;
            var m;
            while ((m = re.exec(val)) !== null) {
                if (m.index > last) {
                    frag.appendChild(document.createTextNode(val.slice(last, m.index)));
                }
                var span = document.createElement('span');
                span.className = 'gr-search-hl';
                span.textContent = m[0];
                frag.appendChild(span);
                last = m.index + m[0].length;
                count++;
            }
            if (last < val.length) {
                frag.appendChild(document.createTextNode(val.slice(last)));
            }
            textNode.parentNode.replaceChild(frag, textNode);
        });


    /* Prev / Next navigation */
        return count;
    var hlEls = Array.from( document.querySelectorAll( '.gr-search-hl' ) );
    var currentIdx = 0;
    function goTo( idx ) {
      hlEls.forEach( function(el) { el.classList.remove( 'gr-search-hl-current' ); } );
      currentIdx = ( idx + hlEls.length ) % hlEls.length;
      var el = hlEls[ currentIdx ];
      el.classList.add( 'gr-search-hl-current' );
      el.scrollIntoView({ behavior: 'smooth', block: 'center' });
     }
     }


     var nextBtn = document.getElementById( 'gr-hl-next' );
     function showDismissBar(query) {
    var prevBtn = document.getElementById( 'gr-hl-prev' );
        var existing = document.getElementById('gr-hl-bar');
    if ( nextBtn ) nextBtn.onclick = function() { goTo( currentIdx + 1 ); };
        if (existing) existing.remove();
    if ( prevBtn ) prevBtn.onclick = function() { goTo( currentIdx - 1 ); };
  }


  function clearHighlights() {
        var count = document.querySelectorAll('.gr-search-hl').length;
    document.querySelectorAll( '.gr-search-hl' ).forEach( function( span ) {
        if (!count) return;
      var parent = span.parentNode;
      while ( span.firstChild ) parent.insertBefore( span.firstChild, span );
      parent.removeChild( span );
    } );
  }


  function escHtml( s ) {
        var isMob = window.innerWidth < 768 || !!document.getElementById('mw-mf-viewport');
    return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
        var bar = document.createElement('div');
  }
        bar.id = 'gr-hl-bar';


  /* ── Inject CSS for highlights ── */
        if (isMob) {
  function injectHighlightCSS() {
            bar.className = 'gr-search-hl-mobile';
    if ( document.getElementById( 'gr-hl-css' ) ) return;
    var s = document.createElement( 'style' );
    s.id = 'gr-hl-css';
    s.textContent = [
      '.gr-search-hl{',
      '  background:#fff176;color:#1a1a1a;',
      '  border-radius:2px;padding:0 1px;',
      ' box-shadow:0 0 0 1px rgba(181,69,27,0.25);',
      '}',
      '.gr-search-hl-current{',
      '  background:#ffb300!important;',
      '  box-shadow:0 0 0 2px #b5451b!important;',
      '}',
      '@keyframes gr-hl-pulse{',
      '  0%{background:#ffb300;}',
      '  50%{background:#fff176;}',
      '  100%{background:#fff176;}',
      '}',
      '.gr-search-hl-pulse{animation:gr-hl-pulse 1.2s ease 2;}',
    ].join('');
    document.head.appendChild( s );
  }


  /* ── Boot ── */
            bar.innerHTML =
  injectHighlightCSS();
                '<button id="gr-hl-results" class="gr-search-bar-btn">' +
  if ( document.readyState === 'loading' ) {
                '<span class="gra-icon gra-icon-search" aria-hidden="true"></span>' +
    document.addEventListener( 'DOMContentLoaded', applyHighlight );
                '<span>' + count + ' match' + (count === 1 ? '' : 'es') + '</span></button>' +
  } else {
                '<button id="gr-hl-prev" class="gr-search-bar-btn">' +
    applyHighlight();
                '<span class="gra-icon gra-icon-prev" aria-hidden="true"></span>' +
  }
                '<span>Prev</span></button>' +
                '<button id="gr-hl-next" class="gr-search-bar-btn">' +
                '<span class="gra-icon gra-icon-next" aria-hidden="true"></span>' +
                '<span>Next</span></button>' +
                '<button id="gr-hl-dismiss" class="gr-search-bar-btn">' +
                '<span class="gra-icon gra-icon-dismiss" aria-hidden="true"></span>' +
                '<span>Close</span></button>';
        } else {
            bar.style.cssText = [
                'position:fixed', 'bottom:0', 'left:0', 'right:0', 'z-index:10200',
                'background:#b5451b', 'color:#fff', 'padding:10px 16px',
                'display:flex', 'align-items:center', 'justify-content:space-between',
                'font-family:system-ui,sans-serif', 'font-size:14px',
                'box-shadow:0 -2px 8px rgba(0,0,0,0.2)'
            ].join(';');


  /* ── Expose storeQueryForLink for readerToolbar to call ── */
            var nav = document.createElement('div');
  window.grStoreSearchHL = storeQueryForLink;
            nav.style.cssText = 'display:flex;align-items:center;gap:12px;';
            nav.innerHTML =
                '<span>🔍 <strong>' + escHtml(query) + '</strong> — ' + count + ' match' + (count === 1 ? '' : 'es') + '</span>' +
                '<button id="gr-hl-prev" style="background:rgba(255,255,255,0.2);border:none;color:#fff;padding:4px 10px;border-radius:4px;cursor:pointer;font-size:13px;min-height:32px;">↑ Prev</button>' +
                '<button id="gr-hl-next" style="background:rgba(255,255,255,0.2);border:none;color:#fff;padding:4px 10px;border-radius:4px;cursor:pointer;font-size:13px;min-height:32px;">↓ Next</button>' +
                '<button id="gr-hl-results" style="background:rgba(255,255,255,0.2);border:none;color:#fff;padding:4px 10px;border-radius:4px;cursor:pointer;font-size:13px;min-height:32px;">← Results</button>';
            bar.appendChild(nav);


}() );
            var db = document.createElement('button');
/* ═══════════════════════════════════════════════════════════════
            db.id = 'gr-hl-dismiss'; db.textContent = '✕ Close';
  Mobile addon — paste at bottom of MediaWiki:Common.js
            db.style.cssText = 'background:rgba(255,255,255,0.15);border:none;color:#fff;padding:4px 12px;border-radius:4px;cursor:pointer;font-size:13px;min-height:32px;';
  Only runs on Minerva (mobile) skin
            bar.appendChild(db);
  ═══════════════════════════════════════════════════════════════ */
        }
( function () {
  if ( !document.body.classList.contains( 'skin-minerva' ) ) return;


  /* ── 1. CSS injected into <head> — beats all other stylesheets ── */
        document.body.appendChild(bar);
  function injectCSS() {
    if ( document.getElementById( 'gr-mob-css' ) ) return;
    var s = document.createElement( 'style' );
    s.id = 'gr-mob-css';
    s.textContent =
      /* Body padding — readerToolbar sets this, we clear it */
      'body,#mw-mf-viewport,#mw-mf-page-center{padding-top:0!important;margin-top:0!important;}' +
      'html,body,#mw-mf-viewport,#mw-mf-page-center{overflow-x:hidden!important;max-width:100vw!important;}' +


      /* Header orange + sticky */
        var hlEls = Array.from(document.querySelectorAll('.gr-search-hl'));
      'header.header-container{background:#b5451b!important;position:sticky!important;top:0!important;z-index:300!important;}' +
        var current = 0;
      '.minerva-header{background:#b5451b!important;min-height:54px!important;}' +


      /* Header: keep only hamburger + branding, hide search */
        function goTo(idx) {
      '.minerva-header .search-toggle,.minerva-header .minerva-user-notifications{display:none!important;}' +
            hlEls.forEach(function (el) { el.classList.remove('gr-search-hl-current'); });
            current = ((idx % hlEls.length) + hlEls.length) % hlEls.length;
            hlEls[current].classList.add('gr-search-hl-current');
            hlEls[current].scrollIntoView({ behavior: 'smooth', block: 'center' });
        }


      /* Logo row: icon + title wrap cleanly */
         function dismiss() { clearHighlights(); bar.remove(); }
      '.branding-box a{display:flex!important;align-items:center!important;' +
         'text-decoration:none!important;max-width:calc(100vw - 80px)!important;}' +
      '.branding-box a::before{content:"";display:block;width:30px;height:30px;flex-shrink:0;' +
        'background:url("/favicon.png") center/contain no-repeat;' +
        'margin-right:8px;}' +
      '.branding-box a span{color:#fff!important;font-size:16px!important;font-weight:700!important;' +
        'font-family:system-ui,sans-serif!important;line-height:1.2!important;' +
        'flex:1 1 auto!important;min-width:0!important;}' +


      /* Header icons white */
        var nb = document.getElementById('gr-hl-next');
      '.minerva-header svg path,.minerva-header svg rect,.minerva-header svg circle{fill:#fff!important;}' +
        var pb = document.getElementById('gr-hl-prev');
      '.minerva-header label{color:#fff!important;}' +
        var rb = document.getElementById('gr-hl-results');
        var db2 = document.getElementById('gr-hl-dismiss');
        if (nb) nb.onclick = function () { goTo(current + 1); };
        if (pb) pb.onclick = function () { goTo(current - 1); };
        if (db2) db2.onclick = dismiss;
        if (rb) rb.onclick = function () {
            bar.remove(); clearHighlights();
            if (window.showSearchDialog) window.showSearchDialog(query);
        };
    }


      /* Hide Page/Discussion tabs + icon toolbar */
    function clearHighlights() {
      '.minerva-tabs,.mw-portlet-associated-pages,.page-actions-menu,' +
        document.querySelectorAll('.gr-search-hl').forEach(function (span) {
        '#page-secondary-actions,.last-modified-bar,.minerva-anon-talk-link{display:none!important;}' +
            var p = span.parentNode; if (!p) return;
            while (span.firstChild) p.insertBefore(span.firstChild, span);
            p.removeChild(span);
        });
    }


      /* Drawer: hide default items, show ours */
    function escHtml(s) {
      /* #mw-mf-page-left is kept — we replace its content in JS */ '' +
         return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
      '#gr-mob-menu-items{display:block!important;}' +
     }
 
      /* Drawer footer: hide About/Disclaimers */
      '.mw-footer.minerva-footer,.footer-places,.footer-info,' +
        '.minerva-footer-logo,#footer-places-about,' +
        '#footer-places-disclaimers,#footer-places-privacy{display:none!important;}' +
 
      /* ReaderToolbar below header */
      '#gr-static-bar{position:sticky!important;top:54px!important;z-index:200!important;}' +
 
      /* Sections expanded */
      '.mf-section-0,.mf-section-1,.mf-section-2,.mf-section-3,.mf-section-4,' +
        '.mf-section-5,.mf-section-6,.mf-section-7,.mf-section-8,.mf-section-9,' +
        '.mf-section-10{display:block!important;visibility:visible!important;}' +
      '.collapsible-block{display:block!important;}' +
      '.section-heading .indicator,.collapsible-heading .indicator{display:none!important;}' +
      '.section-heading,.collapsible-heading{pointer-events:none!important;}' +
 
      /* Home grid single column */
      '.gr-home-grid{flex-direction:column!important;flex-wrap:nowrap!important;' +
        'gap:12px!important;width:100%!important;}' +
      '.gr-home-card{width:100%!important;max-width:100%!important;' +
        'min-width:unset!important;box-sizing:border-box!important;flex:none!important;}' +
      '.gr-home-toggle{flex-wrap:wrap!important;}' +
 
      /* Content */
      '.mw-parser-output{font-size:18px!important;line-height:1.8!important;}' +
      '.mw-parser-output h2,.mw-parser-output h3{width:100%!important;}' +
      '.bhashyam-block{margin-left:8px!important;}' +
      '#footer,.mw-footer,.catlinks,#catlinks{display:none!important;}' +
 
      /* TOC overlay */
      '.gr-mob-toc-panel{position:fixed!important;top:0!important;left:0!important;' +
        'bottom:0!important;width:82vw!important;max-width:340px!important;' +
        'background:#fff!important;z-index:10400!important;' +
        'box-shadow:4px 0 28px rgba(0,0,0,0.22)!important;overflow-y:auto!important;' +
        'padding:0 0 40px!important;transform:translateX(-110%)!important;' +
        'transition:transform 0.26s cubic-bezier(0.4,0,0.2,1)!important;display:block!important;}' +
      '.gr-mob-toc-panel.open{transform:translateX(0)!important;}' +
      '.gr-mob-toc-backdrop{display:none!important;position:fixed!important;inset:0!important;' +
         'background:rgba(0,0,0,0.4)!important;z-index:10399!important;}' +
      '.gr-mob-toc-backdrop.open{display:block!important;}' +
      '.gr-mob-toc-header{position:sticky!important;top:0!important;background:#fff!important;' +
        'display:flex!important;align-items:center!important;justify-content:space-between!important;' +
        'padding:16px 16px 12px!important;border-bottom:1px solid #f0ebe6!important;z-index:1!important;}' +
      '.gr-mob-toc-title{font-size:13px!important;font-weight:700!important;text-transform:uppercase!important;' +
        'letter-spacing:0.08em!important;color:#b5451b!important;font-family:system-ui,sans-serif!important;}' +
      '.gr-mob-toc-close{background:none!important;border:none!important;' +
        'font-size:22px!important;color:#999!important;cursor:pointer!important;padding:4px 8px!important;}' +
      '.gr-mob-toc-body{padding:12px 16px!important;}' +
      '.gr-mob-toc-body a{display:block!important;font-size:16px!important;line-height:1.6!important;' +
        'color:#2c1810!important;text-decoration:none!important;padding:8px 0!important;' +
        'border-bottom:1px solid #f5f0ed!important;}';
    document.head.appendChild( s );
  }
 
  /* ── 2. Expand hidden sections ── */
  function expandSections() {
    document.querySelectorAll( '[class*="mf-section-"], .collapsible-block' )
      .forEach( function ( el ) {
        el.removeAttribute( 'hidden' );
        el.style.setProperty( 'display', 'block', 'important' );
        el.style.setProperty( 'visibility', 'visible', 'important' );
        el.removeAttribute( 'aria-hidden' );
      } );
    document.querySelectorAll( '.section-heading, .collapsible-heading' )
      .forEach( function ( el ) {
        el.setAttribute( 'aria-expanded', 'true' );
        el.style.setProperty( 'pointer-events', 'none', 'important' );
      } );
  }
 
  /* Persistent observer — fight MF re-collapsing */
  function watchSections() {
    var t = null;
    var obs = new MutationObserver( function ( ms ) {
      if ( ms.some( function(m){ return m.attributeName === 'hidden'; } ) ) {
        clearTimeout(t); t = setTimeout( expandSections, 30 );
      }
    } );
    var root = document.querySelector( '#mw-content-text' ) || document.body;
    obs.observe( root, { subtree:true, attributes:true, attributeFilter:['hidden','aria-hidden'] } );
  }
 
  /* ── 3. Body padding observer ── */
  function watchBodyPadding() {
    new MutationObserver( function () {
      if ( document.body.style.paddingTop && document.body.style.paddingTop !== '0px' ) {
        document.body.style.paddingTop = '';
      }
    } ).observe( document.body, { attributes:true, attributeFilter:['style'] } );
  }
 
  /* ── 4. Inject custom links into drawer ── */
  function injectMenuLinks() {
    /* Already injected */
    if ( document.getElementById( 'gr-mob-menu-items' ) ) return;
 
    /* The drawer container is .navigation-drawer (the <nav> element)
      Our links go AFTER the #mw-mf-page-left div (which we hide via CSS) */
    var navDrawer = document.querySelector( '.navigation-drawer' );
    if ( !navDrawer ) return;
 
    var wrap = document.createElement( 'div' );
     wrap.id = 'gr-mob-menu-items';
    wrap.style.cssText = 'width:100%;background:#fff;margin-top:8px;';
 
    var itemStyle = 'display:flex;align-items:center;gap:14px;padding:15px 20px;' +
      'font-size:16px;color:#2c1810;text-decoration:none;' +
      'font-family:system-ui,sans-serif;border-bottom:1px solid #f0ebe6;background:#fff;';


     function makeItem( href, emoji, label ) {
     function injectHighlightCSS() {
      var a = document.createElement( 'a' );
        if (document.getElementById('gr-hl-css')) return;
      a.href = href;
        var s = document.createElement('style');
      a.style.cssText = itemStyle;
        s.id = 'gr-hl-css';
      a.innerHTML =
        s.textContent = [
        '<span>' + label + '</span>';
            '.gr-search-hl{background:#fff176;color:#1a1a1a;border-radius:2px;padding:0 1px;box-shadow:0 0 0 1px rgba(181,69,27,0.25);}',
      return a;
            '.gr-search-hl-current{background:#ffb300!important;box-shadow:0 0 0 2px #b5451b!important;}',
            '@keyframes gr-hl-pulse{0%{background:#ffb300;}50%{background:#fff176;}100%{background:#fff176;}}',
            '.gr-search-hl-pulse{animation:gr-hl-pulse 1.2s ease 2;}',
        ].join('');
        document.head.appendChild(s);
     }
     }


     wrap.appendChild( makeItem( '/Main_Page', '', 'Home' ) );
     injectHighlightCSS();
    wrap.appendChild( makeItem( '/My_wiki:Help', '', 'Help' ) );
    wrap.appendChild( makeItem( '/My_wiki:About', '', 'About' ) );


    var userName = window.mw ? mw.config.get( 'wgUserName' ) : null;
     if (document.readyState === 'loading') {
     if ( userName ) {
        document.addEventListener('DOMContentLoaded', applyHighlight);
      var la = document.querySelector( 'a[href*="action=logout"]' );
      wrap.appendChild( makeItem(
        la ? la.href : '/index.php?title=Special:UserLogout', '', 'Log out'
      ) );
     } else {
     } else {
      wrap.appendChild( makeItem( '/index.php?title=Special:UserLogin', '', 'Log in' ) );
        applyHighlight();
     }
     }


     /* Replace contents of #mw-mf-page-left — it's inside the
     if (window.mw) {
      toggle-list mechanism so it only shows when drawer is open */
        mw.hook('wikipage.content').add(function () {
    var pageLeft = document.getElementById( 'mw-mf-page-left' );
            setTimeout(applyHighlight, 100);
    if ( pageLeft ) {
        });
      /* Clear default items and insert ours */
      while ( pageLeft.firstChild ) pageLeft.removeChild( pageLeft.firstChild );
      pageLeft.style.removeProperty( 'display' ); /* un-hide it */
      pageLeft.appendChild( wrap );
    } else {
      /* Fallback */
      navDrawer.appendChild( wrap );
     }
     }


     /* Hide footer portlets */
     window.grStoreSearchHL = storeQueryForLink;
    document.querySelectorAll(
      '.mw-footer.minerva-footer,.footer-places,.footer-info,' +
      '.minerva-footer-logo,#footer-places-about,' +
      '#footer-places-disclaimers,#footer-places-privacy'
    ).forEach( function(el) { el.style.setProperty('display','none','important'); } );
  }


  /* ── 5. Mobile TOC overlay ── */
}());
  var _tocDone = false;
  function initToc() {
    if ( _tocDone ) return;
    var tocList = document.querySelector( '.vector-toc-contents, .vector-toc .vector-toc-list' );
    if ( !tocList ) return;
    if ( !tocList.querySelector( 'li' ) ) return;
    _tocDone = true;


    var bd = document.createElement( 'div' );
/* ═══════════════════════════════════════════════════════════════
    bd.className = 'gr-mob-toc-backdrop';
  Mobile addon — only runs on Minerva (mobile) skin
    document.body.appendChild( bd );
  ═══════════════════════════════════════════════════════════════ */
 
(function () {
     var panel = document.createElement( 'div' );
     if (!document.body.classList.contains('skin-minerva')) return;
    panel.className = 'gr-mob-toc-panel';
     function injectMenuLinks() {
 
        if (document.getElementById('gr-mob-menu-items')) return;
    var hdr = document.createElement( 'div' );
        var navDrawer = document.querySelector('.navigation-drawer');
     hdr.className = 'gr-mob-toc-header';
        if (!navDrawer) return;
    var ttl = document.createElement( 'div' );
        var wrap = document.createElement('div'); wrap.id = 'gr-mob-menu-items'; wrap.style.cssText = 'width:100%;background:#fff;margin-top:8px;';
    ttl.className = 'gr-mob-toc-title';
        var itemStyle = 'display:flex;align-items:center;gap:14px;padding:15px 20px;font-size:16px;color:#2c1810;text-decoration:none;font-family:system-ui,sans-serif;border-bottom:1px solid #f0ebe6;background:#fff;';
    ttl.textContent = 'विषयसूची';
        function makeItem(href, label) { var a = document.createElement('a'); a.href = href; a.style.cssText = itemStyle; a.innerHTML = '<span>' + label + '</span>'; return a; }
    var cls = document.createElement( 'button' );
        wrap.appendChild(makeItem('/Main_Page', 'Home'));
    cls.className = 'gr-mob-toc-close';
        wrap.appendChild(makeItem('/My_wiki:Help', 'Help'));
    cls.textContent = '✕';
        wrap.appendChild(makeItem('/My_wiki:About', 'About'));
    hdr.appendChild( ttl ); hdr.appendChild( cls );
         var userName = window.mw ? mw.config.get('wgUserName') : null;
    panel.appendChild( hdr );
        if (userName) {
 
            wrap.appendChild(makeItem((window.mw && mw.util && mw.util.getUrl) ? mw.util.getUrl('Special:Profile') : '/Special:Profile', 'Profile'));
    var body = document.createElement( 'div' );
            var la = document.querySelector('a[href*="action=logout"]');
    body.className = 'gr-mob-toc-body';
            wrap.appendChild(makeItem(la ? la.href : '/index.php?title=Special:UserLogout', 'Log out'));
    body.appendChild( tocList.cloneNode( true ) );
    panel.appendChild( body );
    document.body.appendChild( panel );
 
    var btn = document.createElement( 'button' );
    btn.id = 'gr-mob-toc-btn';
    btn.innerHTML = '☰ &nbsp;Contents';
    btn.style.cssText = 'position:fixed;bottom:148px;left:16px;z-index:9100;' +
      'background:#fff;border:1.5px solid #b5451b;border-radius:24px;' +
      'padding:10px 16px;font-size:15px;font-family:system-ui,sans-serif;' +
      'color:#b5451b;font-weight:600;box-shadow:0 3px 14px rgba(0,0,0,0.15);cursor:pointer;';
    document.body.appendChild( btn );
 
    function open() { panel.classList.add('open'); bd.classList.add('open'); document.body.style.overflow='hidden'; }
    function close() { panel.classList.remove('open'); bd.classList.remove('open'); document.body.style.overflow=''; }
 
    btn.onclick = open; cls.onclick = close; bd.onclick = close;
    body.querySelectorAll('a').forEach(function(a){ a.onclick = close; });
  }
 
  /* ── Boot ── */
  injectCSS();
  watchBodyPadding();
 
  function boot() {
    expandSections();
    watchSections();
    injectMenuLinks();
    [100, 400, 900, 1800].forEach(function(ms){ setTimeout(expandSections, ms); });
    setTimeout(initToc, 700);
  }
 
  if ( document.readyState === 'loading' ) {
    document.addEventListener( 'DOMContentLoaded', boot );
  } else {
    boot();
  }
 
  if ( window.mw ) {
    mw.hook( 'wikipage.content' ).add(function() {
      setTimeout(function(){ expandSections(); injectMenuLinks(); initToc(); }, 300);
    });
  }
 
}() );
/**
* grantha-mobile-fixes.js
* Add this to MediaWiki:Common.js (or load as a separate gadget)
*
* Fixes:
*  1. Patches Minerva's ToggleList to guard against null parentNode
*    (prevents "Cannot read properties of null" crash on Main_Page)
*  2. Keeps #gr-home-toggle visible below #gr-static-bar on mobile
*  3. Wires the grantha/author tab toggle if it hasn't been wired yet
*/
 
( function () {
  'use strict';
 
  /* ══════════════════════════════════════════════════════════════
  * 1. TOGGLELIST NULL GUARD
  * Minerva's initMobile.js runs ToggleList.init() which calls
  * el.parentNode on every .collapsible-block it finds.
  * On Main_Page, some of these are dynamically injected and may
  * not yet be in the live DOM when ToggleList runs.
  * We patch by removing any element that has no parentNode
  * before ToggleList.init() fires.
  * ══════════════════════════════════════════════════════════════ */
  mw.hook( 'wikipage.content' ).add( function () {
    /* Wait one tick so Minerva's own DOMReady handlers run first */
    setTimeout( function () {
      var blocks = document.querySelectorAll( '.collapsible-block, .toggle-list' );
      Array.prototype.forEach.call( blocks, function ( el ) {
        /* If the element has no parentNode it's detached — remove it
          before ToggleList tries to call parentNode on it          */
        if ( !el.parentNode ) {
          try { el.remove(); } catch(e) {}
         }
      } );
    }, 0 );
  } );
 
  /* ══════════════════════════════════════════════════════════════
  * 2. MAIN PAGE: keep #gr-home-toggle below the reader bar
  * ══════════════════════════════════════════════════════════════ */
 
  if ( mw.config.get( 'wgPageName' ) !== 'Main_Page' ) return;
 
  mw.loader.using( 'mediawiki.util' ).done( function () {
    $( function () {
      applyHomeToggleOffset();
 
      /* Re-apply when bar height might change (orientation change, etc.) */
      window.addEventListener( 'resize', applyHomeToggleOffset, { passive: true } );
 
      /* Re-apply after a short delay in case the bar hasn't rendered yet */
      setTimeout( applyHomeToggleOffset, 300 );
      setTimeout( applyHomeToggleOffset, 800 );
    } );
  } );
 
  function applyHomeToggleOffset() {
    var bar = document.getElementById( 'gr-static-bar' );
    if ( !bar ) return;
 
    var barRect = bar.getBoundingClientRect();
    /* barRect.bottom = distance from viewport top to bar bottom.
      On load (before any scroll) this equals the bar's actual top offset
      plus its height. After scrolling (Minerva header gone) it's just
      the bar height since bar.top → 0.                                 */
    var barBottom = Math.round( barRect.bottom );
 
    /* #gr-home is the outermost container */
    var homeEl = document.getElementById( 'gr-home' );
    /* #gr-home-toggle is the tab switcher row */
    var toggleEl = document.getElementById( 'gr-home-toggle' );
    /* Also target the mw-parser-output first child as a fallback */
    var firstChild = document.querySelector(
      '#mw-content-text .mw-parser-output > .gr-home, ' +
      '#mw-content-text .mw-parser-output > *:first-child'
    );
 
    /* scroll-margin-top: so that if someone scrolls-to-top the toggle
      is visible below the bar (not behind it)                        */
    [ homeEl, toggleEl, firstChild ].forEach( function ( el ) {
      if ( el ) el.style.scrollMarginTop = ( barBottom + 4 ) + 'px';
    } );
 
    /* The body already has padding-top set by readerToolbar.js.
      But on Main_Page the toggle might STILL be hidden if the
      Minerva header is taller. Force the content area's top
      padding to be at least barBottom.                                */
    var contentText = document.getElementById( 'mw-content-text' );
    if ( contentText ) {
      /* Only add extra padding if we're on mobile */
      var isMob = window.innerWidth < 768 || !!document.getElementById( 'mw-mf-viewport' );
      if ( isMob ) {
        /* Check if the toggle is actually obscured */
        if ( toggleEl ) {
          var toggleRect = toggleEl.getBoundingClientRect();
          /* If toggle top < barBottom, the bar is covering it */
          if ( toggleRect.top < barBottom ) {
            var currentPT = parseInt( window.getComputedStyle( document.body ).paddingTop, 10 ) || 0;
            var needed    = currentPT + ( barBottom - toggleRect.top ) + 4;
            document.body.style.paddingTop = needed + 'px';
          }
         }
         }
      }
        else wrap.appendChild(makeItem('/index.php?title=Special:UserLogin', 'Log in'));
        var pageLeft = document.getElementById('mw-mf-page-left');
        if (pageLeft) { while (pageLeft.firstChild) pageLeft.removeChild(pageLeft.firstChild); pageLeft.style.removeProperty('display'); pageLeft.appendChild(wrap); }
        else navDrawer.appendChild(wrap);
     }
     }
  }
    function injectMoolaUllekhaLinks() {
 
        if (document.getElementById('gr-mob-doc-nav')) return;
  /* ══════════════════════════════════════════════════════════════
        var pageName = (window.mw && mw.config && mw.config.get('wgPageName')) || '';
  * 3. WIRE THE GRANTHA / AUTHOR TAB TOGGLE
        if (pageName === 'Main_Page' || !pageName) return;
  * In case the toggle script hasn't loaded yet or failed
        function wikiUrl(slug) { if (window.mw && mw.util && mw.util.getUrl) return mw.util.getUrl(slug); return ((window.mw && mw.config.get('wgArticlePath')) || '/wiki/$1').replace('$1', encodeURIComponent(slug).replace(/%2F/g, '/')); }
  * ══════════════════════════════════════════════════════════════ */
        var teekaPage = document.querySelector('.gr-teeka-page');
  $( function () {
        var primarySlug = teekaPage ? (teekaPage.getAttribute('data-primary') || pageName.split('/')[0]) : pageName.split('/')[0];
    var $toggle  = $( '#gr-home-toggle' );
        var docTitleEl = document.querySelector('.gr-doc-title');
    var $viewG    = $( '#gr-view-grantha' );
        var hasMoolaPage = docTitleEl && docTitleEl.getAttribute('data-has-moola') === '1';
    var $viewA    = $( '#gr-view-author' );
        var hasUllekhaPage = docTitleEl && docTitleEl.getAttribute('data-has-ullekha') === '1';
    var $btnG    = $( '#gr-toggle-grantha' );
        var showMoolam = !!teekaPage || hasMoolaPage, showUllekha = hasUllekhaPage || !!teekaPage;
    var $btnA    = $( '#gr-toggle-author' );
        if (!showMoolam && !showUllekha) return;
 
        var nav = document.createElement('div'); nav.id = 'gr-mob-doc-nav';
    if ( !$toggle.length || !$viewG.length || !$viewA.length ) return;
        nav.style.cssText = 'display:flex;gap:10px;padding:10px 16px 8px;background:#fdf8f5;border-bottom:1px solid #f0e0d6;font-family:system-ui,sans-serif;';
    /* Only wire if not already wired */
        function makeLink(href, label) { var a = document.createElement('a'); a.href = href; a.textContent = label; a.style.cssText = 'display:inline-flex;align-items:center;padding:5px 16px;border-radius:20px;background:#fff;border:1.5px solid #e8cfc4;color:#b5451b;font-size:14px;font-weight:600;text-decoration:none;'; return a; }
    if ( $toggle.data( 'gr-wired' ) ) return;
         if (teekaPage) nav.appendChild(makeLink(wikiUrl(primarySlug), 'मूल'));
    $toggle.data( 'gr-wired', true );
         else if (hasMoolaPage) nav.appendChild(makeLink(wikiUrl(primarySlug + '/Moola'), 'मूलम्'));
 
         if (showUllekha) nav.appendChild(makeLink(wikiUrl(primarySlug + '/Ullekha'), 'उल्लेख'));
    function showView( which ) {
         var h1 = document.getElementById('firstHeading') || document.querySelector('.page-heading, h1.firstHeading, .mw-first-heading');
      if ( which === 'grantha' ) {
         if (h1 && h1.parentNode) h1.parentNode.insertBefore(nav, h1.nextSibling);
         $viewG.show(); $viewA.hide();
         else { var ct = document.getElementById('mw-content-text'); if (ct) ct.insertBefore(nav, ct.firstChild); }
         $btnG.addClass( 'gr-toggle-active' );
         $btnA.removeClass( 'gr-toggle-active' );
      } else {
         $viewA.show(); $viewG.hide();
         $btnA.addClass( 'gr-toggle-active' );
         $btnG.removeClass( 'gr-toggle-active' );
      }
      try { localStorage.setItem( 'grantha_home_tab', which ); } catch(e){}
     }
     }
    function boot() { injectMenuLinks(); injectMoolaUllekhaLinks();}
    if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
    else boot();
    if (window.mw) mw.hook('wikipage.content');
}());


     $btnG.on( 'click keydown', function(e){
(function () {
      if ( e.type === 'keydown' && e.key !== 'Enter' && e.key !== ' ' ) return;
    'use strict';
      showView( 'grantha' );
     mw.hook('wikipage.content').add(function () {
        setTimeout(function () {
            var blocks = document.querySelectorAll('.collapsible-block, .toggle-list');
            Array.prototype.forEach.call(blocks, function (el) { if (!el.parentNode) { try { el.remove(); } catch (e) { } } });
        }, 0);
     });
     });
     $btnA.on( 'click keydown', function(e){
     if (mw.config.get('wgPageName') !== 'Main_Page') return;
      if ( e.type === 'keydown' && e.key !== 'Enter' && e.key !== ' ' ) return;
    mw.loader.using('mediawiki.util').done(function () {
      showView( 'author' );
        $(function () { applyHomeToggleOffset(); window.addEventListener('resize', applyHomeToggleOffset, { passive: true }); setTimeout(applyHomeToggleOffset, 300); setTimeout(applyHomeToggleOffset, 800); });
     });
     });
 
    function applyHomeToggleOffset() {
    /* Restore last-used tab */
        var bar = document.getElementById('gr-static-bar'); if (!bar) return;
     try {
        var barBottom = Math.round(bar.getBoundingClientRect().bottom);
      var saved = localStorage.getItem( 'grantha_home_tab' );
        [document.getElementById('gr-home'), document.getElementById('gr-home-toggle'), document.querySelector('#mw-content-text .mw-parser-output > .gr-home, #mw-content-text .mw-parser-output > *:first-child')].forEach(function (el) { if (el) el.style.scrollMarginTop = (barBottom + 4) + 'px'; });
      if ( saved === 'author' ) showView( 'author' );
        var isMob = window.innerWidth < 768 || !!document.getElementById('mw-mf-viewport');
      else showView( 'grantha' );
        if (isMob) { var toggleEl = document.getElementById('gr-home-toggle'); if (toggleEl) { var tr = toggleEl.getBoundingClientRect(); if (tr.top < barBottom) { var cp = parseInt(window.getComputedStyle(document.body).paddingTop, 10) || 0; document.body.style.paddingTop = (cp + (barBottom - tr.top) + 4) + 'px'; } } }
    } catch(e) { showView( 'grantha' ); }
    }
  } );
     $(function () {
 
        var $toggle = $('#gr-home-toggle'), $viewG = $('#gr-view-grantha'), $viewA = $('#gr-view-author'), $btnG = $('#gr-toggle-grantha'), $btnA = $('#gr-toggle-author');
}() );
        if (!$toggle.length || !$viewG.length || !$viewA.length) return; if ($toggle.data('gr-wired')) return; $toggle.data('gr-wired', true);
        function showView(which) { if (which === 'grantha') { $viewG.show(); $viewA.hide(); $btnG.addClass('gr-toggle-active'); $btnA.removeClass('gr-toggle-active'); } else { $viewA.show(); $viewG.hide(); $btnA.addClass('gr-toggle-active'); $btnG.removeClass('gr-toggle-active'); } try { localStorage.setItem('grantha_home_tab', which); } catch (e) { } }
        $btnG.on('click keydown', function (e) { if (e.type === 'keydown' && e.key !== 'Enter' && e.key !== ' ') return; showView('grantha'); });
        $btnA.on('click keydown', function (e) { if (e.type === 'keydown' && e.key !== 'Enter' && e.key !== ' ') return; showView('author'); });
        try { var saved = localStorage.getItem('grantha_home_tab'); if (saved === 'author') showView('author'); else showView('grantha'); } catch (e) { showView('grantha'); }
    });
}());
// ── Replace MediaWiki user links with a single username dropdown (Profile + Logout) ──
(function () {
    function wikiHref(title) {
        if (window.mw && mw.util && mw.util.getUrl) return mw.util.getUrl(title);
        var ap = (window.mw && mw.config && mw.config.get('wgArticlePath')) || '/wiki/$1';
        return ap.replace('$1', title);
    }
}());