/* docs/javascripts/extra.js */

document.addEventListener("DOMContentLoaded", function() {
  const tocLinks = document.querySelectorAll(".md-nav--secondary .md-nav__link");

  tocLinks.forEach(function(link) {
    link.addEventListener("click", function(event) {
      tocLinks.forEach(function(el) {
        el.classList.remove("md-nav__link--active");
      });
      this.classList.add("md-nav__link--active");
    });
  });

  initSidebarSearchMode();
  initSearchResultHighlight();
  applySidebarSearchStyleOverrides();
});

function initSidebarSearchMode() {
  if (window.__sidebarSearchDebug == null) {
    window.__sidebarSearchDebug = false;
  }
  debugLog("initSidebarSearchMode: start");
  const sidebarInner = document.querySelector(".md-sidebar--primary .md-sidebar__inner");
  const nav = sidebarInner ? sidebarInner.querySelector(".md-nav--primary") : null;
  debugLog("initSidebarSearchMode: sidebarInner", !!sidebarInner, "nav", !!nav);
  if (!sidebarInner || !nav) return;
  if (sidebarInner.querySelector(".md-sidebar__mode-toggle")) {
    debugLog("initSidebarSearchMode: toggle already exists");
    return;
  }

  const MODE_KEY = "md-sidebar-mode";
  const QUERY_KEY = "md-search-last-query";
  const RESULTS_KEY = "md-search-last-results";
  const STATE_KEY = "md-search-last-state";
  const HAS_RUN_KEY = "md-search-has-run";
  const CLICKED_KEY = "md-search-last-clicked";

  const config = readMdConfig();
  const baseUrl = resolveBaseUrl(config);
  const resetImgUrl = new URL("images/Reset.png", baseUrl).toString();

  const toggle = document.createElement("div");
  toggle.className = "md-sidebar__mode-toggle";
  toggle.innerHTML =
    '<button type="button" class="md-sidebar__mode-btn" data-mode="nav">목차</button>' +
    '<button type="button" class="md-sidebar__mode-btn" data-mode="search">검색결과</button>' +
    '<button type="button" class="md-sidebar__reset-btn" title="검색 초기화"><img src="' + resetImgUrl + '" alt="초기화" style="width:14px;height:14px;display:block;"></button>';

  const searchPanel = document.createElement("div");
  searchPanel.className = "md-sidebar__panel md-sidebar__panel--search";
  searchPanel.innerHTML =
    '<div class="md-sidebar__panel-header">검색 결과</div>' +
    '<div class="md-sidebar__panel-empty">검색어를 입력하면 검색 결과가 표시됩니다.</div>' +
    '<div class="md-sidebar__panel-results"></div>';

  nav.classList.add("md-sidebar__panel", "md-sidebar__panel--nav");
  sidebarInner.prepend(searchPanel);
  sidebarInner.prepend(toggle);

  const buttons = Array.prototype.slice.call(toggle.querySelectorAll(".md-sidebar__mode-btn"));
  const resetBtn = toggle.querySelector(".md-sidebar__reset-btn");
  const emptyEl = searchPanel.querySelector(".md-sidebar__panel-empty");
  const resultsEl = searchPanel.querySelector(".md-sidebar__panel-results");

  function setMode(mode) {
    const isSearch = mode === "search";
    nav.classList.toggle("is-hidden", isSearch);
    searchPanel.classList.toggle("is-active", isSearch);
    buttons.forEach(function(btn) {
      btn.classList.toggle("is-active", btn.getAttribute("data-mode") === mode);
    });
    sessionStorage.setItem(MODE_KEY, mode);
  }

  buttons.forEach(function(btn) {
    btn.addEventListener("click", function() {
      setMode(this.getAttribute("data-mode"));
    });
  });

  resetBtn.addEventListener("click", function() {
    // 1. Clear session storage
    sessionStorage.removeItem(QUERY_KEY);
    sessionStorage.removeItem(RESULTS_KEY);
    sessionStorage.removeItem(STATE_KEY);
    sessionStorage.removeItem(HAS_RUN_KEY);
    sessionStorage.removeItem(CLICKED_KEY);

    // 2. Clear UI
    resultsEl.innerHTML = "";
    emptyEl.style.display = "block";
    emptyEl.textContent = "검색어를 입력하면 검색 결과가 표시됩니다.";
    
    // 3. Clear Search Input (if possible)
    const inputs = document.querySelectorAll(".md-search__input, input[name='query']");
    inputs.forEach(function(input) {
      input.value = "";
    });

    // 4. Reset highlighting in main content (optional but good)
    const highlights = document.querySelectorAll(".md-search-target-highlight");
    highlights.forEach(function(el) {
      const parent = el.parentNode;
      if (parent) {
        parent.replaceChild(document.createTextNode(el.textContent), el);
        parent.normalize(); // Merge adjacent text nodes
      }
    });
  });

  const storedMode = sessionStorage.getItem(MODE_KEY) || "nav";
  setMode(storedMode);

  const storedResults = sessionStorage.getItem(RESULTS_KEY);
  const storedState = sessionStorage.getItem(STATE_KEY);
  const hasRun = sessionStorage.getItem(HAS_RUN_KEY) === "1";

  if (storedResults) {
    const cleanedResults = stripTeaserFromHtml(storedResults);
    resultsEl.innerHTML = cleanedResults;
    emptyEl.style.display = "none";
    sessionStorage.setItem(RESULTS_KEY, cleanedResults);
    highlightClickedResult(resultsEl, CLICKED_KEY);
  } else if (hasRun && storedState === "empty") {
    emptyEl.textContent = "寃??寃곌낵媛 ?놁뒿?덈떎";
    emptyEl.style.display = "block";
  }

  setupSearchSync(resultsEl, emptyEl, {
    QUERY_KEY: QUERY_KEY,
    RESULTS_KEY: RESULTS_KEY,
    STATE_KEY: STATE_KEY,
    HAS_RUN_KEY: HAS_RUN_KEY,
    CLICKED_KEY: CLICKED_KEY
  });
}

function setupSearchSync(resultsEl, emptyEl, keys) {
  const engine = createSidebarSearchEngine(resultsEl, emptyEl, keys);
  if (!engine) {
    debugLog("setupSearchSync: engine not created");
    return;
  }

  function handleQuery(query, source) {
    const trimmed = query.trim();
    debugLog("handleQuery:", { source: source || "unknown", query: query, trimmed: trimmed });
    if (trimmed.length === 0) return;
    sessionStorage.setItem(keys.QUERY_KEY, trimmed);
    sessionStorage.setItem(keys.HAS_RUN_KEY, "1");
    engine.search(trimmed);
  }

  document.addEventListener("input", function(event) {
    const query = extractSearchQuery(event);
    if (query !== null) {
      handleQuery(query, "input");
    }
  }, true);

  document.addEventListener("compositionend", function(event) {
    const query = extractSearchQuery(event);
    if (query !== null) {
      handleQuery(query, "compositionend");
    }
  }, true);

  if (!window.__sidebarSearchPatched) {
    window.__sidebarSearchPatched = true;
    const originalPostMessage = Worker.prototype.postMessage;
    Worker.prototype.postMessage = function(message, transfer) {
      try {
        if (message && message.type === 2 && !message.__sidebarSearch) {
          debugLog("Worker.postMessage intercepted:", message);
          storeSearchEnvelope(message.data);
          const query = extractQueryFromWorkerMessage(message.data);
          if (query) {
            handleQuery(query, "worker");
          } else {
            debugLog("Worker message had no query string:", message.data);
          }
        }
      } catch (err) {
        // ignore
      }
      return originalPostMessage.call(this, message, transfer);
    };
  }

  const savedQuery = sessionStorage.getItem(keys.QUERY_KEY);
  if (savedQuery) {
    handleQuery(savedQuery, "restore");
  }
}

