diff --git "a/assets/main-BBNVSS5C.js" "b/assets/main-BBNVSS5C.js" new file mode 100644--- /dev/null +++ "b/assets/main-BBNVSS5C.js" @@ -0,0 +1,236 @@ +import"./modulepreload-polyfill-B5Qt9EMX.js";import{_ as Tt,i as Bs,l as $s,e as Is,c as Ds,f as Ls,p as Os,g as Fs,d as _s,r as Gs,t as Or,h as Fr,D as nn,a as _r,j as zs,S as Fn,A as Us,K as xo,k as js,b as Gr,m as Hs,n as Ws,o as Ks}from"./preload-helper-BSrbm-kb.js";import{m as Zn,D as er,P as zr,d as Vs,b as qs,M as Js,p as Qs,a as Ys}from"./models-QsPq0tJ5.js";const Xs="/assets/hero-DgsFBh_e.webp",we=e=>``,ue={paste:we(''),trash:we(''),copy:we(''),download:we(''),cancel:we(''),retry:we(''),cpu:we(''),translate:we(''),upload:we(''),board:we(''),flag:we(''),person:we(''),help:we(''),pin:we(''),file:we(''),book:we(''),gear:we('')},Zs=` + + +
+
+
中文0 ký tự
+ + +
+ + + + +
+
+
+
Tiếng Việt
+
+
+ + + + + +
+
+ +
+ +

Dán văn bản hoặc thả file .txt vào đây.

+ +
+ + + + +
+
+ + `,Ur="'Songti SC','SimSun','Noto Serif CJK SC','Noto Serif TC',serif",ea=` + + +
+
+
+ + + + + + +
+

Mặc Hi

+

Dịch truyện Trung – Việt · chạy trọn trong trình duyệt

+
+
+ + + +
+
+ +
+ +
+ + +
+ +

Chuẩn bị…

+
+
+
+

Lần đầu tải ~74 MB trọng số — + các lần sau mở nhanh nhờ bộ nhớ đệm của trình duyệt.

+
+ + + + +
+ +
+ + + + + +
+ + + + + + +
+

+ +
+
+
+ +

Hướng dẫn

+

Dịch truyện Trung – Việt ngay trong trình duyệt: văn bản không rời khỏi + máy, tải mô hình một lần rồi có thể chạy offline.

+
    +
  1. Chọn mô hình — Mặc Hi 30 (~74 MB) gọn hơn; Hachimi 60 + (~113 MB) là lựa chọn lớn hơn để so sánh bản dịch.
  2. +
  3. Nhập truyện — dán văn bản hoặc mở/thả file .txt + (UTF-8 / GB18030/GBK / Big5, tối đa 20 MB).
  4. +
  5. Dịch — bấm Dịch hoặc Ctrl Enter, rồi chép hay tải kết quả.
  6. +
+

Quét tên và từ điển dùng khi nào?

+

Nên dùng trước khi dịch truyện có nhiều nhân vật, địa danh, + tổ chức, hoặc tên phiên âm trong bối cảnh phương Tây / Nhật Bản. + Quét tên sẽ gợi ý cách đọc; thêm những tên cần giữ cố định vào từ điển, + ví dụ 爱丽丝 → Alice hoặc 雪乃 → Yukino.

+
    +
  • Từ điển tên riêng — giữ nhất quán tên, danh xưng và thuật ngữ + theo cách bạn chọn.
  • +
  • Bộ nhớ & cài đặt — cụm đã dịch được nhớ riêng theo từng + mô hình; dịch lại file cũ gần như tức thì.
  • +
+

Cần WebGPU: Chrome/Edge 113+ hoặc Safari 26+. + Quét tên tải thêm khoảng 4 MB ở lần dùng đầu.

+

Văn bản nguồn và bản dịch không rời khỏi thiết bị. + Benchmark/báo lỗi chỉ gửi khi bạn chủ động xác nhận; đoạn văn chỉ đính + kèm nếu bạn tự chọn.

+
+ +
+
+ +

+

Không gửi nội dung văn bản — chỉ các thông số bên dưới.

+

+ + +
JSON đầy đủ sẽ gửi +
+

+
+ + +
+
+
`;function ta(e){e.innerHTML=ea;const t={};for(const n of e.querySelectorAll("[data-ref]"))t[n.dataset.ref]=n;return t}const rt=new Map;function tr(e){if(!e?.id)throw new Error("panel cần id");if(typeof e.mount!="function")throw new Error(`panel ${e.id} cần mount()`);return rt.set(e.id,{prefers:"full",...e}),()=>{rt.delete(e.id)}}function na(e){return[...rt.values()].filter(t=>t.available?!!t.available(e):!0)}const ra=90;function oa(e,t,n){const r=()=>!matchMedia("(min-width: 900px)").matches;let s=0,o=0,a=!1;const i=()=>{a&&(a=!1,t.style.transform="",o>ra&&n())};e.addEventListener("pointerdown",l=>{r()&&(a=!0,s=l.clientY,o=0,e.setPointerCapture?.(l.pointerId))}),e.addEventListener("pointermove",l=>{a&&(o=Math.max(0,l.clientY-s),t.style.transform=`translateY(${o}px)`)}),e.addEventListener("pointerup",i),e.addEventListener("pointercancel",i),e.addEventListener("click",()=>{const l=o;o=0,l<=4&&n()})}function sa({tabs:e,overlay:t,rail:n=null,getState:r=()=>({})}){const s=new Map;let o=null,a=null,i=!1;const l=d=>n?.isOpen()&&d?.prefers==="side"?n:t;function c(d){let p=s.get(d.id);return p||(p=document.createElement("div"),p.className="panel-mount",s.set(d.id,p),d.mount(p)),p}function m(d){!d||!s.has(d)||(s.delete(d),rt.get(d)?.destroy?.())}function h(d,p){const E=document.createElement("button");E.type="button",E.className=o===d.id?"ghost paneltab on":"ghost paneltab",d.icon&&E.insertAdjacentHTML("beforeend",d.icon),E.append(d.title);const S=d.badge?.(p);if(S!=null&&S!==""){const w=document.createElement("span");w.className="tabbadge",w.textContent=String(S),E.append(w)}return E.addEventListener("click",()=>{o===d.id&&l(d)===t?M():k(d.id)}),E}function y(d){e.replaceChildren(...na(d).filter(p=>p.tab!==!1).map(p=>h(p,d)))}function k(d){const p=rt.get(d);if(!p)return;if(o&&o!==d){const w=o,f=a;o=null,a=null,m(w),f?.body.replaceChildren()}const E=c(p),S=l(p);S.title.textContent=p.title,S.body.replaceChildren(E),S===t?t.modal.open||t.modal.showModal():t.modal.open&&(i=!0,t.modal.close(),i=!1),o=d,a=S,n?.onChange?.(S!==t),p.update?.(r()),y(r())}function M(){const d=o,p=a;o=null,a=null,m(d),p?.body.replaceChildren(),n?.onChange?.(!1),t.modal.open?t.modal.close():(n?.body.replaceChildren(),y(r()))}function A(){if(!o)return;const d=l(rt.get(o));d!==a&&(d===t?M():k(o))}function v(){const d=r();y(d),o&&rt.get(o)?.update?.(d)}return t.modal.addEventListener("close",()=>{if(i)return;const d=o;o=null,a=null,m(d),n?.onChange?.(!1),t.body.replaceChildren(),n?.body.replaceChildren(),y(r())}),t.modal.addEventListener("click",d=>{d.target===t.modal&&M()}),t.closeBtn.addEventListener("click",M),t.grip&&oa(t.grip,t.modal,M),{open:k,close:M,refresh:v,rehost:A,openId:()=>o}}const aa="moxhi",ia=2,rn="tm",on="\0",ca=15e4;function Ao({modelId:e,weightsTag:t,dtype:n,tokRev:r}={}){const s=[e??"unknown",t??"dev",n??"f16"];return r&&s.push(r),s.join("|")}function la(e,t){return!!e&&!e.complete&&(e.done??0)>0&&e.file===t.file&&e.size===t.size&&e.encoding===t.encoding&&e.model===t.model}function ua(){return new Promise((e,t)=>{const n=indexedDB.open(aa,ia);n.onupgradeneeded=()=>{const r=n.result;r.objectStoreNames.contains(rn)||r.createObjectStore(rn).createIndex("ts","ts"),r.objectStoreNames.contains("partial")&&r.deleteObjectStore("partial")},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)})}async function at(e,t){const n=await ua();try{return await new Promise((r,s)=>{const o=n.transaction(rn,e),a=t(o.objectStore(rn));o.oncomplete=()=>r(typeof a=="function"?a():a),o.onerror=()=>s(o.error),o.onabort=()=>s(o.error??new Error("tx aborted"))})}finally{n.close()}}async function da(e,t){const n=new Array(t.length).fill(null);try{await at("readonly",r=>{t.forEach((s,o)=>{const a=r.get(e+on+s);a.onsuccess=()=>{a.result&&(n[o]=a.result.t)}})})}catch{}return n}async function ha(e,t){try{const n=Date.now();await at("readwrite",r=>{for(const[s,o]of t)r.put({t:o,ts:n},e+on+s)})}catch{}}async function fa(e=ca){try{const t=await at("readonly",r=>{const s=r.count();return()=>s.result});if(t<=e)return;let n=t-Math.floor(e*.9);await at("readwrite",r=>{const s=r.index("ts").openCursor();s.onsuccess=()=>{const o=s.result;!o||n<=0||(o.delete(),n--,o.continue())}})}catch{}}async function ma({sample:e=64}={}){try{const t=await at("readonly",n=>{const r=[],s=n.openKeyCursor();return s.onsuccess=()=>{const o=s.result;if(!o)return;const a=String(o.key),i=a.indexOf(on);if(i<0)return;const l=a.slice(0,i);r.push(l),o.continue(l+"")},()=>r});return t.length?await at("readonly",n=>{const r=t.map(s=>({ns:s,rows:0,bytes:0}));return t.forEach((s,o)=>{const a=IDBKeyRange.bound(s+on,s+"",!1,!0),i=n.count(a);i.onsuccess=()=>{r[o].rows=i.result};const l=n.getAllKeys(a,e),c=n.getAll(a,e);c.onsuccess=()=>{const m=c.result.length;if(!m)return;const h=(l.result??[]).reduce((y,k)=>y+String(k).length,0)+c.result.reduce((y,k)=>y+(k?.t?.length??0),0);r[o].bytes=Math.round(h/m*2*r[o].rows)}}),()=>r}):[]}catch{return[]}}async function pa(e){try{await at("readwrite",t=>{t.delete(IDBKeyRange.bound(e+"\0",e+"",!1,!0))})}catch{}}function ga(e){const[t="",n="",r="",s=null]=String(e??"").split("|");return{model:t,weights:n,dtype:r,tokRev:s}}function ba(e){const t=/^weights\.([0-9a-f]{6,})\./.exec(String(e??""));return t?t[1]:String(e??"")}function va(e){return e?e<1024?`${e} B`:e<1024*1024?`${Math.round(e/1024)} KB`:`${(e/1048576).toFixed(1)} MB`:"—"}const ya=5e3;function wa({getNamespace:e=()=>null,enabled:t=!0,onChange:n=()=>{},prefs:r=null}={}){let s=null,o=[],a=!1,i=!1,l=null,c=0;const m=()=>o.reduce((p,E)=>p+E.rows,0);async function h(){if(!a){a=!0,d();try{o=(await ma()).sort((p,E)=>E.rows-p.rows)}catch{o=[]}i=!0,d(),n(),a=!1}}function y(){clearTimeout(c),l=null}function k(p){if(l!==p){l=p,clearTimeout(c),c=setTimeout(()=>{l=null,d()},ya),d();return}y(),pa(p).then(h)}function M(p,E="hint"){const S=document.createElement("p");return S.className=E,S.textContent=p,S}function A(p,E,S,w){const f=document.createElement("li");f.className="tmrow";const{model:N,weights:T,dtype:P,tokRev:_}=ga(p.ns),g=document.createElement("div");g.className="tmrow-main";const V=document.createElement("b");if(V.textContent=N||"(không rõ)",V.title=[ba(T),P,_&&`tok ${_}`].filter(Boolean).join(" · "),g.append(V),E){const te=document.createElement("span");te.className="tmcur",te.textContent="đang dùng",g.append(te)}const $=document.createElement("span");$.className="tmrow-meta",$.textContent=`${p.rows.toLocaleString("vi-VN")} cụm`+(p.bytes?` · ≈ ${va(p.bytes)}`:"");const re=document.createElement("button");return re.type="button",re.className=w===p.ns?"ghost tmdanger":"ghost",re.textContent=w===p.ns?"Xóa thật?":"Xóa",re.addEventListener("click",()=>S(p.ns)),f.append(g,$,re),f}function v(){const p=document.createElement("label");p.className="auto";const E=document.createElement("input");E.type="checkbox",E.id="auto-toggle",E.name="auto-toggle",E.checked=r.autoTranslate(),E.addEventListener("change",()=>r.setAutoTranslate(E.checked)),p.append(E," Tự dịch khi ngừng gõ");const S=document.createElement("hr");return S.className="panel-sep",[p,M("Chỉ với đoạn ngắn, không áp dụng khi mở file."),S]}function d(){if(!s)return;const p=e(),E=r?v():[];if(E.push(M("Cụm đã dịch được nhớ trong máy — dịch lại là có ngay.")),t||E.push(M("Phiên này đang chạy với ?tm=0 — không đọc cũng không ghi bộ nhớ.")),!i)E.push(M("đang đọc…"));else if(!o.length)E.push(M("Chưa có gì trong bộ nhớ dịch — dịch một file rồi quay lại."));else{const S=document.createElement("ul");S.className="tmlist",S.append(...o.map(w=>A(w,w.ns===p,k,l))),E.push(S),E.push(M((o.length>1?`Tổng ${m().toLocaleString("vi-VN")} cụm. `:"")+"Xóa chỉ bỏ bộ nhớ — bản dịch đang mở không mất."))}s.replaceChildren(...E)}return h(),{id:"memory",tab:!1,title:r?"Bộ nhớ & cài đặt":"Bộ nhớ dịch",prefers:"full",badge:()=>i&&m()?m().toLocaleString("vi-VN"):null,mount(p){s=p,d()},update(){y(),h()},destroy(){clearTimeout(c)}}}function Sa({store:e,autoStore:t=null,autoEnabled:n=!1,onChange:r=()=>{}}={}){let s=null,o="",a=null,i=null,l=null;function c(p){const E=document.createElement("p");return E.className="hint",E.textContent=p,E}function m(){const p=document.createElement("form");p.className="glossform";const E=document.createElement("input");E.placeholder="名字 (tiếng Trung)",E.setAttribute("aria-label","Tên tiếng Trung");const S=document.createElement("input");S.placeholder="Dịch thành…",S.setAttribute("aria-label","Tên tiếng Việt");const w=document.createElement("button");return w.type="submit",w.className="ghost",w.textContent="Thêm",p.append(E,S,w),p.addEventListener("submit",f=>{f.preventDefault(),e.add({zh:E.value,vi:S.value})&&s.querySelector(".glossform input")?.focus()}),p}function h(p){const E=document.createElement("tr");p.enabled||(E.className="glossoff");const S=document.createElement("td");S.className="glosszh",S.textContent=p.zh;const w=document.createElement("td");w.textContent=p.vi;const f=document.createElement("td");f.className="num";const N=document.createElement("input");N.type="checkbox",N.checked=p.enabled,N.title=p.enabled?"Đang áp dụng — bỏ tick để tắt":"Đang tắt",N.addEventListener("change",()=>e.update(p.zh,{enabled:N.checked})),f.append(N);const T=document.createElement("td");T.className="num";const P=document.createElement("button");return P.type="button",P.className="ghost",P.textContent="Xóa",P.addEventListener("click",()=>e.remove(p.zh)),T.append(P),E.append(S,w,f,T),E}function y(p){const E=document.createElement("table");E.className="tmtable glosstable";const S=document.createElement("thead"),w=document.createElement("tr");for(const[N,T]of[["Tên gốc",""],["Dịch thành",""],["Áp","num"],["","num"]]){const P=document.createElement("th");P.className=T,P.textContent=N,w.append(P)}S.append(w);const f=document.createElement("tbody");return f.append(...p.map(h)),E.append(S,f),E}function k(p){return p.status==="suppressed"?"đã tắt":p.status==="frequency"?"tên 2 chữ cần xuất hiện ít nhất 2 lần":p.status==="overridden"?"mục riêng của bạn đang được ưu tiên":p.overflow?`${p.overflow} lượt vượt giới hạn marker`:p.protected?`đã bảo vệ ${p.protected} lượt`:`${p.count} lượt trong văn bản`}function M(p){const E=document.createElement("tr");p.status!=="eligible"&&(E.className="glossoff");const S=document.createElement("td");S.className="glosszh";const w=document.createElement("span");w.className="autobadge",w.textContent="tự động",S.append(p.zh,w);const f=document.createElement("td");if(l===p.zh){const g=document.createElement("form");g.className="glossautoedit";const V=document.createElement("input");V.value=p.vi,V.setAttribute("aria-label",`Sửa cách dịch ${p.zh}`);const $=document.createElement("button");$.type="submit",$.className="ghost",$.textContent="Lưu";const re=document.createElement("button");re.type="button",re.className="ghost",re.textContent="Hủy",re.addEventListener("click",()=>{l=null,d()}),g.addEventListener("submit",te=>{te.preventDefault();const C=V.value.trim();C&&(l=null,o=`đã chuyển ${p.zh} thành mục riêng`,e.add({zh:p.zh,vi:C}),t.suppress(p.zh,!0))}),g.append(V,$,re),f.append(g)}else{f.append(p.vi);const g=document.createElement("small");g.className="glossreason",g.textContent=k(p),f.append(g)}const N=document.createElement("td");N.className="num glossapply";const T=document.createElement("input");T.type="checkbox",T.checked=p.status!=="suppressed",T.disabled=p.status==="frequency"||p.status==="overridden",T.title=T.disabled?k(p):T.checked?"Đang tự động áp dụng — bỏ tick để tắt":"Đã tắt cho các lần dịch sau",T.addEventListener("change",()=>t.suppress(p.zh,!T.checked)),N.append(T);const P=document.createElement("td");P.className="num glossact";const _=document.createElement("button");return _.type="button",_.className="ghost",_.textContent="Sửa",_.addEventListener("click",()=>{l=p.zh,d()}),P.append(_),E.append(S,f,N,P),E}function A(p){const E=document.createElement("table");E.className="tmtable glosstable glossautotable";const S=document.createElement("thead"),w=document.createElement("tr");for(const[N,T]of[["Tên gốc",""],["Dịch thành",""],["Áp","num"],["","num"]]){const P=document.createElement("th");P.className=T,P.textContent=N,w.append(P)}S.append(w);const f=document.createElement("tbody");return f.append(...p.map(M)),E.append(S,f),E}function v(){const p=document.createElement("div");p.className="glosstools";const E=document.createElement("input");E.type="file",E.accept=".json,application/json",E.hidden=!0;const S=document.createElement("button");S.type="button",S.className="ghost",S.textContent="Nhập JSON",S.addEventListener("click",()=>E.click()),E.addEventListener("change",()=>{const f=E.files[0];if(!f)return;const N=new FileReader;N.onload=()=>{try{const{added:T,updated:P}=e.importJson(String(N.result));o=`đã nhập ${T} tên mới, cập nhật ${P}`}catch(T){o=String(T?.message??T)}d()},N.readAsText(f)});const w=document.createElement("button");return w.type="button",w.className="ghost",w.textContent="Xuất JSON",w.addEventListener("click",()=>{const f=document.createElement("a");f.href=URL.createObjectURL(new Blob([e.exportJson()],{type:"application/json"})),f.download="tu-dien.json",f.click(),URL.revokeObjectURL(f.href)}),p.append(S,w,E),p}function d(){if(!s)return;const p=e.list(),E=[c("Tên trong bảng luôn được dịch đúng như bạn chọn.")];if(E.push(m()),p.length?E.push(y(p)):E.push(c("Chưa có tên nào — thêm ở trên, hoặc nhập từ file JSON.")),E.push(v()),n&&t){const S=document.createElement("h3");S.className="glossautohead",S.textContent="Tên khó tự động",E.push(S);const w=t.listDocumentTerms();w.length?E.push(A(w)):E.push(c("Tên khó khớp trong văn bản sẽ hiện ở đây sau lần dịch kế tiếp."))}o&&E.push(c(o)),s.replaceChildren(...E)}return{id:"glossary",title:"Từ điển tên riêng",icon:ue.book,prefers:"full",badge:()=>{const p=n&&t?t.listDocumentTerms().filter(E=>E.status==="eligible").length:0;return e.count()+p||null},mount(p){s=p,a=e.subscribe(()=>{d(),r()}),i=t?.subscribe(()=>{d(),r()})??null,d()},update(){d()},destroy(){a?.(),a=null,i?.(),i=null}}}function Ea(e={}){let t={...e};const n=new Set;return{get:()=>t,set(r){const s=typeof r=="function"?r(t):{...t,...r};if(s===t)return t;t=s;for(const o of[...n])o(t);return t},subscribe(r){return n.add(r),()=>n.delete(r)}}}const ka={translate:new Set(["translate","analyze"]),analyze:new Set};function Ma({onStart:e,onIdle:t,onError:n}={}){const r=Ea({job:null});let s=null,o=null;const a=()=>r.get().job,i=c=>{const m=a();m&&r.set({job:{...m,...c}})};async function l(c){s=new AbortController,r.set({job:{kind:c.kind,label:c.label??"",phase:c.phase??"",done:0,total:c.total??0,cancellable:c.cancellable!==!1}}),e?.(a());try{return await c.exec({signal:s.signal,progress:i})}finally{s=null,r.set({job:null}),t?.();const m=o;o=null,m&&queueMicrotask(()=>{l(m).catch(h=>n?.(h))})}}return{run(c){const m=a();return m?ka[c.kind]?.has(m.kind)?(o=c,Promise.resolve("queued")):Promise.resolve("refused"):l(c).then(()=>"ran")},cancel(){s?.abort()},cancelAll(){o=null,s?.abort()},current:a,subscribe(c){return r.subscribe(()=>c(a()))}}}const Ca=/[\s:,;(\-–—…]/;function nr(e){const t=[];let n="",r=!1;const s=o=>{n&&(t.push({text:n,q:o}),n="")};for(let o=0;oTo){e.textContent=t;return}const n=document.createDocumentFragment(),r=t.split(` +`);for(let s=0;s0&&n.appendChild(document.createTextNode(` +`));for(const o of nr(r[s]))if(o.q){const a=document.createElement("span");a.className="dlg",a.textContent=o.text,n.appendChild(a)}else n.appendChild(document.createTextNode(o.text))}e.replaceChildren(n)}function xa(e){const t=[],n=/[.!?…:;"”]\s+/g;let r=0;for(let s;s=n.exec(e);)t.push(e.slice(r,s.index+s[0].length)),r=s.index+s[0].length;return rnr(a).map(i=>({q:i.q,pieces:xa(i.text)}))),s=r.reduce((a,i)=>a+i.reduce((l,c)=>l+c.pieces.length,0),0);if(n||s>Aa){Ro(e,t);return}e.replaceChildren();let o=0;for(let a=0;a0&&e.appendChild(document.createTextNode(` +`));for(const i of r[a])for(const l of i.pieces){if(!l)continue;const c=document.createElement("span");c.className=i.q?"ink-in dlg":"ink-in",c.style.animationDelay=`${Math.min(o*40,1200)}ms`,c.textContent=l,c.addEventListener("animationend",()=>{c.className=i.q?"dlg":"",c.style.animationDelay=""},{once:!0}),e.appendChild(c),o++}}}function Ra(e){e&&e.addEventListener("click",t=>{const n=e.getBoundingClientRect(),r=document.createElement("span");r.className="ripple",r.style.left=`${t.clientX-n.left||n.width/2}px`,r.style.top=`${t.clientY-n.top||n.height/2}px`,e.appendChild(r),r.addEventListener("animationend",()=>r.remove())})}const Na=[];function No(e,t={}){let n=e;for(const r of Na)n=r(n,t);return n}function Sn(e){return e?e.split(` +`):[]}function Pa(e){if(!e.length)return 0;let t=e.length-1;for(const n of e)t+=n.length;return t}function Ba(e){return e.length>To?e:e.split(` +`).map(t=>nr(t).map(n=>n.text).join("")).join(` +`)}function $a(e,t,n={},{from:r=0,count:s=1/0,ink:o=!1,reduced:a=!1}={}){const i=No(t,n),l=r===0&&s===1/0?i:i.slice(r,r+s),c=l.join(` +`);return o?Ta(e,c,{reduced:a}):Ro(e,c),{text:c,shown:l.length,total:i.length,chars:Pa(i)}}function rr(e,t={}){return Ba(No(e,t).join(` +`))}let En=null;function _n(){return En??=Tt(()=>import("./hanviet_data-DivPLpiI.js"),[]).then(e=>e.default).catch(e=>{throw En=null,e}),En}function Gn(e,t){return Array.from(e??"").map(n=>{const r=t[n];return r?r.charAt(0).toLocaleUpperCase("vi")+r.slice(1):n}).join(" ").replace(/\s+/g," ").trim()}const Ia=2e4;function Zt(e=""){return{origin:"typed",text:e,name:null,bytes:null,encoding:null}}function Po({name:e,bytes:t,text:n,encoding:r}){return{origin:"file",name:e,bytes:t,text:n,encoding:r}}function Da(e){return e?.text?.length??0}function La(){let e=null,t=0;return(n="")=>(n!==e&&(e=n,t+=1),t)}function Oa(e){return Da(e)>=Ia?"long":"short"}function Fa(e){return e?.origin==="file"||Oa(e)==="long"}const _a=[[/[“”《》⟨⟩]/g,'"'],[/[‘’]/g,"'"],[/【/g,"["],[/】/g,"]"],[/。/g,"."],[/·/g,"-"]];function Ga(e){for(const[t,n]of _a)e=e.replace(t,n);return e}function za(e){return e.replace(/\n+/g,` + +`)}function Ua(e,t=null){const n=e?.origin==="file"?e.name:null;if(!n)return"mac-hi.txt";let r=n.replace(/\.txt$/i,"");return t&&(r=r.replace(/\p{Script=Han}+/gu,s=>` ${Gn(s,t)} `).replace(/\s+/g," ").trim()),`${r}.vi.txt`}const zn=e=>typeof e=="string"?e:"";function ja({userAgent:e="",platform:t="",mobile:n,maxTouchPoints:r=0}={}){const s=zn(e),o=zn(t),a=Number.isFinite(Number(r))?Number(r):0,i=/\b(?:iPad|iPhone|iPod)\b/i.test(s)||/Mac/i.test(o)&&a>1,l=i||/Android/i.test(s)||(typeof n=="boolean"?n:/\b(?:Mobile|Mobi)\b/i.test(s));let c="unknown";return i&&/\b(?:CriOS|FxiOS|EdgiOS|OPiOS)\//i.test(s)?c="ios-other":/\bEdg(?:A|iOS)?\//i.test(s)?c="edge":/\b(?:Chrome|Chromium|CriOS)\//i.test(s)?c="chrome":/\b(?:Firefox|FxiOS)\//i.test(s)?c="firefox":/\bSafari\//i.test(s)&&/\bVersion\//i.test(s)&&(c="safari"),{browser:c,mobile:l,ios:i}}function Ha(e){const t=zn(e?.message??e);return/no adapter/i.test(t)?"no-adapter":/WebGPU unavailable/i.test(t)?"missing-api":"unknown"}const Ce=(e,t=null)=>({text:e,address:t});function Wa(e,t){const n=e==="chrome",r=n?"Chrome":"Edge",s=n?"chrome":"edge",o=`${s}://settings/system`,a=`${s}://gpu`,i=`${s}://flags/#enable-unsafe-webgpu`;return{steps:[Ce(`Cập nhật ${r} lên bản mới nhất rồi mở lại trang này.`),Ce(`Mở địa chỉ dưới đây, bật “Dùng tính năng tăng tốc đồ họa khi có thể”, rồi khởi động lại ${r}.`,o),Ce("Sau khi khởi động lại, mở trang chẩn đoán dưới đây và kiểm tra WebGPU hiển thị “Hardware accelerated”.",a)],advanced:t==="no-adapter"?{text:`Chỉ khi ${a} báo WebGPU bị blocklist hoặc không được hỗ trợ, bạn có thể thử cờ dưới đây rồi khởi động lại ${r}. Đây là cờ thử nghiệm; hãy trả về Default nếu trình duyệt thiếu ổn định.`,address:i}:null}}function Ka(e){const t=e==="edge"?"Edge":"Chrome";return{steps:[Ce(`Cập nhật ${t} và Android lên phiên bản mới nhất.`),Ce("Với Chrome, cấu hình phổ biến cần Chrome 121+ và Android 12+; WebGPU vẫn phụ thuộc GPU và driver được thiết bị hỗ trợ."),Ce(`Đóng hẳn ${t}, mở lại trang này rồi bấm “Kiểm tra lại”.`),Ce("Nếu vẫn không kết nối được GPU, hãy thử Chrome mới nhất hoặc một thiết bị WebGPU khác.")],advanced:null}}function Va(e){return{steps:[Ce(`Cập nhật hệ điều hành trên ${e?"iPhone/iPad":"máy Mac"} để có Safari 26+.`),Ce("Đóng hẳn Safari, mở lại trang này rồi bấm “Kiểm tra lại”."),Ce("Nếu vẫn không kết nối được GPU, thiết bị hoặc phiên bản hệ điều hành hiện tại có thể chưa cung cấp adapter WebGPU phù hợp.")],advanced:null}}function qa(){return{steps:[Ce("Cập nhật iOS/iPadOS và Safari lên phiên bản mới nhất."),Ce("Sao chép địa chỉ trang này và mở lại bằng Safari 26+."),Ce("Trong Safari, bấm “Kiểm tra lại” để thử kết nối GPU.")],advanced:null}}function Ja(e){return{steps:[Ce("Cập nhật trình duyệt và hệ điều hành lên phiên bản mới nhất."),Ce("Mở trang này bằng Chrome hoặc Edge mới nhất trên máy tính/Android, hoặc Safari 26+ trên thiết bị Apple."),Ce(e==="firefox"?"Firefox chưa nằm trong cấu hình được ứng dụng kiểm thử; hãy thử một trình duyệt được liệt kê ở trên.":"Nếu trình duyệt hiện tại vẫn không có WebGPU, hãy thử một thiết bị hoặc trình duyệt được liệt kê ở trên.")],advanced:null}}function Qa({userAgent:e="",platform:t="",mobile:n,maxTouchPoints:r=0,message:s=""}={}){const o=ja({userAgent:e,platform:t,mobile:n,maxTouchPoints:r}),a=Ha(s),i=a==="no-adapter"?"Trình duyệt có WebGPU nhưng chưa kết nối được với GPU phù hợp.":a==="missing-api"?"Trình duyệt chưa cung cấp WebGPU cho trang này.":"Trình duyệt chưa khởi tạo được WebGPU.";let l;return(o.browser==="chrome"||o.browser==="edge")&&o.mobile?l=Ka(o.browser):o.browser==="chrome"||o.browser==="edge"?l=Wa(o.browser,a):o.browser==="safari"?l=Va(o.mobile):o.browser==="ios-other"?l=qa():l=Ja(o.browser),{...o,failureKind:a,summary:i,...l}}const Ya=200,jr=/[。。.!!??;;…]/,Xa=/[”’』」)〉》"')\]]/,Za=/[,、,]/;function ei(e){const t=[];let n=0;for(let s=0;s=0?r+1:t,o=e.slice(0,s).trim(),a=e.slice(s).trim();return[...o?sn(o,t):[],...a?sn(a,t):[]]}function ti(e){return sn(e,Ya)}function Bo(e){const t=[],n=[];for(const r of e.split(` +`)){let s=0;for(const o of ei(r))for(const a of ti(o))t.push(a),s++;n.push(s)}return{sentences:t,paras:n}}function ni(e,t,n=200){const r=[],s=[];let o=0;for(const a of t){let i="",l=0;for(let c=0;cn&&(r.push(i),l++,i=""),i+=m}i&&(r.push(i),l++),o+=a,s.push(l)}return{rows:r,rowParas:s}}function ri(e,t){const n=[];let r=0;for(const s of e)n.push(t.slice(r,r+s).join(" ").trim()),r+=s;return n.join(` +`)}const oi={㑯:"㑔",㑳:"㑇",㑶:"㐹",㓨:"刾",㗲:"𠵾",㘚:"㘎",㜄:"㚯",㜏:"㛣",㜢:"𡞱",㠏:"㟆",㠣:"𫵷",㥮:"㤘",㩜:"㨫",㩳:"㧐",㩵:"擜",㺏:"𤠋",䁪:"𥇢",䁻:"䀥",䃮:"鿎",䊷:"䌶",䋙:"䌺",䋚:"䌻",䋹:"䌿",䋻:"䌾",䍦:"䍠",䎱:"䎬",䓣:"𬜯",䙡:"䙌",䜀:"䜧",䝼:"䞍",䡵:"𫟦",䥇:"䦂",䥑:"鿏",䥕:"𬭯",䥱:"䥾",䦛:"䦶",䦟:"䦷",䧢:"𨸟",䮄:"𫠊",䯀:"䯅",䰾:"鲃",䱷:"䲣",䱽:"䲝",䲁:"鳚",䲘:"鳤",䴉:"鹮",丟:"丢",並:"并",乾:"干",亂:"乱",亙:"亘",亞:"亚",佇:"伫",佈:"布",佔:"占",併:"并",來:"来",侖:"仑",侶:"侣",侷:"局",俁:"俣",係:"系",俔:"伣",俠:"侠",俥:"伡",俬:"私",倀:"伥",倆:"俩",倈:"俫",倉:"仓",個:"个",們:"们",倖:"幸",倫:"伦",倲:"㑈",偉:"伟",偑:"㐽",側:"侧",偵:"侦",偽:"伪",傌:"㐷",傑:"杰",傖:"伧",傘:"伞",備:"备",傢:"家",傭:"佣",傯:"偬",傳:"传",傴:"伛",債:"债",傷:"伤",傾:"倾",僂:"偻",僅:"仅",僉:"佥",僑:"侨",僕:"仆",僞:"伪",僤:"𫢸",僥:"侥",僨:"偾",僱:"雇",價:"价",儀:"仪",儁:"俊",儂:"侬",億:"亿",儈:"侩",儉:"俭",儎:"傤",儐:"傧",儔:"俦",儕:"侪",儘:"尽",償:"偿",優:"优",儲:"储",儷:"俪",儸:"㑩",儺:"傩",儻:"傥",儼:"俨",兇:"凶",兌:"兑",兒:"儿",兗:"兖",內:"内",兩:"两",冊:"册",冑:"胄",冪:"幂",凈:"净",凍:"冻",凜:"凛",凱:"凯",別:"别",刪:"删",剄:"刭",則:"则",剋:"克",剎:"刹",剗:"刬",剛:"刚",剝:"剥",剮:"剐",剴:"剀",創:"创",剷:"铲",劃:"划",劄:"札",劇:"剧",劉:"刘",劊:"刽",劌:"刿",劍:"剑",劏:"㓥",劑:"剂",劚:"㔉",勁:"劲",動:"动",務:"务",勛:"勋",勝:"胜",勞:"劳",勢:"势",勣:"𪟝",勩:"勚",勱:"劢",勳:"勋",勵:"励",勸:"劝",勻:"匀",匭:"匦",匯:"汇",匱:"匮",區:"区",協:"协",卹:"恤",卻:"却",卽:"即",厙:"厍",厠:"厕",厤:"历",厭:"厌",厲:"厉",厴:"厣",參:"参",叄:"叁",叢:"丛",吒:"咤",吳:"吴",吶:"呐",呂:"吕",咼:"呙",員:"员",唄:"呗",唸:"念",問:"问",啓:"启",啞:"哑",啟:"启",啢:"唡",喎:"㖞",喚:"唤",喪:"丧",喫:"吃",喬:"乔",單:"单",喲:"哟",嗆:"呛",嗇:"啬",嗊:"唝",嗎:"吗",嗚:"呜",嗩:"唢",嗰:"𠮶",嗶:"哔",嘆:"叹",嘍:"喽",嘓:"啯",嘔:"呕",嘖:"啧",嘗:"尝",嘜:"唛",嘩:"哗",嘮:"唠",嘯:"啸",嘰:"叽",嘵:"哓",嘸:"呒",嘽:"啴",噁:"恶",噓:"嘘",噚:"㖊",噝:"咝",噠:"哒",噥:"哝",噦:"哕",噯:"嗳",噲:"哙",噴:"喷",噸:"吨",噹:"当",嚀:"咛",嚇:"吓",嚌:"哜",嚐:"尝",嚕:"噜",嚙:"啮",嚥:"咽",嚦:"呖",嚧:"𠰷",嚨:"咙",嚮:"向",嚲:"亸",嚳:"喾",嚴:"严",嚶:"嘤",囀:"啭",囁:"嗫",囂:"嚣",囅:"冁",囈:"呓",囉:"啰",囌:"苏",囑:"嘱",囪:"囱",圇:"囵",國:"国",圍:"围",園:"园",圓:"圆",圖:"图",團:"团",垻:"坝",埡:"垭",埨:"𫭢",埰:"采",執:"执",堅:"坚",堊:"垩",堖:"垴",堝:"埚",堯:"尧",報:"报",場:"场",塊:"块",塋:"茔",塏:"垲",塒:"埘",塗:"涂",塚:"冢",塢:"坞",塤:"埙",塵:"尘",塸:"𫭟",塹:"堑",塿:"𪣻",墊:"垫",墜:"坠",墠:"𫮃",墮:"堕",墰:"坛",墳:"坟",墶:"垯",墻:"墙",墾:"垦",壇:"坛",壋:"垱",壎:"埙",壓:"压",壗:"𡋤",壘:"垒",壙:"圹",壚:"垆",壜:"坛",壞:"坏",壟:"垄",壠:"垅",壢:"坜",壩:"坝",壪:"塆",壯:"壮",壺:"壶",壼:"壸",壽:"寿",夠:"够",夢:"梦",夥:"伙",夾:"夹",奐:"奂",奧:"奥",奩:"奁",奪:"夺",奬:"奖",奮:"奋",奼:"姹",妝:"妆",姍:"姗",姦:"奸",娙:"𫰛",娛:"娱",婁:"娄",婦:"妇",婭:"娅",媧:"娲",媯:"妫",媰:"㛀",媼:"媪",媽:"妈",嫋:"袅",嫗:"妪",嫵:"妩",嫺:"娴",嫻:"娴",嫿:"婳",嬀:"妫",嬃:"媭",嬈:"娆",嬋:"婵",嬌:"娇",嬙:"嫱",嬡:"嫒",嬤:"嬷",嬪:"嫔",嬰:"婴",嬸:"婶",孃:"娘",孋:"㛤",孌:"娈",孫:"孙",學:"学",孻:"𡥧",孿:"孪",宮:"宫",寀:"采",寢:"寝",實:"实",寧:"宁",審:"审",寫:"写",寬:"宽",寵:"宠",寶:"宝",將:"将",專:"专",尋:"寻",對:"对",導:"导",尷:"尴",屆:"届",屍:"尸",屓:"屃",屜:"屉",屢:"屡",層:"层",屨:"屦",屬:"属",岡:"冈",峯:"峰",峴:"岘",島:"岛",峽:"峡",崍:"崃",崑:"昆",崗:"岗",崙:"仑",崢:"峥",崬:"岽",嵐:"岚",嵗:"岁",嵽:"𫶇",嵾:"㟥",嶁:"嵝",嶄:"崭",嶇:"岖",嶔:"嵚",嶗:"崂",嶠:"峤",嶢:"峣",嶧:"峄",嶨:"峃",嶮:"崄",嶸:"嵘",嶺:"岭",嶼:"屿",嶽:"岳",巋:"岿",巒:"峦",巔:"巅",巖:"岩",巘:"𪩘",巰:"巯",巹:"卺",帥:"帅",師:"师",帳:"帐",帶:"带",幀:"帧",幃:"帏",幓:"㡎",幗:"帼",幘:"帻",幟:"帜",幣:"币",幫:"帮",幬:"帱",幷:"并",幹:"干",幾:"几",庫:"库",廁:"厕",廂:"厢",廄:"厩",廈:"厦",廎:"庼",廕:"荫",廚:"厨",廝:"厮",廞:"𫷷",廟:"庙",廠:"厂",廡:"庑",廢:"废",廣:"广",廩:"廪",廬:"庐",廳:"厅",弒:"弑",弔:"吊",弳:"弪",張:"张",強:"强",彄:"𫸩",彆:"别",彈:"弹",彌:"弥",彎:"弯",彔:"录",彙:"汇",彠:"彟",彥:"彦",彫:"雕",彲:"彨",彿:"佛",後:"后",徑:"径",從:"从",徠:"徕",復:"复",徵:"征",徹:"彻",恆:"恒",恥:"耻",悅:"悦",悞:"悮",悵:"怅",悶:"闷",悽:"凄",惡:"恶",惱:"恼",惲:"恽",惻:"恻",愛:"爱",愜:"惬",愨:"悫",愴:"怆",愷:"恺",愾:"忾",慄:"栗",態:"态",慍:"愠",慘:"惨",慚:"惭",慟:"恸",慣:"惯",慤:"悫",慪:"怄",慫:"怂",慮:"虑",慳:"悭",慶:"庆",慺:"㥪",慼:"戚",慾:"欲",憂:"忧",憊:"惫",憐:"怜",憑:"凭",憒:"愦",憖:"慭",憚:"惮",憤:"愤",憫:"悯",憮:"怃",憲:"宪",憶:"忆",懇:"恳",應:"应",懌:"怿",懍:"懔",懞:"蒙",懟:"怼",懣:"懑",懤:"㤽",懨:"恹",懲:"惩",懶:"懒",懷:"怀",懸:"悬",懺:"忏",懼:"惧",懾:"慑",戀:"恋",戇:"戆",戔:"戋",戧:"戗",戩:"戬",戰:"战",戱:"戯",戲:"戏",戶:"户",扞:"捍",拋:"抛",拚:"拼",挩:"捝",挱:"挲",挾:"挟",捨:"舍",捫:"扪",捱:"挨",捲:"卷",掃:"扫",掄:"抡",掆:"㧏",掗:"挜",掙:"挣",掛:"挂",採:"采",揀:"拣",揚:"扬",換:"换",揮:"挥",揯:"搄",損:"损",搖:"摇",搗:"捣",搧:"扇",搵:"揾",搶:"抢",摑:"掴",摜:"掼",摟:"搂",摯:"挚",摳:"抠",摶:"抟",摺:"折",摻:"掺",撈:"捞",撏:"挦",撐:"撑",撓:"挠",撝:"㧑",撟:"挢",撣:"掸",撥:"拨",撫:"抚",撲:"扑",撳:"揿",撻:"挞",撾:"挝",撿:"捡",擁:"拥",擄:"掳",擇:"择",擊:"击",擋:"挡",擓:"㧟",擔:"担",據:"据",擠:"挤",擡:"抬",擣:"捣",擬:"拟",擯:"摈",擰:"拧",擱:"搁",擲:"掷",擴:"扩",擷:"撷",擺:"摆",擻:"擞",擼:"撸",擽:"㧰",擾:"扰",攄:"摅",攆:"撵",攏:"拢",攔:"拦",攖:"撄",攙:"搀",攛:"撺",攜:"携",攝:"摄",攢:"攒",攣:"挛",攤:"摊",攪:"搅",攬:"揽",敎:"教",敓:"敚",敗:"败",敘:"叙",敵:"敌",數:"数",斂:"敛",斃:"毙",斆:"敩",斕:"斓",斬:"斩",斷:"断",於:"于",旂:"旗",旣:"既",昇:"升",時:"时",晉:"晋",晛:"𬀪",晝:"昼",暈:"晕",暉:"晖",暐:"𬀩",暘:"旸",暢:"畅",暫:"暂",曄:"晔",曆:"历",曇:"昙",曉:"晓",曏:"向",曖:"暧",曠:"旷",曥:"𣆐",曨:"昽",曬:"晒",書:"书",會:"会",朥:"𦛨",朧:"胧",朮:"术",東:"东",枴:"拐",柵:"栅",柺:"拐",査:"查",桱:"𣐕",桿:"杆",梔:"栀",梘:"枧",梜:"𬂩",條:"条",梟:"枭",梲:"棁",棄:"弃",棊:"棋",棖:"枨",棗:"枣",棟:"栋",棡:"㭎",棧:"栈",棲:"栖",棶:"梾",椏:"桠",椲:"㭏",楊:"杨",楓:"枫",楨:"桢",業:"业",極:"极",榘:"矩",榦:"干",榪:"杩",榮:"荣",榲:"榅",榿:"桤",構:"构",槍:"枪",槓:"杠",槤:"梿",槧:"椠",槨:"椁",槮:"椮",槳:"桨",槶:"椢",槼:"椝",樁:"桩",樂:"乐",樅:"枞",樑:"梁",樓:"楼",標:"标",樞:"枢",樢:"㭤",樣:"样",樧:"榝",樫:"㭴",樳:"桪",樸:"朴",樹:"树",樺:"桦",樿:"椫",橈:"桡",橋:"桥",機:"机",橢:"椭",橫:"横",橯:"𣓿",檁:"檩",檉:"柽",檔:"档",檜:"桧",檟:"槚",檢:"检",檣:"樯",檮:"梼",檯:"台",檳:"槟",檸:"柠",檻:"槛",櫃:"柜",櫍:"𬃊",櫓:"橹",櫚:"榈",櫛:"栉",櫝:"椟",櫞:"橼",櫟:"栎",櫥:"橱",櫧:"槠",櫨:"栌",櫪:"枥",櫫:"橥",櫬:"榇",櫱:"蘖",櫳:"栊",櫸:"榉",櫻:"樱",欄:"栏",欅:"榉",權:"权",欏:"椤",欒:"栾",欓:"𣗋",欖:"榄",欞:"棂",欽:"钦",歎:"叹",歐:"欧",歟:"欤",歡:"欢",歲:"岁",歷:"历",歸:"归",歿:"殁",殘:"残",殞:"殒",殤:"殇",殨:"㱮",殫:"殚",殭:"僵",殮:"殓",殯:"殡",殰:"㱩",殲:"歼",殺:"杀",殻:"壳",殼:"壳",毀:"毁",毆:"殴",毿:"毵",氂:"牦",氈:"毡",氌:"氇",氣:"气",氫:"氢",氬:"氩",氳:"氲",氾:"泛",汎:"泛",汙:"污",決:"决",沒:"没",沖:"冲",況:"况",泝:"溯",洩:"泄",洶:"汹",浹:"浃",浿:"𬇙",涇:"泾",涗:"涚",涼:"凉",淒:"凄",淚:"泪",淥:"渌",淨:"净",淩:"凌",淪:"沦",淵:"渊",淶:"涞",淺:"浅",渙:"涣",減:"减",渢:"沨",渦:"涡",測:"测",渾:"浑",湊:"凑",湋:"𣲗",湞:"浈",湧:"涌",湯:"汤",溈:"沩",準:"准",溝:"沟",溫:"温",溮:"浉",溳:"涢",溼:"湿",滄:"沧",滅:"灭",滌:"涤",滎:"荥",滙:"汇",滬:"沪",滯:"滞",滲:"渗",滷:"卤",滸:"浒",滻:"浐",滾:"滚",滿:"满",漁:"渔",漊:"溇",漍:"𬇹",漚:"沤",漢:"汉",漣:"涟",漬:"渍",漲:"涨",漵:"溆",漸:"渐",漿:"浆",潁:"颍",潑:"泼",潔:"洁",潕:"𣲘",潙:"沩",潚:"㴋",潛:"潜",潤:"润",潯:"浔",潰:"溃",潷:"滗",潿:"涠",澀:"涩",澆:"浇",澇:"涝",澐:"沄",澗:"涧",澠:"渑",澤:"泽",澦:"滪",澩:"泶",澫:"𬇕",澮:"浍",澱:"淀",澾:"㳠",濁:"浊",濃:"浓",濄:"㳡",濆:"𣸣",濕:"湿",濘:"泞",濚:"溁",濛:"蒙",濜:"浕",濟:"济",濤:"涛",濧:"㳔",濫:"滥",濰:"潍",濱:"滨",濺:"溅",濼:"泺",濾:"滤",瀂:"澛",瀅:"滢",瀆:"渎",瀇:"㲿",瀉:"泻",瀋:"沈",瀏:"浏",瀕:"濒",瀘:"泸",瀝:"沥",瀟:"潇",瀠:"潆",瀦:"潴",瀧:"泷",瀨:"濑",瀰:"弥",瀲:"潋",瀾:"澜",灃:"沣",灄:"滠",灑:"洒",灒:"𪷽",灕:"漓",灘:"滩",灙:"𣺼",灝:"灏",灡:"㳕",灣:"湾",灤:"滦",灧:"滟",灩:"滟",災:"灾",為:"为",烏:"乌",烴:"烃",無:"无",煉:"炼",煒:"炜",煙:"烟",煢:"茕",煥:"焕",煩:"烦",煬:"炀",煱:"㶽",熅:"煴",熒:"荧",熗:"炝",熰:"𬉼",熱:"热",熲:"颎",熾:"炽",燀:"𬊤",燁:"烨",燈:"灯",燉:"炖",燒:"烧",燖:"𬊈",燙:"烫",燜:"焖",營:"营",燦:"灿",燬:"毁",燭:"烛",燴:"烩",燶:"㶶",燻:"熏",燼:"烬",燾:"焘",爍:"烁",爐:"炉",爛:"烂",爭:"争",爲:"为",爺:"爷",爾:"尔",牀:"床",牆:"墙",牘:"牍",牴:"抵",牽:"牵",犖:"荦",犛:"牦",犢:"犊",犧:"牺",狀:"状",狹:"狭",狽:"狈",猙:"狰",猶:"犹",猻:"狲",獁:"犸",獃:"呆",獄:"狱",獅:"狮",獎:"奖",獨:"独",獪:"狯",獫:"猃",獮:"狝",獰:"狞",獱:"㺍",獲:"获",獵:"猎",獷:"犷",獸:"兽",獺:"獭",獻:"献",獼:"猕",玀:"猡",現:"现",琱:"雕",琺:"珐",琿:"珲",瑋:"玮",瑒:"玚",瑣:"琐",瑤:"瑶",瑩:"莹",瑪:"玛",瑲:"玱",璉:"琏",璊:"𫞩",璕:"𬍤",璗:"𬍡",璡:"琎",璣:"玑",璦:"瑷",璫:"珰",璯:"㻅",環:"环",璵:"玙",璸:"瑸",璽:"玺",璿:"璇",瓅:"𬍛",瓊:"琼",瓏:"珑",瓔:"璎",瓚:"瓒",瓛:"𤩽",甌:"瓯",甕:"瓮",產:"产",産:"产",畝:"亩",畢:"毕",畫:"画",異:"异",畵:"画",當:"当",疇:"畴",疊:"叠",痙:"痉",痠:"酸",痾:"疴",瘂:"痖",瘋:"疯",瘍:"疡",瘓:"痪",瘞:"瘗",瘡:"疮",瘧:"疟",瘮:"瘆",瘲:"疭",瘺:"瘘",瘻:"瘘",療:"疗",癆:"痨",癇:"痫",癉:"瘅",癒:"愈",癘:"疠",癟:"瘪",癡:"痴",癢:"痒",癤:"疖",癥:"症",癧:"疬",癩:"癞",癬:"癣",癭:"瘿",癮:"瘾",癰:"痈",癱:"瘫",癲:"癫",發:"发",皁:"皂",皚:"皑",皰:"疱",皸:"皲",皺:"皱",盃:"杯",盜:"盗",盞:"盏",盡:"尽",監:"监",盤:"盘",盧:"卢",盪:"荡",眞:"真",眥:"眦",眾:"众",睍:"𪾢",睏:"困",睜:"睁",睞:"睐",瞘:"眍",瞜:"䁖",瞞:"瞒",瞶:"瞆",瞼:"睑",矇:"蒙",矓:"眬",矚:"瞩",矯:"矫",硃:"朱",硜:"硁",硤:"硖",硨:"砗",硯:"砚",碕:"埼",碩:"硕",碭:"砀",碸:"砜",確:"确",碼:"码",碽:"䂵",磑:"硙",磚:"砖",磠:"硵",磣:"碜",磧:"碛",磯:"矶",磽:"硗",磾:"䃅",礄:"硚",礎:"础",礐:"𬒈",礙:"碍",礦:"矿",礪:"砺",礫:"砾",礬:"矾",礱:"砻",祕:"秘",祿:"禄",禍:"祸",禎:"祯",禕:"祎",禡:"祃",禦:"御",禪:"禅",禮:"礼",禰:"祢",禱:"祷",禿:"秃",秈:"籼",稅:"税",稈:"秆",稏:"䅉",稜:"棱",稟:"禀",種:"种",稱:"称",穀:"谷",穇:"䅟",穌:"稣",積:"积",穎:"颖",穠:"秾",穡:"穑",穢:"秽",穩:"稳",穫:"获",穭:"穞",窩:"窝",窪:"洼",窮:"穷",窯:"窑",窵:"窎",窶:"窭",窺:"窥",竄:"窜",竅:"窍",竇:"窦",竈:"灶",竊:"窃",竪:"竖",競:"竞",筆:"笔",筍:"笋",筧:"笕",筴:"䇲",箇:"个",箋:"笺",箏:"筝",箚:"札",節:"节",範:"范",築:"筑",篋:"箧",篔:"筼",篠:"筿",篢:"𬕂",篤:"笃",篩:"筛",篳:"筚",篸:"𥮾",簀:"箦",簍:"篓",簑:"蓑",簞:"箪",簡:"简",簣:"篑",簫:"箫",簹:"筜",簽:"签",簾:"帘",籃:"篮",籅:"𥫣",籌:"筹",籔:"䉤",籙:"箓",籛:"篯",籜:"箨",籟:"籁",籠:"笼",籤:"签",籩:"笾",籪:"簖",籬:"篱",籮:"箩",籲:"吁",粵:"粤",糉:"粽",糝:"糁",糞:"粪",糧:"粮",糰:"团",糲:"粝",糴:"籴",糶:"粜",糹:"纟",糾:"纠",紀:"纪",紂:"纣",紃:"𬘓",約:"约",紅:"红",紆:"纡",紇:"纥",紈:"纨",紉:"纫",紋:"纹",納:"纳",紐:"纽",紓:"纾",純:"纯",紕:"纰",紖:"纼",紗:"纱",紘:"纮",紙:"纸",級:"级",紛:"纷",紜:"纭",紝:"纴",紞:"𬘘",紡:"纺",紬:"䌷",紮:"扎",細:"细",紱:"绂",紲:"绁",紳:"绅",紵:"纻",紹:"绍",紺:"绀",紼:"绋",紿:"绐",絀:"绌",終:"终",絃:"弦",組:"组",絅:"䌹",絆:"绊",絎:"绗",結:"结",絕:"绝",絛:"绦",絝:"绔",絞:"绞",絡:"络",絢:"绚",給:"给",絨:"绒",絪:"𬘡",絰:"绖",統:"统",絲:"丝",絳:"绛",絶:"绝",絹:"绢",絺:"𫄨",綁:"绑",綃:"绡",綄:"𬘫",綆:"绠",綈:"绨",綉:"绣",綌:"绤",綎:"𬘩",綏:"绥",綐:"䌼",綑:"捆",經:"经",綖:"𫄧",綜:"综",綝:"𬘭",綞:"缍",綠:"绿",綡:"𫟅",綢:"绸",綣:"绻",綧:"𬘯",綪:"𬘬",綫:"线",綬:"绶",維:"维",綯:"绹",綰:"绾",綱:"纲",網:"网",綳:"绷",綴:"缀",綵:"彩",綸:"纶",綹:"绺",綺:"绮",綻:"绽",綽:"绰",綾:"绫",綿:"绵",緄:"绲",緇:"缁",緊:"紧",緋:"绯",緑:"绿",緒:"绪",緓:"绬",緔:"绱",緗:"缃",緘:"缄",緙:"缂",線:"线",緝:"缉",緞:"缎",締:"缔",緡:"缗",緣:"缘",緦:"缌",編:"编",緩:"缓",緬:"缅",緯:"纬",緱:"缑",緲:"缈",練:"练",緶:"缏",緹:"缇",緻:"致",緼:"缊",縈:"萦",縉:"缙",縊:"缢",縋:"缒",縐:"绉",縑:"缣",縕:"缊",縗:"缞",縛:"缚",縝:"缜",縞:"缟",縟:"缛",縣:"县",縧:"绦",縫:"缝",縭:"缡",縮:"缩",縯:"𬙂",縱:"纵",縲:"缧",縳:"䌸",縴:"纤",縵:"缦",縶:"絷",縷:"缕",縹:"缥",總:"总",績:"绩",繃:"绷",繅:"缫",繆:"缪",繒:"缯",織:"织",繕:"缮",繚:"缭",繞:"绕",繡:"绣",繢:"缋",繩:"绳",繪:"绘",繫:"系",繭:"茧",繮:"缰",繯:"缳",繰:"缲",繳:"缴",繶:"𫄷",繸:"䍁",繹:"绎",繻:"𦈡",繼:"继",繽:"缤",繾:"缱",繿:"䍀",纁:"𫄸",纆:"𬙊",纇:"颣",纈:"缬",纊:"纩",續:"续",纍:"累",纏:"缠",纓:"缨",纔:"才",纕:"𬙋",纖:"纤",纘:"缵",纜:"缆",缽:"钵",罃:"䓨",罈:"坛",罌:"罂",罎:"坛",罰:"罚",罵:"骂",罷:"罢",羅:"罗",羆:"罴",羈:"羁",羋:"芈",羣:"群",羥:"羟",羨:"羡",義:"义",羶:"膻",習:"习",翫:"玩",翬:"翚",翹:"翘",翽:"翙",耬:"耧",耮:"耢",聖:"圣",聞:"闻",聯:"联",聰:"聪",聲:"声",聳:"耸",聵:"聩",聶:"聂",職:"职",聹:"聍",聽:"听",聾:"聋",肅:"肃",脅:"胁",脈:"脉",脛:"胫",脣:"唇",脩:"修",脫:"脱",脹:"胀",腎:"肾",腖:"胨",腡:"脶",腦:"脑",腫:"肿",腳:"脚",腸:"肠",膃:"腽",膕:"腘",膚:"肤",膞:"䏝",膠:"胶",膢:"𦝼",膩:"腻",膽:"胆",膾:"脍",膿:"脓",臉:"脸",臍:"脐",臏:"膑",臘:"腊",臚:"胪",臟:"脏",臠:"脔",臢:"臜",臥:"卧",臨:"临",臺:"台",與:"与",興:"兴",舉:"举",舊:"旧",舖:"铺",舘:"馆",艙:"舱",艤:"舣",艦:"舰",艫:"舻",艱:"艰",艷:"艳",芻:"刍",苧:"苎",茲:"兹",荊:"荆",莊:"庄",莖:"茎",莢:"荚",莧:"苋",華:"华",菴:"庵",菸:"烟",萇:"苌",萊:"莱",萬:"万",萴:"荝",萵:"莴",葉:"叶",葒:"荭",葤:"荮",葦:"苇",葯:"药",葷:"荤",蒍:"𫇭",蒐:"搜",蒓:"莼",蒔:"莳",蒕:"蒀",蒞:"莅",蒼:"苍",蓀:"荪",蓆:"席",蓋:"盖",蓮:"莲",蓯:"苁",蓴:"莼",蓽:"荜",蔄:"𬜬",蔔:"卜",蔘:"参",蔞:"蒌",蔣:"蒋",蔥:"葱",蔦:"茑",蔭:"荫",蔯:"𫈟",蔿:"𫇭",蕁:"荨",蕆:"蒇",蕎:"荞",蕒:"荬",蕓:"芸",蕕:"莸",蕘:"荛",蕢:"蒉",蕩:"荡",蕪:"芜",蕭:"萧",蕷:"蓣",薀:"蕰",薈:"荟",薊:"蓟",薌:"芗",薑:"姜",薔:"蔷",薘:"荙",薟:"莶",薦:"荐",薩:"萨",薳:"䓕",薴:"苧",薵:"䓓",薹:"苔",薺:"荠",藍:"蓝",藎:"荩",藝:"艺",藥:"药",藪:"薮",藭:"䓖",藴:"蕴",藶:"苈",藹:"蔼",藺:"蔺",蘀:"萚",蘄:"蕲",蘆:"芦",蘇:"苏",蘊:"蕴",蘋:"苹",蘚:"藓",蘞:"蔹",蘟:"𦻕",蘢:"茏",蘭:"���",蘺:"蓠",蘿:"萝",虆:"蔂",虉:"𬟁",處:"处",虛:"虚",虜:"虏",號:"号",虧:"亏",虯:"虬",蛺:"蛱",蛻:"蜕",蜆:"蚬",蝀:"𬟽",蝕:"蚀",蝟:"猬",蝦:"虾",蝨:"虱",蝸:"蜗",螄:"蛳",螞:"蚂",螢:"萤",螮:"䗖",螻:"蝼",螿:"螀",蟄:"蛰",蟈:"蝈",蟎:"螨",蟣:"虮",蟬:"蝉",蟯:"蛲",蟲:"虫",蟳:"𫊻",蟶:"蛏",蟻:"蚁",蠁:"蚃",蠅:"蝇",蠆:"虿",蠍:"蝎",蠐:"蛴",蠑:"蝾",蠔:"蚝",蠟:"蜡",蠣:"蛎",蠨:"蟏",蠱:"蛊",蠶:"蚕",蠻:"蛮",衆:"众",衊:"蔑",術:"术",衕:"同",衚:"胡",衛:"卫",衝:"冲",袞:"衮",袷:"夹",裊:"袅",裏:"里",補:"补",裝:"装",裡:"里",製:"制",複:"复",褌:"裈",褘:"袆",褲:"裤",褳:"裢",褸:"褛",褻:"亵",襀:"𫌀",襇:"裥",襉:"裥",襏:"袯",襖:"袄",襝:"裣",襠:"裆",襤:"褴",襪:"袜",襬:"摆",襯:"衬",襲:"袭",襴:"襕",覈:"核",見:"见",覎:"觃",規:"规",覓:"觅",視:"视",覘:"觇",覡:"觋",覥:"觍",覦:"觎",親:"亲",覬:"觊",覯:"觏",覲:"觐",覷:"觑",覺:"觉",覽:"览",覿:"觌",觀:"观",觴:"觞",觶:"觯",觸:"触",訁:"讠",訂:"订",訃:"讣",計:"计",訊:"讯",訌:"讧",討:"讨",訏:"𬣙",訐:"讦",訒:"讱",訓:"训",訕:"讪",訖:"讫",託:"托",記:"记",訛:"讹",訝:"讶",訟:"讼",訢:"䜣",訣:"诀",訥:"讷",訩:"讻",訪:"访",設:"设",許:"许",訴:"诉",訶:"诃",診:"诊",註:"注",証:"证",詀:"𧮪",詁:"诂",詆:"诋",詎:"讵",詐:"诈",詒:"诒",詔:"诏",評:"评",詖:"诐",詗:"诇",詘:"诎",詛:"诅",詝:"𬣞",詞:"词",詠:"咏",詡:"诩",詢:"询",詣:"诣",試:"试",詩:"诗",詪:"𬣳",詫:"诧",詬:"诟",詭:"诡",詮:"诠",詰:"诘",話:"话",該:"该",詳:"详",詵:"诜",詷:"𫍣",詼:"诙",詿:"诖",誄:"诔",誅:"诛",誆:"诓",誇:"夸",誌:"志",認:"认",誑:"诳",誒:"诶",誕:"诞",誘:"诱",誚:"诮",語:"语",誠:"诚",誡:"诫",誣:"诬",誤:"误",誥:"诰",誦:"诵",誨:"诲",說:"说",説:"说",誰:"谁",課:"课",誶:"谇",誹:"诽",誼:"谊",誾:"訚",調:"调",諂:"谄",諄:"谆",談:"谈",諉:"诿",請:"请",諍:"诤",諏:"诹",諑:"诼",諒:"谅",諓:"𬣡",論:"论",諗:"谂",諛:"谀",諜:"谍",諝:"谞",諞:"谝",諟:"𬤊",諡:"谥",諢:"诨",諤:"谔",諦:"谛",諧:"谐",諫:"谏",諭:"谕",諮:"咨",諱:"讳",諲:"𬤇",諳:"谙",諴:"𫍯",諶:"谌",諷:"讽",諸:"诸",諺:"谚",諼:"谖",諾:"诺",謀:"谋",謁:"谒",謂:"谓",謄:"誊",謅:"诌",謊:"谎",謎:"谜",謏:"𫍲",謐:"谧",謔:"谑",謖:"谡",謗:"谤",謙:"谦",謚:"谥",講:"讲",謝:"谢",謠:"谣",謡:"谣",謨:"谟",謫:"谪",謬:"谬",謭:"谫",謳:"讴",謹:"谨",謾:"谩",譁:"哗",證:"证",譎:"谲",譏:"讥",譓:"𬤝",譖:"谮",識:"识",譙:"谯",譚:"谭",譜:"谱",譞:"𫍽",譟:"噪",譫:"谵",譭:"毁",譯:"译",議:"议",譴:"谴",護:"护",譸:"诪",譽:"誉",譾:"谫",讀:"读",讅:"谉",變:"变",讋:"詟",讌:"䜩",讎:"雠",讒:"谗",讓:"让",讕:"谰",讖:"谶",讚:"赞",讜:"谠",讞:"谳",谿:"溪",豈:"岂",豎:"竖",豐:"丰",豔:"艳",豬:"猪",豶:"豮",貍:"狸",貓:"猫",貙:"䝙",貝:"贝",貞:"贞",貟:"贠",負:"负",財:"财",貢:"贡",貧:"贫",貨:"货",販:"贩",貪:"贪",貫:"贯",責:"责",貯:"贮",貰:"贳",貲:"赀",貳:"贰",貴:"贵",貶:"贬",買:"买",貸:"贷",貺:"贶",費:"费",貼:"贴",貽:"贻",貿:"贸",賀:"贺",賁:"贲",賂:"赂",賃:"赁",賄:"贿",賅:"赅",資:"资",賈:"贾",賊:"贼",賑:"赈",賒:"赊",賓:"宾",賕:"赇",賙:"赒",賚:"赉",賜:"赐",賞:"赏",賠:"赔",賡:"赓",賢:"贤",賣:"卖",賤:"贱",賦:"赋",賧:"赕",質:"质",賫:"赍",賬:"账",賭:"赌",賰:"䞐",賴:"赖",賵:"赗",賺:"赚",賻:"赙",購:"购",賽:"赛",賾:"赜",贄:"贽",贅:"赘",贇:"赟",贈:"赠",贊:"赞",贋:"赝",贍:"赡",贏:"赢",贐:"赆",贓:"赃",贔:"赑",贖:"赎",贗:"赝",贛:"赣",贜:"赃",赬:"赪",趕:"赶",趙:"赵",趨:"趋",趲:"趱",跡:"迹",踐:"践",踰:"逾",踴:"踊",蹌:"跄",蹕:"跸",蹟:"迹",蹠:"跖",蹣:"蹒",蹤:"踪",蹺:"跷",躂:"跶",躉:"趸",躊:"踌",躋:"跻",躍:"跃",躎:"䟢",躑:"踯",躒:"跞",躓:"踬",躕:"蹰",躚:"跹",躡:"蹑",躥:"蹿",躦:"躜",躪:"躏",軀:"躯",車:"车",軋:"轧",軌:"轨",軍:"军",軏:"𫐄",軑:"轪",軒:"轩",軔:"轫",軛:"轭",軝:"𬨂",軟:"软",軤:"轷",軫:"轸",軲:"轱",軸:"轴",軹:"轵",軺:"轺",軻:"轲",軼:"轶",軾:"轼",較:"较",輄:"𨐈",輅:"辂",輇:"辁",輈:"辀",載:"载",輊:"轾",輋:"𪨶",輒:"辄",輓:"挽",輔:"辅",輕:"轻",輗:"𫐐",輛:"辆",輜:"辎",輝:"辉",輞:"辋",輟:"辍",輥:"辊",輦:"辇",輩:"辈",輪:"轮",輬:"辌",輮:"𫐓",輯:"辑",輳:"辏",輶:"𬨎",輸:"输",輻:"辐",輼:"辒",輾:"辗",輿:"舆",轀:"辒",轂:"毂",轄:"辖",轅:"辕",轆:"辘",轉:"转",轍:"辙",轎:"轿",轔:"辚",轟:"轰",轡:"辔",轢:"轹",轤:"轳",辦:"办",辭:"辞",辮:"辫",辯:"辩",農:"农",迴:"回",逕:"径",這:"这",連:"连",週:"周",進:"进",遊:"游",運:"运",過:"过",達:"达",違:"违",遙:"遥",遜:"逊",遞:"递",遠:"远",遡:"溯",適:"适",遲:"迟",遶:"绕",遷:"迁",選:"选",遺:"遗",遼:"辽",邁:"迈",還:"还",邇:"迩",邊:"边",邏:"逻",邐:"逦",郟:"郏",郵:"邮",鄆:"郓",鄉:"乡",鄒:"邹",鄔:"邬",鄖:"郧",鄧:"邓",鄩:"𬩽",鄭:"郑",鄰:"邻",鄲:"郸",鄳:"𫑡",鄴:"邺",鄶:"郐",鄺:"邝",酇:"酂",酈:"郦",醃:"腌",醖:"酝",醜:"丑",醞:"酝",醟:"蒏",醣:"糖",醫:"医",醬:"酱",醱:"酦",醲:"𬪩",釀:"酿",釁:"衅",釃:"酾",釅:"酽",釋:"释",釐:"厘",釒:"钅",釓:"钆",釔:"钇",釕:"钌",釗:"钊",釘:"钉",釙:"钋",針:"针",釣:"钓",釤:"钐",釦:"扣",釧:"钏",釩:"钒",釴:"𬬩",釵:"钗",釷:"钍",釹:"钕",釺:"钎",釾:"䥺",釿:"𬬱",鈀:"钯",鈁:"钫",鈃:"钘",鈄:"钭",鈅:"钥",鈇:"𫓧",鈈:"钚",鈉:"钠",鈍:"钝",鈎:"钩",鈐:"钤",鈑:"钣",鈒:"钑",鈔:"钞",鈕:"钮",鈞:"钧",鈡:"钟",鈣:"钙",鈥:"钬",鈦:"钛",鈧:"钪",鈮:"铌",鈰:"铈",鈳:"钶",鈴:"铃",鈷:"钴",鈸:"钹",鈹:"铍",鈺:"钰",鈽:"钸",鈾:"铀",鈿:"钿",鉀:"钾",鉅:"巨",鉆:"钻",鉈:"铊",鉉:"铉",鉊:"𬬿",鉋:"铇",鉍:"铋",鉑:"铂",鉕:"钷",鉗:"钳",鉚:"铆",鉛:"铅",鉝:"𫟷",鉞:"钺",鉢:"钵",鉤:"钩",鉥:"𬬸",鉦:"钲",鉧:"𬭁",鉬:"钼",鉭:"钽",鉮:"𬬹",鉳:"锫",鉶:"铏",鉷:"𫟹",鉸:"铰",鉺:"铒",鉻:"铬",鉿:"铪",銀:"银",銃:"铳",銅:"铜",銈:"𫓯",銍:"铚",銑:"铣",銓:"铨",銖:"铢",銘:"铭",銚:"铫",銛:"铦",銜:"衔",銠:"铑",銣:"铷",銥:"铱",銦:"铟",銨:"铵",銩:"铥",銪:"铕",銫:"铯",銬:"铐",銱:"铞",銳:"锐",銶:"𨱇",銷:"销",銹:"锈",銻:"锑",銼:"锉",鋁:"铝",鋃:"锒",鋅:"锌",鋇:"钡",鋌:"铤",鋏:"铗",鋐:"𬭎",鋒:"锋",鋗:"𫓶",鋙:"铻",鋝:"锊",鋟:"锓",鋣:"铘",鋤:"锄",鋥:"锃",鋦:"锔",鋨:"锇",鋩:"铓",鋪:"铺",鋭:"锐",鋮:"铖",鋯:"锆",鋰:"锂",鋱:"铽",鋶:"锍",鋸:"锯",鋹:"𬬮",鋼:"钢",錀:"𬬭",錁:"锞",錄:"录",錆:"锖",錇:"锫",錈:"锩",錏:"铔",錐:"锥",錒:"锕",錕:"锟",錘:"锤",錙:"锱",錚:"铮",錛:"锛",錞:"𬭚",錟:"锬",錠:"锭",錡:"锜",錢:"钱",錤:"𫓹",錦:"锦",錨:"锚",錩:"锠",錫:"锡",錮:"锢",錯:"错",録:"录",錳:"锰",錶:"表",錸:"铼",錼:"镎",鍀:"锝",鍁:"锨",鍃:"锪",鍅:"钫",鍆:"钔",鍇:"锴",鍈:"锳",鍊:"炼",鍋:"锅",鍍:"镀",鍔:"锷",鍘:"铡",鍚:"钖",鍛:"锻",鍠:"锽",鍤:"锸",鍥:"锲",鍩:"锘",鍬:"锹",鍭:"𬭤",鍰:"锾",鍵:"键",鍶:"锶",鍺:"锗",鍼:"针",鍾:"钟",鎂:"镁",鎄:"锿",鎇:"镅",鎊:"镑",鎌:"镰",鎓:"𬭩",鎔:"镕",鎖:"锁",鎘:"镉",鎚:"锤",鎛:"镈",鎝:"𨱏",鎡:"镃",鎢:"钨",鎣:"蓥",鎦:"镏",鎧:"铠",鎩:"铩",鎪:"锼",鎬:"镐",鎭:"镇",鎮:"镇",鎰:"镒",鎲:"镋",鎳:"镍",鎵:"镓",鎶:"鿔",鎸:"镌",鎿:"镎",鏃:"镞",鏇:"旋",鏈:"链",鏌:"镆",鏍:"镙",鏏:"𬭬",鏐:"镠",鏑:"镝",鏗:"铿",鏘:"锵",鏜:"镗",鏝:"镘",鏞:"镛",鏟:"铲",鏡:"镜",鏢:"镖",鏤:"镂",鏨:"錾",鏰:"镚",鏵:"铧",鏷:"镤",鏹:"镪",鏺:"䥽",鏻:"𬭸",鏽:"锈",鐃:"铙",鐄:"𨱑",鐇:"𫔍",鐋:"铴",鐍:"𫔎",鐏:"𨱔",鐐:"镣",鐒:"铹",鐓:"镦",鐔:"镡",鐘:"钟",鐙:"镫",鐝:"镢",鐠:"镨",鐥:"䦅",鐦:"锎",鐧:"锏",鐨:"镄",鐩:"𬭼",鐫:"镌",鐮:"镰",鐯:"䦃",鐲:"镯",鐳:"镭",鐵:"铁",鐶:"镮",鐸:"铎",鐺:"铛",鐽:"𫟼",鐿:"镱",鑄:"铸",鑊:"镬",鑌:"镔",鑑:"鉴",鑒:"鉴",鑔:"镲",鑕:"锧",鑞:"镴",鑠:"铄",鑣:"镳",鑥:"镥",鑪:"𬬻",鑭:"镧",鑰:"钥",鑱:"镵",鑲:"镶",鑷:"镊",鑹:"镩",鑼:"锣",鑽:"钻",鑾:"銮",鑿:"凿",钁:"镢",钂:"镋",長:"长",門:"门",閂:"闩",閃:"闪",閆:"闫",閈:"闬",閉:"闭",開:"开",閌:"闶",閎:"闳",閏:"闰",閑:"闲",閒:"闲",間:"间",閔:"闵",閘:"闸",閡:"阂",閣:"阁",閤:"合",閥:"阀",閨:"闺",閩:"闽",閫:"阃",閬:"阆",閭:"闾",閱:"阅",閲:"阅",閶:"阊",閹:"阉",閻:"阎",閼:"阏",閽:"阍",閾:"阈",閿:"阌",闃:"阒",闆:"板",闇:"暗",闈:"闱",闉:"𬮱",闊:"阔",闋:"阕",闌:"阑",闍:"阇",闐:"阗",闑:"𫔶",闒:"阘",闓:"闿",闔:"阖",闕:"阙",闖:"闯",關:"关",闞:"阚",闠:"阓",闡:"阐",闢:"辟",闤:"阛",闥:"闼",陘:"陉",陝:"陕",陞:"升",陣:"阵",陰:"阴",陳:"陈",陸:"陆",陽:"阳",隉:"陧",隊:"队",階:"阶",隑:"𬮿",隕:"陨",際:"际",隤:"𬯎",隨:"随",險:"险",隮:"𬯀",隯:"陦",隱:"隐",隴:"陇",隸:"隶",隻:"只",雋:"隽",雖:"虽",雙:"双",雛:"雏",雜:"杂",雞:"鸡",離:"离",難:"难",雲:"云",電:"电",霑:"沾",霢:"霡",霧:"雾",霽:"霁",靂:"雳",靄:"霭",靆:"叇",靈:"灵",靉:"叆",靚:"靓",靜:"静",靝:"靔",靦:"腼",靨:"靥",鞏:"巩",鞝:"绱",鞦:"秋",鞽:"鞒",韁:"缰",韃:"鞑",韆:"千",韉:"鞯",韋:"韦",韌:"韧",韍:"韨",韓:"韩",韙:"韪",韜:"韬",韝:"鞲",韞:"韫",韻:"韵",響:"响",頁:"页",頂:"顶",頃:"顷",項:"项",順:"顺",頇:"顸",須:"须",頊:"顼",頌:"颂",頍:"𫠆",頎:"颀",頏:"颃",預:"预",頑:"顽",頒:"颁",頓:"顿",頔:"𬱖",頗:"颇",領:"领",頜:"颌",頠:"𬱟",頡:"颉",頤:"颐",頦:"颏",頫:"𫖯",頭:"头",頮:"颒",頰:"颊",頲:"颋",頴:"颕",頵:"𫖳",頷:"颔",頸:"颈",頹:"颓",頻:"频",頽:"颓",顆:"颗",題:"题",額:"额",顎:"颚",顏:"颜",顒:"颙",顓:"颛",顔:"颜",顗:"𫖮",願:"愿",顙:"颡",顛:"颠",類:"类",顢:"颟",顥:"颢",顧:"顾",顫:"颤",顬:"颥",顯:"显",顰:"颦",顱:"颅",顳:"颞",顴:"颧",風:"风",颭:"飐",颮:"飑",颯:"飒",颱:"台",颳:"刮",颶:"飓",颸:"飔",颺:"飏",颻:"飖",颼:"飕",飀:"飗",飄:"飘",飆:"飙",飈:"飚",飛:"飞",飠:"饣",飢:"饥",飣:"饤",飥:"饦",飩:"饨",飪:"饪",飫:"饫",飭:"饬",飯:"饭",飱:"飧",飲:"饮",飴:"饴",飼:"饲",飽:"饱",飾:"饰",飿:"饳",餃:"饺",餄:"饸",餅:"饼",餈:"糍",餉:"饷",養:"养",餌:"饵",餎:"饹",餏:"饻",餑:"饽",餒:"馁",餓:"饿",餕:"馂",餖:"饾",餗:"𫗧",餘:"余",餚:"肴",餛:"馄",餜:"馃",餞:"饯",餡:"馅",館:"馆",餬:"糊",餱:"糇",餳:"饧",餵:"喂",餶:"馉",餷:"馇",餸:"𩠌",餺:"馎",餼:"饩",餾:"馏",餿:"馊",饁:"馌",饃:"馍",饅:"馒",饈:"馐",饉:"馑",饊:"馓",饋:"馈",饌:"馔",饑:"饥",饒:"饶",饗:"飨",饘:"𫗴",饜:"餍",饞:"馋",饢:"馕",馬:"马",馭:"驭",馮:"冯",馱:"驮",馳:"驰",馴:"驯",馹:"驲",馼:"𫘜",駁:"驳",駃:"𫘝",駉:"𬳶",駐:"驻",駑:"驽",駒:"驹",駓:"𬳵",駔:"驵",駕:"驾",駘:"骀",駙:"驸",駛:"驶",駝:"驼",駟:"驷",駡:"骂",駢:"骈",駪:"𬳽",駭:"骇",駰:"骃",駱:"骆",駸:"骎",駼:"𬳿",駿:"骏",騁:"骋",騂:"骍",騄:"𫘧",騅:"骓",騊:"𫘦",騌:"骔",騍:"骒",騎:"骑",騏:"骐",騑:"𬴂",騖:"骛",騙:"骗",騞:"𬴃",騠:"𫘨",騤:"骙",騧:"䯄",騫:"骞",騭:"骘",騮:"骝",騰:"腾",騱:"𫘬",騵:"𫘪",騶:"驺",騷:"骚",騸:"骟",騾:"骡",驀:"蓦",驁:"骜",驂:"骖",驃:"骠",驄:"骢",驅:"驱",驊:"骅",驌:"骕",驍:"骁",驎:"𬴊",驏:"骣",驕:"骄",驗:"验",驚:"惊",驛:"驿",驟:"骤",驢:"驴",驤:"骧",驥:"骥",驦:"骦",驪:"骊",驫:"骉",骯:"肮",髏:"髅",髒:"脏",體:"体",髕:"髌",髖:"髋",髮:"发",鬆:"松",鬍:"胡",鬚:"须",鬢:"鬓",鬥:"斗",鬧:"闹",鬨:"哄",鬩:"阋",鬮:"阄",鬱:"郁",鬹:"鬶",魎:"魉",魘:"魇",魚:"鱼",魛:"鱽",魟:"𫚉",魢:"鱾",魨:"鲀",魯:"鲁",魴:"鲂",魷:"鱿",魺:"鲄",鮀:"𬶍",鮁:"鲅",鮃:"鲆",鮆:"𫚖",鮈:"𬶋",鮊:"鲌",鮋:"鲉",鮍:"鲏",鮎:"鲇",鮐:"鲐",鮑:"鲍",鮒:"鲋",鮓:"鲊",鮚:"鲒",鮜:"鲘",鮝:"鲞",鮞:"鲕",鮟:"𩽾",鮠:"𬶏",鮡:"𬶐",鮣:"䲟",鮦:"鲖",鮪:"鲔",鮫:"鲛",鮭:"鲑",鮮:"鲜",鮳:"鲓",鮶:"鲪",鮸:"𩾃",鮺:"鲝",鯀:"鲧",鯁:"鲠",鯇:"鲩",鯉:"鲤",鯊:"鲨",鯒:"鲬",鯔:"鲻",鯕:"鲯",鯖:"鲭",鯗:"鲞",鯛:"鲷",鯝:"鲴",鯡:"鲱",鯢:"鲵",鯤:"鲲",鯧:"鲳",鯨:"鲸",鯪:"鲮",鯫:"鲰",鯰:"鲶",鯴:"鲺",鯷:"鳀",鯻:"𬶟",鯽:"鲫",鯿:"鳊",鰁:"鳈",鰂:"鲗",鰃:"鳂",鰆:"䲠",鰈:"鲽",鰉:"鳇",鰊:"𬶠",鰌:"䲡",鰍:"鳅",鰏:"鲾",鰐:"鳄",鰒:"鳆",鰓:"鳃",鰛:"鳁",鰜:"鳒",鰟:"鳑",鰠:"鳋",鰣:"鲥",鰤:"𫚕",鰥:"鳏",鰧:"䲢",鰨:"鳎",鰩:"鳐",鰭:"鳍",鰮:"鳁",鰱:"鲢",鰲:"鳌",鰳:"鳓",鰵:"鳘",鰶:"𬶭",鰷:"鲦",鰹:"鲣",鰺:"鲹",鰻:"鳗",鰼:"鳛",鰾:"鳔",鱀:"𬶨",鱂:"鳉",鱅:"鳙",鱇:"𩾌",鱈:"鳕",鱉:"鳖",鱒:"鳟",鱔:"鳝",鱖:"鳜",鱗:"鳞",鱘:"鲟",鱚:"𬶮",鱝:"鲼",鱟:"鲎",鱠:"鲙",鱣:"鳣",鱤:"鳡",鱧:"鳢",鱨:"鲿",鱭:"鲚",鱯:"鳠",鱲:"𫚭",鱷:"鳄",鱸:"鲈",鱺:"鲡",鳥:"鸟",鳧:"凫",鳩:"鸠",鳬:"凫",鳲:"鸤",鳳:"凤",鳴:"鸣",鳶:"鸢",鳾:"䴓",鴆:"鸩",鴇:"鸨",鴉:"鸦",鴒:"鸰",鴕:"鸵",鴛:"鸳",鴝:"鸲",鴞:"鸮",鴟:"鸱",鴣:"鸪",鴦:"鸯",鴨:"鸭",鴯:"鸸",鴰:"鸹",鴴:"鸻",鴷:"䴕",鴻:"鸿",鴿:"鸽",鵁:"䴔",鵂:"鸺",鵃:"鸼",鵏:"𬷕",鵐:"鹀",鵑:"鹃",鵒:"鹆",鵓:"鹁",鵜:"鹈",鵝:"鹅",鵟:"𫛭",鵠:"鹄",鵡:"鹉",鵪:"鹌",鵬:"鹏",鵮:"鹐",鵯:"鹎",鵰:"雕",鵲:"鹊",鵷:"鹓",鵾:"鹍",鶄:"䴖",鶇:"鸫",鶉:"鹑",鶊:"鹒",鶓:"鹋",鶖:"鹙",鶘:"鹕",鶚:"鹗",鶠:"𬸘",鶡:"鹖",鶥:"鹛",鶩:"鹜",鶪:"䴗",鶬:"鸧",鶯:"莺",鶱:"𬸣",鶲:"鹟",鶴:"鹤",鶹:"鹠",鶺:"鹡",鶻:"鹘",鶼:"鹣",鶿:"鹚",鷀:"鹚",鷁:"鹢",鷂:"鹞",鷄:"鸡",鷉:"䴘",鷊:"鹝",鷓:"鹧",鷖:"鹥",鷗:"鸥",鷙:"鸷",鷚:"鹨",鷟:"𬸦",鷥:"鸶",鷦:"鹪",鷫:"鹔",鷭:"𬸪",鷯:"鹩",鷲:"鹫",鷳:"鹇",鷴:"鹇",鷸:"鹬",鷹:"鹰",鷺:"鹭",鷽:"鸴",鸂:"㶉",鸇:"鹯",鸊:"䴙",鸌:"鹱",鸏:"鹲",鸑:"𬸚",鸕:"鸬",鸘:"鹴",鸚:"鹦",鸛:"鹳",鸝:"鹂",鸞:"鸾",鹵:"卤",鹹:"咸",鹺:"鹾",鹼:"碱",鹽:"盐",麗:"丽",麥:"麦",麩:"麸",麪:"面",麫:"面",麬:"𤿲",麯:"曲",麳:"𪎌",麴:"曲",麵:"面",麼:"么",麽:"么",黃:"黄",黌:"黉",點:"点",黨:"党",黲:"黪",黴:"霉",黶:"黡",黷:"黩",黽:"黾",黿:"鼋",鼂:"鼌",鼉:"鼍",鼕:"冬",鼴:"鼹",齊:"齐",齋:"斋",齎:"赍",齏:"齑",齒:"齿",齔:"龀",齕:"龁",齗:"龂",齘:"𬹼",齙:"龅",齜:"龇",齟:"龃",齠:"龆",齡:"龄",齣:"出",齦:"龈",齧:"啮",齪:"龊",齬:"龉",齮:"𬺈",齯:"𫠜",齲:"龋",齶:"腭",齷:"龌",齼:"𬺓",龍:"龙",龎:"厐",龐:"庞",龑:"䶮",龔:"龚",龕:"龛",龜:"龟","鿁":"䜤","鿓":"鿒","𠁞":"𠀾","𠗣":"㓆","𡃕":"𠴛","𡅏":"𠲥","𡑍":"𫭼","𡑭":"𡋗","𡓾":"𡋀","𡔖":"𡍣","𡞵":"㛟","𡠹":"㛿","𡢃":"㛠","𡮉":"𡭜","𡮣":"𡭬","𡳳":"𡳃","𡻕":"岁","𡾱":"㟜","𢣚":"𢘝","𢶫":"𢫞","𢹿":"𢬦","𣈶":"暅","𣙎":"㭣","𣞻":"𣘓","𣠩":"𣞎","𣠲":"𣑶","𣯶":"毶","𣾷":"㳢","𤁣":"𣺽","𤅶":"𣷷","𤓩":"𤊰","𤪺":"㻘","𤫩":"㻏","𤳸":"𤳄","𥊝":"𥅿","𥌃":"𥅘","𥕥":"𥐰","𥖅":"𥐯","𥗽":"𬒗","𥢢":"䅪","𥸠":"𥮋","𥼽":"𥹥","𦘧":"𡳒","𦣎":"𦟗","𦪙":"䑽","𧜗":"䘞","𧜵":"䙊","𧝞":"䘛","𧟀":"𧝧","𧩙":"䜥","𧵳":"䞌","𧶧":"䞎","𨊰":"䢀","𨊸":"䢁","𨋢":"䢂","𨤻":"𨤰","𨦫":"䦀","𨧀":"𬭊","𨧜":"䦁","𨨏":"𬭛","𨭆":"𬭶","𨭎":"𬭳","𨯅":"䥿","𩞯":"䭪","𩠴":"𩠠","𩣑":"䯃","𩶘":"䲞","𰻞":"𰻝","「":"“","」":"”","『":"‘","』":"’"},or={一坏:"一坯",一目瞭然:"一目了然",七逕:"七迳",上逕:"上迳",上鍊:"上链",不可貲計:"不可赀計",不瞭解:"不了解",么麼:"幺麽",么麽:"幺麽",九逕山:"九迳山",乾佑縣:"乾佑县",乾元:"乾元",乾卦:"乾卦",乾嘉:"乾嘉",乾圖:"乾图",乾坤:"乾坤",乾坤一擲:"乾坤一掷",乾坤再造:"乾坤再造",乾坤大挪移:"乾坤大挪移",乾宅:"乾宅",乾安縣:"乾安县",乾安鎮:"乾安镇",乾州:"乾州",乾斷:"乾断",乾旦:"乾旦",乾曜:"乾曜",乾清宮:"乾清宫",乾盛世:"乾盛世",乾紅:"乾红",乾綱:"乾纲",乾縣:"乾县",乾象:"乾象",乾造:"乾造",乾道:"乾道",乾闥婆:"乾闼婆",乾陵:"乾陵",乾隆:"乾隆",乾隆年間:"乾隆年间",乾隆皇帝:"乾隆皇帝",二噁英:"二𫫇英",以免藉口:"以免借口",傢俱:"家具",允祕:"允祕",八濛山:"八濛山",其陰多蒐:"其阴多蒐",凌藉:"凌借",函覆:"函复",剋架:"剋架",剋毒:"剋毒",千鍾粟:"千锺粟",南氾:"南氾",南逕:"南迳",反反覆覆:"反反复复",反覆:"反复",反覆思維:"反复思维",反覆思量:"反复思量",反覆性:"反复性",名覆金甌:"名复金瓯",吳祕:"吴祕",吳育昇:"吴育昇",哪吒:"哪吒",回覆:"回复",土坏:"土坯",坏土:"坯土",坏子:"坯子",坏布:"坯布",坏戶:"坯户",墨沈沈:"墨沉沉",壺裏乾坤:"壶里乾坤",大目乾連冥間救母變文:"大目乾连冥间救母变文",宫商角徵羽:"宫商角徵羽",尼乾子:"尼乾子",尼乾陀:"尼乾陀",年釐:"年釐",幺麼:"幺麽",幺麼小丑:"幺麽小丑",幺麼小醜:"幺麽小丑",康乾:"康乾",張昇:"张昇",張法乾:"张法乾",彷彿:"仿佛",徐胤昇:"徐胤昇",復甦:"复苏",徵弦:"徵弦",徵絃:"徵弦",徵羽摩柯:"徵羽摩柯",徵聲:"徵声",徵調:"徵调",徵音:"徵音",意志消沈:"意志消沉",憑藉:"凭借",憑藉着:"凭借着",懷釐:"怀釐",手鍊:"手链",打坏:"打坯",扞格:"扞格",扭轉乾坤:"扭转乾坤",批覆:"批复",找藉口:"找借口",折戟沈沙:"折戟沉沙",折戟沈河:"折戟沉河",拉坏:"拉坯",拉鍊:"拉链",拉鍊工程:"拉链工程",拜覆:"拜复",挨剋:"挨剋",捏坏:"捏坯",擊沈:"击沉",據瞭解:"据了解",於世成:"於世成",於乎:"於乎",於仲完:"於仲完",於倫:"於伦",於其一:"於其一",於則:"於则",於勇明:"於勇明",於呼哀哉:"於呼哀哉",於單:"於单",於坦:"於坦",於崇文:"於崇文",於忠祥:"於忠祥",於惟一:"於惟一",於戲:"於戏",於敖:"於敖",於梨華:"於梨华",於清言:"於清言",於潛:"於潜",於琳:"於琳",於穆:"於穆",於竹屋:"於竹屋",於菟:"於菟",於邑:"於邑",於陵子:"於陵子",旋乾轉坤:"旋乾转坤",旋轉乾坤:"旋转乾坤",旋轉乾坤之力:"旋转乾坤之力",明瞭:"明了",明覆:"明复",昏沈:"昏沉",春蒐:"春蒐",春釐:"春釐",暗沈沈:"暗沉沉",書中自有千鍾粟:"书中自有千锺粟",朝乾夕惕:"朝乾夕惕",木吒:"木吒",李乾德:"李乾德",李昇:"李昇",李昇勳:"李昇勋",李澤鉅:"李泽钜",李祕:"李祕",李鍊福:"李链福",李鍾郁:"李锺郁",束脩:"束脩",東氾:"东氾",梁昇卿:"梁昇卿",梁章鉅:"梁章钜",楊聯陞:"杨联陞",樊於期:"樊於期",死氣沈沈:"死气沉沉",段脩:"段脩",毛坏:"毛坯",水逕:"水迳",氾勝之:"氾胜之",氾南:"氾南",氾國:"氾国",氾水:"氾水",沈下:"沉下",沈不住氣:"沉不住气",沈住氣:"沉住气",沈冤:"沉冤",沈厚:"沉厚",沈吟:"沉吟",沈寂:"沉寂",沈得住氣:"沉得住气",沈思:"沉思",沈思往事:"沉思往事",沈悶:"沉闷",沈沒:"沉没",沈沒成本:"沉没成本",沈浮:"沉浮",沈浸:"沉浸",沈浸於:"沉浸于",沈淪:"沉沦",沈湎:"沉湎",沈湎酒色:"沉湎酒色",沈溺:"沉溺",沈滯:"沉滞",沈滯性:"沉滞性",沈澱:"沉淀",沈澱出來:"沉淀出来",沈澱劑:"沉淀剂",沈澱法:"沉淀法",沈澱物:"沉淀物",沈濁:"沉浊",沈甸甸:"沉甸甸",沈痛:"沉痛",沈痼:"沉痼",沈痾:"沉疴",沈睡:"沉睡",沈睡不醒:"沉睡不醒",沈砂池:"沉砂池",沈積:"沉积",沈積岩:"沉积岩",沈積石:"沉积石",沈筒:"沉筒",沈船:"沉船",沈落:"沉落",沈迷:"沉迷",沈迷不醒:"沉迷不醒",沈醉:"沉醉",沈重:"沉重",沈降:"沉降",沈陷:"沉陷",沈靜:"沉静",沈靜下來:"沉静下来",沈香:"沉香",沈鬱:"沉郁",沈魚落雁:"沉鱼落雁",沈默:"沉默",沈默不語:"沉默不语",沈默寡言:"沉默寡言",沙逕:"沙迳",河逕:"河迳",流徵:"流徵",浪蕩乾坤:"浪荡乾坤",浮沈:"浮沉",海哩:"海里",深沈:"深沉",深沈不露:"深沉不露",溫昇豪:"温昇豪",滑藉:"滑借",烏昇:"乌昇",烏沈沈:"乌沉沉",烏逕:"乌迳",狐藉虎威:"狐借虎威",王彥昇:"王彦昇",珍珠項鍊:"珍珠项链",甚鉅:"甚钜",甦生:"苏生",甦醒:"苏醒",申昇勳:"申昇勋",申覆:"申复",畢昇:"毕昇",盧象昇:"卢象昇",目劄:"目劄",瞭如:"了如",瞭如指掌:"了如指掌",瞭然:"了然",瞭然於心:"了然于心",瞭若指掌:"了若指掌",瞭解:"了解",瞭解到:"了解到",破釜沈舟:"破釜沉舟",磚坏:"砖坯",示覆:"示复",社逕:"社迳",祕丕笈:"祕丕笈",祕彭祖:"祕彭祖",祕瓊:"祕琼",祝釐:"祝釐",稟覆:"禀复",竺乾:"竺乾",答覆:"答复",篤麼:"笃麽",簡單明瞭:"简单明了",籌畫:"筹划",素藉:"素借",耳沈:"耳沉",肉脩:"肉脩",肘手鍊足:"肘手链足",胤祕:"胤祕",脩敬:"脩敬",脩炳:"脩炳",脩脡:"脩脡",脩脯:"脩脯",脩金:"脩金",脫坏:"脱坯",腶脩:"腶脩",英哩:"英里",茅蒐:"茅蒐",茵藉:"茵借",萬鍾:"万锺",落雁沈魚:"落雁沉鱼",蒐于紅:"蒐于红",蒐於紅:"蒐于红",蒐狩:"蒐狩",蒐獮:"蒐狝",蒐獵:"蒐猎",蒐田:"蒐田",蒐畋:"蒐畋",蒐苗:"蒐苗",蒜薹:"蒜薹",蔣昇:"蒋昇",蕓薹:"芸薹",蕭乾:"萧乾",藉代:"借代",藉以:"借以",藉助:"借助",藉助於:"借助于",藉卉:"借卉",藉口:"借口",藉喻:"借喻",藉寇兵:"借寇兵",藉寇兵齎盜糧:"借寇兵赍盗粮",藉手:"借手",藉據:"借据",藉故:"借故",藉故推辭:"借故推辞",藉方:"借方",藉條:"借条",藉槁:"借槁",藉機:"借机",藉此:"借此",藉此機會:"借此机会",藉甚:"借甚",藉由:"借由",藉着:"借着",藉端:"借端",藉端生事:"借端生事",藉箸代籌:"借箸代筹",藉草枕塊:"借草枕块",藉詞:"借词",藉讀:"借读",藉資:"借资",衹得:"只得",衹見樹木:"只见树木",衹見樹木不見森林:"只见树木不见森林",袁祕:"袁祕",袖裏乾坤:"袖里乾坤",袷袢:"袷袢",製坏:"制坯",覆信:"复信",覆呈:"复呈",覆命:"复命",覆墓:"复墓",覆帳:"复帐",覆按:"复按",覆文:"复文",覆校:"复校",覆電:"复电",見覆:"见复",角徵:"角徵",角徵羽:"角徵羽",計畫:"计划",變徵:"变徵",變徵之聲:"变徵之声",變徵之音:"变徵之音",谿工:"谿工",赤石逕:"赤石迳",踅門瞭戶:"踅门了户",躪藉:"躏借",載沈載浮:"载沉载浮",載浮載沈:"载浮载沉",辛祕:"辛祕",逆釐:"逆釐",逕口:"迳口",逕聯:"迳联",逕頭:"迳头",郭子乾:"郭子乾",酒逢知己千鍾少:"酒逢知己千锺少",醞藉:"酝借",重覆:"重复",金吒:"金吒",金昇玟:"金昇玟",金鍊:"金链",鈞覆:"钧复",鉅子:"钜子",鉅萬:"钜万",鉅防:"钜防",鉸鍊:"铰链",銀鍊:"银链",鋼坏:"钢坯",錢鍾書:"钱锺书",鍊墜:"链坠",鍊子:"链子",鍊形:"链形",鍊條:"链条",鍊錘:"链锤",鍊鎖:"链锁",鍛鍾:"锻锺",鍾繇:"锺繇",鍾萬梅:"锺万梅",鍾重發:"锺重发",鍾鍛:"锺锻",鍾馗:"锺馗",鎖鍊:"锁链",鐵鍊:"铁链",鑽石項鍊:"钻石项链",鑿坏:"凿坯",閻鶴昇:"阎鹤昇",陰沈:"阴沉",陰沈沈:"阴沉沉",陰陰沈沈:"阴阴沉沉",陳志昇:"陈志昇",陳昇:"陈昇",陶坏:"陶坯",雁杳魚沈:"雁杳鱼沉",電覆:"电复",韓昇延:"韩昇延",項鍊:"项链",頸鍊:"颈链",顛乾倒坤:"颠乾倒坤",顛倒乾坤:"颠倒乾坤",顧藉:"顾借",魏徵:"魏徵",魚沈雁杳:"鱼沉雁杳",麪坏兒:"面坯儿",麼些族:"麽些族",黃鍾公:"黄锺公",黑沈沈:"黑沉沉",龔昇:"龚昇"};let Rt=null,gt=null;function $o(){Rt=new Map(Object.entries(oi)),gt=new Map;for(const e of Object.keys(or)){const t=e[0];let n=gt.get(t);n||gt.set(t,n=[]),n.push(e)}for(const e of gt.values())e.sort((t,n)=>n.length-t.length)}function De(e){Rt||$o();let t="",n=0,r=0;const s=e.length;for(;r{r.push(i),r.length>=t&&(n.push(r.join("")),r.length=0)};for(;oString(n??"")).join(" ").toLowerCase();return/swiftshader|llvmpipe|basic render/.test(t)||String(e?.vendor??"").toLowerCase().trim()==="google"}function Do(e){return(e.flags?.length??0)>0?"flags":e.schedule!==void 0&&e.schedule!==null?"schedule-autotune":((e.tmHits??0)+(e.resumeHits??0))/Math.max(1,e.sentences??0)>.05?"tm-reuse":e.decodedRows!==void 0&&e.decodedRows!==null&&e.decodedRows<30?"few-rows":e.mode==="file"||(e.sentences??0)>=30?null:"small"}const ii={gpuWebgl:512,gpuName:256,model:128,platformVersion:64,cpuArch:32,browserFull:128};[...Object.keys(ii)];function ci(e){if(typeof e!="string"||!e.trim())return null;let t=e.trim();const n=t.match(/^ANGLE \((.+)\)$/);if(n){const s=n[1].split(", ");t=s.length>=3?s.slice(1,-1).join(", "):s[s.length-1]}const r=t.match(/^Vulkan[\s\d.]+\((.+)\)$/i);return r&&(t=r[1]),t=t.replace(/ANGLE Metal Renderer:\s*/i,"").replace(/\(0x[0-9A-Fa-f]+\)/g,"").replace(/\b(Direct3D\d+|vs_\d+_\d+|ps_\d+_\d+|OpenGL(?: ES)?[\d. ]*)\b/g,"").replace(/\((TM|R|C)\)/gi,"").replace(/\s{2,}/g," ").trim().replace(/[,;·]+$/,"").replace(/\s+GPU$/i,"").trim().replace(/^(\S+)( \1)+(?= |$)/i,"$1"),t||null}const li={nvidia:["nvidia","geforce"],amd:["amd","radeon","ati"],intel:["intel"],apple:["apple"],qualcomm:["qualcomm","adreno"],arm:["arm","mali"],samsung:["samsung","xclipse"]};function Lo(e,t,n){const r=String(e??"").toLowerCase().trim();if(!r||r==="google")return!1;const s=`${t??""} ${n??""}`.toLowerCase();return(li[r]??[r]).some(o=>s.includes(o))}function ui(e,t){return t&&/\d/.test(t)?t:e}function di(e){if(typeof e!="string"||!e.trim())return e;const t=o=>/\S\s+\S/.test(o);let n=e.trim();const r=n.replace(/^(NVIDIA\s+(GeForce\s+)?|AMD\s+|Qualcomm\s+)/i,"");t(r)&&(n=r);const s=n.replace(/\s+(Graphics|GPU)$/i,"");return t(s)&&(n=s),n}function hi(e){const t=String(e??"");return/\b[ab]\d{3}\b/i.test(t)||/hpg/i.test(t)?!1:/\b(intel|iris|uhd|xe)\b/i.test(t)?!0:/\bradeon\b/i.test(t)&&(/\b\d{3}m\b/i.test(t)||/\bradeon(\s*\(tm\))?\s+graphics$/i.test(t))}function sr(){try{const e=document.createElement("canvas"),t=e.getContext("webgl2",{powerPreference:"high-performance"})??e.getContext("webgl",{powerPreference:"high-performance"});if(!t)return null;const n=t.getExtension("WEBGL_debug_renderer_info"),r=n?{vendor:String(t.getParameter(n.UNMASKED_VENDOR_WEBGL)??""),renderer:String(t.getParameter(n.UNMASKED_RENDERER_WEBGL)??"")}:null;return t.getExtension("WEBGL_lose_context")?.loseContext(),r}catch{return null}}function fi(e,t,n=sr()){return Io(e)?/swiftshader/i.test(String(e?.architecture??""))?"Google SwiftShader":t:!n||!Lo(e?.vendor,n.vendor,n.renderer)?t:ui(t,ci(n.renderer))}function Nt(e){let t;try{t=window[`${e}Storage`];const n="moxhi.storage.probe";t.setItem(n,"1"),t.removeItem(n)}catch{const n=new Map;return{persistent:!1,getItem:r=>n.get(r)??null,setItem:(r,s)=>{n.set(r,String(s))},removeItem:r=>{n.delete(r)}}}return{persistent:!0,getItem:n=>{try{return t.getItem(n)}catch{return null}},setItem:(n,r)=>{try{t.setItem(n,r)}catch{}},removeItem:n=>{try{t.removeItem(n)}catch{}}}}const mi=1,en=1e3,kn="moxhi.scheduleAuto.seed.v1",pi=new Set(["off","shadow","apply","auto"]),gi=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;if(!Number.isInteger(en)||en<0||en>1e4)throw new Error("schedule auto rollout basis points must be an integer from 0 to 10000");function Hr(e){return typeof e!="string"||!gi.test(e)?null:Number.parseInt(e.slice(0,8),16)%1e4}function Ne(e,t,n,r){return{mode:e,source:t,reason:n,revision:mi,rolloutBps:r}}function bi({enabled:e=!1,explicitMode:t=null,rolloutBps:n=en,getStorage:r=()=>null,createSeed:s=()=>null}={}){if(t!==null){const l=pi.has(t)?t:"off";return Ne(l,"explicit",l===t?"explicit":"explicit-invalid",n)}if(e!==!0)return Ne("off","default","caller-disabled",n);if(!Number.isInteger(n)||n<0||n>1e4)return Ne("off","default","rollout-invalid",0);if(n===0)return Ne("off","default","rollout-disabled",0);let o;try{o=r()}catch{return Ne("off","default","storage-error",n)}if(o?.persistent!==!0)return Ne("off","default","storage-unavailable",n);let a;try{a=o.getItem(kn)}catch{return Ne("off","default","storage-error",n)}if(a===null){try{a=s()}catch{return Ne("off","default","seed-generation-failed",n)}if(Hr(a)===null)return Ne("off","default","seed-generation-failed",n);try{if(o.setItem(kn,a),o.getItem(kn)!==a)return Ne("off","default","seed-write-failed",n)}catch{return Ne("off","default","seed-write-failed",n)}}const i=Hr(a);return i===null?Ne("off","default","seed-invalid",n):in)throw new Error(`${t} must be a non-empty string of at most ${n} chars`);return e}function Pt(e,t){return ze(e,t),e===0?0:2**Math.ceil(Math.log2(e))}function Bt(e){if(!Array.isArray(e)||e.length===0)return null;const t=[...e].sort((r,s)=>r-s),n=t.length>>1;return t.length%2?t[n]:(t[n-1]+t[n])/2}function Kr(e,t){if(!Array.isArray(e)||!Array.isArray(t)||e.length===0||e.length!==t.length)return null;let n=0,r=0;for(let s=0;s0?n/r:null}function Un(e,t){if(!Array.isArray(e)||e.length===0)return null;const n=[...e].sort((a,i)=>a-i),r=(n.length-1)*t,s=Math.floor(r),o=Math.ceil(r);return s===o?n[s]:n[s]+(n[o]-n[s])*(r-s)}function jn(e){if(Array.isArray(e))return e.map(jn);if(e&&typeof e=="object"){const t={};for(const n of Object.keys(e).sort())t[n]=jn(e[n]);return t}return e}function lr(e){return JSON.stringify(jn(e))}function Ii(e){return!!e&&xt.some(t=>e.inFlight===t.inFlight&&e.groupSteps===t.groupSteps)}function Di(e){return xe(e,"groupSteps")}function Li(e,t=null){const n=xe(e,"groupSteps");return t==null?n:Math.min(n,xe(t,"carry groupSteps"))}function Oi(e,t){const n=xe(e,"carry groupSteps"),r=xe(t,"groupStepsFinal");return Math.min(n,r)}function Fi(e){return e===1/0?"inf":Pt(e,"policy.tokenBudget")}function Vr(e,t,n){return t.map(r=>Pt(Un(e,r),n))}function _i(e){const t=new Map;for(const n of e){const r=xe(n,"plannedSourceBuckets value");t.set(r,(t.get(r)??0)+1)}return[...t.entries()].sort((n,r)=>n[0]-r[0]).map(([n,r])=>[n,Pt(r,"bucket count")])}function Gi({batchSizes:e,plannedSourceBuckets:t,sourceTokenLengths:n,modelId:r,weightsId:s,dtype:o,policy:a}={}){if(!Array.isArray(e)||e.length===0)throw new Error("batchSizes must be a non-empty array");const i=e.map(m=>xe(m,"batchSizes value"));if(!Array.isArray(t)||t.length!==i.length)throw new Error("plannedSourceBuckets must align with batchSizes");if(!Array.isArray(n))throw new Error("sourceTokenLengths must be an array");const l=i.reduce((m,h)=>m+h,0);if(n.length!==l)throw new Error("sourceTokenLengths must contain one value per planned row");const c=n.map(m=>xe(m,"sourceTokenLengths value"));if(!a||typeof a!="object")throw new Error("policy must be an object");return{protocolRev:Ve,rowCountBand:Pt(l,"rowCount"),batchCountBand:Pt(i.length,"batchCount"),plannedSourceBucketHistogram:_i(t),batchSizeQuantiles:Vr(i,[.25,.5,.75],"batchSize quantile"),sourceTokenQuantiles:Vr(c,[.25,.5,.75,.9],"sourceToken quantile"),model:[fe(r,"modelId"),fe(s,"weightsId"),fe(o,"dtype",32)],policy:{pack:a.pack===!0,kvPlanner:fe(a.kvPlanner,"policy.kvPlanner"),tokenBudgetBand:Fi(a.tokenBudget),immediates:fe(a.immediates,"policy.immediates",32),uniformPool:a.uniformPool===!0}}}function zi(e){if(!e||typeof e!="object")throw new Error("signature must be an object");return lr(e)}function Ui(e,t=ar,n=null){if(!Array.isArray(e)||e.length===0)throw new Error("batch cost list must be non-empty");const r=e.map(h=>ie(h,"batch cost"));if(!Array.isArray(t)||t.length===0||t.some(h=>!Number.isFinite(h)||h<=0||h>=1))throw new Error("sample quantiles must be finite values between zero and one");let s=null;if(n!=null){if(!Array.isArray(n)||n.length!==r.length)throw new Error("batch regions must align with batch costs");s=n.map((h,y)=>{if(Number.isInteger(h)&&h>0||typeof h=="string"&&h.length>0&&h.length<=64)return h;throw new Error(`batch region at index ${y} is invalid`)})}if(r.length<=t.length)return r.map((h,y)=>y);const o=r.reduce((h,y)=>h+y,0);let a=0;const i=r.map(h=>{const y=(a+h/2)/o;return a+=h,y}),l=new Set,c=new Set,m=s?Math.min(t.length,new Set(s.map(String)).size):0;for(const h of t){let y=null;const k=s&&c.sizeh-y)}function ln(e){return`${typeof e}:${String(e)}`}function ji(e,t){return typeof e=="number"&&typeof t=="number"?e-t:typeof e=="number"?-1:typeof t=="number"?1:String(e).localeCompare(String(t))}function Mn(e,t,n){return e.filter(({index:r})=>!n.has(r)).map(r=>({...r,distance:Math.abs(r.center-t)})).sort((r,s)=>r.distance-s.distance||r.index-s.index)[0]??null}function qr(e,t){const n=e.entries.filter(({index:o})=>t.has(o));if(n.length===0)return null;const r=n.reduce((o,a)=>o+a.cost,0);return n.reduce((o,a)=>o+a.center*a.cost,0)/r<.5?.75:.25}function Cn(e){return[...e].sort((t,n)=>n.mass-t.mass||ji(t.region,n.region)||t.entries[0].index-n.entries[0].index)}function Hi(e,t,n=null){if(!Array.isArray(e)||e.length===0)throw new Error("batch cost list must be non-empty");const r=e.map(S=>ie(S,"batch cost"));if(!Array.isArray(t)||t.length===0)throw new Error("sample batch indices must be a non-empty array");const s=t.map(S=>{if(!Number.isInteger(S)||S<0||S>=r.length)throw new Error("sample batch index is out of range");return S});if(new Set(s).size!==s.length)throw new Error("sample batch indices contain a duplicate");if(r.length-s.length<2)throw new Error("confirmation planning requires two unused batches");let o;if(n==null)o=new Array(r.length).fill("all");else{if(!Array.isArray(n)||n.length!==r.length)throw new Error("batch regions must align with batch costs");o=n.map((S,w)=>{if(Number.isInteger(S)&&S>0||typeof S=="string"&&S.length>0&&S.length<=64)return S;throw new Error(`batch region at index ${w} is invalid`)})}const a=new Map;for(let S=0;Sln(o[S]))),h=S=>S.entries.some(({index:w})=>!c.has(w)),k=Cn(i.filter(S=>m.has(S.key)&&h(S)))[0];if(!k)throw new Error("confirmation planning requires an unused stability batch");const M=qr(k,l),A=Mn(k.entries,M,c);if(!A)throw new Error("confirmation planning could not select a stability batch");c.add(A.index);let d=Cn(i.filter(S=>!m.has(S.key)&&h(S)))[0]??null,p=.5;d||(d=Cn(i.filter(w=>m.has(w.key)&&w.key!==k.key&&h(w)))[0]??null,d&&(p=qr(d,l)));let E;if(d)E=Mn(d.entries,p,c);else{let S=0;const w=r.reduce((N,T)=>N+T,0),f=r.map((N,T)=>{const P={index:T,cost:N,center:(S+N/2)/w};return S+=N,P});E=Mn(f,.5,c)}if(!E)throw new Error("confirmation planning could not select a coverage batch");return Object.freeze([Object.freeze({role:"stability",batchIndex:A.index,region:o[A.index]}),Object.freeze({role:"coverage",batchIndex:E.index,region:o[E.index]})])}function Wi(e,t){if(!Array.isArray(e)||e.length===0)throw new Error("batch cost list must be non-empty");const n=e.map(c=>ie(c,"batch cost"));if(!Array.isArray(t)||t.length===0)throw new Error("sample batch indices must be a non-empty array");const r=t.map(c=>{if(!Number.isInteger(c)||c<0||c>=n.length)throw new Error("sample batch indices must address the batch cost list");return c});if(new Set(r).size!==r.length)throw new Error("sample batch indices must not contain duplicates");r.sort((c,m)=>c-m);const s=n.reduce((c,m)=>c+m,0);let o=0;const a=n.map(c=>{const m=(o+c/2)/s;return o+=c,m}),i=r.map(c=>a[c]),l=new Array(r.length).fill(0);for(let c=0;cMath.abs(a[c]-k)),h=Math.min(...m),y=m.map((k,M)=>({distance:k,owner:M})).filter(({distance:k})=>Math.abs(k-h)<=Number.EPSILON*8);for(const{owner:k}of y)l[k]+=n[c]/y.length}return l.map(c=>c/s)}function Ki({fileMode:e=!1,pack:t=!1,isMobile:n=!1,uncachedRows:r=0,plannedBatches:s=0,kernelTuneSource:o=null,manualOverrides:a={},memorySafe:i=!1}={}){if(!e)return{eligible:!1,reason:"typed-text"};if(!t)return{eligible:!1,reason:"packing-disabled"};if(n)return{eligible:!1,reason:"mobile-v1-skip"};for(const l of Ci){const c=a?.[l];if(c!=null)return{eligible:!1,reason:`manual-override:${l}`}}return o==="partial"?{eligible:!1,reason:"kernel-autotune-partial"}:o!=="measured"&&o!=="cache"?{eligible:!1,reason:"kernel-autotune-untrusted"}:i?!Number.isInteger(r)||r0||typeof e?.region=="number"&&Number.isFinite(e.region))&&Number.isFinite(e?.baselineWallMs)&&e.baselineWallMs>0&&Number.isFinite(e?.candidateWallMs)&&e.candidateWallMs>0&&Number.isFinite(e?.baselineDecodeMs)&&e.baselineDecodeMs>0&&Number.isFinite(e?.candidateDecodeMs)&&e.candidateDecodeMs>0}function $t(e){return Number.isInteger(e)&&e>=0}function Hn(e){if(!Array.isArray(e)||e.length===0)return{pairCount:0,wallGain:null,decodeGain:null,medianWallGain:null,medianDecodeGain:null,weightedWallGain:null,weightedDecodeGain:null,favorableRegions:0,complete:!1,exact:!1,shrinkFree:!1};const t=e.some(v=>v?.weight!==void 0),r=(!t||e.every(v=>Number.isFinite(v?.weight)&&v.weight>0))&&e.every(Uo),s=r&&e.every(v=>v.complete===!0),o=e.every(v=>v.exact===!0),i=e.every(v=>$t(v.baselineSubmitShrinks)&&$t(v.candidateSubmitShrinks))&&e.every(v=>v.baselineSubmitShrinks===0&&v.candidateSubmitShrinks===0),l=r?e.map(v=>un(v.baselineWallMs,v.candidateWallMs)):[],c=r?e.map(v=>un(v.baselineDecodeMs,v.candidateDecodeMs)):[],m=t&&r?e.map(v=>v.weight):[],h=Bt(l),y=Bt(c),k=t?Kr(l,m):null,M=t?Kr(c,m):null,A=new Set;return r&&e.forEach((v,d)=>{l[d]>0&&A.add(String(v.region))}),{pairCount:e.length,wallGain:k===null?h:Math.min(h,k),decodeGain:M===null?y:Math.min(y,M),medianWallGain:h,medianDecodeGain:y,weightedWallGain:k,weightedDecodeGain:M,favorableRegions:A.size,complete:s,exact:o,shrinkFree:i}}function Vi(e,t="base"){if(!Array.isArray(e)||e.length===0)throw new Error("screen results must be a non-empty array");const n=e.find(s=>s?.id===t);if(!n)throw new Error(`screen results are missing baseline ${t}`);const r=e.filter(s=>s?.id!==t&&s?.exact===!0&&s?.submitShrinks===0&&Number.isFinite(s?.score)&&s.score>0).sort((s,o)=>s.score-o.score||String(s.id).localeCompare(String(o.id)))[0]??null;return{base:n,candidate:r}}function Jr({screenPairs:e,confirmationPairs:t=[]}={}){const n=Hn(e),r=Array.isArray(t)?t:[],s=Hn(r),o=Array.isArray(t)&&r.length<=ot.length&&r.every((d,p)=>d?.role===ot[p]),a=r.every(Uo),i=a?r.map(d=>un(d.baselineWallMs,d.candidateWallMs)):[],l=a?r.map(d=>un(d.baselineDecodeMs,d.candidateDecodeMs)):[],c=i.length>0?Math.min(...i):null,m=Number.isFinite(n.wallGain)?Math.min(n.wallGain,...i):n.wallGain,h=Number.isFinite(n.decodeGain)?Math.min(n.decodeGain,...l):n.decodeGain,y=[...Array.isArray(e)?e:[],...r],k=y.every(d=>$t(d?.baselineSubmitShrinks)&&$t(d?.candidateSubmitShrinks)&&d.baselineSubmitShrinks===0&&d.candidateSubmitShrinks===0),M=y.every(d=>d?.exact===!0),A={promote:!1,reason:null,wallGain:m,screenWallGain:n.wallGain,confirmationMinWallGain:c,decodeGain:h,favorableRegions:n.favorableRegions,confirmationCount:Array.isArray(t)?r.filter(d=>d?.complete===!0).length:0,requiredConfirmations:ot.length,completedRoles:r.filter(d=>d?.complete===!0).map(d=>d.role)};return!n.complete||!o||r.length>0&&!s.complete?{...A,reason:"incomplete"}:k?M?n.favorableRegions=wi?n.decodeGain>=0?i.some(d=>d<=0)||l.some(d=>d<0)?{...A,reason:"confirmation-regression"}:i.some(d=>die(l,"run cost"));ie(r,"safetyFactor");const i=a.reduce((l,c)=>l+s*(c/o),0);return{rawGpuMs:i,projectedMs:i*r,runCount:a.length}}function qi({kernelReferenceMs:e,kernelReferenceCost:t,sampleCosts:n,armCount:r=Ge.length,confirmationRounds:s=2,pretokenizeMs:o=0,safetyFactor:a=mn}={}){const i=ie(e,"kernelReferenceMs"),l=ie(t,"kernelReferenceCost");if(!Array.isArray(n)||n.length===0)throw new Error("sampleCosts must be a non-empty array");const c=n.map(k=>ie(k,"sample cost"));if(xe(r,"armCount"),!Number.isInteger(s)||s<0)throw new Error("confirmationRounds must be a non-negative integer");ze(o,"pretokenizeMs"),ie(a,"safetyFactor");const m=c.flatMap(k=>Array(r).fill(k)),h=s*2;m.push(...Array(h).fill(Bt(c)));const y=Wn({referenceMs:i,referenceCost:l,runCosts:m,safetyFactor:a});return{rawGpuMs:y.rawGpuMs,rawProjectedMs:o+y.rawGpuMs,projectedMs:o+y.projectedMs,screenRuns:c.length*r,confirmationRuns:h,completeRuns:m.length,runCosts:m}}function Ji(e,t=fn,n=ir){const r=e?.projectedMs,s=e?.rawProjectedMs;if(!Number.isFinite(r)||r<0||!Number.isFinite(t)||t<=0||!Number.isFinite(n)||n<0||n>=t)return{admit:!1,reason:"invalid-projection",projectedMs:Number.isFinite(r)?r:null,rawProjectedMs:Number.isFinite(s)?s:null,budgetMs:Number.isFinite(t-n)?t-n:null,admission:null};const o=t-n,a=r<=o,i=!a&&Number.isFinite(s)&&s>=0&&s<=o,l=a||i;return{admit:l,reason:l?null:"projected-over-budget",projectedMs:r,rawProjectedMs:Number.isFinite(s)?s:null,budgetMs:o,admission:a?"full":i?"pilot":null}}function Qi({elapsedMs:e,projectedRunMs:t,deadlineMs:n=fn,marginMs:r=ir,safetyFactor:s=mn}={}){if(!(Number.isFinite(e)&&e>=0&&Number.isFinite(t)&&t>0&&Number.isFinite(n)&&n>0&&Number.isFinite(r)&&r>=0&&Number.isFinite(s)&&s>0))return{admit:!1,reason:"invalid-projection",projectedEndMs:null,remainingMs:Number.isFinite(n-e)?n-e:null};const a=e+t*s+r;return{admit:a<=n,reason:a<=n?null:"projected-over-budget",projectedEndMs:a,remainingMs:n-e}}function xn({elapsedMs:e,deadlineMs:t=fn}={}){ze(e,"elapsedMs"),ie(t,"deadlineMs");const n=Math.max(0,e-t);return{elapsedMs:e,deadlineMs:t,deadlineExceeded:n>0,overrunMs:n}}function jo({adapterKey:e,modelId:t,weightsId:n,dtype:r,browserMajor:s,kernelTuneId:o,modes:a,signature:i}={}){if(!Number.isInteger(s)||s<0)throw new Error(`browserMajor must be a non-negative integer, got ${s}`);if(!a||typeof a!="object"||Array.isArray(a))throw new Error("modes must be an object");if(!i||typeof i!="object")throw new Error("signature must be an object");const l={};for(const[c,m]of Object.entries(a)){if(!Ri.has(c))throw new Error(`modes contains unknown key ${c}`);if(Ni.has(c)){if(typeof m!="boolean")throw new Error(`modes.${c} must be boolean`);l[c]=m}else c==="tokenBudget"?l[c]=m===1/0?"inf":ie(m,"modes.tokenBudget"):l[c]=fe(m,`modes.${c}`)}return lr({protocolRev:Ve,adapterKey:fe(e,"adapterKey"),modelId:fe(t,"modelId"),weightsId:fe(n,"weightsId"),dtype:fe(r,"dtype",32),browserMajor:s,kernelTuneId:fe(o,"kernelTuneId"),modes:l,signature:i})}function Yi(e={}){const t=lr({amortizationRev:Lt,scheduleIdentity:jo(e)});return fe(t,"observation identity",Ye)}function Ho(e){let t=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}function Xi(e){return fe(e,"cache identity",Ye),`moxhi.schedule.v${Ve}.${Ho(e)}`}function Zi(e){return fe(e,"observation scope identity",Ye),`moxhi.schedule-observation.v${Lt}.${Ho(e)}`}function Kn(e,t="observedShape"){if(e!=null){if(!e||typeof e!="object")throw new Error(`${t} must be an object`);if(ie(e.targetTokenP50,`${t}.targetTokenP50`),ie(e.targetTokenP90,`${t}.targetTokenP90`),e.targetTokenP901)throw new Error(`${t}.compactionRate must be between zero and one`)}}function It(e){if(!e||typeof e!="object"||Array.isArray(e))throw new Error("cache entry must be an object");if(!Number.isInteger(e.protocolRev)||e.protocolRev<=0)throw new Error("cache entry protocolRev must be a positive integer");if(fe(e.identity,"cache entry identity",Ye),fe(e.scopeKey,"cache entry scopeKey",512),fe(e.kernelTuneId,"cache entry kernelTuneId",512),fe(e.signatureKey,"cache entry signatureKey",Ye),ze(e.createdAt,"cache entry createdAt"),ze(e.lastUsedAt,"cache entry lastUsedAt"),!xi.has(e.ttlClass))throw new Error(`cache entry ttlClass is invalid: ${e.ttlClass}`);if(!Ai.has(e.verdict))throw new Error(`cache entry verdict is invalid: ${e.verdict}`);if(!Ii(e.schedule))throw new Error("cache entry schedule is not a version-1 arm");if(!Number.isInteger(e.screenSubmitShrinks)||e.screenSubmitShrinks<0)throw new Error("cache entry screenSubmitShrinks must be a non-negative integer");const t=e.schedule.inFlight===Le.inFlight&&e.schedule.groupSteps===Le.groupSteps,n=Ti.has(e.verdict);if(n&&e.ttlClass!=="negative"||!n&&e.ttlClass!=="normal")throw new Error("cache entry ttlClass does not match its verdict");if(e.verdict==="selected"){if(t)throw new Error("selected cache verdict must use a non-default schedule");if(e.screenSubmitShrinks!==0)throw new Error("selected cache verdict requires zero-shrink proof")}else if(!t)throw new Error("non-selected cache verdict must use the default schedule");if(e.verdict==="keep-default"&&e.screenSubmitShrinks!==0)throw new Error("keep-default cache verdict requires zero-shrink proof");if(e.verdict==="safety-fallback"&&e.screenSubmitShrinks===0)throw new Error("safety-fallback cache verdict requires a submit shrink");if(n&&e.screenSubmitShrinks!==0)throw new Error("negative cache verdict cannot contain completed shrink evidence");if(Kn(e.observedShape),e.invalidatedReason!==void 0&&(typeof e.invalidatedReason!="string"||e.invalidatedReason.length===0||e.invalidatedReason.length>128))throw new Error("cache entry invalidatedReason is invalid");if(!e.evidence||typeof e.evidence!="object"||Array.isArray(e.evidence))throw new Error("cache entry evidence must be an object");for(const[s,o]of Object.entries(e.evidence)){if(!Pi.has(s))throw new Error(`cache entry evidence contains unknown key ${s}`);if(Bi.has(s)){if(!Number.isInteger(o)||o<0)throw new Error(`cache entry evidence.${s} must be a non-negative integer`)}else if($i.has(s))ze(o,`cache entry evidence.${s}`);else if(s==="exact"){if(typeof o!="boolean")throw new Error("cache entry evidence.exact must be boolean")}else if(!Number.isFinite(o))throw new Error(`cache entry evidence.${s} must be finite`)}if(e.verdict==="selected"&&e.evidence.confirmationCount!==ot.length)throw new Error("selected cache verdict requires both confirmation roles");let r;try{r=JSON.stringify(e.evidence??null).length}catch{throw new Error("cache entry evidence is not serializable")}if(r>Mi)throw new Error("cache entry evidence exceeds the bounded payload limit");return e}function Wo(e){e.forEach(It);const t=new Map;for(const n of e){const r=(t.get(n.scopeKey)??0)+1;if(r>cr)throw new Error("cache entries exceed the per-scope LRU bound");t.set(n.scopeKey,r)}}function ec({identity:e,scopeKey:t,kernelTuneId:n,signatureKey:r,createdAt:s,lastUsedAt:o=s,ttlClass:a,verdict:i,schedule:l,observedShape:c=null,screenSubmitShrinks:m=0,evidence:h={}}={}){const y={protocolRev:Ve,identity:e,scopeKey:t,kernelTuneId:n,signatureKey:r,createdAt:s,lastUsedAt:o,ttlClass:a,verdict:i,schedule:l&&{inFlight:l.inFlight,groupSteps:l.groupSteps},observedShape:c?{...c}:null,screenSubmitShrinks:m,evidence:{...h}};return It(y),y}function tc(e){if(!Array.isArray(e)||e.length>an)throw new Error(`cache entries must be an array of at most ${an}`);return Wo(e),JSON.stringify({schema:Go,entries:e})}function nc(e){if(e==null||e==="")return{status:"miss",entries:[]};try{const t=JSON.parse(e);return t?.schema!==Go||!Array.isArray(t.entries)||t.entries.length>an?{status:"corrupt",entries:[]}:(Wo(t.entries),{status:null,entries:t.entries})}catch{return{status:"corrupt",entries:[]}}}function Qr(e,t){return Math.max(e,t)/Math.min(e,t)}function Ko(e,t){try{Kn(e,"storedShape"),Kn(t,"currentShape")}catch{return!0}return!e||!t?!1:Qr(e.targetTokenP50,t.targetTokenP50)>Wr||Qr(e.targetTokenP90,t.targetTokenP90)>Wr}function rc(e,{now:t=Date.now(),identity:n,kernelTuneId:r,signatureKey:s,observedShape:o=null}={}){try{It(e)}catch{return{status:"corrupt-entry",entry:null}}if(e.protocolRev!==Ve)return{status:"protocol-mismatch",entry:null};if(e.invalidatedReason)return{status:e.invalidatedReason,entry:null};if(e.identity!==n)return{status:"identity-mismatch",entry:null};if(e.kernelTuneId!==r)return{status:"kernel-tune-mismatch",entry:null};if(e.signatureKey!==s)return{status:"signature-mismatch",entry:null};const a=e.ttlClass==="negative"?Ei:Fo,i=t-e.createdAt;return!Number.isFinite(t)||i<0||i>=a?{status:"expired",entry:null}:o&&e.observedShape&&Ko(e.observedShape,o)?{status:"shape-drift",entry:null}:{status:null,entry:e}}function Yr(e,t,n=cr){if(!Array.isArray(e))throw new Error("cache entries must be an array");It(t),xe(n,"maxPerScope");const r=e.map(a=>It(a)).filter(a=>a.identity!==t.identity);r.push(t);const s=new Map;for(const a of r){const i=s.get(a.scopeKey)??[];i.push(a),s.set(a.scopeKey,i)}const o=[];for(const a of s.values())a.sort((i,l)=>l.lastUsedAt-i.lastUsedAt||l.createdAt-i.createdAt||i.identity.localeCompare(l.identity)),o.push(...a.slice(0,n));return o.sort((a,i)=>i.lastUsedAt-a.lastUsedAt||i.createdAt-a.createdAt||a.identity.localeCompare(i.identity)).slice(0,an)}function An(e,t){if(!Array.isArray(e))throw new Error("cache entries must be an array");return fe(t,"cache identity",Ye),e.filter(n=>n?.identity!==t)}const oc=new Set(["amortizationRev","protocolRev","identity","scopeKey","kernelTuneId","signatureKey","createdAt","lastUsedAt","schedule","profiledWallMs","profiledDecodeMs","rowCount","batchCount","tokenCount","submitShrinks"]);function yt(e){if(!e||typeof e!="object"||Array.isArray(e))throw new Error("observation entry must be an object");for(const t of Object.keys(e))if(!oc.has(t))throw new Error(`observation entry contains unknown key ${t}`);if(!Number.isInteger(e.amortizationRev)||e.amortizationRev<=0)throw new Error("observation entry amortizationRev must be a positive integer");if(!Number.isInteger(e.protocolRev)||e.protocolRev<=0)throw new Error("observation entry protocolRev must be a positive integer");if(fe(e.identity,"observation entry identity",Ye),fe(e.scopeKey,"observation entry scopeKey",512),fe(e.kernelTuneId,"observation entry kernelTuneId",512),fe(e.signatureKey,"observation entry signatureKey",Ye),ze(e.createdAt,"observation entry createdAt"),ze(e.lastUsedAt,"observation entry lastUsedAt"),e.lastUsedAt_o)throw new Error("observations exceed the per-scope LRU bound");t.set(n.scopeKey,r)}}function sc({amortizationRev:e,protocolRev:t,identity:n,scopeKey:r,kernelTuneId:s,signatureKey:o,createdAt:a,lastUsedAt:i=a,schedule:l=Le,profiledWallMs:c,profiledDecodeMs:m,rowCount:h,batchCount:y,tokenCount:k,submitShrinks:M=0,...A}={}){const v=Object.keys(A)[0];if(v)throw new Error(`observation entry contains unknown key ${v}`);const d={amortizationRev:Lt,protocolRev:Ve,identity:n,scopeKey:r,kernelTuneId:s,signatureKey:o,createdAt:a,lastUsedAt:i,schedule:l&&{inFlight:l.inFlight,groupSteps:l.groupSteps},profiledWallMs:c,profiledDecodeMs:m,rowCount:h,batchCount:y,tokenCount:k,submitShrinks:M};return yt(d),d}function ac(e){if(!Array.isArray(e)||e.length>cn)throw new Error(`observations must be an array of at most ${cn}`);return Vo(e),JSON.stringify({schema:zo,entries:e})}function Xr(e){if(e==null||e==="")return{status:"miss",entries:[]};try{const t=JSON.parse(e);return t?.schema!==zo||!Array.isArray(t.entries)||t.entries.length>cn||Object.keys(t).some(n=>!["schema","entries"].includes(n))?{status:"corrupt",entries:[]}:(Vo(t.entries),{status:null,entries:t.entries})}catch{return{status:"corrupt",entries:[]}}}function ic(e,{now:t=Date.now(),identity:n,kernelTuneId:r,signatureKey:s}={}){try{yt(e)}catch{return{status:"corrupt-entry",entry:null}}return e.amortizationRev!==Lt?{status:"amortization-mismatch",entry:null}:e.protocolRev!==Ve?{status:"protocol-mismatch",entry:null}:e.identity!==n?{status:"identity-mismatch",entry:null}:e.kernelTuneId!==r?{status:"kernel-tune-mismatch",entry:null}:e.signatureKey!==s?{status:"signature-mismatch",entry:null}:!Number.isFinite(t)||t=ki?{status:"expired",entry:null}:{status:null,entry:e}}function Zr(e,t,n=_o){if(!Array.isArray(e))throw new Error("observations must be an array");yt(t),xe(n,"maxPerScope");const r=e.map(a=>yt(a)).filter(a=>a.identity!==t.identity);r.push(t);const s=new Map;for(const a of r){const i=s.get(a.scopeKey)??[];i.push(a),s.set(a.scopeKey,i)}const o=[];for(const a of s.values())a.sort((i,l)=>l.lastUsedAt-i.lastUsedAt||l.createdAt-i.createdAt||i.identity.localeCompare(l.identity)),o.push(...a.slice(0,n));return o.sort((a,i)=>i.lastUsedAt-a.lastUsedAt||i.createdAt-a.createdAt||a.identity.localeCompare(i.identity)).slice(0,cn)}function Tn(e){return{status:"needs-baseline-observation",reason:e,admit:!1,observedProfiledWallMs:null,minimumExpectedSavingMs:null,projectedWorstCaseScreenMs:null,paybackRatio:null}}function cc({observation:e=null,projection:t=null,promotionGain:n=Oo}={}){if(!e)return Tn("missing-observation");try{yt(e)}catch{return Tn("invalid-observation")}const r=t?.projectedMs;if(!(Number.isFinite(r)&&r>0&&Number.isFinite(n)&&n>0&&n<=1))return Tn("invalid-projection");const s=e.profiledWallMs,o=s*n,a=o/r,i=o>=r;return{status:i?"admitted":"unamortized",reason:i?null:"insufficient-payback",admit:i,observedProfiledWallMs:s,minimumExpectedSavingMs:o,projectedWorstCaseScreenMs:r,paybackRatio:a}}function lc(e,t,{required:n=!1,max:r=1/0}={}){if(!Array.isArray(e)||n&&e.length===0)throw new Error(`${t} must be ${n?"a non-empty":"an"} array`);if(e.length>r)throw new Error(`${t} exceeds its bounded size`);const s=e.map(o=>{if(!Number.isInteger(o)||o<0)throw new Error(`${t} must contain non-negative integers`);return o});if(new Set(s).size!==s.length)throw new Error(`${t} must not contain duplicates`);return[...s].sort((o,a)=>o-a)}function uc(e){if(!Array.isArray(e))throw new Error("confirmationPlan must be an array");if(e.length>ot.length)throw new Error("confirmationPlan exceeds its bounded size");const t=e.map((n,r)=>{if(!n||typeof n!="object"||Array.isArray(n))throw new Error(`confirmationPlan[${r}] must be an object`);if(Object.keys(n).some(i=>!["role","batchIndex","region"].includes(i)))throw new Error(`confirmationPlan[${r}] contains an unknown key`);const o=ot[r];if(n.role!==o)throw new Error(`confirmationPlan[${r}] must have role ${o}`);if(!Number.isInteger(n.batchIndex)||n.batchIndex<0)throw new Error(`confirmationPlan[${r}].batchIndex must be non-negative`);if(!(Number.isInteger(n.region)&&n.region>0||typeof n.region=="string"&&n.region.length>0&&n.region.length<=64))throw new Error(`confirmationPlan[${r}].region is invalid`);return{role:n.role,batchIndex:n.batchIndex,region:n.region}});if(new Set(t.map(({batchIndex:n})=>n)).size!==t.length)throw new Error("confirmationPlan batch indices must not contain duplicates");return t}function dc(e,t){const n=t%e.length;return[...e.slice(n),...e.slice(0,n)]}function eo(e,t=e.groupSteps){return{inFlight:e.inFlight,groupSteps:Li(e.groupSteps,t)}}function hc(e,t){return`${e}:${t}`}function fc(e){if(!Array.isArray(e)||e.length===0)throw new Error("runBatch rows must be a non-empty array");const t=e.map((n,r)=>{if(!n||typeof n!="object"||!Array.isArray(n.ids)||n.ids.length<2||n.ids.some(s=>!Number.isInteger(s)||s<0)||typeof n.forcedEos!="boolean")throw new Error(`runBatch rows[${r}] is invalid`);return[n.ids,n.forcedEos]});return{fingerprint:JSON.stringify(t),targetTokenLengths:e.map(n=>n.ids.length-1)}}function mc(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw new Error("runBatch result must be an object");if(e.cleanupComplete!==!0)throw new Error("runBatch cleanupComplete evidence must be true");const n=xe(e.groupStepsStart,"runBatch groupStepsStart"),r=xe(e.groupStepsFinal,"runBatch groupStepsFinal");if(n!==t.groupSteps)throw new Error("runBatch groupStepsStart does not match the admitted schedule");if(r>n)throw new Error("runBatch groupStepsFinal must not grow");if(!$t(e.submitShrinks))throw new Error("runBatch submitShrinks must be a non-negative integer");if(e.submitShrinks===0&&r!==n||e.submitShrinks>0&&r>=n)throw new Error("runBatch submitShrinks and groupStepsFinal are inconsistent");if(!Number.isInteger(e.compactions)||e.compactions<0)throw new Error("runBatch compactions must be a non-negative integer");return{...fc(e.rows),groupStepsStart:n,groupStepsFinal:r,submitShrinks:e.submitShrinks,wallMs:ie(e.wallMs,"runBatch wallMs"),decodeMs:ie(e.decodeMs,"runBatch decodeMs"),compactions:e.compactions}}function pc(e){return Ge.map(t=>{const n=e.get(t.id),r=Bt(n.records.map(a=>a.wallMs)),s=Bt(n.records.map(a=>a.decodeMs)),o={id:t.id,status:n.status==="pending"&&n.records.length>0?"partial":n.status,completedRuns:n.records.length,submitShrinks:n.records.reduce((a,i)=>a+i.submitShrinks,0)};return r!==null&&(o.medianWallMs=r),s!==null&&(o.medianDecodeMs=s),o})}function gc(e){if(!e||e.records.length===0)return null;const t=e.records.filter(r=>r.phase==="screen"),n=t.flatMap(r=>r.targetTokenLengths);return n.length===0?null:{targetTokenP50:Un(n,.5),targetTokenP90:Un(n,.9),compactionRate:t.filter(r=>r.compactions>0).length/t.length}}function bc(e){if(!e||typeof e!="object"||Array.isArray(e))throw new Error("safetyOptions must be an object");if(ie(e.submitBudgetMs,"safetyOptions.submitBudgetMs"),typeof e.encSplitSubmits!="boolean")throw new Error("safetyOptions.encSplitSubmits must be boolean");return Object.freeze({...e})}function to(e){const t=e();if(!Number.isFinite(t))throw new Error("schedule tuner clock must be finite");return t}function no({decision:e=null,sampleCount:t=0,confirmationCount:n=0,tuneMs:r,projectedMs:s,actualMs:o,overrunMs:a,exact:i=!1,includePerformance:l=!0}){const c={sampleCount:t,confirmationCount:n,tuneMs:r,projectedMs:s,actualMs:o,overrunMs:a,exact:i};return l&&(c.favorableRegions=e?.favorableRegions??0,Number.isFinite(e?.wallGain)&&(c.wallGain=e.wallGain),Number.isFinite(e?.screenWallGain)&&(c.screenWallGain=e.screenWallGain),Number.isFinite(e?.confirmationMinWallGain)&&(c.confirmationMinWallGain=e.confirmationMinWallGain),Number.isFinite(e?.decodeGain)&&(c.decodeGain=e.decodeGain)),c}async function qo({sampleBatchIndices:e,confirmationPlan:t=[],workloadBatchCosts:n,batchRegions:r=null,kernelReferenceMs:s,kernelReferenceCost:o,safetyOptions:a,pretokenize:i,estimateBatch:l,runBatch:c,now:m=Date.now,isCancelled:h=()=>!1,isDeviceHealthy:y=()=>!1,deadlineMs:k=fn,marginMs:M=ir,safetyFactor:A=mn,pretokenizeEstimateMs:v=0}={}){const d=lc(e,"sampleBatchIndices",{required:!0,max:ar.length}),p=uc(t);if(p.some(({batchIndex:x})=>d.includes(x)))throw new Error("confirmationPlan batches must be unused by the screen");const E=Wi(n,d),S=new Map(d.map((x,R)=>[x,E[R]]));let w=null;if(r!=null){if(!Array.isArray(r)||r.length===0)throw new Error("batchRegions must be a non-empty array");if(w=r.map((R,F)=>{if(Number.isInteger(R)&&R>0||typeof R=="string"&&R.length>0&&R.length<=64)return R;throw new Error(`batchRegions[${F}] is invalid`)}),Math.max(...d,...p.map(({batchIndex:R})=>R))>=w.length)throw new Error("batchRegions must cover every screen and confirmation batch");for(const R of p)if(ln(R.region)!==ln(w[R.batchIndex]))throw new Error(`confirmationPlan ${R.role} region does not match batchRegions`)}for(const[x,R]of[[i,"pretokenize"],[l,"estimateBatch"],[c,"runBatch"],[m,"now"],[h,"isCancelled"],[y,"isDeviceHealthy"]])if(typeof x!="function")throw new Error(`${R} must be a function`);if(ie(s,"kernelReferenceMs"),ie(o,"kernelReferenceCost"),ie(k,"deadlineMs"),ze(M,"marginMs"),M>=k)throw new Error("marginMs must be below deadlineMs");ie(A,"safetyFactor"),ze(v,"pretokenizeEstimateMs");const f=bc(a),N=new Map(Ge.map(x=>[x.id,{arm:x,carry:Di(x.groupSteps),status:"pending",records:[]}])),T=d.flatMap((x,R)=>dc(Ge,R).map(F=>({phase:"screen",batchIndex:x,samplePosition:R,region:w?.[x]??`sample-${R+1}`,arm:F}))),P=new Map,_=async(x,R)=>{const F=hc(x,R.id);if(P.has(F))return P.get(F);const H=ie(await l(x,eo(R)),`estimateBatch(${x}, ${R.id})`);return P.set(F,H),H};let g=null,V=null,$=0,re=null,te=0,C=!1,G=[];const K=[],z=()=>{if(re===null)return 0;const x=to(m)-re;if(!Number.isFinite(x)||x<0)throw new Error("schedule tuner clock must be monotonic");return x},I=({verdict:x,reason:R=x,schedule:F=Le,source:H="default",cacheable:ae,ttlClass:X,decision:se=null,exact:Y=!1,includeCandidateEvidence:be=!0,includeObservedShape:Xe=!0})=>{const Z=z(),$e=xn({elapsedMs:Z,deadlineMs:k}),it=no({decision:se,sampleCount:C?d.length:G.length,confirmationCount:K.length,tuneMs:Z,projectedMs:$,actualMs:Z,overrunMs:$e.overrunMs,exact:Y,includePerformance:!0}),wt=ae?no({decision:se,sampleCount:C?d.length:G.length,confirmationCount:K.length,tuneMs:Z,projectedMs:$,actualMs:Z,overrunMs:$e.overrunMs,exact:Y,includePerformance:X!=="negative"}):{};return{protocolRev:Ve,verdict:x,reason:R,schedule:{inFlight:F.inFlight,groupSteps:F.groupSteps},source:H,screenSubmitShrinks:te,scheduleTuneMs:Z,evidence:it,confirmationPlan:p.map(Ze=>({...Ze})),completedConfirmationRoles:se?.completedRoles?[...se.completedRoles]:[],candidateEvidence:be?pc(N):[],observedShape:Xe?gc(N.get("base")):null,projection:{preGate:g?{rawGpuMs:g.rawGpuMs,rawProjectedMs:g.rawProjectedMs,projectedMs:g.projectedMs,runCount:g.runCount,budgetMs:g.budgetMs,admission:g.admission}:null,postPilot:V?{...V}:null},deadline:$e,cache:{cacheable:ae,ttlClass:X,evidence:wt}}},O=()=>I({verdict:"cancelled",cacheable:!1,ttlClass:null,includeCandidateEvidence:!1,includeObservedShape:!1}),q=x=>I({verdict:x,cacheable:!0,ttlClass:"negative",includeCandidateEvidence:!1,includeObservedShape:!1});if(h())return O();const U=[];for(const x of T){if(h())return O();U.push(await _(x.batchIndex,x.arm))}const me=Wn({referenceMs:s,referenceCost:o,runCosts:U,safetyFactor:A});g={...me,rawProjectedMs:v+me.rawGpuMs,projectedMs:v+me.projectedMs},$=g.projectedMs;const ge=Ji(g,k,M);if(g.budgetMs=ge.budgetMs,g.admission=ge.admission,!ge.admit)return q("projected-over-budget");re=to(m);const Se=[...new Set([...d,...p.map(({batchIndex:x})=>x)])].sort((x,R)=>x-R);for(const x of Se)if(h()||(await i(x),h()))return O();if(z()>=k)return q("timeout");let oe={ms:s,cost:o};const J=async x=>{if(h())return{terminal:O()};const R=z();if(R>=k)return{terminal:q("timeout")};const F=N.get(x.arm.id),H=eo(x.arm,F.carry),ae=await _(x.batchIndex,x.arm),X=oe.ms*(ae/oe.cost),se=Qi({elapsedMs:R,projectedRunMs:X,deadlineMs:k,marginMs:M,safetyFactor:A});if(!se.admit)return Number.isFinite(se.projectedEndMs)&&($=se.projectedEndMs),{terminal:q("projected-over-budget")};let Y;try{Y=await c(x.batchIndex,H,f)}catch(Z){if(h())return{terminal:O()};if(x.arm.id==="base"||!await y(Z))throw Z;return F.status="error",xn({elapsedMs:z(),deadlineMs:k}).deadlineExceeded?{terminal:q("admission-overrun")}:{candidateError:!0}}const be=mc(Y,H);if(h())return{terminal:O()};if(be.submitShrinks>0){te+=be.submitShrinks;const Z={...be};return delete Z.fingerprint,F.status="submit-shrink",F.records.push({phase:x.phase,batchIndex:x.batchIndex,region:x.region,...Z}),{terminal:I({verdict:"safety-fallback",reason:"submit-shrink",source:"measured",cacheable:!0,ttlClass:"normal",exact:!1})}}return F.carry=Oi(F.carry,be.groupStepsFinal),xn({elapsedMs:z(),deadlineMs:k}).deadlineExceeded?{terminal:q("admission-overrun")}:{trial:{...be,cost:ae}}},B=new Map,Ae=(x,R)=>{const F=N.get(x.arm.id),{fingerprint:H,...ae}=R,X={phase:"screen",batchIndex:x.batchIndex,region:x.region,...ae};F.records.push(X);const se=B.get(x.batchIndex)??new Map;if(se.set(x.arm.id,H),B.set(x.batchIndex,se),x.arm.id==="base")for(const Y of Ge.slice(1)){const be=se.get(Y.id);be!==void 0&&be!==H&&(N.get(Y.id).status="output-mismatch")}else{const Y=se.get("base");Y!==void 0&&Y!==H&&(F.status="output-mismatch")}},Q=T[0],pe=await J(Q);if(pe.terminal)return pe.terminal;Ae(Q,pe.trial),oe={ms:pe.trial.wallMs,cost:pe.trial.cost};const Ee=U.slice(1);if(Ee.length>0){const x=Wn({referenceMs:oe.ms,referenceCost:oe.cost,runCosts:Ee,safetyFactor:A}),R=z(),F=R+x.rawGpuMs+M,H=R+x.projectedMs+M,ae=H<=k,X=!ae&&F<=k;if(V={rawGpuMs:x.rawGpuMs,projectedMs:x.projectedMs,runCount:x.runCount,rawProjectedEndMs:F,projectedEndMs:H,admission:ae?"full":X?"per-run":null},$=V.projectedEndMs,!ae&&!X)return q("projected-over-budget")}let He=Q.batchIndex;for(const x of T.slice(1)){x.batchIndex!==He&&(B.delete(He),He=x.batchIndex);const R=N.get(x.arm.id);if(x.arm.id!=="base"&&R.status!=="pending")continue;const F=await J(x);if(F.terminal)return F.terminal;F.candidateError||Ae(x,F.trial)}B.clear(),C=!0,N.get("base").status="complete";for(const x of Ge.slice(1)){const R=N.get(x.id),F=R.records.filter(H=>H.phase==="screen");R.status==="pending"&&(R.status=F.length===d.length?"complete":"incomplete")}const he=new Map,ke=x=>{const R=N.get(x.id);return d.map(F=>{const H=N.get("base").records.find(X=>X.phase==="screen"&&X.batchIndex===F),ae=R.records.find(X=>X.phase==="screen"&&X.batchIndex===F);return{region:H.region,weight:S.get(F),baselineWallMs:H.wallMs,candidateWallMs:ae.wallMs,baselineDecodeMs:H.decodeMs,candidateDecodeMs:ae.decodeMs,complete:!0,exact:!0,baselineSubmitShrinks:H.submitShrinks,candidateSubmitShrinks:ae.submitShrinks}})},Re=Ge.map(x=>{const R=N.get(x.id),F=R.records.filter(X=>X.phase==="screen"),H=x.id==="base"||R.status==="complete";let ae=1;if(x.id!=="base"&&H){const X=ke(x);he.set(x.id,X);const se=Hn(X);ae=1-(se.weightedWallGain??se.wallGain)}return{id:x.id,score:ae,exact:H,submitShrinks:F.reduce((X,se)=>X+se.submitShrinks,0)}}),{candidate:j}=Vi(Re);if(!j)return I({verdict:"keep-default",reason:"no-exact-candidate",source:"measured",cacheable:!0,ttlClass:"normal",exact:!1});const Te=N.get(j.id).arm,Pe=N.get(j.id);G=he.get(j.id);let ce=Jr({screenPairs:G});if(ce.reason!=="needs-confirmation")return I({verdict:"keep-default",reason:ce.reason,source:"measured",cacheable:!0,ttlClass:"normal",decision:ce,exact:!0});for(let x=0;xn.inFlight===e.inFlight&&n.groupSteps===e.groupSteps);if(!t)throw new Error("decodeScheduleOverride must be a version-1 schedule arm");return{inFlight:t.inFlight,groupSteps:t.groupSteps}}function ro(e=null){return e==="shadow"?"shadow":e==="1"||e==="apply"?"apply":e==="auto"?"auto":"off"}function Ec(e,t,n,r={}){const s=e??{},o=["dModel","heads","headDim","ffn","encLayers","decLayers","vocab","maxPos","srcCap","decodeCap"].map(c=>t[c]??"").join("x"),a=`${r.subgroupMinSize??0}-${r.subgroupMaxSize??0}`,i=r.immediates==="on"?"on":"off",l=r.uniformPool===!0||r.uniformPool==="on"||r.uniformPool==="b64"?"b64":"off";return[`moxhi.autotune.v${xo}`,s.vendor??"",s.architecture??"",s.device??"",`sg${a}`,o,n,`imm${i}`,`pool${l}`,r.browserMajor??"unknown"].join("|")}const kc=720*3600*1e3;function Mc(e){if(e==null)return{parsed:null,status:"miss"};try{const t=JSON.parse(e);return!t||typeof t!="object"||Array.isArray(t)?{parsed:null,status:"corrupt"}:{parsed:t,status:null}}catch{return{parsed:null,status:"corrupt"}}}function Cc(e,t,n=Date.now(),r=kc){const s=Date.parse(e?.date??""),o=n-s;return!Number.isFinite(s)||o<0||o>=r?{status:"expired",measuredAt:null}:js(e?.tuned,t)?{status:null,measuredAt:s}:{status:"safety-rejected",measuredAt:null}}function oo(e,t){return Ws(e,t)?"accepted":"mismatch"}async function xc({cachedUs:e,measure:t}){let n=await t(),r=null,s=oo(e,n.medianUs)==="accepted";return!s&&Number.isFinite(e)&&e>0&&(r=n.medianUs,n=await t(),s=oo(e,n.medianUs)==="accepted"),{accepted:s,current:n,retriedUs:r}}const Ac=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Tc=e=>typeof e=="string"&&Ac.test(e)?e:null,Mt=(e,{priorTuneId:t=null,cachedUs:n=null,currentUs:r=null,retriedUs:s=null,error:o=null}={})=>({status:e,priorTuneId:t,cachedUs:n,currentUs:r,retriedUs:s,error:o});function Rc(e){return e.map((t,n)=>n).sort((t,n)=>e[t]-e[n])}function Nc(e,t=192,n=576){return Math.max(t,Math.min(n,Math.floor(t*224/e)))}function dr({ua:e="",maxTouchPoints:t=0}={}){const n=typeof e=="string"?e:"";return/iPhone|iPad|iPod|Android/.test(n)||/Macintosh/.test(n)&&t>1}function Pc({ua:e=""}={}){return/Android/.test(typeof e=="string"?e:"")}function Jo({ua:e="",maxTouchPoints:t=0,capParam:n=null}={}){const r=Math.floor(Number(n));return Number.isFinite(r)&&r>=1?Math.min(r,2048):dr({ua:e,maxTouchPoints:t})?192:576}function Qo({ua:e="",maxTouchPoints:t=0,budgetParam:n=null}={}){if(typeof n=="string"&&n.trim()==="0")return 1/0;const r=Math.floor(Number(n));return n!==""&&n!==null&&n!==void 0&&Number.isFinite(r)&&r>=1?Math.min(r,1024*1024):dr({ua:e,maxTouchPoints:t})?16*1024:1/0}const so="moxhi-mobile-kv-v2";function Yo(e=null){if(e==null||String(e).trim()==="")return{mode:"auto",capacity:null};const t=String(e).trim();if(t==="0")return{mode:"legacy",capacity:null};if(!/^\d+$/.test(t))return{mode:"legacy",capacity:null};const n=Number(t);return!Number.isInteger(n)||n<1||n>nn?{mode:"legacy",capacity:null}:{mode:"forced",capacity:n}}function Bc(e,{modelId:t="",mobile:n=!1,plannerParam:r=null,kvcapParam:s=null,tokenBudget:o=1/0}={}){if(!Number.isInteger(e)||e<1)throw new Error(`file KV policy: bad S=${e}`);const a=Yo(s),i=r==="1"&&n&&t==="moxhi"&&a.mode!=="legacy",l=a.mode==="forced"?a.capacity:null;if(!i)return{rowCap:null,tokenBudget:o,kvCapacity:l,label:l?`forced-kv${l}`:"legacy-full-kv",autoRows:!1};let c=192,m=nn,h=o;return e<=32?(c=384,m=64,h=1/0):e<=64?(c=192,m=112,h=1/0):e<=96&&(c=192,m=128,h=1/0),{rowCap:c,tokenBudget:h,kvCapacity:l??m,label:l?`${so}+forced-kv${l}`:so,autoRows:!0}}function $c({modelId:e="",ua:t="",maxTouchPoints:n=0,plannerParam:r=null,kvcapParam:s=null,capParam:o=null,budgetParam:a=null}={}){const i=dr({ua:t,maxTouchPoints:n}),l=Yo(s),c=r==="1"&&i&&e==="moxhi"&&l.mode!=="legacy",m=Qo({ua:t,maxTouchPoints:n,budgetParam:a}),h=Jo({ua:t,maxTouchPoints:n,capParam:o}),y=o!=null&&String(o).trim()!==""&&Number.isFinite(Number(o))&&Math.floor(Number(o))>=1,k=c&&!y?576:h,M=v=>Bc(v,{modelId:e,mobile:i,plannerParam:r,kvcapParam:s,tokenBudget:m}),A=M(32);return{mobile:i,autoRows:c,absCap:k,tokenBudget:m,forcedCapacity:l.mode==="forced"?l.capacity:null,policyLabel:A.label,policyForS:M,kvCapacityForS:v=>M(v).kvCapacity}}function Ic({param:e=null}={}){return e==="1"}function ao(){return Jo({ua:navigator.userAgent??"",maxTouchPoints:navigator.maxTouchPoints??0,capParam:new URLSearchParams(location.search).get("cap")})}function Dc(){return Qo({ua:navigator.userAgent??"",maxTouchPoints:navigator.maxTouchPoints??0,budgetParam:new URLSearchParams(location.search).get("tokenbudget")})}function Xo(e,t,n,r=192,s=576,o=1/0,a=null){const i=[],l=[];for(let c=0;cS)break;h=M,y=A,m++}i.push([c,m]),l.push(y),c=m}return{ranges:i,buckets:l}}function Lc(e,t,n,r=192,s=576,o=1/0,a=null){return Xo(e,t,n,r,s,o,a).ranges}function Oc(){return Ic({param:new URLSearchParams(location.search).get("inplacecompact")})}const Be=e=>Math.round(e*10)/10,Rn=e=>Math.round(e*100)/100;async function Fc(e,t=globalThis.crypto){if(!t?.subtle?.digest)throw new Error("SHA-256 unavailable");const n=new TextEncoder().encode(String(e));return[...new Uint8Array(await t.subtle.digest("SHA-256",n))].map(s=>s.toString(16).padStart(2,"0")).join("")}function _c(e,t=null){if(!Array.isArray(e))throw new Error("aggregateBatchProfile needs an array");const n=e.reduce((o,a)=>o+(Number(a.ms)||0),0),r=e.reduce((o,a)=>o+(Number(a.decodeMs)||0),0),s={};for(const o of e){if(!Number.isInteger(o.S)||o.S<1)throw new Error(`aggregateBatchProfile: bad S=${o.S}`);const a=s[o.S]??={batches:0,rows:0,tokens:0,compactions:0,kvGrows:0,kvGrowsWithPending:0,kvGrowBindGroupsPurged:0,ms:0,encoderMs:0,decodeMs:0,maxB:0,maxCap:0,maxSteps:0,maxSourceTokenArea:0,minInitialKvCapacity:1/0,maxInitialKvCapacity:0,maxFinalKvCapacity:0,logicalArenaPeakMB:0,submittedArenaPeakMB:0};a.batches++,a.rows+=Number(o.B)||0,a.tokens+=Number(o.tokens)||0,a.compactions+=Number(o.compactions)||0,a.kvGrows+=Number(o.kvGrows)||0,a.kvGrowsWithPending+=Number(o.kvGrowsWithPending)||0,a.kvGrowBindGroupsPurged+=Number(o.kvGrowBindGroupsPurged)||0,a.ms+=Number(o.ms)||0,a.encoderMs+=Number(o.encoderMs)||0,a.decodeMs+=Number(o.decodeMs)||0,a.maxB=Math.max(a.maxB,Number(o.B)||0),a.maxCap=Math.max(a.maxCap,Number(o.cap)||0),a.maxSteps=Math.max(a.maxSteps,Number(o.steps)||0);const i=Number(o.initialKvCapacity)||0;i>0&&(a.minInitialKvCapacity=Math.min(a.minInitialKvCapacity,i)),a.maxInitialKvCapacity=Math.max(a.maxInitialKvCapacity,i),a.maxFinalKvCapacity=Math.max(a.maxFinalKvCapacity,Number(o.finalKvCapacity)||0),a.maxSourceTokenArea=Math.max(a.maxSourceTokenArea,(Number(o.B)||0)*o.S),a.logicalArenaPeakMB=Math.max(a.logicalArenaPeakMB,Number(o.logicalArenaPeakMB)||0),a.submittedArenaPeakMB=Math.max(a.submittedArenaPeakMB,Number(o.submittedArenaPeakMB)||0)}for(const o of Object.values(s))Number.isFinite(o.minInitialKvCapacity)||(o.minInitialKvCapacity=0),o.ms=Be(o.ms),o.encoderMs=Be(o.encoderMs),o.decodeMs=Be(o.decodeMs),o.batchWallPct=n>0?Rn(o.ms/n*100):0,o.decodeSharePct=r>0?Rn(o.decodeMs/r*100):0,o.fileWallPct=Number.isFinite(t)&&t>0?Rn(o.ms/t*100):null;return{profiledMs:Be(n),profiledDecodeMs:Be(r),sBuckets:s}}const Vn=64,Gc=Vn;function tn(e,t="unknown"){return(String(e??"").trim()||t).slice(0,96)}function zc(e={},{subgroupMinSize:t=0,subgroupMaxSize:n=0}={}){return[tn(e.vendor),tn(e.architecture),tn(e.device),`sg${Number(t)||0}-${Number(n)||0}`].join("|")}function Uc({batchSize:e,plannedS:t,maxChars:n}={}){if(!Number.isInteger(e)||e<1)throw new Error(`schedule batchSize must be positive, got ${e}`);if(!Number.isInteger(t)||t<1)throw new Error(`schedule plannedS must be positive, got ${t}`);if(!Number.isFinite(n)||n<0)throw new Error(`schedule maxChars must be non-negative, got ${n}`);const r=Ks(n),s=Math.sqrt(e/Vn),o=Math.max(1,t/96);return Vn*s*r*o}function io(e,t){const n=[...e].sort((a,i)=>a-i),r=(n.length-1)*t,s=Math.floor(r),o=Math.ceil(r);return s===o?n[s]:n[s]+(n[o]-n[s])*(r-s)}function jc(e,t,n){return e.length===0||n<1?null:{targetTokenP50:io(e,.5),targetTokenP90:io(e,.9),compactionRate:t/n}}function Nn(e,t){if(!e?.getItem)return null;try{return e.getItem(t)}catch{return null}}function mt(e,t,n){if(e)try{n.length===0?e.removeItem?.(t):e.setItem?.(t,tc(n))}catch{}}function qt(e,t,n){if(!e)return!1;try{if(n.length===0){if(typeof e.removeItem!="function")return!1;e.removeItem(t)}else{if(typeof e.setItem!="function")return!1;e.setItem(t,ac(n))}return!0}catch{return!1}}function Jt({selectedSchedule:e,telemetry:t,cacheHit:n=!1,cachedObservedShape:r=null,driftBatchIndices:s=[],invalidate:o=()=>{},recordBaselineObservation:a=()=>!1}){return{selectedSchedule:{inFlight:e.inFlight,groupSteps:e.groupSteps},telemetry:t,cacheHit:n,cachedObservedShape:r,driftBatchIndices:[...s],invalidate:o,recordBaselineObservation:a}}async function Hc({enabled:e=!1,amortizationPolicy:t="bypass",configuredSchedule:n=Le,eligibilityInput:r={},buildWorkload:s,adapterKey:o,modelId:a,weightsId:i,dtype:l,browserMajor:c,kernelTuneId:m,modes:h,scopeKey:y,kernelReferenceMs:k,kernelReferenceCost:M=Gc,safetyOptions:A,storage:v=null,runner:d=qo,pretokenize:p,estimateBatch:E,runBatch:S,isCancelled:w=()=>!1,isDeviceHealthy:f=()=>!1,clock:N=()=>performance.now(),cacheNow:T=()=>Date.now()}={}){const P={inFlight:n.inFlight,groupSteps:n.groupSteps},_=t==="automatic",g={protocolRev:Ve,enabled:e===!0,eligible:!1,source:"default",reason:e===!0?null:"disabled",configuredSchedule:{...P},selectedSchedule:{...P},effectiveSchedule:{...P},workload:null,evidence:null,candidateEvidence:[],observedShape:null,projection:null,deadline:null,screenSubmitShrinks:0,selectedGain:null,screenGain:null,confirmationMinGain:null,sampleCount:0,confirmationCount:0,confirmationPlan:[],completedConfirmationRoles:[],scheduleTuneMs:0,invalidatedReason:null,cache:{status:"not-checked",write:null,verdict:null,persistent:v?.persistent!==!1},amortization:{revision:Lt,status:e&&!_?"bypass":"not-checked",reason:null,observationCacheState:"not-checked",observationAgeMs:null,observedProfiledWallMs:null,minimumExpectedSavingMs:null,projectedWorstCaseScreenMs:null,paybackRatio:null,write:null,persistent:v?.persistent!==!1}},V=()=>Jt({selectedSchedule:P,telemetry:g});if(!e)return V();const $=Ki(r);if(g.eligible=$.eligible,g.reason=$.reason,!$.eligible)return V();if(!(Number.isFinite(k)&&k>0))return g.reason="kernel-reference-missing",V();if(typeof s!="function"||typeof d!="function")return g.reason="integration-unavailable",V();if(w())return g.reason="cancelled",V();const re=N(),te=()=>{const Q=N()-re;g.scheduleTuneMs=Number.isFinite(Q)&&Q>0?Q:0};let C,G,K,z,I,O,q,U=[],me,ge;try{if(C=await s(),!C||!Array.isArray(C.batchCosts)||C.batchCosts.length===0)throw new Error("schedule workload is missing batch costs");const Q=C.batchRegions??C.signatureInput?.plannedSourceBuckets??null;me=Ui(C.batchCosts,ar,Q),ge=Hi(C.batchCosts,me,Q),G=Gi(C.signatureInput),K=zi(G);const pe={adapterKey:o,modelId:a,weightsId:i,dtype:l,browserMajor:c,kernelTuneId:m,modes:h,signature:G};z=jo(pe),I=Xi(y),_&&(O=Yi(pe),q=Zi(y))}catch(Q){return g.reason="workload-preparation-error",g.error=String(Q?.message??Q).slice(0,160),te(),V()}g.workload=G;const Se=nc(Nn(v,I));U=Se.entries,g.cache.status=Se.status??"miss",Se.status==="corrupt"&&mt(v,I,[]);const oe=T();let J=U.find(Q=>Q.identity===z)??null;if(J){const Q=rc(J,{now:oe,identity:z,kernelTuneId:m,signatureKey:K});if(Q.entry){J={...Q.entry,lastUsedAt:oe},U=Yr(U,J),mt(v,I,U),g.source="cache",g.reason=J.verdict,g.selectedSchedule={...J.schedule},g.effectiveSchedule={...J.schedule},g.evidence={...J.evidence},g.observedShape=J.observedShape?{...J.observedShape}:null,g.screenSubmitShrinks=J.screenSubmitShrinks,g.selectedGain=J.evidence.wallGain??null,g.screenGain=J.evidence.screenWallGain??null,g.confirmationMinGain=J.evidence.confirmationMinWallGain??null,g.sampleCount=J.evidence.sampleCount??0,g.confirmationCount=J.evidence.confirmationCount??0,g.cache.status="hit",g.cache.verdict=J.verdict,_&&(g.amortization.status="cache-hit",g.amortization.reason=null),te();const pe=Ee=>{U=An(U,z),mt(v,I,U),J=null,g.invalidatedReason=Ee,g.cache.status=Ee};return Jt({selectedSchedule:J.schedule,telemetry:g,cacheHit:!0,cachedObservedShape:J.observedShape,driftBatchIndices:me,invalidate:pe})}U=An(U,z),mt(v,I,U),g.cache.status=Q.status,J=null}if(w())return g.reason="cancelled",te(),V();if(_){const Q=Xr(Nn(v,q));let pe=Q.entries;g.amortization.observationCacheState=Q.status??"miss",Q.status==="corrupt"&&qt(v,q,[]);let Ee=pe.find(ke=>ke.identity===O)??null;if(Ee){const ke=ic(Ee,{now:oe,identity:O,kernelTuneId:m,signatureKey:K});ke.entry?(Ee={...ke.entry,lastUsedAt:oe},pe=Zr(pe,Ee),qt(v,q,pe),g.amortization.observationCacheState="hit",g.amortization.observationAgeMs=oe-Ee.createdAt):(pe=pe.filter(Re=>Re.identity!==O),qt(v,q,pe),g.amortization.observationCacheState=ke.status,Ee=null)}let He=null;if(Ee)try{He=qi({kernelReferenceMs:k,kernelReferenceCost:M,sampleCosts:me.map(ke=>C.batchCosts[ke]),armCount:Ge.length,confirmationRounds:2,pretokenizeMs:0})}catch{He=null}const he=cc({observation:Ee,projection:He});if(Object.assign(g.amortization,he),!he.admit){g.reason=he.status;let ke=!1;const Re=(j={})=>{if(ke)return g.amortization.write="duplicate",!1;ke=!0;const Te=ce=>ce?.inFlight===Le.inFlight&&ce?.groupSteps===Le.groupSteps;if(!(j.complete===!0&&j.cancelled===!1&&j.deviceHealthy===!0&&Te(j.configuredSchedule)&&Te(j.effectiveSchedule)&&j.rowCount===r.uncachedRows&&j.batchCount===C.batchCosts.length&&j.submitShrinks===0))return g.amortization.write="rejected",!1;try{const ce=T(),x=sc({identity:O,scopeKey:y,kernelTuneId:m,signatureKey:K,createdAt:ce,schedule:Le,profiledWallMs:j.profiledWallMs,profiledDecodeMs:j.profiledDecodeMs,rowCount:j.rowCount,batchCount:j.batchCount,tokenCount:j.tokenCount,submitShrinks:j.submitShrinks}),R=Xr(Nn(v,q)),F=Zr(R.status===null?R.entries:[],x),H=qt(v,q,F);return g.amortization.write=H?"stored":"unavailable",H}catch{return g.amortization.write="rejected",!1}};return te(),Jt({selectedSchedule:P,telemetry:g,recordBaselineObservation:Re})}}const B=await d({sampleBatchIndices:me,confirmationPlan:ge,workloadBatchCosts:[...C.batchCosts],batchRegions:C.batchRegions??C.signatureInput?.plannedSourceBuckets??null,kernelReferenceMs:k,kernelReferenceCost:M,safetyOptions:A,pretokenize:p,estimateBatch:E,runBatch:S,now:N,isCancelled:w,isDeviceHealthy:f});if(te(),w())return g.source="default",g.reason="cancelled",g.cache.write="not-cacheable",V();g.source=B.source,g.reason=B.reason,g.selectedSchedule={...B.schedule},g.effectiveSchedule={...B.schedule},g.evidence=B.evidence?{...B.evidence}:null,g.candidateEvidence=Array.isArray(B.candidateEvidence)?B.candidateEvidence.map(Q=>({...Q})):[],g.observedShape=B.observedShape?{...B.observedShape}:null,g.projection=B.projection?{...B.projection}:null,g.deadline=B.deadline?{...B.deadline}:null,g.screenSubmitShrinks=B.screenSubmitShrinks??0,g.selectedGain=B.evidence?.wallGain??null,g.screenGain=B.evidence?.screenWallGain??null,g.confirmationMinGain=B.evidence?.confirmationMinWallGain??null,g.sampleCount=B.evidence?.sampleCount??0,g.confirmationCount=B.evidence?.confirmationCount??0,g.confirmationPlan=Array.isArray(B.confirmationPlan)?B.confirmationPlan.map(Q=>({...Q})):ge.map(Q=>({...Q})),g.completedConfirmationRoles=Array.isArray(B.completedConfirmationRoles)?[...B.completedConfirmationRoles]:[],g.cache.verdict=B.verdict,B.cache?.cacheable?(J=ec({identity:z,scopeKey:y,kernelTuneId:m,signatureKey:K,createdAt:oe,ttlClass:B.cache.ttlClass,verdict:B.verdict,schedule:B.schedule,observedShape:B.observedShape,screenSubmitShrinks:B.screenSubmitShrinks,evidence:B.cache.evidence}),U=Yr(U,J),mt(v,I,U),g.cache.write="stored"):g.cache.write="not-cacheable";const Ae=Q=>{J&&(U=An(U,z),mt(v,I,U),J=null),g.invalidatedReason=Q,g.cache.status=Q};return Jt({selectedSchedule:B.schedule,telemetry:g,invalidate:Ae})}async function Wc({model:e=Zn(er),onPhase:t,onProgress:n,onDeviceLost:r,scheduleAutotuneRunner:s=qo,scheduleCacheStorage:o=null,scheduleDefaultEnabled:a=!1,scheduleDefaultSeedFactory:i=()=>globalThis.crypto?.randomUUID?.()}={}){t?.("gpu");const l=await Bs(),c=Io(l.adapterInfo),m=l.hasF16?"f16":"f32";let h=null;l.device.lost.then(M=>{M?.reason!=="destroyed"&&(h={reason:M?.reason??"unknown",message:M?.message??""},console.error(`WebGPU device lost (${h.reason}): ${h.message}`),r?.(h))});let y=null,k=!1;try{t?.("tokenizer");const M=await $s(e.tokenizerId,e.tokRev),A=new URLSearchParams(location.search);let v=o;const p=["shortlist","directq8","immediates","uniformpool","kvplanner","kvcap","cap","tokenbudget","tm","inplacecompact","submitbudget","encsplit","inflight","groupsteps","scheduletune","truncrescue"].filter(he=>A.get(he)!==null).map(he=>`${he}=${String(A.get(he)).slice(0,24)}`),E=A.has("scheduletune")?ro(A.get("scheduletune")):null,S=bi({enabled:a===!0,explicitMode:E,getStorage:()=>v??=Nt("local"),createSeed:i}),w=S.mode,f=A.get("shortlist")!=="0",N=A.get("directq8")!=="0",T=A.get("truncrescue")!=="0",P=A.get("immediates")==="0"?"off":"auto",_=P==="auto"&&l.hasImmediates?"on":"off",g=yc(_,A.get("uniformpool")),V=A.get("submitbudget"),$=V===null?void 0:Number(V)>0?Number(V):null,re=Oc(),te=wc({inFlightParam:A.get("inflight"),groupStepsParam:A.get("groupsteps")}),C=$c({modelId:e.id,ua:navigator.userAgent??"",maxTouchPoints:navigator.maxTouchPoints??0,plannerParam:A.get("kvplanner"),kvcapParam:A.get("kvcap"),capParam:A.get("cap"),budgetParam:A.get("tokenbudget")}),G=A.get("encsplit"),K=G===null?Pc({ua:navigator.userAgent??""}):G==="1",z=m==="f16"&&f?Is(M.idToToken):null;t?.("weights"),y=await Ds(l.device,e.weightsUrl,{targetDtype:m,lmHeadQ8:m==="f16",ffnWT:m==="f16",projWT:m==="f16",directQ8:N,...z?{lmHeadIds:z}:{},onProgress:n}),t?.("gpucheck");let I=null,O=null,q=null,U="default",me=null,ge=null,Se=null;if(c)console.warn("WebGPU software adapter — autotune probes skipped, default routing");else try{const he=Ec(l.adapterInfo,Ls(),m,{subgroupMinSize:l.subgroupMinSize,subgroupMaxSize:l.subgroupMaxSize,immediates:_,uniformPool:g,browserMajor:ur(navigator.userAgent??"")}),ke=localStorage.getItem(he),Re=Mc(ke),j=Re.parsed;if(Re.status==="corrupt")try{localStorage.removeItem(he)}catch{}Re.status&&(Se=Mt(Re.status));const Te=await Os({...l,dtype:m});I=Te;let Pe=!1;const ce=j?Cc(j,Te):null,x=Tc(j?.tuneId);if(ce?.status&&(Se=Mt(ce.status,{priorTuneId:x})),j&&!ce?.status){const R=j.timings?.b64?.def?.medianUs;let F=null;try{const H=await xc({cachedUs:R,measure:()=>Fs({...l,dtype:m},y,{immediates:P,uniformPool:g})}),ae=H.current;if(F=H.retriedUs,Pe=H.accepted,Pe){let X=x,se="accepted";if(!X){X=crypto.randomUUID(),se="legacy-upgraded";try{localStorage.setItem(he,JSON.stringify({...j,tuneId:X}))}catch{}}q=j.tuned,U="cache",O=j.timings??null,me=X,ge=ce.measuredAt,Se=Mt(se,{priorTuneId:x,cachedUs:Number.isFinite(R)?R:null,currentUs:ae.medianUs,retriedUs:F})}else Se=Mt("mismatch",{priorTuneId:x,cachedUs:Number.isFinite(R)?R:null,currentUs:ae.medianUs,retriedUs:F}),console.info(`autotune cache power-state mismatch (cached ${R??"missing"}us vs ${ae.medianUs}us${F!=null?` — warm retry, first read ${F}us`:""}); remeasuring`)}catch(H){Se=Mt("canary-error",{priorTuneId:x,cachedUs:Number.isFinite(R)?R:null,retriedUs:F,error:String(H?.message??H).slice(0,128)}),console.warn("autotune cache canary failed; remeasuring:",H)}}if(!Pe){t?.("autotune");const R=await _s({...l,dtype:m},y,{reductionSafety:Te,immediates:P,uniformPool:g,maxB:ao()});if(q=R.tuned,O=R.timings??null,me=crypto.randomUUID(),ge=Date.now(),U=R.partial?"partial":"measured",!R.partial)try{localStorage.setItem(he,JSON.stringify({tuned:q,timings:R.timings,tuneId:me,date:new Date(ge).toISOString()}))}catch{}}}catch(he){if(he?.code==="WEBMT_NO_SAFE_REDUCTION")throw he;console.warn("autotune unavailable, falling back to auto routing:",he)}t?.("ready");const oe=l.adapterInfo,J=oe.description||[oe.vendor,oe.architecture].filter(Boolean).join(" ")||"GPU",B=sr(),Ae=fi(oe,J,B),Q=[Ae!==J?J:null,oe.subgroupMinSize&&oe.subgroupMaxSize?`subgroup ${oe.subgroupMinSize}–${oe.subgroupMaxSize}`:null,navigator.deviceMemory?`RAM ${navigator.deviceMemory>=32?"≥":"~"}${navigator.deviceMemory}GB`:null,navigator.hardwareConcurrency?`~${navigator.hardwareConcurrency} luồng CPU`:null].filter(Boolean).join(" · "),pe=m==="f16"?2:4;async function Ee(he,{onBatch:ke,shouldStop:Re,pack:j=!1,resume:Te=null,tm:Pe=null,glossary:ce=null,scheduleTuneMode:x=w,decodeScheduleOverride:R=null,onScheduleTune:F=null}={}){const H=Sc(R)??{...te},ae=performance.now(),X=De(he);he=X.text;const se=Bo(he);let Y=se.sentences,be=se.paras;if(j){const D=ni(Y,be);Y=D.rows,be=D.rowParas}if(Y.length===0)return{text:"",cancelled:!1,stats:{sentences:0,tokens:0,ms:0,tokPerSec:0}};const Xe=Array.isArray(Te)&&Te.length===Y.length,Z=Xe?[...Te]:new Array(Y.length).fill(""),$e=Xe?Z.reduce((D,ee)=>D+(ee?1:0),0):0;let it=0,wt=0;if(j&&Pe?.get){const D=performance.now();try{const ee=await Pe.get(Y);for(let ne=0;neZ[ee]?null:ce.protect(D)):null,Cs=Ze?Ze.filter(Boolean).length:0,wr=[],Ot=(j?Rc(Y.map(D=>D.length)):Y.map((D,ee)=>ee)).filter(D=>!Z[D]),Sr=j?C.absCap:ao(),pn=Math.min(192,Sr),xs=j?C.tokenBudget:Dc(),Ft=Ot.map(D=>Y[D].length),_t=j?Xo(Ft,l,pe,pn,Sr,xs,C.policyForS):{ranges:Lc(Ft,l,pe,pn,pn),buckets:[]},{ranges:_e}=_t,gn=D=>{const[ee,ne]=_e[D],le=Ot.slice(ee,ne),Me=j?_t.buckets[D]:null;return{start:ee,end:ne,idx:le,plannedS:Me,sources:le.map(ve=>Ze?.[ve]?.text??Y[ve]),initialKvCapacity:j?C.kvCapacityForS(Me):C.forcedCapacity}},Er=async(D,ee,{primeNext:ne=!1,safetyOptions:le=null}={})=>{if(h)throw new Error(`GPU device lost (${h.reason}): ${h.message}`);const Me=gn(D),ve=le?le.submitBudgetMs:$,W=le?le.encSplitSubmits:K;Gs();const tt=performance.now(),{rows:jt,metrics:ht}=await Or({...l,dtype:m},y,M,Me.sources,{..._r(q,Me.end-Me.start),immediates:P,uniformPool:g,...ee,...ve!==void 0?{submitBudgetMs:ve}:{},encSplitSubmits:W,inPlaceCompact:j&&re,kvCapacity:Me.initialKvCapacity,...j?{maxNewTokens:nn}:{},onPrimed:ne&&D+1<_e.length?()=>{const Wt=gn(D+1);Wt.idx.every(ft=>Z[ft])||Fr(M,Wt.sources).catch(()=>{})}:null}),Ht=performance.now();return{plan:Me,rows:jt,metrics:ht,wallMs:Ht-tt,endedAt:Ht,arenaStats:zs()}};let St=0,Et=0,Gt=0,ct=!1;const kt=[],kr=new Map;let zt=0;const qe={timingMode:"overlapping-gpu-windows",gpuWindowsOverlap:!0,prepMs:0,tmMs:wt,scheduleTuneMs:0,tokenizeMs:0,encoderMs:0,decodeMs:0,detokMs:0,gapMs:0},lt=[],Mr=performance.now();qe.prepMs=Mr-ae-wt;const We=R===null&&j?ro(x):"off",Cr=zc(l.adapterInfo,{subgroupMinSize:l.subgroupMinSize,subgroupMaxSize:l.subgroupMaxSize}),bn=tn(y.weightsTag??e.weightsUrl,"dev"),As=[Cr,e.id,bn,m].join("|").slice(0,512);let vn=null;const xr=D=>{if(typeof F=="function")try{F({active:D,mode:We})}catch{}},Ts=typeof s=="function"?async D=>{xr(!0);try{return await s(D)}finally{xr(!1)}}:null,de=await Hc({enabled:We!=="off",amortizationPolicy:We==="auto"?"automatic":"bypass",configuredSchedule:H,eligibilityInput:{fileMode:j,pack:j,isMobile:C.mobile,uncachedRows:Ot.length,plannedBatches:_e.length,kernelTuneSource:U,manualOverrides:{inflight:R===null?A.get("inflight"):String(H.inFlight),groupsteps:R===null?A.get("groupsteps"):String(H.groupSteps),submitbudget:A.get("submitbudget"),encsplit:A.get("encsplit")},memorySafe:j&&_e.length>0},buildWorkload:async()=>{const D=Ft.map(ne=>Math.max(1,Math.min(Fn,ne+1)));return vn={batchCosts:_e.map(([ne,le],Me)=>{let ve=0;for(let W=ne;Wle-ne),plannedSourceBuckets:[..._t.buckets],sourceTokenLengths:D,modelId:e.id,weightsId:bn,dtype:m,policy:{pack:j,kvPlanner:C.policyLabel,tokenBudget:C.tokenBudget,immediates:_,uniformPool:g}}},vn},adapterKey:Cr,modelId:e.id,weightsId:bn,dtype:m,browserMajor:vc(navigator.userAgent??""),kernelTuneId:me??"untrusted",modes:{pack:j,kvPlanner:C.policyLabel,kvPolicy:C.policyLabel,tokenBudget:C.tokenBudget,immediates:_,uniformPool:g,inPlaceCompact:j&&re,compact:!0,parameterMode:_},scopeKey:As,kernelReferenceMs:Number(O?.b64?.def?.medianUs)/1e3,safetyOptions:{submitBudgetMs:$===void 0?1e3:$,encSplitSubmits:K},storage:We!=="off"?v??=Nt("local"):v,runner:Ts,pretokenize:async D=>{const ee=gn(D);await Fr(M,ee.sources)},estimateBatch:async D=>vn.batchCosts[D],runBatch:async(D,ee,ne)=>{const le=await Er(D,ee,{safetyOptions:ne});return{rows:le.rows,groupStepsStart:le.metrics.groupStepsStart,groupStepsFinal:le.metrics.groupStepsFinal,submitShrinks:le.metrics.submitShrinks,wallMs:le.wallMs,decodeMs:le.metrics.decodeMs,compactions:le.metrics.compactions,cleanupComplete:!0}},isCancelled:()=>Re?.()===!0,isDeviceHealthy:()=>!h,clock:()=>performance.now()});qe.scheduleTuneMs=de.telemetry.scheduleTuneMs;const Ar={...de.selectedSchedule},ut=We==="apply"||We==="auto"?{...Ar}:{...H};de.telemetry.mode=We,de.telemetry.requestedSchedule={...H},de.telemetry.predictedSchedule={...Ar},de.telemetry.configuredSchedule={...ut};const Rs=We==="auto"&&["admitted","cache-hit"].includes(de.telemetry.amortization?.status);de.telemetry.canonicalUsesTunerVerdict=de.telemetry.eligible&&(We==="apply"||Rs);let et={...ut},dt=et.groupSteps;de.telemetry.effectiveSchedule={...et};const Tr=[];let Rr=0,yn=0;const Nr=new Set(de.driftBatchIndices);let wn=performance.now();for(let D=0;D<_e.length;D++){if(Re?.()){ct=!0;break}const ee=performance.now();qe.gapMs+=ee-wn;const ne={inFlight:et.inFlight,groupSteps:Math.min(et.groupSteps,dt)},le=await Er(D,ne,{primeNext:!0}),{plan:Me,rows:ve,metrics:W,endedAt:tt,arenaStats:jt}=le,{idx:ht,plannedS:Ht}=Me;qe.tokenizeMs+=W.tokenizeMs,qe.encoderMs+=W.encoderMs,qe.decodeMs+=W.decodeMs,qe.detokMs+=W.detokMs,W.groupStepsFinal&&(dt=Math.min(dt,W.groupStepsFinal)),wn=tt;const Wt=wn-ee;lt.push({B:W.B,S:W.S,cap:W.cap,steps:W.steps,submits:W.submits,compactions:W.compactions,compactMode:W.compactMode,inFlight:ne.inFlight,configuredInFlight:ut.inFlight,configuredGroupSteps:ut.groupSteps,groupSteps:W.groupStepsStart,awaitMs:Be(W.awaitMs),cpuEncodeMs:Be(W.cpuEncodeMs),groupStepsFinal:W.groupStepsFinal,submitShrinks:W.submitShrinks,maxGroupAwaitMs:Be(W.maxGroupAwaitMs),plannedS:Ht,initialKvCapacity:W.initialKvCapacity,finalKvCapacity:W.finalKvCapacity,kvGrows:W.kvGrows,kvGrowsWithPending:W.kvGrowsWithPending,kvCapacitySequence:W.kvCapacitySequence,kvGrowBindGroupsPurged:W.kvGrowBindGroupsPurged,sourceTokenArea:W.B*W.S,tokens:W.tokensGenerated,ms:Be(Wt),encoderMs:Be(W.encoderMs),decodeMs:Be(W.decodeMs),logicalArenaPeakMB:Be(jt.highWaterBytes/1048576),submittedArenaPeakMB:Be(jt.submittedHighWaterBytes/1048576)});let ft=null;if(de.telemetry.enabled&&de.telemetry.eligible&&!de.telemetry.invalidatedReason&&W.submitShrinks>0)ft="submit-shrink";else if(de.cacheHit&&!de.telemetry.invalidatedReason&&de.cachedObservedShape&&Nr.has(D)){for(const Ie of ve)Tr.push(Math.max(1,(Ie.ids?.length??1)-1));if(W.compactions>0&&Rr++,yn++,yn===Nr.size){const Ie=jc(Tr,Rr,yn);de.telemetry.canonicalObservedShape=Ie,Ko(de.cachedObservedShape,Ie)&&(ft="shape-drift")}}ft&&(de.invalidate(ft),et={...Le},dt=Math.min(dt,Le.groupSteps)),de.telemetry.effectiveSchedule={inFlight:et.inFlight,groupSteps:Math.min(et.groupSteps,dt)};const Ir=new Set;if(ve.forEach((Ie,Kt)=>{const Oe=ht[Kt];let Vt=Ie.text.normalize("NFC");if(Ie.srcTruncated){kt.push(Oe),kr.set(Oe,Vt),Z[Oe]="";return}const Dr=Ze?.[Oe];if(Dr){const Lr=ce.restore(Vt,Dr.marks);Vt=Lr.text,Lr.ok||(wr.push(Oe),Ir.add(Oe))}Z[Oe]=Vt,Ie.forcedEos&&Et++}),Gt+=ve.length,St+=W.tokensGenerated,j&&Pe?.put){const Ie=[];if(ve.forEach((Kt,Oe)=>{!Kt.srcTruncated&&!Kt.forcedEos&&!Ir.has(ht[Oe])&&Ie.push([Y[ht[Oe]],Z[ht[Oe]]])}),Ie.length)try{Pe.put(Ie)}catch{}}ke?.(D+1,_e.length,Z)}const Pr=async(D,ee=0)=>{if(h)throw new Error(`GPU device lost (${h.reason}): ${h.message}`);const ne=sn(D,Math.max(8,Math.ceil(D.length/2)));if(ne.length<=1)return{text:null,forcedEos:!1};const le=await Or({...l,dtype:m},y,M,ne,{..._r(q,ne.length),immediates:P,uniformPool:g,encSplitSubmits:K,...$!==void 0?{submitBudgetMs:$}:{},maxNewTokens:nn});St+=le.metrics.tokensGenerated;const Me=[];for(let ve=0;ve=2)return{text:null,forcedEos:W.forcedEos};const tt=await Pr(ne[ve],ee+1);if(tt.text===null)return{text:null,forcedEos:W.forcedEos||tt.forcedEos};Me.push(tt.text)}else{if(W.forcedEos)return{text:null,forcedEos:!0};Me.push(W.text.normalize("NFC"))}}return{text:Me.join(" "),forcedEos:!1}};for(const D of kt){if(ct||Re?.()){ct=!0;break}let ee=null;if(T){const ne=await Pr(Y[D]);if(ee=ne.text,ne.forcedEos&&Et++,ee!==null&&(zt++,Z[D]=ee,j&&Pe?.put&&!Ze?.[D]))try{Pe.put([[Y[D],ee]])}catch{}}ee===null&&(Z[D]=kr.get(D)??"")}const Ut=performance.now()-Mr;kt.length>zt&&console.warn(`translateText: ${kt.length-zt}/${Y.length} rows exceeded SRC_CAP and kept a prefix-only translation`),Et>0&&console.warn(`translateText: ${Et}/${Y.length} rows hit the token cap (tail may be cut)`);const{profiledMs:Br,profiledDecodeMs:$r,sBuckets:Ns}=_c(lt,Ut),Ps=lt.reduce((D,ee)=>D+(ee.submitShrinks??0),0);return de.recordBaselineObservation({complete:!ct&&Gt===Ot.length&<.length===_e.length,cancelled:ct,deviceHealthy:!h,configuredSchedule:ut,effectiveSchedule:de.telemetry.effectiveSchedule,profiledWallMs:Br,profiledDecodeMs:$r,rowCount:Gt,batchCount:lt.length,tokenCount:St,submitShrinks:Ps}),{text:ri(be,Z),rowTexts:Z,cancelled:ct,stats:{sentences:Y.length,tokens:St,ms:Ut,forcedEos:Et,t2s:X.changed,srcTruncated:kt.length,truncRescued:zt,glossaryRows:Cs,glossaryFailed:wr,batches:_e.length,stages:qe,resumeHits:$e,tmHits:it,decodedRows:Gt,batchStats:lt,decodeSchedule:{...ut},requestedDecodeSchedule:{...H},effectiveDecodeSchedule:{...de.telemetry.effectiveSchedule},scheduleAutotune:de.telemetry,profiledMs:Br,profiledDecodeMs:$r,sBuckets:Ns,tokPerSec:Ut>0?St/Ut*1e3:0}}}const He={info:{gpuName:Ae,gpuTitle:Q,dtype:m,softwareAdapter:c,lmHeadQ8:m==="f16",lmShortN:z?.length??0,directQ8:y.q8Stats.directTensors>0,immediates:_,uniformPool:g?"b64":"off",inPlaceCompact:re?"explicit":"off",decodeSchedule:{...te},scheduleTuneMode:w,scheduleDefault:{source:S.source,reason:S.reason,revision:S.revision,rolloutBps:S.rolloutBps},kvPolicy:C.policyLabel,kvPlannerOverride:A.get("kvplanner"),kvCapacityOverride:A.get("kvcap"),q8Stats:y.q8Stats,tunedFrom:U,modelId:e.id,modelName:e.name,weightsTag:y.weightsTag??"dev",tokRev:e.tokRev??null,bench:{adapterInfo:{...l.adapterInfo},subgroupMinSize:l.subgroupMinSize,subgroupMaxSize:l.subgroupMaxSize,hasF16:l.hasF16,limits:{...l.limits},kernelRev:xo,safety:I?{...I.verdicts,forceSg:I.forceSg}:null,tuned:q,tunedFrom:U,timings:O,protocolRev:Us,tuneId:me,measuredAt:ge,cacheCheck:Se,flags:p,gpuName:Ae,gpuWebgl:B?.renderer??null,webglSameGpu:!!(B&&Lo(oe.vendor,B.vendor,B.renderer)),adapterLimits:{...l.adapterLimits},features:[...l.features??[]],wgslFeatures:(()=>{try{return[...navigator.gpu?.wgslLanguageFeatures??[]]}catch{return[]}})()}},translateText:Ee,isLost:()=>h,destroy:()=>{try{y.buffer.destroy()}catch{}try{l.device.destroy()}catch{}}};return k=!0,He}finally{if(!k){try{y?.buffer?.destroy()}catch{}try{l.device.destroy()}catch{}}}}const Kc=["auto","utf-8","gb18030","big5","utf-16le","utf-16be"],Vc=new Set("的一是不了人我在有他这为之大来以个中上们到说国和地也子时道出而要于就下得可你年生自会那后能对着事其里所去行过家十用发天如然作方成者多日都三小军二无同么经法当起与好看学进种将还分此心前面又定见只主没公从知世什两次使身被高已亲话常活正感明问力理尔点文几本特做外孩相西果走月实向声车全信重机工物气每并别真打太新比才便夫再书部水像眼等体却加电主界门利海受听表德少克代员许先口由死安写性马光白或住难望教命花结乐色更拉东神记处让母父应直字场平报友关放至张认接告入笑内英军候民岁往何度山觉路带万男边风解叫任金快原吃妈变通师立象数四失满战远格士音轻目条呢病始达深完今提求清王化空业思切怎非找片罗钱吗语元喜曾离飞科言干流欢约各即指合反题必该论交终林请医晚制球决传画保读运及则房早院量苦火布品近坐产答星精视五连司巴這為來個們說國時過還進裡著見兩麼開關門問間東車書興學實現點戰處條讓報馬場話認遠飛樂氣師難聽當義務長員島洋歐陽於億敵獨隊淚類燈爾談請諸講謝證識護賽選遺醫錢鐵閒陳陰險陸雙雞離電靈頭頗題顧風餘體高鬥魚鳥龍發夢舊聲應轉醒覺對藥雲會後".split("")).add(",").add("。").add("、"),Pn=(e,...t)=>t.every((n,r)=>e[r]===n);function co(e){let t=0,n=0,r=0;for(const s of e){const o=s.codePointAt(0);if(o===65533){r++;continue}(o>=19968&&o<=40959||o>=12288&&o<=12351||o>=65280&&o<=65374)&&(t++,Vc.has(s)&&n++)}return t+r===0?-1:(n-4*r)/(t+r)}function qc(e){if(e.length>=3&&Pn(e,239,187,191))return"utf-8";if(e.length>=2&&Pn(e,255,254))return"utf-16le";if(e.length>=2&&Pn(e,254,255))return"utf-16be";try{return new TextDecoder("utf-8",{fatal:!0}).decode(e),"utf-8"}catch{}const t=e.subarray(0,65536),n=new TextDecoder("gb18030").decode(t),r=new TextDecoder("big5").decode(t),s=co(n),o=co(r);return o>s*1.05&&o>0?"big5":"gb18030"}function Zo(e,t="auto"){const n=t==="auto"?qc(e):t;return{text:new TextDecoder(n).decode(e),encoding:n}}const es=["QX7","KX7","RX7","ZX9","ZQ1","VX1"];function Jc(e){let t=2166136261;for(let n=0;n>>0).toString(16).padStart(8,"0")}function ts(e,t=""){const n=[...new Set(e)].sort().join("");return Jc(t?`${n}${t}`:n)}function Qc(e){const t=(e??[]).filter(n=>n?.enabled!==!1&&n?.zh&&n?.vi).map(n=>({zh:De(n.zh).text,vi:n.vi})).filter((n,r,s)=>s.findIndex(o=>o.zh===n.zh)===r).sort((n,r)=>r.zh.length-n.zh.length);return t.length?{terms:t}:null}function ns(e,t){const n=[];for(const r of t.terms){let s=0;for(;(s=e.indexOf(r.zh,s))!==-1;){const o=s+r.zh.length;n.some(a=>sa.start)||n.push({start:s,end:o,term:r}),s=o}}return n.sort((r,s)=>r.start-s.start)}function Yc(e,t){if(!t)return null;const n=ns(e,t);if(!n.length)return null;const r=es.filter(i=>!e.includes(i)),s=new Map,o=[];for(const i of n){let l=s.get(i.term.zh);if(!l){if(!r.length)continue;l={marker:r.shift(),vi:i.term.vi,count:0},s.set(i.term.zh,l)}l.count++,o.push({start:i.start,end:i.end,marker:l.marker})}if(!o.length)return null;let a=e;for(let i=o.length-1;i>=0;i--){const l=o[i];a=a.slice(0,l.start)+l.marker+a.slice(l.end)}return{text:a,marks:[...s.values()]}}function rs(e,t){let n=!0,r=e;for(const s of t){const o=r.split(s.marker).length-1;o!==s.count&&(n=!1),o&&(r=r.split(s.marker).join(s.vi))}return{text:r,ok:n}}function lo(e,t){if(!t)return null;const n=ns(e,t);return n.length?ts(n.map(r=>`${r.term.zh}${r.term.vi}`)):null}const uo="moxhi.glossary",Xc="file không đúng định dạng";function ho(e){return e?.version!==1||!Array.isArray(e.terms)?null:e.terms.filter(t=>t&&typeof t.zh=="string"&&typeof t.vi=="string").map(t=>({zh:t.zh.trim(),vi:t.vi.trim(),enabled:t.enabled!==!1})).filter(t=>t.zh&&t.vi)}function Zc({storage:e=Nt("local")}={}){let t;try{t=ho(JSON.parse(e.getItem(uo)??"null"))??[]}catch{t=[]}const n=new Set;function r(){e.setItem(uo,JSON.stringify({version:1,terms:t}));for(const o of n)o()}function s({zh:o,vi:a}){if(o=String(o??"").trim(),a=String(a??"").trim(),!o||!a)return!1;const i=t.find(l=>l.zh===o);return i?(i.vi=a,i.enabled=!0):t.push({zh:o,vi:a,enabled:!0}),r(),!0}return{list:()=>t.map(o=>({...o})),count:()=>t.filter(o=>o.enabled).length,add:s,update(o,a){const i=t.find(l=>l.zh===o);i&&(typeof a?.vi=="string"&&a.vi.trim()&&(i.vi=a.vi.trim()),typeof a?.enabled=="boolean"&&(i.enabled=a.enabled),r())},remove(o){const a=t.length;t=t.filter(i=>i.zh!==o),t.length!==a&&r()},importJson(o){let a;try{a=ho(JSON.parse(o))}catch{a=null}if(!a)throw new Error(Xc);let i=0,l=0;for(const c of a){const m=t.find(h=>h.zh===c.zh);m?(m.vi=c.vi,m.enabled=c.enabled,l++):(t.push(c),i++)}return r(),{added:i,updated:l}},exportJson:()=>JSON.stringify({version:1,terms:t},null,2),subscribe(o){return n.add(o),()=>n.delete(o)}}}const bt="autodict-v1",el=(e,t)=>et?1:0,tl=e=>Array.from(e).length,nl=(e,t)=>e.startt.start,qn=e=>`${e.source}\0${e.zh}`,nt=Object.freeze([]),rl=Object.freeze({candidateSpans:nt,spans:nt,protectedSpans:nt,overflowSpans:nt,rejectedSpans:nt,marks:nt,signatureMaterial:Object.freeze({pairs:nt,hasAuto:!1})});function ol(e,t,n){const r=De(String(e?.zh??"").trim()).text,s=String(e?.vi??"").trim().normalize("NFC");return!r||!s?null:{...e,zh:r,vi:s,source:t,order:n,pointLength:tl(r)}}function dn(e,t="auto"){const n=[],r=new Map;for(const[o,a]of(e??[]).entries()){const i=ol(a,a?.source??t,o);if(!i)continue;const l=r.get(i.zh);if(l){if(l.vi!==i.vi)throw new Error(`conflicting canonical target for ${i.zh}`);continue}r.set(i.zh,i),n.push(i)}const s=new Map;for(const o of n){const a=o.zh[0],i=s.get(a)??[];i.push(o),s.set(a,i)}for(const o of s.values())o.sort((a,i)=>i.zh.length-a.zh.length||a.order-i.order);return{terms:n,byFirst:s}}function sl(e,t){if(!t)return{terms:e.terms,revision:e.revision,policy:null};if(t.version!==1||t.protocol!=="autodict-runtime-policy-v1"||!/^sha256:[0-9a-f]{64}$/.test(t.revision??"")||t.baseArtifactRevision!==e.revision||!Array.isArray(t.demote)||!Array.isArray(t.guards))throw new Error("hard-name runtime policy is incompatible with the mined artifact");const n=new Map(e.terms.map(o=>[De(o.zh).text,o])),r=new Set;for(const o of t.demote){const a=De(String(o?.zh??"").trim()).text,i=n.get(a);if(!a||r.has(a)||!i||i.vi!==o.vi)throw new Error(`invalid hard-name runtime demotion: ${o?.id??""}`);r.add(a)}const s=new Map;for(const o of t.guards){const a=De(String(o?.zh??"").trim()).text,i=n.get(a),l=[...new Set((o?.excludeWithin??[]).map(c=>De(String(c??"").trim()).text).filter(Boolean))];if(!a||s.has(a)||r.has(a)||!i||i.vi!==o.vi||!l.length||l.some(c=>c===a||!c.includes(a)))throw new Error(`invalid hard-name runtime guard: ${o?.id??""}`);s.set(a,l)}return{terms:e.terms.filter(o=>!r.has(De(o.zh).text)).map(o=>{const a=s.get(De(o.zh).text);return a?{...o,excludeWithin:a}:o}),revision:t.revision,policy:t}}function al(e,t=null){if(e?.version!==1||!Array.isArray(e.terms)||typeof e.revision!="string"||!e.revision)throw new Error("hard_names.json has an unsupported schema");if((e.protocol??bt)!==bt)throw new Error(`hard_names.json needs protocol ${bt}`);const n=sl(e,t),r=dn(n.terms.map(s=>({...s,source:"auto"})));return r.terms.sort((s,o)=>el(s.zh,o.zh)),{version:1,revision:n.revision,minedRevision:e.revision,protocol:e.protocol??bt,sources:e.sources??[],runtimePolicy:n.policy,terms:r.terms,index:dn(r.terms)}}function il(e,t){for(const n of t.term.excludeWithin??[]){let r=0;for(;(r=e.indexOf(n,r))!==-1;){const s=r+n.length;if(r<=t.start&&s>=t.end)return!0;r=s}}return!1}function Jn(e,t){if(!t?.terms?.length||!e)return[];const n=[];for(let r=0;re.startsWith(s.zh,n)))return!0;return!1}function mo(e,t=[]){const n=[],r=[],s=[...e].sort((o,a)=>a.term.zh.length-o.term.zh.length||o.term.order-a.term.order||o.start-a.start);for(const o of s)[...t,...n].some(a=>nl(o,a))?r.push({...o,reason:"overlap"}):n.push(o);return{selected:n,rejected:r}}function cl(e,t){const n=new Map;for(const r of Jn(e,t))n.set(r.term.zh,(n.get(r.term.zh)??0)+1);return n}function ll({userCompiled:e=null,autoLexicon:t,documentText:n="",suppressions:r=[]}={}){const s=(e?.terms??[]).map((h,y)=>({...h,source:"user",order:y})),o=dn(s,"user"),a=si(String(n??"")).text,i=cl(a,t?.index),l=new Set([...r].map(h=>De(String(h??"").trim()).text).filter(Boolean)),c=new Set(o.terms.map(h=>h.zh)),m=(t?.terms??[]).filter(h=>(i.get(h.zh)??0)>0).map(h=>{const y=i.get(h.zh);let k="eligible";c.has(h.zh)?k="overridden":h.pointLength===2&&y<2&&(k="frequency");const M=l.has(h.zh)?"suppressed":k;return{zh:h.zh,vi:h.vi,src:h.src,count:y,status:M,baseStatus:k}});return{userIndex:o,autoIndex:t?.index??dn([]),artifactRevision:t?.revision??"",protocol:t?.protocol??bt,documentCounts:i,documentTerms:m,suppressed:l}}function po(e,t){const n=new Set,r=[];for(const s of e.filter(o=>o.term.source===t).sort((o,a)=>o.start-a.start)){const o=qn(s.term);n.has(o)||(n.add(o),r.push(s.term))}return r}function ul(e,t){if(!fo(e,t?.userIndex)&&!fo(e,t?.autoIndex))return rl;const n=Jn(e,t?.userIndex),r=mo(n),s=Jn(e,t?.autoIndex),o=[],a=[];for(const v of s)t.suppressed.has(v.term.zh)?a.push({...v,reason:"suppressed"}):il(e,v)?a.push({...v,reason:"context"}):v.term.pointLength===2&&(t.documentCounts.get(v.term.zh)??0)<2?a.push({...v,reason:"frequency"}):o.push(v);const i=mo(o,r.selected);a.push(...i.rejected);const l=[...r.selected,...i.selected].sort((v,d)=>v.start-d.start),c=es.filter(v=>!e.includes(v)),m=new Map,h=new Set,y=[...po(l,"user"),...po(l,"auto")];for(const v of y){const d=qn(v);c.length?m.set(d,{marker:c.shift(),vi:v.vi,count:0}):h.add(d)}const k=[],M=[];for(const v of l){const d=m.get(qn(v.term));if(!d){M.push(v);continue}d.count++,k.push({...v,marker:d.marker})}const A=l.map(v=>`${v.term.zh}${v.term.vi}`);return{candidateSpans:s,spans:l,protectedSpans:k,overflowSpans:M,rejectedSpans:a,marks:[...m.values()],signatureMaterial:{pairs:A,hasAuto:l.some(v=>v.term.source==="auto")}}}function dl(e,t){if(!t?.protectedSpans.length)return null;let n=e;const r=[...t.protectedSpans].sort((s,o)=>o.start-s.start);for(const s of r)n=n.slice(0,s.start)+s.marker+n.slice(s.end);return{text:n,marks:t.marks}}function hl(e,{artifactRevision:t="",protocol:n=bt}={}){const r=e?.signatureMaterial;if(!r?.pairs.length)return null;const s=r.hasAuto?`auto=${t}protocol=${n}`:"";return ts(r.pairs,s)}let Bn=null,$n=null;async function fl(){return $n?{lexicon:$n,metrics:{cold:!1,loadMs:0,indexMs:0}}:(Bn??=(async()=>{const e=performance.now(),[t,n]=await Promise.all([Tt(()=>import("./hard_names-IXaPbn85.js"),[]),Tt(()=>import("./hard_name_runtime_policy-DqURZSqL.js"),[])]),r=performance.now()-e,s=performance.now(),o=al(t.default,n.default),a=performance.now()-s;return $n=o,{lexicon:o,metrics:{cold:!0,loadMs:r,indexMs:a}}})().catch(e=>{throw Bn=null,e}),Bn)}function ml({documentText:e,userCompiled:t,autoLexicon:n,suppressions:r}={}){const s=ll({documentText:e,userCompiled:t,autoLexicon:n,suppressions:r}),o=new Map;let a=0,i=0,l=0;const c=new WeakMap,m=[],h=v=>{let d=o.get(v);if(d)l++;else{const p=performance.now();d=ul(v,s),a+=performance.now()-p,i++,(d.spans.length||d.candidateSpans.length)&&o.set(v,d)}return d};return{ctx:s,glossary:{protect:v=>{const d=h(v),p=dl(v,d);return p&&c.set(p.marks,d.protectedSpans.some(E=>E.term.source==="auto")),p},restore:(v,d)=>{const p=rs(v,d);return p.ok||m.push(c.get(d)===!0),p}},signature:v=>hl(h(v),{artifactRevision:s.artifactRevision,protocol:s.protocol}),resolutionFor:h,takeUserRetryRows:v=>{const d=[...v??[]],p=m.splice(0,d.length);return p.length!==d.length?d:d.filter((E,S)=>p[S])},summary:()=>{const v=new Map,d={frequency:0,suppressed:0,context:0,overlap:0};let p=0,E=0;for(const w of o.values()){const f=w.spans.filter(T=>T.term.source==="auto");f.length&&p++;const N=new Set(w.overflowSpans.filter(T=>T.term.source==="auto").map(T=>T.term.zh));E+=N.size;for(const T of w.rejectedSpans)Object.hasOwn(d,T.reason)&&d[T.reason]++;for(const T of f){const P=v.get(T.term.zh)??{selected:0,protected:0,overflow:0};P.selected++,w.protectedSpans.some(_=>_.start===T.start&&_.end===T.end&&_.term.source==="auto")&&P.protected++,w.overflowSpans.some(_=>_.start===T.start&&_.end===T.end&&_.term.source==="auto")&&P.overflow++,v.set(T.term.zh,P)}}const S=s.documentTerms.map(w=>({...w,...v.get(w.zh)??{selected:0,protected:0,overflow:0}}));return{enabled:!0,artifactRevision:s.artifactRevision,protocol:s.protocol,autoDictRows:p,markerOverflowTerms:E,rejectedSpans:d,resolvedUniqueRows:o.size,resolveCalls:i,cacheHits:l,resolveMs:a,documentTerms:S}}}}const go="moxhi.autodict.suppressions.v1",Qt=e=>De(String(e??"").trim()).text;function pl({storage:e=Nt("local")}={}){let t=new Set,n=[];try{const a=JSON.parse(e.getItem(go)??"null");a?.version===1&&Array.isArray(a.terms)&&(t=new Set(a.terms.map(Qt).filter(Boolean)))}catch{}const r=new Set,s=()=>{for(const a of r)a()},o=()=>{e.setItem(go,JSON.stringify({version:1,terms:[...t].sort()})),s()};return{suppressions:()=>[...t],isSuppressed:a=>t.has(Qt(a)),suppress(a,i=!0){const l=Qt(a);l&&(i?t.add(l):t.delete(l),n=n.map(c=>Qt(c.zh)===l?{...c,status:i?"suppressed":c.baseStatus??"eligible"}:c),o())},listDocumentTerms:()=>n.map(a=>({...a})),setDocumentTerms(a){n=(a??[]).map(i=>({...i})),s()},clearDocumentTerms(){n.length&&(n=[],s())},subscribe(a){return r.add(a),()=>r.delete(a)}}}const bo=e=>[...e?.stats?.glossaryFailed??[]];function vo(e,t){const n=[...e.rowTexts];for(const r of t)n[r]="";return n}async function gl({runOnce:e,initial:t,combinedGlossary:n,combinedTm:r,userGlossary:s=null,userTm:o=null,rawTm:a=null,selectUserRetryRows:i=null,canRetry:l=()=>!0}){let c=await e({glossary:n,resume:t,tm:r});const m=c.stats,h=bo(c);let y=0,k=0;if(!h.length||c.cancelled||!l())return c;let M=[...h];if(s&&i){const A=new Set(i(h,c)??[]),v=h.filter(d=>A.has(d));if(M=h.filter(d=>!A.has(d)),y=v.length,v.length&&(c=await e({glossary:s,resume:vo(c,v),tm:o}),M.push(...bo(c))),c.cancelled||!l())return{...c,stats:{...m,glossaryFailed:h,autoDictUserRetryRows:y,autoDictRawRetryRows:0}}}return M=[...new Set(M)],M.length?(k=M.length,c=await e({glossary:null,resume:vo(c,M),tm:a}),{...c,stats:{...m,glossaryFailed:h,autoDictUserRetryRows:y,autoDictRawRetryRows:k}}):{...c,stats:{...m,glossaryFailed:h,autoDictUserRetryRows:y,autoDictRawRetryRows:0}}}const bl=Object.freeze({stage:"TP-r6b-WebGPU",manifestSha256:"1f09298a34baaf2e10ace82c56931b50398c8c2c672f1abf39fbab32177721d9",imageSha256:"291c2de621b0057c3e07802df62d3e96da6e64fc126f9d78882ec11153009419",remapSha256:"7ba177d9aa9551a7369c44dff93ef112e69d6143e8244df5f2c5dbbce6e2b758"});function yo(e,t){const n=new Error(e,t?{cause:t}:void 0);return n.code="unsupported",n}function vl({gpuAssetBase:e="/model-tp-gpu",loadGpuEngine:t=()=>Tt(()=>import("./index-CYR4sZ9g.js"),[]),hasWebGpu:n=()=>typeof navigator<"u"&&!!navigator.gpu}={}){let r=null,s=null,o=0;async function a({onProgress:i}){if(!n())throw yo("Trình duyệt không hỗ trợ WebGPU nên không quét tên được.");const{createD10Ner:l}=await t();try{return await l({assetBase:e,onProgress:i,pins:bl})}catch(c){throw/shader-f16/i.test(c?.message??"")?yo("GPU này thiếu shader-f16 nên không quét tên được (phần dịch vẫn chạy bình thường).",c):c}}return{id:"r6b-tp",label:"r6b TP",downloadMB:3.9,async load({onProgress:i}={}){r||(s??=(async()=>{const l=o;try{const c=await a({onProgress:i});if(l!==o){try{c.releaseWorkspaces?.()}catch{}try{c.destroy?.()}catch{}throw new DOMException("panel đã đóng trong lúc tải mô hình","AbortError")}r=c}catch(c){throw l===o&&(s=null),c}})(),await s)},async run(i,{onProgress:l,signal:c}={}){if(!r)throw new Error("provider chưa load()");const m=await r.analyze(i,{signal:c,onProgress:l}),h=[];return m.forEach((y,k)=>{for(const M of y.entities)h.push({text:M.text,type:M.type,row:k,start:M.startCodepoint,end:M.endCodepoint,confidence:M.confidence})}),{entities:h}},release(){o+=1;try{r?.releaseWorkspaces()}catch{}try{r?.destroy()}catch{}r=null,s=null}}}function yl(e){const t=new Map;for(const n of e){const r=`${n.text}\0${n.type}`,s=t.get(r);s?(s.count+=1,(n.rowr.count-n.count||n.text.localeCompare(r.text,"zh"))}function wl(e){const t={all:e.length,Nh:0,Ns:0,Ni:0};for(const n of e)n.type in t&&(t[n.type]+=1);return t}let In=null;function wo(){return In??=Tt(()=>import("./names_data-BiNDx6YF.js"),[]).then(e=>e.default).catch(e=>{throw In=null,e}),In}function So(e,t){const n=String(e??"");return t.latin[n]??t.latin[De(n).text]??null}function Sl(e,t){const n=Array.from(String(e??""));return n.length<3?!1:n.every(r=>t.translit.includes(r))}const At={Nh:"Người",Ns:"Địa danh",Ni:"Tổ chức"},os={Nh:ue.person,Ns:ue.pin,Ni:ue.flag},Yt=200;function El(e){const t=document.createElement("span");return t.className="enttypeicon",t.innerHTML=os[e]??"",t.title=At[e]??e,t.setAttribute("role","img"),t.setAttribute("aria-label",At[e]??e),t}function kl({provider:e,glossaryStore:t,jobs:n,getRows:r,hasText:s,getFp:o=()=>"",onChange:a=()=>{}}={}){let i=null,l=null,c=[],m=null,h=null,y=Yt,k=null,M="",A=null,v=null,d=null,p=null,E=null;const S=C=>`${C.text}\0${C.type}`,w=()=>!!n.current();function f(C){const G=document.createElement("p");return G.className="hint",G.textContent=C,G}function N(C){if(d){if(!C||C.kind!=="analyze"){d.hidden=!0;return}d.hidden=!1,d.firstChild.textContent=C.phase==="tải mô hình"?`Tải mô hình ${(C.done/1048576).toFixed(1)}/${(C.total/1048576).toFixed(1)} MB…`:`Phân tích ${C.done}/${C.total} câu…`}}function T(){l&&m!==o()&&(l=null,c=[],m=null,k=null,h=null,M="Văn bản đã đổi — bấm Quét tên để cập nhật.")}async function P(){const C=r();if(!C.length)return M="Chưa có văn bản để quét.",te(),"empty";M="";const G=o(),K=Promise.all([_n(),wo()]).then(([O,q])=>{A=O,v=q}).catch(()=>{}),z=n.run({kind:"analyze",label:"Quét thực thể",total:C.length,exec:async O=>{await e.load({onProgress:U=>{U.stage==="weights"&&O.progress({phase:"tải mô hình",done:U.loaded??0,total:U.total??0})}}),O.progress({phase:"phân tích",done:0,total:C.length});const q=await e.run(C,{signal:O.signal,onProgress:U=>{U.stage==="analysis"&&O.progress({done:U.completedRows,total:U.totalRows})}});l=yl(q.entities),c=C,h=null,y=Yt,k=null}});te();let I="ok";try{await z==="refused"&&(M="Đang bận việc khác — chờ xong rồi quét.",I="refused")}catch(O){O?.name==="AbortError"?(M="Đã hủy quét.",I="cancelled"):(M=O?.code==="unsupported"?O.message:`Quét lỗi: ${O?.message??O}`,I="error")}return I==="ok"&&(m=G),await K,te(),a(),I}function _(){const C=wl(l),G=document.createElement("div");G.className="entfilter";for(const[K,z,I]of[[null,"Tất cả",C.all],["Nh",At.Nh,C.Nh],["Ns",At.Ns,C.Ns],["Ni",At.Ni,C.Ni]]){const O=document.createElement("button");O.type="button",O.className=h===K?"ghost on":"ghost",K&&(O.innerHTML=os[K]),O.append(`${z} ${I}`),O.addEventListener("click",()=>{h=K,y=Yt,te()}),G.append(O)}return G}function g(C){const G=Array.from(c[C.firstRow]??""),K=document.createElement("p");K.className="entexample";const z=document.createElement("mark");return z.textContent=G.slice(C.firstStart,C.firstEnd).join(""),K.append(G.slice(0,C.firstStart).join(""),z,G.slice(C.firstEnd).join("")),K}function V(C){const G=document.createElement("form");G.className="entadd";const K=document.createElement("input"),z=v?So(C.text,v):null;K.value=z??(A?Gn(C.text,A):""),K.setAttribute("aria-label","Dịch thành");const I=document.createElement("button");if(I.type="submit",I.className="ghost",I.textContent="Lưu",G.append(K,I),!z&&v&&Sl(C.text,v)){const O=document.createElement("p");O.className="hint",O.textContent="Có vẻ là tên phiên âm phương Tây — thường giữ dạng Latin thay vì Hán-Việt.",G.append(O)}return G.addEventListener("submit",O=>{O.preventDefault(),t.add({zh:C.text,vi:K.value})?(M=`đã thêm ${C.text} → ${K.value.trim()}`,k=null):(M="Cần nhập nghĩa tiếng Việt.",te())}),G}function $(C,G,K){const z=S(C),I=document.createElement("tr"),O=document.createElement("td");O.className="entzh",O.append(El(C.type),C.text);const q=document.createElement("td");q.className="enthv",q.textContent=A?Gn(C.text,A):"";const U=document.createElement("td");U.className="entvi";const me=K.get(C.text),ge=!me&&v?So(C.text,v):null;me!=null?(U.textContent=me,U.title="Theo từ điển tên riêng"):ge?(U.textContent=ge,U.classList.add("entguess"),U.title="Gợi ý tên Tây/Nhật — bấm Thêm để sửa và lưu"):(U.textContent="—",U.classList.add("entnone"),U.title="Chưa thêm — form Thêm sẽ điền sẵn âm Hán-Việt");const Se=document.createElement("td");Se.className="num entn",Se.textContent=`×${C.count}`;const oe=document.createElement("td");if(oe.className="num entact",G)oe.classList.add("entdone"),oe.textContent="✓",oe.title="Đã có trong từ điển — sửa bên panel Từ điển tên riêng";else{const B=document.createElement("button");B.type="button",B.className="ghost",B.textContent="Thêm",B.addEventListener("click",async Ae=>{Ae.stopPropagation(),[A,v]=await Promise.all([_n(),wo()]),k={key:z,add:!0},te(),i?.querySelector(".entadd input")?.focus()}),oe.append(B)}I.append(O,q,U,Se,oe),I.addEventListener("click",()=>{k=k?.key===z?null:{key:z,add:!1},te()});const J=[I];if(k?.key===z){const B=document.createElement("tr");B.className="entdetail";const Ae=document.createElement("td");Ae.colSpan=5,Ae.append(g(C)),k.add&&!G&&Ae.append(V(C)),B.append(Ae),B.addEventListener("click",Q=>Q.stopPropagation()),J.push(B)}return J}function re(C){const G=document.createElement("table");G.className="tmtable enttable";const K=document.createElement("thead"),z=document.createElement("tr");for(const[q,U,me]of[["Tên",""],["Hán-Việt",""],["Dịch thành",""],["×","num","Số lần xuất hiện"],["","num"]]){const ge=document.createElement("th");ge.className=U,ge.textContent=q,me&&(ge.title=me),z.append(ge)}K.append(z);const I=document.createElement("tbody"),O=new Map(t.list().map(q=>[q.zh,q.vi]));return I.append(...C.slice(0,y).flatMap(q=>$(q,O.has(q.text),O))),G.append(K,I),G}function te(){if(!i)return;const C=[],G=document.createElement("button");if(G.type="button",G.className="ghost",G.textContent=l===null?"Quét văn bản":"Quét lại",G.disabled=w()||!s(),G.addEventListener("click",P),l===null){C.push(f("Tìm tên người, địa danh, tổ chức trong văn bản rồi thêm vào từ điển. Mô hình ~4 MB, tải một lần."));const z=document.createElement("div");z.className="enttools",z.append(G),C.push(z)}else{const z=document.createElement("div");z.className="enthead",z.append(f(`${l.length} tên riêng trong ${c.length} câu.`),G),C.push(z)}d=document.createElement("p"),d.className="entprog",d.append(document.createTextNode(""));const K=document.createElement("button");if(K.type="button",K.className="ghost",K.textContent="Hủy",K.addEventListener("click",()=>n.cancel()),d.append(K),N(n.current()),C.push(d),!s()&&l===null&&C.push(f("Chưa có văn bản — dán hoặc mở file trước.")),l?.length){C.push(_());const z=h?l.filter(I=>I.type===h):l;if(C.push(re(z)),z.length>y){const I=document.createElement("button");I.type="button",I.className="ghost entmore",I.textContent=`Hiện thêm (còn ${z.length-y})`,I.addEventListener("click",()=>{y+=Yt,te()}),C.push(I)}}else l&&C.push(f("Không tìm thấy tên riêng nào."));M&&C.push(f(M)),i.replaceChildren(...C)}return{id:"entity",title:"Nhân vật & địa danh",icon:ue.pin,prefers:"full",badge:()=>(T(),l&&l.length||null),scan:P,mount(C){i=C,p=n.subscribe(N),E=t.subscribe(()=>{te(),a()}),T(),te()},update(){T(),te()},destroy(){n.current()?.kind==="analyze"&&n.cancel(),p?.(),p=null,E?.(),E=null,e.release(),i=null,d=null}}}const Ml=e=>[...e].map(t=>t.toString(16).padStart(2,"0")).join("");async function Cl(e){if(!e.persistent)return null;let t=e.getItem(zr);return t||(t=Ml(crypto.getRandomValues(new Uint8Array(16))),e.setItem(zr,t)),Vs(t)}function ss(e=navigator){return e.userAgentData?.platform||e.platform||""}const Fe=(e,t=1)=>typeof e=="number"&&Number.isFinite(e)?Math.round(e*10**t)/10**t:null;function xl(e){if(!e||typeof e!="object")return null;const t=Array.isArray(e.plannedSourceBucketHistogram)?e.plannedSourceBucketHistogram:[];return{rowCountBand:e.rowCountBand,batchCountBand:e.batchCountBand,sourceBucketHistogram:Object.fromEntries(t),batchSizeQuantiles:[...e.batchSizeQuantiles??[]],sourceTokenQuantiles:[...e.sourceTokenQuantiles??[]]}}function Al(e){return!e||typeof e!="object"?null:{amortizationRev:e.revision,amortizationStatus:e.status,amortizationAdmitted:e.admit??null,observationCacheState:e.observationCacheState,observationAgeMs:Fe(e.observationAgeMs),observationWrite:e.write??null,observedProfiledWallMs:Fe(e.observedProfiledWallMs),minimumExpectedSavingMs:Fe(e.minimumExpectedSavingMs),projectedWorstCaseScreenMs:Fe(e.projectedWorstCaseScreenMs),paybackRatio:Fe(e.paybackRatio,6)}}function Tl(e){const t=e?.scheduleAutotune;if(!t||!["shadow","apply","auto"].includes(t.mode))return null;const n=t.requestedSchedule??e.requestedDecodeSchedule,r=t.predictedSchedule??t.selectedSchedule,s=e.decodeSchedule??t.configuredSchedule,o=e.effectiveDecodeSchedule??t.effectiveSchedule,a=(e.batchStats??[]).reduce((y,k)=>y+(Number.isInteger(k?.submitShrinks)?k.submitShrinks:0),0),i=t.screenSubmitShrinks??0,l=t.invalidatedReason??(i>0?"submit-shrink":null)??(["promoted","selected"].includes(t.reason)?null:t.reason??null),c=Al(t.amortization),m=Fe(t.screenGain,6),h=Fe(t.confirmationMinGain,6);return{mode:t.mode,protocolRev:t.protocolRev,requested:{...n},predicted:{...r},configured:{...s},effective:{...o},source:t.source,cacheState:t.cache?.status??"not-checked",cacheWrite:t.cache?.write??null,scheduleTuneMs:Fe(t.scheduleTuneMs??e.stages?.scheduleTuneMs??0),selectedGain:Fe(t.selectedGain,6),...m!==null?{screenGain:m}:{},...h!==null?{confirmationMinGain:h}:{},sampleCount:t.sampleCount??0,confirmationCount:t.confirmationCount??0,projectedMs:Fe(t.evidence?.projectedMs??t.projection?.postPilot?.projectedMs??t.projection?.preGate?.projectedMs),overrunMs:Fe(t.deadline?.overrunMs??t.evidence?.overrunMs),screenSubmitShrinks:i,canonicalSubmitShrinks:a,fallbackReason:l,...c??{},workload:xl(t.workload)}}function as({info:e,stats:t,mode:n,srcChars:r,build:s,pseudo:o,ua:a,platform:i,extras:l=null}){const c=e.bench,m=Tl(t);return{v:ai,id:crypto.randomUUID(),ts:Date.now(),pseudo:o,run:{build:s,model:e.modelId,dtype:e.dtype,t2s:!!t.t2s,mode:n,srcChars:r,sentences:t.sentences,ms:Math.round(t.ms),tokPerSec:Math.round(t.tokPerSec*10)/10,outputTokens:t.tokens??null,decodedRows:t.decodedRows??null,batches:t.batches??null,tmHits:t.tmHits??null,resumeHits:t.resumeHits??null,forcedEos:t.forcedEos??null,stages:t.stages?Object.fromEntries(Object.entries(t.stages).map(([h,y])=>[h,typeof y=="number"?Math.round(y):y])):null,sBuckets:t.sBuckets??null,flags:[...c.flags??[]],weightsTag:e.weightsTag??null,...m?{schedule:m}:{}},device:{...c.adapterInfo,subgroupMin:c.subgroupMinSize,subgroupMax:c.subgroupMaxSize,fp16:c.hasF16,immediates:e.immediates,uniformPool:e.uniformPool,browserMajor:ur(a),platform:i,limits:{...c.limits},gpuName:c.gpuName??null,gpuWebgl:c.gpuWebgl??null,webglSameGpu:c.webglSameGpu??null,adapterLimits:c.adapterLimits?{...c.adapterLimits}:null,features:c.features?[...c.features]:null,wgslFeatures:c.wgslFeatures?[...c.wgslFeatures]:null,...l??{}},autotune:{kernelRev:c.kernelRev,cacheState:c.tunedFrom,tuned:c.tuned,probeTimings:c.timings,safety:c.safety,protocolRev:c.protocolRev??null,tuneId:c.tuneId??null,measuredAt:c.measuredAt??null,cacheCheck:c.cacheCheck??null}}}function Rl({base:e,reason:t,phase:n,deviceLostReason:r=null,attachedSegment:s=null,comment:o=null,crumb:a=null}){return{...e,reason:t,phase:n,deviceLostReason:r,attachedSegment:s,comment:o,...a?{crumb:a}:{}}}let Dn=null;const Qn="moxhi.deviceLost";async function hr(e=navigator,t=null){if(!Dn){let o={};try{o=await e.userAgentData?.getHighEntropyValues?.(["model","platformVersion","architecture","bitness","fullVersionList"])??{}}catch{o={}}const a=(o.fullVersionList??[]).find(i=>!/Not.A.Brand/i.test(i.brand));Dn={model:o.model||null,platformVersion:o.platformVersion||null,cpuArch:o.architecture?`${o.architecture}${o.bitness?`-${o.bitness}`:""}`:null,browserFull:a?`${a.brand} ${a.version}`:null,deviceMemory:e.deviceMemory??null,cpuThreads:e.hardwareConcurrency??null}}let n=null,r=null;try{const o=await e.getBattery?.();n=o?.charging??null,r=o?.level??null}catch{}let s=null;if(t){const o=Math.floor(Number(t.getItem(Qn)??0));s=Number.isFinite(o)&&o>=0?o:0}return{...Dn,charging:n,batteryLevel:r,deviceLostCount:s}}async function Nl(e=null,t=navigator){const n={error:e?String(e).slice(0,300):null,webgpu:!!t.gpu,adapter:null,gpuWebgl:null,browserFull:null,model:null,platform:null};try{const r=await t.gpu?.requestAdapter?.({powerPreference:"high-performance"});r&&(n.adapter={vendor:String(r.info?.vendor??""),architecture:String(r.info?.architecture??""),fp16:!!r.features?.has?.("shader-f16")})}catch{}try{n.gpuWebgl=sr()?.renderer?.slice(0,512)??null}catch{}try{const r=await hr(t);n.browserFull=r.browserFull?.slice(0,128)??null,n.model=r.model?.slice(0,128)??null}catch{}try{n.platform=t.userAgentData?.platform?.slice(0,64)??null}catch{}return n}async function is(e,t){const n=await fetch(qs()+e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t)});if(!n.ok)throw new Error(`HTTP ${n.status}`);return n.json()}const Pl=20*1024*1024,Bl=600,$l=900,cs="moxhi.autotranslate",fr="moxhi.model",mr=new URLSearchParams(location.search).get("autodict")==="1",ye=Nt("local"),pr=Zc({}),vt=pl({}),Ln={auto:"Tự động","utf-8":"UTF-8",gb18030:"GB18030 / GBK",big5:"Big5","utf-16le":"UTF-16 LE","utf-16be":"UTF-16 BE"},Il=matchMedia("(prefers-reduced-motion: reduce)").matches,u=ta(document.querySelector("#app"));Ra(u.goBtn);const Dl=new URLSearchParams(location.search).get("profilestats")==="1",b={engine:null,doc:null,stashedTyped:null,srcWindow:0,outWindow:1/0,outRows:[],fileResultText:null,fileProfileText:null,docRevision:0,filePartial:null,lastRun:null,pseudo:void 0};let Ke=null;async function ls(){if(!(Ke&&!Ke.released))try{Ke=await navigator.wakeLock?.request("screen")??null,Ke?.addEventListener("release",()=>{Ke=null})}catch{Ke=null}}function Ll(){Ke?.release().catch(()=>{}),Ke=null}const Ue=Ma({onStart:ls,onIdle:Ll,onError:e=>console.error(e)});function us(){b.docRevision++,vt.clearDocumentTerms(),Ue.cancelAll()}let Eo=!1;Ue.subscribe(e=>{const t=!!e;t!==Eo&&(Eo=t,u.goBtn.classList.toggle("busy",t),u.chipBadge.classList.toggle("busy",t),u.goBtn.disabled=t,u.scanBtn.disabled=t,u.modelSelect.disabled=t)});let On=!1;Ue.subscribe(e=>{e?.kind==="analyze"?(On=!0,L(u.cancelBtn,!0),u.progress.textContent=e.phase==="tải mô hình"?`tải mô hình quét tên ${(e.done/1048576).toFixed(1)}/${(e.total/1048576).toFixed(1)} MB…`:`quét tên ${e.done}/${e.total} câu…`):!e&&On&&(On=!1,L(u.cancelBtn,!1),u.progress.textContent="")});document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&Ue.current()&&!Ke&&ls()});const L=(e,t=!0)=>{e.hidden=!t},hn=e=>(e/1048576).toFixed(1),Xt=e=>e<950?`${Math.round(e)}ms`:`${(e/1e3).toFixed(1)}s`;function st(e,t,n=null){u.errMsg.textContent=e,L(u.errBanner),u.retryBtn.onclick=()=>{L(u.errBanner,!1),t()},L(u.reportErrBtn,!!n),u.reportErrBtn.onclick=n?()=>fs(n):null}function ds({title:e,summary:t,payload:n,attach:r=!1,attachDefault:s=!1,comment:o=!1,send:a}){u.benchModalTitle.textContent=e,u.benchSummary.textContent=t;const i=r&&s;u.benchPrivacyHint.textContent=i?"Đoạn đang hiển thị được gửi kèm để mình dò lỗi — bỏ tick ô bên dưới nếu bạn không muốn.":r?"Mặc định không gửi nội dung văn bản — chỉ gửi đoạn lỗi nếu bạn tick ô bên dưới.":"Không gửi nội dung văn bản — chỉ các thông số bên dưới.",L(u.benchAttachRow,r),u.benchAttachTgl.checked=i,L(u.benchComment,o),u.benchComment.value="",u.benchStatus.textContent="",u.benchCancelBtn.textContent="Hủy";const l=()=>{const c=typeof n=="function"?n():n;return u.benchJson.textContent=JSON.stringify(c,null,2),c};l(),u.benchAttachTgl.onchange=l,u.benchSendBtn.disabled=!1,u.benchSendBtn.onclick=async()=>{u.benchSendBtn.disabled=!0,u.benchStatus.textContent="đang gửi…";try{await a(l(),c=>{c instanceof Node?u.benchStatus.replaceChildren(c):u.benchStatus.textContent=c}),u.benchCancelBtn.textContent="Đóng"}catch(c){u.benchStatus.textContent=navigator.onLine===!1?"đang offline — thử lại sau nhé":`gửi lỗi: ${c?.message??c}`,u.benchSendBtn.disabled=!1}},u.benchCancelBtn.onclick=()=>u.benchModal.close(),u.benchModal.showModal()}async function hs(){return b.pseudo===void 0&&(b.pseudo=await Cl(ye)),b.pseudo}function Ol(){const e=Math.floor(Number(ye.getItem(Qn)??0));ye.setItem(Qn,String((Number.isFinite(e)&&e>=0?e:0)+1))}let ko=0,pt=0;function Fl(e){const t=Do(e);if(t==="tm-reuse"){const n=(e.tmHits??0)+(e.resumeHits??0);return`Đã ghi nhận — cảm ơn bạn! Run này không xếp hạng: ${Math.round(n/Math.max(1,e.sentences??0)*100)}% câu lấy sẵn từ bộ nhớ dịch (${e.decodedRows??0} hàng dịch mới) nên tốc độ không phản ánh sức GPU.`}return t==="flags"?"Đã ghi nhận! Run chạy với cờ thử nghiệm trên URL nên không xếp hạng — data debug vẫn quý.":t==="schedule-autotune"?"Đã ghi nhận! Run autotune lịch giải mã hiện chỉ dùng để phân tích, chưa xếp hạng cho đến khi board có policy tách cold/warm rõ ràng.":t==="few-rows"||t==="small"?"Đã ghi nhận — cảm ơn bạn! Run nhỏ không xếp hạng (bảng cần ≥30 câu dịch mới), vẫn là data quý.":"Đã ghi nhận — cảm ơn bạn!"}function _l(e=null){const t="c762e11";if(b.engine){const n=b.lastRun?.stats??{sentences:0,ms:0,tokPerSec:0,t2s:!1};return as({info:b.engine.info,stats:n,mode:b.lastRun?.mode??"paste",srcChars:b.lastRun?.srcChars??0,build:t,pseudo:b.pseudo??null,ua:navigator.userAgent??"",platform:ss(),extras:e})}return{v:1,id:crypto.randomUUID(),ts:Date.now(),pseudo:b.pseudo??null,run:null,device:null,autotune:null}}async function fs(e){await hs();const t=_l(await hr(navigator,ye));b.engine||(t.boot=await Nl(e.bootError??null)),ds({title:e.title??"Báo lỗi",summary:e.summary??"",attach:!!e.attach,attachDefault:!!e.attachDefault,comment:!0,payload:()=>Rl({base:t,reason:e.reason,phase:e.phase,deviceLostReason:e.deviceLostReason??null,attachedSegment:e.attach&&u.benchAttachTgl.checked?{src:u.src.value.slice(0,1e3),dst:rr(b.outRows).slice(0,1e3)}:null,comment:u.benchComment.value.trim()||null,crumb:e.crumb??null}),send:async(n,r)=>{await is("/api/report",n),r("Đã ghi nhận — cảm ơn bạn!")}})}const gr="moxhi.lastfile";function Gl(e){ye.setItem(gr,JSON.stringify(e))}function ms(){try{return JSON.parse(ye.getItem(gr)??"null")}catch{return null}}function zl(){ye.removeItem(gr)}const br="moxhi.crumb";function Mo(e){ye.setItem(br,JSON.stringify({...e,ts:Date.now(),build:"c762e11"}))}function vr(){ye.removeItem(br)}async function Ul(){let e=null;try{e=JSON.parse(ye.getItem(br)??"null")}catch{}if(!e)return;vr(),console.warn("[moxhi] phiên dịch trước dừng đột ngột (nghi hệ điều hành ngắt vì thiếu bộ nhớ):",e);const t=ms(),n=!!t&&!t.complete&&(t.done??0)>0&&t.file===e.file;st(`Phiên dịch file trước dừng đột ngột ở cụm ${e.done??0}/${e.rows??"?"} (batch ${e.batch??0}/${e.batches??"?"}) — thường do thiết bị cạn bộ nhớ.`+(n?' Phần đã dịch vẫn còn: mở lại đúng file đó rồi bấm "Dịch file" để dịch tiếp.':" Hãy dịch lại từ đầu."),()=>{},{reason:"oom",phase:"translate",title:"Báo lỗi văng phiên dịch",crumb:{batch:e.batch,batches:e.batches,done:e.done,rows:e.rows,build:e.build,model:e.model}})}addEventListener("pagehide",vr);const jl={gpu:"Gọi linh khí GPU…",weights:"Tải trọng số…",tokenizer:"Nạp từ điển…",gpucheck:"Kiểm tra GPU…",autotune:"Đo mạch thiết bị (chỉ lần đầu)…"};async function Je(){const e=++pt;if(b.engine){try{b.engine.destroy()}catch{}b.engine=null,window.__moxhi=null}L(u.gate,!1),L(u.studio,!1),L(u.loading,!0);const t=Zn(ye.getItem(fr)??er);u.modelSelect.value=t.id,u.modelSelect.disabled=!0,u.loadNote.innerHTML=`Lần đầu tải ~${t.downloadMB} MB trọng số (${t.name}) — các lần sau mở nhanh nhờ bộ nhớ đệm của trình duyệt.`;try{const v=await Wc({model:t,scheduleDefaultEnabled:!0,onPhase:d=>{e!==pt||d==="ready"||(u.phaseLabel.textContent=jl[d]??d,d==="tokenizer"&&(u.brushFill.style.width="100%",u.brushBar.setAttribute("aria-valuenow","100")))},onProgress:(d,p)=>{if(e!==pt)return;const E=p?Math.round(d/p*100):0;u.brushFill.style.width=`${E}%`,u.brushBar.setAttribute("aria-valuenow",String(E)),u.phaseLabel.textContent=`Tải trọng số — ${hn(d)} / ${hn(p)} MB (${E}%)`},onDeviceLost:d=>{if(Ol(),e===pt&&!Ue.current()){if(b.engine&&Date.now()-ko>6e5){ko=Date.now(),console.warn(`GPU lost while idle (${d.reason}) — tự khởi động lại bộ dịch`),Je();return}st(`GPU bị ngắt kết nối (${d.reason}): ${d.message||"không rõ nguyên nhân"}. Bấm thử lại để khởi động lại bộ dịch.`,Je,{reason:"device-lost",phase:"idle",deviceLostReason:`${d.reason}: ${d.message??""}`})}}});if(e!==pt){v.destroy();return}b.engine=v}catch(v){if(e!==pt)return;console.error(v),u.modelSelect.disabled=!1,L(u.chipBadge,!1),L(u.gpuTip,!1),window.__moxhi=null;const d=String(v?.message??v);/WebGPU unavailable|no adapter/i.test(d)?(L(u.loading,!1),tu(d),L(u.gate,!0)):st(`Không khởi động được bộ dịch: ${d}`,Je,{reason:"other",phase:"load",bootError:d});return}u.modelSelect.disabled=!1;const{gpuName:n,dtype:r,lmHeadQ8:s,lmShortN:o,tunedFrom:a,modelName:i}=b.engine.info,l=a==="cache"?"autotune đệm":a==="measured"?"autotune":a==="partial"?"autotune một phần":"routing mặc định",c="c762e11",m=new URLSearchParams(location.search).get("cap"),h=new URLSearchParams(location.search).get("tokenbudget"),y=new URLSearchParams(location.search).get("kvplanner"),k=new URLSearchParams(location.search).get("inplacecompact"),M=s?`·int8${o?` ${Math.round(o/1e3)}k`:""}`:"",A=di(n);u.modelLink.textContent=i,t.credit?.url?(u.modelLink.href=t.credit.url,u.modelLink.title=t.credit.label):(u.modelLink.removeAttribute("href"),u.modelLink.removeAttribute("title")),u.statGpu.textContent=` · ${A} · ${r}${M} · ${l} · ${c}`+(m?` · cap=${m}`:"")+(h!==null?` · tokenbudget=${h}`:"")+(y!==null?` · kvplanner=${y}`:"")+(k!==null?` · inplacecompact=${k}`:""),L(u.chipBadge),u.chipBadge.title=[A!==n?n:null,b.engine.info.gpuTitle||null].filter(Boolean).join(" · "),L(u.gpuTip,hi(n)),L(u.loading,!1),L(u.studio,!0),b.engine.info.softwareAdapter&&st("WebGPU đang chạy bằng giả lập CPU (SwiftShader) nên dịch sẽ RẤT chậm. GPU thật của máy không được trình duyệt cấp cho WebGPU — kiểm tra chrome://gpu, cập nhật driver GPU (Linux cần driver Vulkan), rồi bấm Thử lại.",Je,{reason:"other",phase:"load"}),u.src.focus(),window.__moxhi={engine:b.engine,build:c,translate:v=>b.engine.translateText(v)},document.dispatchEvent(new CustomEvent("moxhi:ready"))}function Hl(e){u.dstNote.textContent=e?`${e} ký tự`:""}function Qe(e,t={}){b.outRows=e,t.count!==void 0&&(b.outWindow=t.count);const{chars:n,shown:r,total:s}=$a(u.out,e,{},{...t,count:b.outWindow});Hl(n),L(u.outMoreBtn,rUe.cancelAll());u.src.addEventListener("keydown",e=>{(e.ctrlKey||e.metaKey)&&e.key==="Enter"&&(e.preventDefault(),Dt())});u.reportOutBtn.addEventListener("click",()=>fs({title:"Báo lỗi dịch",reason:"wrong-output",phase:"translate",attach:!0,attachDefault:!0,summary:"Bản dịch sai/lệch nghĩa? Đoạn đang hiển thị được đính kèm sẵn — không có nó thì mình không dò được lỗi."}));u.benchSubmitBtn.addEventListener("click",async()=>{if(!b.engine||!b.lastRun||b.lastRun.submitted)return;const e=await hs();if(!e)return;const t=await hr(navigator,ye);b.lastRun.payload??=as({info:b.engine.info,stats:b.lastRun.stats,mode:b.lastRun.mode,srcChars:b.lastRun.srcChars,build:"c762e11",pseudo:e,ua:navigator.userAgent??"",platform:ss(),extras:t}),mr&&!b.lastRun.payload.run.flags.includes("autodict")&&b.lastRun.payload.run.flags.push("autodict");const n=b.lastRun.payload;ds({title:"Gửi benchmark",summary:`${Qs(e).emoji} ${Ys(e)} · ${b.engine.info.gpuName} · ${b.engine.info.modelName} · ${Math.round(n.run.tokPerSec)} tok/s · ${n.run.sentences} câu`+(Do(n.run)?" · sẽ không xếp hạng":""),payload:n,send:async(r,s)=>{const o=await is("/api/submit",r);if(b.lastRun.submitted=!0,L(u.benchSubmitBtn,!1),o.rank){const a=document.createDocumentFragment(),i=document.createElement("a");i.href="/board",i.textContent="xem bảng tốc độ",a.append(`Hạng ${o.rank} bảng ${b.engine.info.modelName} — `,i),s(a)}else s(Fl(r.run))}})});let Yn=(ye.getItem(cs)??"1")==="1";const Kl={autoTranslate:()=>Yn,setAutoTranslate:e=>{Yn=e,ye.setItem(cs,e?"1":"0")}},gs=matchMedia("(min-width: 1440px)"),Vl=()=>gs.matches,ql=()=>({doc:b.doc,job:Ue.current()}),Jl=La(),je=sa({tabs:u.panelTabs,overlay:{modal:u.panelModal,title:u.panelTitle,body:u.panelBody,closeBtn:u.panelCloseBtn,grip:u.panelGrip},rail:{isOpen:Vl,title:u.railTitle,body:u.railBody,onChange:e=>u.page.classList.toggle("rail-open",e)},getState:ql}),bs=wa({getNamespace:()=>b.engine?Ao(b.engine.info):null,enabled:new URLSearchParams(location.search).get("tm")!=="0",onChange:()=>je.refresh(),prefs:Kl});tr(bs);tr(Sa({store:pr,autoStore:vt,autoEnabled:mr,onChange:()=>je.refresh()}));const vs=kl({provider:vl(),glossaryStore:pr,jobs:Ue,getRows:()=>{const e=b.doc??Zt(u.src.value);return e.text.trim()?Bo(e.text).sentences:[]},hasText:()=>!!(b.doc??Zt(u.src.value)).text.trim(),getFp:()=>Jl((b.doc??Zt(u.src.value)).text),onChange:()=>je.refresh()});tr(vs);u.scanBtn.addEventListener("click",async()=>{const e=await vs.scan();(e==="ok"||e==="empty"||e==="error")&&je.open("entity")});u.settingsBtn.addEventListener("click",()=>je.open("memory"));u.helpBtn.addEventListener("click",()=>u.helpModal.showModal());u.helpCloseBtn.addEventListener("click",()=>u.helpModal.close());u.helpModal.addEventListener("click",e=>{e.target===u.helpModal&&u.helpModal.close()});u.railCloseBtn.addEventListener("click",()=>je.close());gs.addEventListener("change",()=>je.rehost());je.refresh();u.modelSelect.replaceChildren(...Js.map(e=>{const t=document.createElement("option");return t.value=e.id,t.textContent=e.name,t}));u.modelSelect.value=Zn(ye.getItem(fr)??er).id;u.modelSelect.addEventListener("change",()=>{ye.setItem(fr,u.modelSelect.value),b.filePartial=null,u.progress.textContent="",b.engine?.destroy?.(),b.engine=null,b.lastRun=null,L(u.benchSubmitBtn,!1),L(u.reportOutBtn,!1),Je()});let Co=0;u.src.addEventListener("input",()=>{if(u.srcCount.textContent=`${u.src.value.length} ký tự`,b.filePartial=null,b.doc||us(),je.refresh(),clearTimeout(Co),!(!Yn||!b.engine||b.doc)){if(u.src.value.length>Bl){u.progress.textContent="văn bản dài — bấm Dịch";return}u.progress.textContent="",Co=setTimeout(Dt,$l)}});u.pasteBtn.addEventListener("click",async()=>{try{u.src.value=await navigator.clipboard.readText(),u.src.dispatchEvent(new Event("input"))}catch{u.src.focus(),u.progress.textContent="trình duyệt chặn đọc clipboard — dán bằng Ctrl+V"}});u.clearBtn.addEventListener("click",()=>{u.src.value="",Qe([]),L(u.reportOutBtn,!1),u.src.dispatchEvent(new Event("input")),u.src.focus()});u.copyBtn.addEventListener("click",async()=>{const e=rr(b.outRows);e&&await navigator.clipboard.writeText(e).catch(()=>{})});function ys(e,t){const n=document.createElement("a"),r=za(Ga(t));n.href=URL.createObjectURL(new Blob(["\uFEFF",r],{type:"text/plain;charset=utf-8"})),n.download=e,n.click(),URL.revokeObjectURL(n.href)}u.saveBtn.addEventListener("click",async()=>{const e=rr(b.outRows);if(!e)return;const t=await _n().catch(()=>null);ys(Ua(b.doc,t),e)});function Ql(e){u.encSelect.replaceChildren(...Kc.map(t=>{const n=document.createElement("option");return n.value=t,n.textContent=t==="auto"?`${Ln.auto} (${Ln[e]??e})`:Ln[t],n})),u.encSelect.value="auto"}const Yl=2e3,Xl=400;function ws(){const{text:e}=b.doc,t=Math.min(b.srcWindow,e.length);u.srcView.textContent=e.slice(0,t)+(tPl){st(`File ${hn(e.size)} MB vượt giới hạn 20 MB.`,()=>{});return}const n=new Uint8Array(await e.arrayBuffer());if(t!==Xn)return;const{text:r,encoding:s}=Zo(n,"auto");b.fileResultText=null,b.fileProfileText=null,b.filePartial=null,Ql(s),yr(Po({name:e.name,bytes:n,text:r,encoding:s})),Qe([]),L(u.profileBtn,!1),L(u.reportOutBtn,!1),u.progress.textContent="";const o=ms(),a=Ss();la(o,a)?u.progress.textContent=`phiên trước dừng ở ${o.done}/${o.rows} cụm — "Dịch file" sẽ dịch tiếp từ bộ nhớ dịch`:o&&!o.complete&&(o.done??0)>0&&o.file===a.file&&o.model===a.model&&(u.progress.textContent="file đã thay đổi so phiên dịch dở trước — phần trùng sẽ lấy lại từ bộ nhớ dịch")}u.openBtn.addEventListener("click",()=>u.fileInput.click());u.fileInput.addEventListener("change",()=>Es(u.fileInput.files[0]));u.srcMoreBtn.addEventListener("click",()=>{b.srcWindow*=4,ws()});let Ct=0;const ks=e=>{Ct=e?Ct+1:Math.max(0,Ct-1),L(u.dropveil,Ct>0)};u.panes.addEventListener("dragenter",e=>{e.preventDefault(),ks(!0)});u.panes.addEventListener("dragover",e=>{e.preventDefault()});u.panes.addEventListener("dragleave",e=>{e.preventDefault(),ks(!1)});u.panes.addEventListener("drop",e=>{e.preventDefault(),Ct=0,L(u.dropveil,!1),Es(e.dataTransfer.files[0])});u.encSelect.addEventListener("change",()=>{const e=u.encSelect.value,{text:t,encoding:n}=Zo(b.doc.bytes,e);b.doc.text=t,b.doc.encoding=n,b.filePartial=null,b.fileProfileText=null,L(u.profileBtn,!1),u.progress.textContent="",yr(Po({...b.doc,text:t,encoding:n}))});u.docCloseBtn.addEventListener("click",()=>{Xn++,b.fileResultText=null,b.fileProfileText=null,b.filePartial=null,u.fileInput.value="",L(u.profileBtn,!1),yr(null)});async function Zl(e){const t=b.docRevision,n=()=>b.docRevision===t,r=b.doc??Zt(u.src.value),s=r.origin==="file",o=Fa(r);if(!s&&!r.text.trim()){ps();return}L(u.benchSubmitBtn,!1),L(u.cancelBtn,!0),L(u.profileBtn,!1),b.fileProfileText=null,o||(u.progress.textContent="đang dịch…"),s&&Mo({file:r.name,batch:0,model:b.engine?.info.modelId??""});const a=s?Ss():null,i=Ao(b.engine.info),l=Qc(pr.list()),c=l?{protect:w=>Yc(w,l),restore:(w,f)=>rs(w,f)}:null;let m=c,h=l?w=>lo(w,l):()=>null,y=null,k=null;if(mr){u.progress.textContent="tải từ điển tên khó…";try{const w=await fl();if(!n())return;const f=performance.now();y=ml({documentText:r.text,userCompiled:l,autoLexicon:w.lexicon,suppressions:vt.suppressions()}),k={...w.metrics,ctxMs:performance.now()-f},m=y.glossary,h=y.signature,vt.setDocumentTerms(y.ctx.documentTerms)}catch(w){console.warn("[moxhi] automatic hard-name glossary unavailable:",w),vt.clearDocumentTerms(),k={error:String(w?.message??w)}}}const M=w=>{const f=h(w);return f?w+"\0"+f:w},A=l?w=>{const f=lo(w,l);return f?w+"\0"+f:w}:w=>w,v=o&&new URLSearchParams(location.search).get("tm")!=="0",d=v&&(b.engine.info.bench.flags?.length??0)===0,p=w=>v?{get:async f=>{u.progress.textContent="tra bộ nhớ dịch…";const N=await da(i,f.map(w)),T=N.filter(Boolean).length;return u.progress.textContent=T?`khôi phục ${T}/${f.length} cụm từ bộ nhớ dịch`:"",N},put:d?f=>ha(i,f.map(([N,T])=>[w(N),T])):null}:null,E=performance.now(),S=({glossary:w,resume:f,tm:N})=>b.engine.translateText(r.text,{pack:o,glossary:w,scheduleTuneMode:o?b.engine.info.scheduleTuneMode:void 0,onScheduleTune:o?({active:T})=>{T?u.progress.textContent="đang tối ưu GPU…":u.progress.textContent==="đang tối ưu GPU…"&&(u.progress.textContent="")}:null,resume:f,tm:N,shouldStop:()=>e.signal.aborted,onBatch:o?(T,P,_)=>{if(!n())return;b.filePartial={docRev:t,rows:_};const g=_.filter(Boolean).length;s&&(Mo({file:r.name,batch:T,batches:P,done:g,rows:_.length,model:b.engine?.info.modelId??""}),Gl({...a,done:g,rows:_.length}));const V=Math.round(T/P*100),$=(performance.now()-E)/1e3,re=T>0?Math.max(0,$/T*(P-T)):0;u.progress.textContent=`${g}/${_.length} cụm câu · ${V}% · còn ~${Math.ceil(re)}s`}:(T,P,_)=>{if(!n())return;const g=_.filter(Boolean).length;u.progress.textContent=`câu ${g}/${_.length}`,P>1&&Qe(Sn(_.filter(Boolean).join(" ")))}});try{const w=o&&b.filePartial?.docRev===t?b.filePartial.rows:null;let f=await gl({runOnce:S,initial:w,combinedGlossary:m,combinedTm:p(M),userGlossary:c,userTm:p(A),rawTm:p(g=>g),selectUserRetryRows:y?.takeUserRetryRows??null,canRetry:n});if(!n())return;if(y){const g=y.summary();f={...f,stats:{...f.stats,autoDict:{...g,...k}}},vt.setDocumentTerms(g.documentTerms)}else k&&(f={...f,stats:{...f.stats,autoDict:{enabled:!1,...k}}});const N=(f.stats.glossaryFailed??[]).length,T=f.stats.autoDict?.documentTerms?.filter(g=>g.status==="eligible"&&g.selected>0).length??0,P=f.stats.autoDict?.markerOverflowTerms??0,_=Math.max(0,(f.stats.srcTruncated??0)-(f.stats.truncRescued??0));if(!o){f.cancelled?u.progress.textContent="đã hủy":(Qe(Sn(f.text),{ink:!0,reduced:Il}),u.progress.textContent="",u.statPerf.textContent=`${Math.round(f.stats.tokPerSec)} tok/s · ${Xt(f.stats.ms)} · ${f.stats.sentences} câu`+(f.stats.t2s?" · phồn→giản":"")+(f.stats.forcedEos?` · ⚠ ${f.stats.forcedEos} câu chạm trần token`:"")+(_?` · ⚠ ${_} câu nguồn quá dài (bị cắt)`:"")+(T?` · ${T} tên tự động`:"")+(P?` · ⚠ ${P} tên vượt marker`:"")+(N?` · ⚠ ${N} câu lỗi term`:""),b.lastRun={stats:f.stats,mode:"paste",srcChars:r.text.length,submitted:!1},ye.persistent&&L(u.benchSubmitBtn,!0),L(u.reportOutBtn,!0));return}if(f.cancelled||(b.filePartial=null,s&&zl(),fa()),b.fileResultText=f.text+(f.cancelled?` + +[— bản dịch dở dang —]`:""),u.progress.textContent=f.cancelled?"đã hủy — phần dịch dở vẫn tải được":`xong — ${Xt(f.stats.ms)} · ${Math.round(f.stats.tokPerSec)} tok/s`+(f.stats.tmHits?` · ${f.stats.tmHits} cụm từ bộ nhớ dịch`:"")+(f.stats.forcedEos?` · ⚠ ${f.stats.forcedEos} cụm chạm trần token`:"")+(_?` · ⚠ ${_} cụm nguồn quá dài (bị cắt)`:"")+(T?` · ${T} tên tự động`:"")+(P?` · ⚠ ${P} tên vượt marker`:"")+(N?` · ⚠ ${N} cụm lỗi term`:""),Qe(Sn(b.fileResultText),{count:Xl}),Dl){const g=new URLSearchParams(location.search);let V=null;try{V=await Fc(b.fileResultText)}catch(te){console.warn("[moxhi profile] output SHA-256 unavailable:",te)}if(!n())return;const $=f.stats.scheduleAutotune??{},re={build:"c762e11",capturedAt:new Date().toISOString(),file:{name:r.name,bytes:r.bytes?.length??null,encoding:r.encoding},engine:{modelId:b.engine.info.modelId,modelName:b.engine.info.modelName,gpuName:b.engine.info.gpuName,dtype:b.engine.info.dtype,immediates:b.engine.info.immediates,uniformPool:b.engine.info.uniformPool,inPlaceCompact:b.engine.info.inPlaceCompact,scheduleTuneMode:b.engine.info.scheduleTuneMode,scheduleDefault:{...b.engine.info.scheduleDefault},kvPolicy:b.engine.info.kvPolicy,kvPlannerOverride:b.engine.info.kvPlannerOverride,kvCapacityOverride:b.engine.info.kvCapacityOverride},policy:{cap:g.get("cap"),tokenbudget:g.get("tokenbudget"),kvplanner:g.get("kvplanner"),kvcap:g.get("kvcap"),inplacecompact:g.get("inplacecompact"),scheduletune:g.get("scheduletune"),tm:g.get("tm"),autodict:g.get("autodict")},totals:{cancelled:f.cancelled,sentences:f.stats.sentences,tokens:f.stats.tokens,ms:Math.round(f.stats.ms*10)/10,tokPerSec:Math.round(f.stats.tokPerSec*10)/10,forcedEos:f.stats.forcedEos,srcTruncated:f.stats.srcTruncated,truncRescued:f.stats.truncRescued,batches:f.stats.batches,resumeHits:f.stats.resumeHits,tmHits:f.stats.tmHits,decodedRows:f.stats.decodedRows,profiledMs:f.stats.profiledMs,profiledDecodeMs:f.stats.profiledDecodeMs,stages:f.stats.stages,glossaryFailed:f.stats.glossaryFailed?.length??0,autoDictUserRetryRows:f.stats.autoDictUserRetryRows??0,autoDictRawRetryRows:f.stats.autoDictRawRetryRows??0,outputSha256:V},autoDict:f.stats.autoDict?{enabled:!!f.stats.autoDict.enabled,artifactRevision:f.stats.autoDict.artifactRevision??null,protocol:f.stats.autoDict.protocol??null,matchedTerms:f.stats.autoDict.documentTerms?.length??0,autoDictRows:f.stats.autoDict.autoDictRows??0,markerOverflowTerms:f.stats.autoDict.markerOverflowTerms??0,rejectedSpans:f.stats.autoDict.rejectedSpans??null,resolvedUniqueRows:f.stats.autoDict.resolvedUniqueRows??0,resolveCalls:f.stats.autoDict.resolveCalls??0,cacheHits:f.stats.autoDict.cacheHits??0,cold:f.stats.autoDict.cold??null,loadMs:f.stats.autoDict.loadMs??null,indexMs:f.stats.autoDict.indexMs??null,ctxMs:f.stats.autoDict.ctxMs??null,resolveMs:f.stats.autoDict.resolveMs??null,error:f.stats.autoDict.error??null}:{enabled:!1},schedule:{featureMode:$.mode??"off",requested:f.stats.requestedDecodeSchedule??null,predicted:$.predictedSchedule??null,configured:f.stats.decodeSchedule??null,effective:f.stats.effectiveDecodeSchedule??null,canonicalUsesTunerVerdict:$.canonicalUsesTunerVerdict??!1,source:$.source??"default",protocolRev:$.protocolRev??null,reason:$.reason??null,fallbackReason:$.invalidatedReason??($.source==="default"?$.reason??null:null),invalidatedReason:$.invalidatedReason??null,cache:$.cache??null,workload:$.workload??null,evidence:$.evidence??null,candidateEvidence:$.candidateEvidence??[],projection:$.projection??null,deadline:$.deadline??null,screenSubmitShrinks:$.screenSubmitShrinks??0,selectedGain:$.selectedGain??null,sampleCount:$.sampleCount??0,confirmationCount:$.confirmationCount??0,scheduleTuneMs:$.scheduleTuneMs??0},sBuckets:f.stats.sBuckets,batchStats:f.stats.batchStats};b.fileProfileText=JSON.stringify(re,null,2),globalThis.__moxhiLastProfile=re,console.log("[moxhi profile]",re),L(u.profileBtn,!0)}if(u.statPerf.textContent=`${Math.round(f.stats.tokPerSec)} tok/s · ${Xt(f.stats.ms)} · ${f.stats.sentences} cụm câu`+(f.stats.t2s?" · phồn→giản":""),f.cancelled||(b.lastRun={stats:f.stats,mode:s?"file":"paste",srcChars:r.text.length,submitted:!1},ye.persistent&&L(u.benchSubmitBtn,!0),s||L(u.reportOutBtn,!0)),f.stats.stages){const g=f.stats.stages,V=$=>`${($/1e3).toFixed(1)}s ${Math.round($/f.stats.ms*100)}%`;console.log(`[moxhi] ${f.stats.batches} batch · ${Xt(f.stats.ms)} — tokenize ${V(g.tokenizeMs)} · encoder ${V(g.encoderMs)} · decode ${V(g.decodeMs)} · detok ${V(g.detokMs)} · gap ${V(g.gapMs)} · encoder/decode là cửa sổ chồng lấn (không cộng)`+(g.tmMs?` · tm ${(g.tmMs/1e3).toFixed(1)}s (ngoài wall)`:""))}}catch(w){console.error(w);const f=b.filePartial?.docRev===t?b.filePartial.rows.filter(Boolean).length:0;if(b.engine?.isLost?.()){const N=f>0&&n(),{reason:T,message:P}=b.engine.isLost();u.progress.textContent=N?`đã dịch ${f} cụm — sẽ tiếp tục từ đó`:"",st(`GPU bị ngắt kết nối (${T}): ${P||"không rõ nguyên nhân"}. Thử lại sẽ khởi động lại bộ dịch${N?" và dịch tiếp từ chỗ dừng":""}.`,async()=>{await Je(),Dt()},{reason:"device-lost",phase:"translate",deviceLostReason:`${T}: ${P??""}`})}else n()&&(u.progress.textContent="",st(`${s?"Dịch file lỗi":"Dịch lỗi"}: ${w?.message??w}`,Dt,{reason:"other",phase:"translate"}))}finally{s&&vr(),L(u.cancelBtn,!1),o&&bs.update()}}u.outMoreBtn.addEventListener("click",()=>{Qe(b.outRows,{count:b.outWindow*4})});u.profileBtn.addEventListener("click",async()=>{if(b.fileProfileText)try{await navigator.clipboard.writeText(b.fileProfileText),u.profileBtn.title="Đã chép profile"}catch{const e=b.doc?.name?.replace(/\.txt$/i,"")||"moxhi";ys(`${e}.profile.json`,b.fileProfileText)}});function Ms(e){const t=document.createElement("div");t.className="gate-address";const n=document.createElement("code");n.textContent=e;const r=document.createElement("button");return r.type="button",r.className="ghost gate-copy",r.dataset.copyAddress=e,r.textContent="Sao chép",r.setAttribute("aria-label",`Sao chép địa chỉ ${e}`),t.append(n,r),t}function eu(e){const t=document.createElement("li"),n=document.createElement("span");return n.className="gate-step-text",n.textContent=e.text,t.append(n),e.address&&t.append(Ms(e.address)),t}function tu(e){const t=navigator.userAgentData,n=Qa({userAgent:navigator.userAgent,platform:t?.platform??navigator.platform,mobile:t?.mobile,maxTouchPoints:navigator.maxTouchPoints,message:e});if(u.gateSummary.textContent=n.summary,u.gateSteps.replaceChildren(...n.steps.map(eu)),u.gateCopyStatus.textContent="",u.gateAdvanced.open=!1,u.gateAdvancedBody.replaceChildren(),L(u.gateAdvanced,!!n.advanced),n.advanced){const r=document.createElement("p");r.textContent=n.advanced.text,u.gateAdvancedBody.append(r),n.advanced.address&&u.gateAdvancedBody.append(Ms(n.advanced.address))}u.gateErr.textContent=`Chi tiết kỹ thuật: ${e}`}u.gate.addEventListener("click",async e=>{const t=e.target.closest?.("[data-copy-address]");if(!t||!u.gate.contains(t))return;const n=t.dataset.copyAddress;try{if(!navigator.clipboard?.writeText)throw new Error("clipboard unavailable");await navigator.clipboard.writeText(n),u.gateCopyStatus.textContent=`Đã sao chép ${n}`}catch{u.gateCopyStatus.textContent="Trình duyệt chặn sao chép tự động — hãy chọn địa chỉ rồi sao chép thủ công."}});u.gateRetryBtn.addEventListener("click",Je);Ul();Je();"serviceWorker"in navigator&&window.addEventListener("load",()=>{navigator.serviceWorker.register("/sw.js").catch(()=>{})});