function createSidebarSearchEngine(resultsEl, emptyEl, keys) {
  const config = readMdConfig();
  const baseUrl = resolveBaseUrl(config);
  const siteRoot = baseUrl;
  const searchJsonUrl = new URL("search.json", baseUrl);
  const workerUrl = resolveWorkerUrl(config, baseUrl);
  debugLog("createSidebarSearchEngine:", {
    config: config,
    baseUrl: baseUrl ? baseUrl.toString() : null,
    searchJsonUrl: searchJsonUrl.toString(),
    workerUrl: workerUrl.toString()
  });

  let worker = null;
  let ready = false;
  let queuedQuery = null;
  let searchItems = [];
  let currentQuery = "";
  let collectingAll = false;
  let accumulatedItems = [];
  let accumulatedTotal = 0;
  let accumulatedIds = null;

  if (keys && keys.CLICKED_KEY && !resultsEl.__clickedHandlerAttached) {
    resultsEl.addEventListener("click", function(event) {
      const link = event.target && event.target.closest
        ? event.target.closest("a.md-search-result__link")
        : null;
      if (!link) return;
      try { sessionStorage.setItem(keys.CLICKED_KEY, link.href); } catch (err) { /* ignore */ }
      highlightClickedResult(resultsEl, keys.CLICKED_KEY);
    }, true);
    resultsEl.__clickedHandlerAttached = true;
  }


  function stripBreadcrumbSpan(value) {
    if (!value) return "";
    let text = String(value);
    // Remove breadcrumb spans like: <span>Home &gt; ...</span>
    text = text.replace(/<span[^>]*>\s*Home\s*&gt;[\s\S]*?<\/span>/gi, "");
    // Remove plain breadcrumb tails like: "... Home &gt; ..."
    text = text.replace(/\s*Home\s*&gt;[\s\S]*$/i, "");
    text = text.replace(/\s*Home\s*>\s*[\s\S]*$/i, "");
    return text.trim();
  }

  function sanitizeSearchData(data) {
    if (!data || !Array.isArray(data.items)) return data;
    for (let i = 0; i < data.items.length; i += 1) {
      const item = data.items[i];
      if (!item) continue;
      if (item.title) item.title = stripBreadcrumbSpan(item.title);
      if (item.text) item.text = stripBreadcrumbSpan(item.text);
    }
    return data;
  }

  function appendSearchQueryParam(href, query) {
    if (!href || !query) return href;
    try {
      const url = new URL(href, window.location.href);
      url.searchParams.set("q", query);
      return url.toString();
    } catch (err) {
      const sep = href.indexOf("?") === -1 ? "?" : "&";
      return href + sep + "q=" + encodeURIComponent(query);
    }
  }


  function renderResults(result) {
    const items = result && result.items ? result.items : [];
    const total = typeof result.total === "number" ? result.total : items.length;
    debugLog("renderResults:", { items: items.length, total: total });

    if (items.length === 0) {
      emptyEl.textContent = "寃??寃곌낵媛 ?놁뒿?덈떎";
      emptyEl.style.display = "block";
      resultsEl.innerHTML = "";
      sessionStorage.setItem(keys.STATE_KEY, "empty");
      sessionStorage.setItem(keys.RESULTS_KEY, "");
      return;
    }

    emptyEl.style.display = "none";
    sessionStorage.setItem(keys.STATE_KEY, "results");

    let html = '<div class="md-search-result">';
    html += '<div class="md-search-result__meta">' + total + ' results</div>';
    html += '<ol class="md-search-result__list">';

    for (let i = 0; i < items.length; i += 1) {
      const hit = items[i];
      const doc = searchItems[hit.id];
      if (!doc) continue;

      const rawTitle = doc.title || (doc.path && doc.path.length ? doc.path[doc.path.length - 1] : doc.location);
      const title = htmlToText(rawTitle);
      const text = sanitizeSearchText(doc.text || "");
      const snippet = text.length > 140 ? text.slice(0, 140) + "..." : text;
      let link = new URL(doc.location, siteRoot).toString();
      link = appendSearchQueryParam(link, currentQuery);

      html += '<li class="md-search-result__item">';
      html += '<a class="md-search-result__link" href="' + link + '">';
      html += '<div class="md-search-result__title">' + escapeHtml(title) + '</div>';
      html += '</a></li>';
    }

    html += "</ol></div>";
    resultsEl.innerHTML = html;
    highlightClickedResult(resultsEl, keys.CLICKED_KEY);

    sessionStorage.setItem(keys.RESULTS_KEY, html);
  }

  function createWorkerSafe(url) {
    if (location.protocol === "file:") {
      return new Worker(URL.createObjectURL(new Blob([`"use strict";(()=>{var vt=Object.create;var K=Object.defineProperty,wt=Object.defineProperties,bt=Object.getOwnPropertyDescriptor,Tt=Object.getOwnPropertyDescriptors,Mt=Object.getOwnPropertyNames,W=Object.getOwnPropertySymbols,kt=Object.getPrototypeOf,Y=Object.prototype.hasOwnProperty,Et=Object.prototype.propertyIsEnumerable;var B=(t,e,n)=>e in t?K(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,R=(t,e)=>{for(var n in e||(e={}))Y.call(e,n)&&B(t,n,e[n]);if(W)for(var n of W(e))Et.call(e,n)&&B(t,n,e[n]);return t},Q=(t,e)=>wt(t,Tt(e));var Ft=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Rt=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let l of Mt(e))!Y.call(t,l)&&l!==n&&K(t,l,{get:()=>e[l],enumerable:!(r=bt(e,l))||r.enumerable});return t};var qt=(t,e,n)=>(n=t!=null?vt(kt(t)):{},Rt(e||!t||!t.__esModule?K(n,"default",{value:t,enumerable:!0}):n,t));var L=(t,e,n)=>B(t,typeof e!="symbol"?e+"":e,n);var E=(t,e,n)=>new Promise((r,l)=>{var o=u=>{try{s(n.next(u))}catch(i){l(i)}},a=u=>{try{s(n.throw(u))}catch(i){l(i)}},s=u=>u.done?r(u.value):Promise.resolve(u.value).then(o,a);s((n=n.apply(t,e)).next())});var xt=Ft(mt=>{"use strict";function C(t,e,n={}){return{name:t,from:e,meta:n}}function H(t,e){let n=[{value:t,depth:0}];for(let r=0,l=-1,o=0;r>=0;){let{value:a,depth:s}=n[r];if(l<=s&&a.type==="operator"&&a.data.operands.length>0)for(let u=a.data.operands.length;u>0;)n[++r]={value:a.data.operands[--u],depth:s+1};else{let u=e(a,o++,s);if(typeof u<"u")return u;--r}l=s}}var P=class extends Error{constructor(t,e){super(e),this.code=t}};function $(t,e){let n=zt(t);for(let r=0;r<n.length;r++){let l=e(n[r]);if(typeof l<"u")return l}}function zt(t){return t.items}function X(t,e){return $(t,n=>{let{matches:r}=n;for(let l=0;l<r.length;l++){let o=e(r[l],n);if(typeof o<"u")return o}})}function G(t,e=new Map){return(n,...r)=>{let l=e.get(n);return typeof l>"u"&&e.set(n,l=t(n,...r)),l}}function D(t,e){return Object.defineProperty(e,"name",{value:t}),e}function tt(t){return E(this,null,function*(){let e=[];if(typeof t.plugins<"u")for(let n=0;n<t.plugins.length;n++){let r=t.plugins[n];e.push(typeof r=="function"?yield r(t):r)}return e})}function et(t,e){return E(this,null,function*(){for(let n=0;n<t.length;n++){let r=e(t[n]);r instanceof Promise&&(yield r)}})}function z(t,e,n){for(let r=0;r<t.length;r++){let l=e(n,t[r]);typeof l<"u"&&(n=l)}return n}function At(t,e,n){return E(this,null,function*(){var r;for(let l=0;l<t.length;l++){let o=e(n,t[l]);typeof o<"u"&&(n=o instanceof Promise?(r=yield o)!=null?r:n:o)}return n})}function Qt(t){return typeof t!="object"?{node:t,children:[]}:t}function It(t){return typeof t=="object"&&t!==null&&"select"in t&&"values"in t}function N(t){return Math.max(1,Math.ceil(Math.log2(t)))}function St(t){if(t.d+t.f+t.x>32)throw new RangeError("Bit format exceeds 32 bits");return t}function nt(t,e,n){let r=N(t),l=N(e),o=typeof n<"u"?N(n):32-r-l;return St({d:r,f:l,x:o})}var T=[0];for(let t=0;t<32;t++)T.push(T[t]|1<<t);function Ot(t){return new Uint8Array(t)}function jt(t){return new Uint32Array(t)}function k(){return[0].slice(0,0)}function Ct(){return[1/0].slice(0,0)}var J=class{constructor(t=[]){L(this,"magnitude",0);this.data=t}add(t,e,n){this.data.push({start:t,end:e,value:n}),this.magnitude=0}get(t){for(let e=0;e<this.data.length;e++){let{start:n,end:r,value:l}=this.data[e];if(t>=n&&t<r)return l}return 0}forEach(t){for(let e=0;e<this.data.length;e++){let{start:n,end:r,value:l}=this.data[e];for(let o=n;o<r;o++)t(o,l)}}get length(){return this.magnitude||(this.magnitude=rt(this))}},j=class{constructor(t,e=k()){L(this,"magnitude",0);this.data=t,this.cols=e}add(t,e){this.cols.push(t),this.data.push(e),this.magnitude=0}get(t){for(let e=0;e<this.cols.length;e++)if(this.cols[e]===t)return this.data[e];return 0}forEach(t){for(let e=0;e<this.cols.length;e++)t(this.cols[e],this.data[e])}get length(){return this.magnitude||(this.magnitude=rt(this))}};function rt(t){let e=0;return t.forEach((n,r)=>{e+=r*r}),Math.sqrt(e)}function Pt(t,e){t instanceof J?t.data.forEach((n,r)=>{e(n,r)}):t.forEach((n,r)=>{e({start:n,end:n+1,value:1},r)})}var O=class{constructor(t,e=jt(Math.ceil(t/32))){this.size=t,this.data=e}get(t){return this.data[t>>>5]>>>t&1}set(t){this.data[t>>>5]|=1<<(t&31)}forEach(t){let e=this.size&31;for(let n=0;n<this.data.length;n++){if(this.data[n]===0)continue;let r=this.data[n];e&&n===this.data.length-1&&(r=r&T[e]);for(let l=0,o=32-Math.clz32(r);l<o;l++)r&1<<l&&t((n<<5)+l)}}};function lt(t,e){for(let n=0;n<t.data.length;n++)t.data[n]&=~e.data[n]}function A(t,e){e*=T[32]>>>0;for(let n=0;n<t.data.length;n++)t.data.fill(e)}function V(t,e){for(let n=0;n<t.data.length;n++)t.data[n]&=e.data[n]}function at(t){for(let e=0;e<t.data.length;e++)t.data[e]^=T[31]}function I(t,e){for(let n=0;n<t.data.length;n++)t.data[n]|=e.data[n]}function Dt(t,e){let n=[{value:t,depth:0}];for(let r=1,l=0;r>0;l++){let{value:o,depth:a}=n[--r],s=e(o,l,a);if(typeof s<"u")return s;for(let u=o.children.length;u>0;)n[r++]={value:o.children[--u],depth:a+1}}}function Vt(t,e){return E(this,null,function*(){let{fields:n,plugins:r=[]}=e,l=nt(t.length,n.length),o=[];for(let u=0;u<n.length;u++)o.push({terms:[],index:new Map});for(let u=0;u<t.length;u++)for(let i=0;i<n.length;i++){let d=n[i].from(t[u]);if(typeof d>"u")continue;let f=u<<l.f|i;d=z(r,(p,g)=>{var m;return(m=g.onFilterInput)==null?void 0:m.call(g,p,f,l)},d);let c=o[i],h=k();d=Array.isArray(d)?d:[d];for(let p=0;p<d.length;p++){let g=Qt(d[p]);Dt(g,(m,y,x)=>{let v=c.index.get(m.node);typeof v>"u"&&c.index.set(m.node,v=k());let w=c.terms.length;for(let b=0;b<v.length;b++){let F=c.terms[v[b]];if(F.position.depth===x){if(x&&h[x-1]!==F.position.prior)continue;w=v[b];break}}w===c.terms.length&&c.terms.push({value:m.node,occurrences:k(),position:{prior:x?h[x-1]:w,depth:x}});let{occurrences:M}=c.terms[w];M.push(f<<l.x|y),h[x]=w;for(let b=0;b<v.length;b++)if(v[b]===w)return;v.push(w)})}}let a={documents:t.length,fields:n.length},s={shards:o,space:l,count:a};return yield et(r,u=>{var i;return(i=u.onFilterStore)==null?void 0:i.call(u,s,e,t)}),s})}function Ut(t,e,n,r={}){let l=[];if(e<0||e>=t.count.fields)return l;let o=t.shards[e],a=new Map,{count:s=1/0,depth:u=1/0}=r;for(let i=0;i<o.terms.length;i++){let d=o.terms[i],f=n(d,i);if(typeof f<"u"){let{prior:c,depth:h}=d.position;if(h>u)continue;let p=a.get(d);typeof p>"u"&&a.set(d,p={node:f,children:[]});let g=l;h>0&&(g=a.get(o.terms[c]).children),g.length<s&&g.push(p)}}return l}function _t(t,e,n){let{documents:r,terms:l}=U(t);if(n<0||n>=t.count.fields)return{documents:r,terms:l};let o=t.shards[n];return e.forEach(a=>{let{occurrences:s}=o.terms[a];for(let u=0;u<s.length;u++){let i=s[u]>>>t.space.x>>>t.space.f;r.set(i)}l[n].set(a)}),{documents:r,terms:l}}function Bt(t){let{documents:e,terms:n}=U(t);A(e,1);for(let r=0;r<n.length;r++)A(n[r],1);return{documents:e,terms:n}}function U(t){return{documents:new O(t.count.documents),terms:t.shards.map(({terms:e})=>new O(e.length))}}function Kt(t,e,n){let{compiler:r,fields:l,plugins:o=[]}=n,{input:a,scope:s,abort:u=!1}=z(o,(f,c)=>{var h;return(h=c.onFilterQuery)==null?void 0:h.call(c,f,t,n)},e),i={items:[],query:{select:U(t),values:[]}},d=new Map;if(u===!1){let f=r(n),{select:c,values:h}=f(a,t);typeof s<"u"&&V(c.documents,s);let p=new Map;i.query={select:c,values:h},c.terms.forEach((g,m)=>{g.forEach(y=>{let x=t.shards[m],{occurrences:v}=x.terms[y];for(let w=0;w<v.length;w++){let M=v[w],b=M>>>t.space.x,F=b>>>t.space.f;if(!c.documents.get(F))continue;let S=p.get(b);typeof S>"u"&&p.set(b,S=new j(k()));let yt=M&T[t.space.x];S.add(yt,y)}})}),c.documents.forEach(g=>{let m={id:g,matches:[]};i.items.push(m),d.set(g,m)}),p.forEach((g,m)=>{let y=m>>>t.space.f,x=m&T[t.space.f];d.get(y).matches.push({id:m,field:l[x].name,value:{filter:g},score:0})})}return z(o,(f,c)=>{var h;return(h=c.onFilterResult)==null?void 0:h.call(c,f,t,n)},i)}function st(t){let{fields:e}=t;return(n,r)=>{if(It(n))return n;let l=[Bt(r)],o=[],a=0;return H(n,({type:s,data:u})=>{switch(s){case"value":let i=e.findIndex(({name:c})=>c===u.field);if(i===-1){l[a++]=U(r);break}let d=u.value;if(typeof d!="object"){let c=new j(k()),h=r.shards[i],p=h.index.get(d);if(typeof p<"u")for(let g=0;g<p.length;g++){let m=p[g];if(typeof u.depth<"u"){let{position:y}=h.terms[m];if(y.depth!==u.depth)continue}c.add(m,1)}d=c}l[a++]=_t(r,d,i),o.push(Q(R({},u),{value:d}));break;case"operator":let f=a-u.operands.length;switch(u.operator){case"or":for(;a>f+1&&a--;){I(l[f].documents,l[a].documents);for(let c=0;c<e.length;c++)I(l[f].terms[c],l[a].terms[c])}break;case"and":for(;a>f+1&&a--;){V(l[f].documents,l[a].documents);for(let c=0;c<e.length;c++)I(l[f].terms[c],l[a].terms[c])}break;case"not":at(l[f].documents);for(let c=0;c<e.length;c++)A(l[f].terms[c],0);for(;a>f+1&&a--;)lt(l[f].documents,l[a].documents)}}}),{select:l[0],values:o}}}function Lt(t){return{name:t.name,data:t.data,onFilterOptions:t.onFilterOptions,onFilterInput:t.onFilterInput,onFilterStore:t.onFilterStore,onFilterQuery:t.onFilterQuery,onFilterResult:t.onFilterResult}}function ot(t){return typeof t=="object"&&t!==null&&"type"in t&&"data"in t}function Nt(t){return typeof t=="object"&&t!==null&&"select"in t&&"values"in t}function Gt(t){return t.normalize("NFKD").toLowerCase()}function Ht(t,e){let n=Math.min(t.length,e.length);for(let r=0;r<n;r++)if(t.charCodeAt(r)!==e.charCodeAt(r))return r;return n}function Jt(t,e,n=0,r=t.length){for(let l=0;n<r;n+=1+ +(l>65535)){let o=e(l=t.codePointAt(n),n);if(typeof o<"u")return o}}function ut(t,e,n=0,r=t.length){let l=k();return Jt(t,o=>{l.push(o);let a=e(String.fromCodePoint(...l),l.length);if(typeof a<"u")return a},n,r)}function Wt(t,e,n=0,r=t.length){let l=n;for(let o=0;l<r;l++)switch(o=t.charCodeAt(l),o){case 60:l>n&&e(n,n=l);continue;case 62:n=l+1}l>n&&e(n,l)}function it(t,e,n,r=0){return Wt(t,(l,o)=>e(t,(a,s)=>{r=n({value:t.slice(a,s),index:r,start:a,end:s})},l,o)),r}function Yt(t,e,n,r=0){for(let l=0,o=0;l<t.length;o+=t[l++].length)r=it(t[l],e,a=>(a.start+=o,a.end+=o,n(a)),r);return r}function Zt(t){let e=new RegExp(t,"gu");return(n,r,l=0,o=n.length)=>{var u;e.lastIndex=l;let a,s=0;do{a=e.exec(n);let i=(u=a==null?void 0:a.index)!=null?u:o;l<i&&r(l,Math.min(i,o)),a&&(s=a[0].length,l=a.index+s,s===0&&(e.lastIndex=a.index+1))}while(a&&l<o)}}function $t(t,e){return E(this,null,function*(){let{separator:n,transform:r,fields:l,plugins:o=[]}=e,a=nt(t.length,l.length),s=new Map;for(let f=0;f<t.length;f++)for(let c=0;c<l.length;c++){let h=l[c].from(t[f]);if(typeof h>"u")continue;let p=f<<a.f|c;h=z(o,(g,m)=>{var y;return(y=m.onTextInput)==null?void 0:y.call(m,g,p,a)},h),h=Array.isArray(h)?h:[h],Yt(h,n,g=>{let m=z(o,(y,x)=>{var v;return(v=x.onTextTokens)==null?void 0:v.call(x,y)},[g]);for(let y=0;y<m.length;y++){g=m[y];let x=r(g.value),v=s.get(x);typeof v>"u"?s.set(x,[p<<a.x|g.index]):v.push(p<<a.x|g.index)}return m.length?g.index+1:g.index})}let u={documents:t.length,fields:l.length},i={terms:[],index:new Map,space:a,count:u},d=[...s.keys()].sort();for(let f=0;f<d.length;f++)i.index.set(d[f],f),i.terms.push({value:d[f],occurrences:s.get(d[f])});return yield et(o,f=>{var c;return(c=f.onTextStore)==null?void 0:c.call(f,i,e,t)}),i})}function Xt(t,e,n){let{documents:r,terms:l}=_(t);return n<0||n>=t.count.fields?{documents:r,terms:l}:(e.forEach(o=>{let{occurrences:a}=t.terms[o];for(let s=0;s<a.length;s++){let u=a[s]>>>t.space.x;if((u&T[t.space.f])!==n)continue;let i=u>>>t.space.f;r.set(i)}l.set(o)}),{documents:r,terms:l})}function te(t,e){let{documents:n,terms:r}=_(t),l=t.space.f+t.space.x;return e.forEach(o=>{let{occurrences:a}=t.terms[o];for(let s=0;s<a.length;s++)n.set(a[s]>>>l);r.set(o)}),{documents:n,terms:r}}function _(t){return{documents:new O(t.count.documents),terms:new O(t.terms.length)}}function ee(t,e,n){let{compiler:r,fields:l,plugins:o=[]}=n,{input:a,scope:s,abort:u=!1}=z(o,(f,c)=>{var h;return(h=c.onTextQuery)==null?void 0:h.call(c,f,t,n)},e),i={items:[],query:{select:_(t),values:[]}},d=new Map;if(u===!1){let f=r(n),{select:c,values:h}=f(a,t);typeof s<"u"&&V(c.documents,s);let p=new O(l.length),g=new Map;i.query={select:c,values:h},c.terms.forEach(m=>{A(p,0);for(let x=0;x<h.length;x++){let{field:v,value:w}=h[x];if(v==="*"){A(p,1);break}else if(w.get(m)){for(let M=0;M<l.length;M++)if(l[M].name===v){p.set(M);break}}}let{occurrences:y}=t.terms[m];for(let x=0;x<y.length;x++){let v=y[x],w=v>>>t.space.x,M=w>>>t.space.f;if(!c.documents.get(M))continue;let b=w&T[t.space.f];if(!p.get(b))continue;let F=g.get(w);typeof F>"u"&&g.set(w,F=new j(k()));let S=v&T[t.space.x];F.add(S,m)}}),c.documents.forEach(m=>{let y={id:m,matches:[]};i.items.push(y),d.set(m,y)}),g.forEach((m,y)=>{let x=y>>>t.space.f,v=y&T[t.space.f];d.get(x).matches.push({id:y,field:l[v].name,value:{text:m},score:0})})}return z(o,(f,c)=>{var h;return(h=c.onTextResult)==null?void 0:h.call(c,f,t,n)},i)}function ne(t,e=10){return t.length>1?1+t[t.length-1]-t[0]:e}function re(t,e,n,r=10){let l=[];t.value.text.forEach((s,u)=>{for(let i=0;i<e.data.length;i++){let{start:d,end:f}=e.data[i];d<=u&&u<f&&l.push({index:s,value:i})}}),l.sort((s,u)=>s.index-u.index);let o=l.slice(0,1),a=0;for(let s=0;s<l.length-1;s++){let u=l[s],i=l[s+1],d;if(i.index-u.index>r||i.value===u.value)d=o.map(({index:f})=>f),o=[l[s+1]];else{for(let f=0;f<o.length;f++){let c=o[f];if(c.value===i.value){if(u.index-c.index>i.index-u.index){let h=o.splice(f+1);d=o.map(({index:p})=>p),o=[...h,l[s+1]]}else d=o.map(({index:h})=>h),o=[l[s+1]];break}}typeof d>"u"&&o.push(l[s+1])}if(typeof d<"u"){let f=n(d,a++);if(typeof f<"u")return f}}if(o.length)return n(o.map(({index:s})=>s),a)}function le(t){let{transform:e,parser:n,fields:r}=t,l=n(t);return(o,a)=>{if(Nt(o))return o;typeof o=="string"&&(o=l(o));let s=[_(a)],u=[],i=0;return H(o,({type:d,data:f})=>{switch(d){case"value":let c=f.value;if(typeof c=="string"){let p=new j(k()),g=a.index.get(e(c));typeof g<"u"&&p.add(g,1),c=p}if(f.field==="*")s[i++]=te(a,c);else{let p=r.findIndex(({name:g})=>g===f.field);s[i++]=Xt(a,c,p)}u.push(Q(R({},f),{value:c}));break;case"operator":let h=i-f.operands.length;switch(f.operator){case"or":for(;i>h+1&&i--;)I(s[h].documents,s[i].documents),I(s[h].terms,s[i].terms);break;case"and":for(;i>h+1&&i--;)V(s[h].documents,s[i].documents),I(s[h].terms,s[i].terms);break;case"not":for(at(s[h].documents),A(s[h].terms,0);i>h+1&&i--;)lt(s[h].documents,s[i].documents)}}}),{select:s[0],values:u}}}function ft(t,e){return H(t,(n,r,l)=>{if(n.type!=="value")return;let o=e(n.data,r,l);if(typeof o<"u")return o})}function ct(t){if(t.length===0)return[];let e=[],n=[];for(let o=0;o<t.length;o++){let{start:a,end:s}=t[o];n.push({index:a,value:o}),n.push({index:s,value:o})}n.sort((o,a)=>o.index-a.index);let r=new Set([n[0].value]),l=n[0].index;for(let o=1;o<n.length;o++){let{index:a,value:s}=n[o];if(r.size&&l<a){let u=s;r.forEach(i=>{t[i].start>l||t[i].end<a||t[u].start!==t[i].start&&t[u].end!==t[i].end&&(u=i)}),e.push({start:l,end:a,value:t[u].value})}l=a,r.has(s)?r.delete(s):r.add(s)}return e}function dt(t){let e=[];for(let n=0;n<t.values.length;n++){let{value:r}=t.values[n];Pt(r,({start:l,end:o})=>{e.push({start:l,end:o,value:n})})}return new J(ct(e))}function ae(t,e="or",n){let{separator:r}=t;return n!=null||(n=l=>({field:"*",value:l.value})),l=>{let o=[];return it(l,r,a=>{let s=n(a);typeof s<"u"&&o.push({type:"value",data:s})}),{type:"operator",data:{operator:e,operands:o}}}}function se(t,e){return E(this,null,function*(){let n=yield tt(e),r=yield At(n,(o,a)=>{var s;return(s=a.onTextOptions)==null?void 0:s.call(a,o,t)},Q(R({},e),{plugins:n})),l=yield $t(t,r);return D("text",o=>{if(o.type!=="text")throw new P("unsupported");return{type:o.type,data:ee(l,o.data,r)}})})}function q(t){return{name:t.name,data:t.data,onTextOptions:t.onTextOptions,onTextInput:t.onTextInput,onTextTokens:t.onTextTokens,onTextStore:t.onTextStore,onTextQuery:t.onTextQuery,onTextResult:t.onTextResult}}function oe(t){let{handlers:e}=t,n,r=new Map;return Lt({name:"aggregation",onFilterStore(l,o){for(let a=0;a<e.length;a++){let s=e[a](l,o);r.set(s.name,s)}},onFilterQuery(l){var o,a;n=(a=(o=l.aggregation)==null?void 0:o.input)!=null?a:[]},onFilterResult(l){let{select:o}=l.query;l.aggregations=[];for(let a of n){let s=r.get(a.type);if(typeof s>"u")continue;let u=!0;o.documents.forEach(i=>{u=!1}),u&&A(o.documents,1),l.aggregations.push(s(a,o))}}})}function ue(t={}){let{empty:e=!1,limit:n}=t;return(r,{fields:l})=>{let o=r.space.f+r.space.x;return D("term",({type:a,data:s},{documents:u})=>{if(a!=="term")throw new P("unsupported");let i=l.findIndex(({name:f})=>f===s.field),d=Ut(r,i,f=>{let c=0,{occurrences:h}=f;for(let p=0;p<h.length;p++)u.get(h[p]>>>o)&&c++;if(!(e===!1&&c===0))return{value:f.value,count:c}},R(R({},n),s.limit));return{type:a,data:{field:s.field,value:d}}})}}function ie(t,e="prefix"){return{type:e,data:t}}function fe(t){return typeof t=="object"&&"type"in t&&typeof t.type=="string"&&"data"in t&&typeof t.data=="string"}function ce(t,e={}){var u;let{prefix:n=2,filter:r=[]}=e,l=t.terms,o=new Map,a=Ot(l.length),s=k();for(let i=0;i<l.length;i++){let d=l[i];ut(d,(c,h)=>{var p;return o.set(c,(p=o.get(c))!=null?p:i),h===n||void 0});let f=i?l[i-1]:"";a[i]=Ht(f,d)}for(let i=0;i<r.length;i++){let d=r[i],f=(u=t.index)==null?void 0:u.get(d);typeof f<"u"&&s.push(f)}return s.sort((i,d)=>i-d),{terms:l,index:o,cover:a,exact:s}}function de(t,e){let n="",r=-1,l=-1;if(ut(e,s=>{let u=t.index.get(s);if(typeof u>"u")return!0;n=s,r=u}),r!==-1)for(let s=n.length;s<e.length;){let u=t.terms[r];if(u.length===s)if(++r===t.terms.length){r=-1;break}else continue;if(u.charCodeAt(s)===e.charCodeAt(s))s++;else if(t.terms.length===++r||t.cover[r]<s){r=-1;break}}if(r===-1)return;for(l=r+1;l<t.terms.length&&!(t.cover[l]<e.length);l++);let o=[],a=t.exact.filter(s=>s>r&&s<l);for(let s=0;s<a.length;s++)r<a[s]&&o.push({start:r,end:a[s]-1,value:1}),r=a[s]+1;return r<=l&&o.push({start:r,end:l,value:1}),new J(o)}function he(t={}){return q({name:"expansion",onTextStore(e,n){var l,o;let{transform:r}=n;(o=this.data)!=null||(this.data=ce({terms:e.terms.map(({value:a})=>a),index:e.index},{prefix:t.prefix,filter:(l=t.filter)==null?void 0:l.map(r)}))},onTextQuery(e,n,r){let{transform:l,parser:o}=r;if(typeof e.input=="string")e.input=o(r)(e.input);else if(!ot(e.input))return;ft(e.input,a=>{var u;let s=a.value;if(fe(s))s=l(s.data);else return;a.value=(u=de(this.data,s))!=null?u:s})}})}function pe(t){let e=Q(R({},t),{plugins:[]}),n,r,l;return q({name:"filter",onTextOptions(a,s){return E(this,null,function*(){e.plugins=yield tt(t),l=yield Vt(s,e)})},onTextQuery(a){typeof a.filter<"u"&&(n=a.filter,r!=null||(r=st(e)),n.input=r(n.input,l),a.scope=n.input.select.documents)},onTextResult(a){if(typeof n<"u"){let s=!0;a.query.select.documents.forEach(i=>{s=!1}),s||(n.scope=a.query.select.documents);let u=Kt(l,n,e);a.aggregations=u.aggregations,n=void 0}}})}function ht(t,e){let n=[],r=t/e>>>0,l=t%e,o=0;if(r)for(let a=0;a<e-l;a++,o+=r)n.push(o);if(l)for(let a=0;a<l;a++,o+=r+1)n.push(o);return n.push(o),n}function ge(t,e){let n=ht(t.length,e),r=[];for(let l=0;l<n.length-1;l++)r.push(t.slice(n[l],n[l+1]));return r}function me(t,e,n){let r=ht(e,n+1),l=t.length-e,o=[];for(let a=0;a<r.length-1;a++){let s=r[a+1]-r[a],u=1+r[a],i=Math.max(u-a,u+l-(n-a),1),d=Math.min(u+a,u+l+(n-a),1+t.length-s);o[a]=[];for(let f=i-1;f<d;f++)o[a].push(t.slice(f,f+s))}return o}function xe(t,e={}){let{threshold:n=2}=e,r=t.terms.map((a,s)=>s);r.sort((a,s)=>t.terms[a].length-t.terms[s].length||t.terms[a].localeCompare(t.terms[s]));let l=0;for(let a=0;a<t.terms.length;a++)t.terms[a].length>l&&(l=t.terms[a].length);let o=[];for(let a=0;a<l+1;a++){let s=[];o.push(s);for(let u=0;u<n+1;u++)s.push(new Map)}for(let a=0;a<r.length;a++){let s=t.terms[r[a]],u=o[s.length],i=ge(s,n+1);for(let d=0;d<i.length;d++){let f=i[d],c=u[d].get(f);typeof c>"u"?u[d].set(f,[r[a]]):c.push(r[a])}}return{index:o,terms:t.terms,idxmp:r}}var ye=[["id","di","rr"],["dr","rd"],["dd"]];function pt(t,e,n=2){if(t.length<e.length)return pt(e,t,n);let r=t.length,l=e.length,o=r-l;if(o>n)return;let a,s,u,i=n+1;for(let d of ye[o]){for(u=a=s=0;a<r&&s<l;)if(t[a]!==e[s]){if(++u>n)break;switch(d[u-1]){case"d":a++;break;case"i":s++;break;case"r":a++,s++;break}}else a++,s++;u+=r-a+(l-s),u<i&&(i=u)}return i<n+1?i:void 0}function ve(t,e,n=pt){let r=new j(Ct());for(let l=-2;l<3;l++){let o=e.length+l;if(typeof t.index[o]>"u")continue;let a=me(e,o,2);for(let s=0;s<a.length;s++){let u=t.index[o][s],i=a[s];for(let d=0;d<i.length;d++){let f=u.get(i[d]);if(!(typeof f>"u"))for(let c of f){let h=t.terms[c].length,p=n(t.terms[c],e);typeof p<"u"&&r.add(c,(h-p)/h)}}}}if(r.data.length)return r}function we(t={}){return q({name:"fuzzy",onTextStore(e){var n;(n=this.data)!=null||(this.data=xe({terms:e.terms.map(({value:r})=>r)},t))},onTextQuery(e,n,r){let{transform:l,parser:o}=r;if(typeof e.input=="string")e.input=o(r)(e.input);else if(!ot(e.input))return;ft(e.input,a=>{var u;let s=a.value;if(typeof s=="string")s=l(s);else return;n.index.get(s)||(a.value=(u=ve(this.data,s))!=null?u:s)})}})}function be(){return{tables:new Map}}function Te(t,e={}){let{count:n}=e;return D("term",r=>{let l=dt(r);return(o,a)=>{let s=[];return o.value.text.forEach((u,i)=>{let d=a[u]>>>10,f=a[u]&T[10];for(let p=0;p<l.data.length;p++){let{start:g,end:m}=l.data[p];if(g<=i&&i<m){i=l.data[p].value;break}}let c=d,h=d+f;s.push({start:c,end:h,value:i})}),s.sort((u,i)=>u.start-i.start),{ranges:ct(s).slice(0,n)}}})}function Me(t){let e,n;return q({name:"highlight",data:be(),onTextInput(r,l){let{tables:o}=this.data;o.set(l,n=k())},onTextTokens(r){for(let l=0;l<r.length;l++){let{index:o,start:a,end:s}=r[l];n[o]=a<<10|s-a}},onTextStore(r){e=t.handler(r)},onTextResult(r){let{tables:l}=this.data,o=e(r.query);X(r,a=>{let s=l.get(a.id);if(a.value.highlight)return;let u=o(a,s);a.value=Q(R({},a.value),{highlight:u})})}})}function ke(){return{directives:[]}}function gt(...t){return(e,n)=>{for(let r=0;r<t.length;r++){let l=t[r](e,n);if(l!==0)return l}return 0}}function Ee(t){let{comparators:e}=t;return D("match",(n,{type:r,data:l})=>{if(r!=="match")throw new P("unsupported");let o=Fe(t),a=gt(...e.map(s=>s(n)));return $(n,({matches:s})=>{s.sort(o)}),(s,u)=>{let i=Math.min(s.matches.length,u.matches.length);for(let d=0,f=0;d<i;d++)if(f=o(s.matches[d],u.matches[d]),f!==0||(f=a(s.matches[d],u.matches[d]),f!==0))return f;return u.matches.length-s.matches.length}})}function Fe(t){var o;let{fields:e,direction:n}=t,r=n==="ascending"?1:-1,l=new Map;for(let a=0;a<e.length;a++){let{name:s,meta:u}=e[a];l.set(s,(o=u.weight)!=null?o:1)}return(a,s)=>r*(l.get(a.field)-l.get(s.field))}function Re(t,e={}){let n=dt(t.query),r=G(re),l=G(ne);return(o,a)=>{let s=r(o,n,f=>f),u=r(a,n,f=>f);if(s.length!==u.length)return u.length-s.length;let i=l(s),d=l(u);return i!==d?i-d:s[0]!==u[0]?s[0]-u[0]:0}}function qe(t){let e=new Map;return q({name:"order",data:ke(),onTextOptions(r,l){return E(this,null,function*(){for(let o=0;o<t.handlers.length;o++){let a=yield t.handlers[o](r,l);e.set(a.name,a)}})},onTextQuery(r){var l,o,a;this.data.directives=(a=(o=r.order)!=null?o:(l=t.defaults)==null?void 0:l.order)!=null?a:[]},onTextResult(r){let{directives:l}=this.data,o=[];for(let a=0;a<l.length;a++){let s=l[a],u=e.get(s.type);if(typeof u>"u")throw new P("unknown");o.push(u(r,s))}r.items.sort(gt(...o))}})}function ze(t){let e=t.handler();return q({name:"pagination",onTextQuery(n){return e.onQuery(n,t)},onTextResult(n){return e.onResult(n,t)}})}function Ae(t){let{id:e,size:n=10,from:r=0}=t;if(r-n>=0)return{id:e,size:n,from:r-n}}function Qe(t,e){let{id:n,size:r=10,from:l=0}=t;if(l+r<e)return{id:n,size:r,from:l+r}}function Ie(){return{query:null,result:null}}function Se(t={}){let{cache:e=Ie(),expires:n=1/0}=t;return{data:e,onQuery(r,{size:l=10}){var s,u,i,d;let o=(i=(u=(s=e.query)==null?void 0:s.page)==null?void 0:u.id)!=null?i:0,a=Date.now()-o<n;e.query=Object.assign({},r),e.result&&((d=r.page)==null?void 0:d.id)===o&&a?r.abort=!0:(e.query.page={id:Date.now(),size:l,from:0},e.result=null)},onResult(r){var a;let l=e.query.page;(a=e.result)!=null||(e.result=r),r=Object.assign({},e.result);let o=e.result.items.length;return r.pagination={total:o,prev:Ae(l),next:Qe(l,o)},r.items=e.result.items.slice(l.from,l.from+l.size),r}}}var Z=null;self.onmessage=t=>E(null,null,function*(){let e=t.data;switch(e.type){case 0:Z=yield se(e.data.items,{separator:Zt(e.data.config.separator),transform:G(Gt),parser:r=>ae(r,"and",l=>({field:"*",value:ie(l.value),range:{start:l.start,end:l.end,value:l.index}})),compiler:le,fields:[C("title",r=>r.title,{weight:3}),C("text",r=>r.text),C("path",r=>r.path,{weight:2})],plugins:[he(),we(),pe({compiler:st,fields:[C("tags",r=>r.tags)],plugins:[oe({handlers:[ue()]})]}),qe({handlers:[r=>Ee({fields:r.fields,comparators:[Re]})],defaults:{order:[{type:"match",data:{field:"*"}}]}}),()=>q({onTextResult(r){r.total=r.items.length}}),ze({handler:Se,size:10}),Me({handler:r=>Te(r)}),()=>q({onTextResult(r){let{query:l}=r,o=l.values.map(({range:a,value:s})=>{var i,d;let u=!1;return s.forEach((f,c)=>{!u&&c<1&&(u=!0)}),u?-1:((i=a==null?void 0:a.end)!=null?i:0)-((d=a==null?void 0:a.start)!=null?d:0)});X(r,a=>{var s;(s=a.value.highlight)==null||s.ranges.forEach(u=>{u.value=o[u.value]})})}})]}),self.postMessage({type:1});break;case 2:let n=Z({type:"text",data:e.data});self.postMessage({type:3,data:n.data});break}})});var _e=qt(xt());})();`], {type: "application/javascript"})));
    }
    return new Worker(url);
  }

  function loadSearchData() {
    if (location.protocol === "file:") {
      return new Promise(function(resolve, reject) {
        if (typeof __index !== "undefined") {
          resolve(__index);
          return;
        }
        var script = document.createElement("script");
        script.src = new URL("search.js", siteRoot).toString();
        script.onload = function() {
          document.head.removeChild(script);
          if (typeof __index !== "undefined") {
            resolve(__index);
          } else {
            reject(new Error("__index not defined"));
          }
        };
        script.onerror = function() {
          document.head.removeChild(script);
          reject(new Error("Failed to load search.js"));
        };
        document.head.appendChild(script);
      });
    }
    return fetch(searchJsonUrl).then(function(response) { return response.json(); });
  }

  function initWorker() {
    if (worker) return;
    try {
      worker = createWorkerSafe(workerUrl);
    } catch (err) {
      debugLog("worker creation failed:", err);
      emptyEl.textContent = "검색 엔진을 초기화할 수 없습니다.";
      emptyEl.style.display = "block";
      return;
    }
    worker.addEventListener("error", function(event) {
      debugLog("worker error:", event);
    });
    worker.addEventListener("message", function(event) {
      const data = event.data || {};
      debugLog("worker message:", data);
      if (data.type === 1) {
        ready = true;
        if (queuedQuery) {
          search(queuedQuery);
          queuedQuery = null;
        }
      } else if (data.type === 3) {
        handleSearchResult(data.data || {});
      }
    });

    loadSearchData()
      .then(function(searchData) {
        const sanitizedSearchData = sanitizeSearchData(searchData);
        searchItems = sanitizedSearchData.items || [];
        debugLog("search.json items:", searchItems.length);
        worker.postMessage({ type: 0, data: sanitizedSearchData });
      })
      .catch(function(err) {
        debugLog("search data load failed:", err);
        emptyEl.textContent = "검색 데이터를 불러올 수 없습니다.";
        emptyEl.style.display = "block";
      });
  }

  function search(query) {
    if (!worker) initWorker();
    if (!ready) {
      queuedQuery = query;
      debugLog("search queued:", query);
      return;
    }
    currentQuery = query;
    collectingAll = true;
    accumulatedItems = [];
    accumulatedIds = new Set();
    accumulatedTotal = 0;
    sendSearchPayload(query);
  }

  function sendSearchPayload(query, page) {
    const payload = buildSearchPayload(query);
    if (typeof page !== "undefined") {
      payload.page = page;
    } else if ("page" in payload) {
      payload.page = undefined;
    }
    debugLog("search send:", payload);
    worker.postMessage({ type: 2, data: payload, __sidebarSearch: true });
  }

  function handleSearchResult(data) {
    const items = Array.isArray(data.items) ? data.items : [];
    const total = typeof data.total === "number"
      ? data.total
      : (data.pagination && typeof data.pagination.total === "number"
        ? data.pagination.total
        : items.length);

    if (!collectingAll) {
      renderResults({ items: items, total: total });
      return;
    }

    if (!accumulatedIds) accumulatedIds = new Set();
    for (let i = 0; i < items.length; i += 1) {
      const hit = items[i];
      if (!hit || typeof hit.id === "undefined") continue;
      if (accumulatedIds.has(hit.id)) continue;
      accumulatedIds.add(hit.id);
      accumulatedItems.push(hit);
    }

    accumulatedTotal = Math.max(accumulatedTotal, total);

    if (data.pagination && typeof data.pagination.next !== "undefined") {
      sendSearchPayload(currentQuery, data.pagination.next);
      return;
    }

    collectingAll = false;
    renderResults({ items: accumulatedItems, total: accumulatedTotal || accumulatedItems.length });
  }

  function escapeHtml(text) {
  return String(text)
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/\"/g, "&quot;")
      .replace(/'/g, "&#39;");
  }

  return { search: search };
}

function htmlToText(value) {
  if (!value) return "";
  const temp = document.createElement("div");
  temp.innerHTML = String(value);
  return (temp.textContent || "").trim();
}

function sanitizeSearchText(value) {
  const text = htmlToText(value);
  return text.replace(/\s+/g, " ").trim();
}

function extractQueryFromWorkerMessage(data) {
  if (typeof data === "string") return data;
  if (!data || typeof data !== "object") return null;

  if (typeof data.input === "string") return data.input;
  if (data.input && typeof data.input.data === "string") return data.input.data;
  if (data.input && data.input.data && typeof data.input.data.value === "string") return data.input.data.value;

  if (typeof data.query === "string") return data.query;
  if (typeof data.term === "string") return data.term;
  if (typeof data.value === "string") return data.value;
  if (typeof data.text === "string") return data.text;

  return null;
}

function storeSearchEnvelope(data) {
  if (!data || typeof data !== "object") return;
  if (!window.__sidebarSearchEnvelope) {
    window.__sidebarSearchEnvelope = {};
  }
  try {
    window.__sidebarSearchEnvelope = JSON.parse(JSON.stringify(data));
  } catch (err) {
    window.__sidebarSearchEnvelope = data;
  }
}

function buildSearchPayload(query) {
  const template = window.__sidebarSearchEnvelope;
  if (template && typeof template === "object") {
    const cloned = cloneSearchEnvelope(template);
    cloned.input = query;
    if ("page" in cloned) {
      cloned.page = undefined;
    }
    return cloned;
  }

  return {
    input: query,
    filter: {
      input: { type: "operator", data: { operator: "and", operands: [] } },
      aggregation: { input: [{ type: "term", data: { field: "tags" } }] }
    }
  };
}

function cloneSearchEnvelope(source) {
  try {
    return JSON.parse(JSON.stringify(source));
  } catch (err) {
    const fallback = {};
    for (const key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        fallback[key] = source[key];
      }
    }
    return fallback;
  }
}

function debugLog() {
  if (!window.__sidebarSearchDebug) return;
  const args = Array.prototype.slice.call(arguments);
  args.unshift("[sidebar-search]");
  console.log.apply(console, args);
}

function readMdConfig() {
  const configEl = document.getElementById("__config");
  if (!configEl) return null;
  try {
    return JSON.parse(configEl.textContent);
  } catch (err) {
    return null;
  }
}

function resolveBaseUrl(config) {
  if (config && config.base) {
    try {
      return new URL(config.base, window.location.href);
    } catch (err) {
      // fall through
    }
  }

  if (window.__md_scope instanceof URL) {
    return window.__md_scope;
  }

  const scriptEl = document.currentScript || document.querySelector("script[src$=\"javascripts/extra.js\"]");
  const scriptUrl = scriptEl ? scriptEl.src : window.location.href;
  const baseUrl = new URL(".", scriptUrl);
  return new URL("../", baseUrl);
}

function resolveWorkerUrl(config, baseUrl) {
  if (config && config.search) {
    try {
      return new URL(config.search, window.location.href);
    } catch (err) {
      // fall through
    }
  }
  return new URL("assets/javascripts/workers/search.e2d2d235.min.js", baseUrl);
}

function extractSearchQuery(event) {
  const path = typeof event.composedPath === "function" ? event.composedPath() : [];
  for (let i = 0; i < path.length; i += 1) {
    const node = path[i];
    if (!(node instanceof HTMLInputElement)) continue;
    const isSearchInput = node.type === "search" ||
      node.classList.contains("md-search__input") ||
      (node.getAttribute("aria-label") || "").toLowerCase() === "search";
    if (isSearchInput) {
      return node.value || "";
    }
  }
  return null;
}

function cleanupURLSearchParam(name) {
  if (!name) return;
  try {
    const url = new URL(window.location.href);
    if (!url.searchParams.has(name)) return;
    url.searchParams.delete(name);
    const next = url.pathname + (url.search ? url.search : "") + url.hash;
    window.history.replaceState(null, "", next);
  } catch (err) {
    // ignore
  }
}

function initSearchResultHighlight() {
  let query = "";
  let hadQueryParam = false;
  try {
    const params = new URLSearchParams(window.location.search);
    const paramQuery = (params.get("q") || "").trim();
    if (paramQuery) {
      query = paramQuery;
      hadQueryParam = true;
    }
  } catch (err) {
    query = "";
  }
  if (!query) {
    try {
      query = (sessionStorage.getItem("md-search-last-query") || "").trim();
    } catch (err) {
      query = "";
    }
  }
  if (!query) return;
  const token = query.split(/\s+/).filter(Boolean)[0] || query;

  const root = document.querySelector(".md-content__inner .md-typeset") || document.querySelector(".md-typeset");
  if (!root) return;

  const lowerQuery = token.toLowerCase();
  const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
    acceptNode: function(node) {
      if (!node || !node.nodeValue) return NodeFilter.FILTER_REJECT;
      const parent = node.parentElement;
      if (!parent) return NodeFilter.FILTER_REJECT;
      const tag = (parent.tagName || "").toUpperCase();
      if (tag === "SCRIPT" || tag === "STYLE" || tag === "CODE" || tag === "PRE") {
        return NodeFilter.FILTER_REJECT;
      }
      if ((parent.className || "").indexOf("md-search-target-highlight") !== -1) {
        return NodeFilter.FILTER_REJECT;
      }
      return NodeFilter.FILTER_ACCEPT;
    }
  });

  // If there is an anchor hash, start searching from that element
  if (window.location.hash) {
    try {
      const id = window.location.hash.substring(1);
      const anchor = document.getElementById(id);
      if (anchor && root.contains(anchor)) {
        walker.currentNode = anchor;
      }
    } catch (e) { /* ignore */ }
  }

  let targetNode = null;
  let matchIndex = -1;
  while (walker.nextNode()) {
    const text = walker.currentNode.nodeValue || "";
    const idxInText = text.toLowerCase().indexOf(lowerQuery);
    if (idxInText === -1) continue;
    targetNode = walker.currentNode;
    matchIndex = idxInText;
    break;
  }

  if (!targetNode || matchIndex < 0) {
    if (hadQueryParam) cleanupURLSearchParam("q");
    return;
  }

  const fullText = targetNode.nodeValue || "";
  const before = fullText.slice(0, matchIndex);
  const matchText = fullText.slice(matchIndex, matchIndex + token.length);
  const after = fullText.slice(matchIndex + token.length);

  const highlight = document.createElement("span");
  highlight.className = "md-search-target-highlight";
  highlight.textContent = matchText;

  const fragment = document.createDocumentFragment();
  if (before) fragment.appendChild(document.createTextNode(before));
  fragment.appendChild(highlight);
  if (after) fragment.appendChild(document.createTextNode(after));

  if (targetNode.parentNode) {
    targetNode.parentNode.replaceChild(fragment, targetNode);
  }

  setTimeout(function() {
    // Only scroll if there is NO anchor hash (prevent jumping away from anchor)
    if (!window.location.hash) {
      try {
        highlight.scrollIntoView({ block: "center", inline: "nearest", behavior: "smooth" });
      } catch (err) {
        highlight.scrollIntoView(true);
      }
    }
    if (hadQueryParam) cleanupURLSearchParam("q");
  }, 300);
}

function highlightClickedResult(resultsEl, clickedKey) {
  if (!resultsEl || !clickedKey) return;
  let clickedHref = null;
  try { clickedHref = sessionStorage.getItem(clickedKey); } catch (err) { clickedHref = null; }
  const items = resultsEl.querySelectorAll(".md-search-result__item");
  for (let i = 0; i < items.length; i += 1) {
    items[i].classList.remove("is-clicked");
  }
  if (!clickedHref) return;
  const links = resultsEl.querySelectorAll("a.md-search-result__link");
  for (let i = 0; i < links.length; i += 1) {
    if (links[i].href !== clickedHref) continue;
    const item = links[i].closest(".md-search-result__item");
    if (item) {
      item.classList.add("is-clicked");

    }
    break;
  }
}

function applySidebarSearchStyleOverrides() {
  const id = "md-sidebar-search-overrides";
  if (document.getElementById(id)) return;
  const style = document.createElement("style");
  style.id = id;
  style.textContent = [
    ".md-sidebar__panel--search .md-search-result__meta { font-size: 0.85rem; }",
    ".md-sidebar__panel--search .md-search-result__teaser { display: none; }",
    ".md-sidebar__panel--search .md-search-result__item::marker { font-size: 0.8rem; }",
    ".md-sidebar__panel--search .md-search-result__list { max-height: none; }",
    ".md-sidebar__panel--search .md-search-result__excerpt { display: none; }",
    ".md-sidebar__reset-btn { margin-left: auto; align-self: center; padding: 4px; background: transparent; border: 1px solid transparent; border-radius: 4px; cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center; }",
    ".md-sidebar__reset-btn:hover { background: rgba(0,0,0,0.05); border-color: #ddd; }",
    ".md-sidebar__reset-btn img { opacity: 0.6; transition: opacity 0.2s; }",
    ".md-sidebar__reset-btn:hover img { opacity: 1.0; }"
  ].join("\n");
  document.head.appendChild(style);
}

function stripTeaserFromHtml(html) {
  if (!html) return html;
  const temp = document.createElement("div");
  temp.innerHTML = html;
  const teasers = temp.querySelectorAll(".md-search-result__teaser");
  for (let i = teasers.length - 1; i >= 0; i -= 1) {
    teasers[i].remove();
  }
  const excerpts = temp.querySelectorAll(".md-search-result__excerpt");
  for (let i = excerpts.length - 1; i >= 0; i -= 1) {
    excerpts[i].remove();
  }
  return temp.innerHTML;
}











