1var Yt=Object.defineProperty;var s=(t,e)=>Yt(t,"name",{value:e,configurable:!0});import{SIMULATIONS as k,listAllCategories as L,listSimulationsByCategory as Xt,filterByComplexity as $t}from"/tool/modules/registry/simulations.js";import{getComplexityMode as R,setComplexityMode as xt,COMPLEXITY_EVENT as Gt}from"/js/common/complexity-preference.js";import{applyModeVisibility as St,watchModeVisibility as Jt}from"/js/common/mode-visibility.js";import{SEVERITY_MAP as H,getConditionFacts as Wt,REFERENCE_STRIP as Qt}from"/tool/modules/registry/condition-facts.js";import{fieldKind as Zt,fieldCss as te}from"/js/tool/vision-field-effects.js";import{panelManager as u}from"/tool/modules/floating/panel-manager.js";import{ensureControlCenter as ee}from"/tool/modules/floating/control-center.js";const x="__all__",$="__open__",q="__image__",ae=120,Et="aa_vd_guide_dismissed",wt="aa_vd_active_category";let p=x,N="";function d(t){return document.getElementById(t)}s(d,"$");function A(t,e=document){return Array.from(e.querySelectorAll(t))}s(A,"$$");function v(t){return String(t).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}s(v,"escapeHtml");function K(t){const e=L().find(a=>a.slug===t);return e?e.name:t}s(K,"categoryName");function z(){return $t(k,R())}s(z,"visibleSimulations");function V(t){return $t(Xt(t),R())}s(V,"visibleSimsByCategory");function Ct(){const t=d("vd-tabs");if(!t)return;const e=L(),a=z().length,n=[`<button class="anz-tab-btn vd-tab-image" type="button" role="tab" data-cat="${q}" 2 aria-selected="false" 3 data-tooltip-title="Image processing" 4 data-tooltip-description="Set the universal source image and process it across simulation panels."> 5 <span class="anz-tab-icon">\u{1F5BC}\uFE0F</span> Image 6 </button>`,`<button class="anz-tab-btn" type="button" role="tab" data-cat="${x}" 7 aria-selected="false" 8 data-tooltip-title="All simulations" 9 data-tooltip-description="Show every visible simulation across all categories."> 10 <span class="anz-tab-icon">\u2318</span> All 11 <span class="anz-tab-badge zero">${a}</span> 12 </button>`];for(const i of e){const l=V(i.slug).length,c=l===0?'data-empty="true"':"";n.push(` 13 <button class="anz-tab-btn" type="button" role="tab" 14 data-cat="${v(i.slug)}" 15 aria-selected="false" ${c} 16 data-tooltip-title="${v(i.name)}" 17 data-tooltip-description="Browse the ${v(i.name)} category."> 18 <span class="anz-tab-icon">\u25CF</span> 19 ${v(i.name)} 20 <span class="anz-tab-badge zero">${l}</span> 21 </button> 22 `)}n.push(` 23 <button class="anz-tab-btn" type="button" role="tab" 24 data-cat="${E}" 25 aria-selected="false" 26 data-tooltip-title="Favourites" 27 data-tooltip-description="Show only your starred simulations."> 28 <span class="anz-tab-icon">\u2605</span> Favourites 29 <span class="anz-tab-badge zero" id="vd-fav-count">0</span> 30 </button> 31 <button class="anz-tab-btn" type="button" role="tab" 32 data-cat="${F}" 33 aria-selected="false" 34 data-tooltip-title="Side-by-side compare" 35 data-tooltip-description="Compare how colours appear across multiple deficiencies simultaneously."> 36 <span class="anz-tab-icon">\u229E</span> Compare 37 </button> 38 <button class="anz-tab-btn" type="button" role="tab" 39 data-cat="${U}" 40 aria-selected="false" 41 data-tooltip-title="Audit a palette" 42 data-tooltip-description="Bring your own colours and see which pairs stop being distinguishable under each condition."> 43 <span class="anz-tab-icon" aria-hidden="true">\u25D1</span> Palette audit 44 </button> 45 <button class="anz-tab-btn" type="button" role="tab" 46 data-cat="${T}" 47 aria-selected="false" 48 data-tooltip-title="Intelligence dashboard" 49 data-tooltip-description="Heat map, mind map, statistics, and detailed export tools.">
50 <span class="anz-tab-icon">\u25C9</span> Analytics 51 </button> 52 <button class="anz-tab-btn" type="button" role="tab" 53 data-cat="${$}" 54 aria-selected="false" 55 data-tooltip-title="Open panels" 56 data-tooltip-description="Live view of currently open floating simulation panels."> 57 <span class="anz-tab-icon">\u25A2</span> Open Panels 58 <span class="anz-tab-badge zero" id="vd-open-count">0</span> 59 </button> 60 `),t.innerHTML=n.join(""),t.querySelectorAll(".anz-tab-btn").forEach(i=>{i.addEventListener("click",()=>S(i.dataset.cat))}),ne(),Lt(p)}s(Ct,"renderTabs");function Lt(t){A(".anz-tab-btn",d("vd-tabs")).forEach(e=>{const a=e.dataset.cat===t;e.classList.toggle("active",a),e.setAttribute("aria-selected",a?"true":"false")}),dt(t)}s(Lt,"setActiveTab");function ne(){const t=d("vd-scope-menu");if(!t)return;const e=s((n,i,l,c="")=>` 61 <button class="vd-scope-row" type="button" role="menuitemradio" 62 data-cat="${v(n)}" aria-checked="false" ${c}> 63 <b>${v(i)}</b>${l==null?"":`<em>${l}</em>`} 64 </button>`,"row"),a=[e(x,"All conditions",z().length),e(E,"Favourites",Bt()),'<hr class="vd-scope-rule" />'];for(const n of L()){const i=V(n.slug).length;a.push(e(n.slug,n.name,i,i===0?'data-empty="true"':""))}a.push('<hr class="vd-scope-rule" />'),a.push(e(q,"Source image",null)),a.push(e($,"Open panels",u.count())),t.innerHTML=a.join(""),t.querySelectorAll(".vd-scope-row").forEach(n=>{n.addEventListener("click",()=>{S(n.dataset.cat),D()})}),dt(p)}s(ne,"renderScopeMenu");function se(t){return t===x?"All conditions":t===E?"Favourites":t===q?"Source image":t===$?"Open panels":t===U?"Palette audit":t===T?"Analytics":t===F?"Compare":K(t)}s(se,"scopeLabelFor");function dt(t){const e=document.querySelector("[data-vd-scope-label]"),a=document.querySelector("[data-vd-scope-count]");if(e&&(e.textContent=se(t)),a){const n=t===x?z().length:t===E?Bt():t===$?u.count():ft(t)?V(t).length:null;a.hidden=n==null,n!=null&&(a.textContent=String(n))}A(".vd-scope-row",d("vd-scope-menu")).forEach(n=>{n.setAttribute("aria-checked",n.dataset.cat===t?"true":"false")})}s(dt,"syncScope");function oe(t){const e=Wt(t.slug),a=[`<span class="vd-card-tag vd-card-tag--kind">${e?.preview?"Per-colour":"Field effect"}</span>`];t.complexity==="advanced"?a.push('<span class="vd-card-tag vd-card-tag--advanced">Advanced</span>'):a.push('<span class="vd-card-tag">Basic</span>'),t.bespoke&&a.push('<span class="vd-card-tag vd-card-tag--bespoke">Bespoke</span>'),u.has(t.slug)&&a.push('<span class="vd-card-tag vd-card-tag--open">\u25CF Open</span>');const n=H[t.slug],i=n?.score,l=i!=null?`<span class="vd-card-sev" style="background:${Ce(i)};color:#111" title="Severity ${i}/10" aria-label="Severity ${i} of 10">${i}</span>`:"",c=n?.desc?`<p class="vd-card-desc">${v(n.desc)}</p>`:"",f=s(h=>h.map(P=>`<span style="background:${v(P)}"></span>`).join(""),"strip"),b=e?.preview?`<div class="vd-card-strip" aria-hidden="true">${f(e.preview)}</div>`:(()=>{const h=te(Zt({slug:t.slug,cat:t.category}),.85);return`<div class="vd-card-strip vd-card-strip--field" aria-hidden="true" 65 style="--fx:${h.filter}"> 66 ${f(Qt)} 67 <i style="background:${h.overlay}"></i> 68 </div>`})();return n?.prev&&n.prev!=="N/A"&&a.push(`<span class="vd-card-tag vd-card-tag--prev" title="Prevalence">${v(n.prev)}</span>`),` 69 <button class="vd-card" type="button" 70 data-slug="${v(t.slug)}" 71 data-cat="${v(t.category)}" 72 data-kind="${e?.preview?"colour":"field"}" 73 data-complexity="${v(t.complexity)}" 74 data-bespoke="${t.bespoke?"true":"false"}" 75 aria-label="Open ${v(t.name)} simulation"> 76 <span class="vd-fav-btn${nt(t.slug)?" is-fav":""}" 77 data-fav-slug="${v(t.slug)}" 78 role="button" tabindex="-1" 79 aria-label="${nt(t.slug)?"Remove from":"Add to"} favourites" 80 title="Favourite">${be}</span> 81 ${l}
82 <span class="vd-card-cat">${v(K(t.category))}</span> 83 <h3 class="vd-card-name">${v(t.name)}</h3> 84 ${b} 85 ${c} 86 <div class="vd-card-meta">${a.join("")}</div> 87 </button> 88 `}s(oe,"renderCard");function ut(t,e){const a=L().find(i=>i.slug===t),n=e.length;return n===0?"":` 89 <section class="vd-category-section" data-cat="${v(t)}"> 90 <header class="vd-category"> 91 <h2 class="vd-category-title">${v(a?.name||t)}</h2> 92 <span class="vd-category-count">${n} simulation${n===1?"":"s"}</span> 93 <span class="vd-category-rule" aria-hidden="true"></span> 94 </header> 95 <div class="vd-grid">${e.map(oe).join("")}</div> 96 </section> 97 `}s(ut,"renderCategorySection");function et(){const t=d("vd-grid"),e=d("vd-app");e&&(e.classList.toggle("vd-app--audit",p===U),e.classList.toggle("vd-app--analytics",p===T),e.classList.toggle("vd-app--report",!ft(p)));const a=d("vd-empty");if(!t)return;const n=p===q;if(globalThis.AAVisionUniversal?.setActive&&globalThis.AAVisionUniversal.setActive(n),t.hidden=n,n){a&&(a.hidden=!0);return}if(p===$){pt(t),a&&(a.hidden=!0);return}if(p===U){import("/js/tool/vision-audit.js").then(l=>l.renderPaletteAudit(t)).catch(()=>{t.innerHTML='<div class="vd-empty"><strong>The palette audit did not load.</strong> Reload the page and try again.</div>'}),a&&(a.hidden=!0),at(0);return}if(p===T){import("/js/tool/vision-analytics.js").then(l=>l.renderAnalytics(t,{categories:L(),simulations:z(),all:k,severity:H,favourites:C,recents:Y,open:s(c=>M({dataset:{slug:c}}),"open"),renderMap:Le,exportJson:Ae,exportCsv:Me,random:Vt,shortcuts:Ut})).catch(()=>{t.innerHTML='<div class="vd-empty"><strong>Analytics did not load.</strong> Reload the page and try again.</div>'}),a&&(a.hidden=!0),at(0);return}if(p===F){import("/js/tool/vision-compare.js").then(l=>l.renderCompareSheet(t)).catch(()=>{t.innerHTML='<div class="vd-empty"><strong>The compare sheet did not load.</strong> Reload the page and try again.</div>'}),a&&(a.hidden=!0),at(0);return}if(p===E){const l=z().filter(c=>nt(c.slug));if(!l.length)t.innerHTML=` 98 <div class="vd-empty"> 99 <strong>No favourites yet.</strong> 100 Click the \u2605 star on any simulation card to save it here. 101 </div>`,a&&(a.hidden=!0);else{const c=L();t.innerHTML=c.map(f=>ut(f.slug,l.filter(b=>b.category===f.slug))).join(""),a&&(a.hidden=!0),Tt(t)}return}let i;p===x?i=L().map(c=>ut(c.slug,V(c.slug))).join(""):i=ut(p,V(p)),i.trim()?(t.innerHTML=i,a&&(a.hidden=!0),Tt(t),B(N)):(t.innerHTML="",a&&(a.hidden=!1)),St()}s(et,"renderGrid");const At=new Set;function Mt(t){const e=t.dataset.slug;if(!e||At.has(e))return;const a=k.find(i=>i.slug===e);if(!a||a.bespoke)return;At.add(e);const n=document.createElement("link");n.rel="modulepreload",n.href=a.modulePath,n.crossOrigin="anonymous",document.head.appendChild(n)}s(Mt,"prewarmCard");function Tt(t){t.querySelectorAll(".vd-card").forEach(e=>{e.addEventListener("click",a=>{const n=a.target.closest(".vd-fav-btn");if(n){$e(n.dataset.favSlug,a);return}M(e,a)}),e.addEventListener("keydown",a=>{(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),M(e,a))}),e.addEventListener("mouseenter",()=>Mt(e),{once:!0}),e.addEventListener("focusin",()=>Mt(e),{once:!0})})}s(Tt,"bindCardHandlers");function M(t,e=null){const a=t.dataset.slug,n=k.find(c=>c.slug===a);if(!n)return;we(a);const i=!!(e&&(e.shiftKey||e.ctrlKey||e.metaKey)),l={slug:n.slug,name:n.name,category:n.category,categoryName:K(n.category),prefix:n.prefix,bespoke:n.bespoke,models:n.models,complexity:n.complexity,legacyHref:n.legacyHref,modulePath:n.modulePath};u.open(l,{allowDuplicate:i})}s(M,"onCardActivate");function pt(t){const e=u.list(),a=u.linkedCount(),n=e.length>0&&a===e.length,i=` 102 <div class="vd-panel-toolbar" role="toolbar" aria-label="Multi-panel actions"> 103 <button type="button" class="vd-toolbar-btn" data-tool="tile" 104 ${e.length===0?"disabled":""} 105 title="Tile all open panels into a grid">\u229E Tile</button> 106 <button type="button" class="vd-toolbar-btn" data-tool="cascade" 107 ${e.length===0?"disabled":""} 108 title="Cascade all open panels with a stacked offset">\u2AF7 Cascade</button> 109 <button type="button" class="vd-toolbar-btn ${n?"active":""}" 110 data-tool="${n?"unlink-all":"link-all"}" 111 ${e.length<2?"disabled":""} 112 title="${n?"Unlink every panel":"Link every panel to sync controls"}"> 113 \u{1F517} ${n?"Unlink all":"Link all"}</button> 114 <button type="button" class="vd-toolbar-btn" data-tool="export-grid" 115 ${e.length===0?"disabled":""} 116 title="Compose every panel's simulated canvas into a single PNG and download"> 117 \u{1F4CB} Export comparison</button>
118 <span class="vd-toolbar-spacer"></span> 119 <button type="button" class="vd-toolbar-btn vd-toolbar-btn-danger" data-tool="close-all" 120 ${e.length===0?"disabled":""} 121 title="Close all panels (pinned panels are skipped)">\xD7 Close all</button> 122 </div> 123 `;if(e.length===0){const c=u.readSession(),f=c?.slugs?.length?` 124 <div class="vd-restore-prompt" role="status"> 125 <div class="vd-restore-text"> 126 <strong>Restore last session?</strong> 127 ${c.slugs.length} panel${c.slugs.length===1?"":"s"} 128 from your last visit 129 ${c.linkedSlugs?.length?`\xB7 ${c.linkedSlugs.length} linked`:""} 130 ${c.pinnedSlugs?.length?`\xB7 ${c.pinnedSlugs.length} pinned`:""} 131 </div> 132 <button type="button" class="vd-toolbar-btn active" data-tool="restore-session">\u21BB Restore</button> 133 <button type="button" class="vd-toolbar-btn" data-tool="dismiss-session">Dismiss</button> 134 </div> 135 `:"";t.innerHTML=` 136 ${i} 137 ${f} 138 <div class="vd-empty"> 139 <strong>No floating panels open.</strong> 140 Pick any simulation card to open it as a movable, resizable panel. 141 Up to ${u.MAX_PANELS} panels can be open simultaneously, 142 with link-mode for synced cross-panel comparisons. 143 </div> 144 `,_t(t);return}const l=e.map(c=>{const f=[];return c.pinned&&f.push('<span class="vd-card-tag vd-card-tag--advanced">Pinned</span>'),c.linked&&f.push('<span class="vd-card-tag vd-card-tag--linked">\u{1F517} Linked</span>'),f.push('<span class="vd-card-tag">Click to focus</span>'),f.push(` 145 <span class="vd-card-tag" data-action="close-panel" 146 data-panel-id="${v(c.id)}" 147 role="button" tabindex="0" 148 aria-label="Close ${v(c.name)}">\xD7 Close</span> 149 `),` 150 <button class="vd-card ${c.linked?"is-linked":""}" type="button" 151 data-action="focus" data-panel-id="${v(c.id)}" 152 aria-label="Focus ${v(c.name)}"> 153 <span class="vd-card-cat">Open \xB7 ${v(c.category)}</span> 154 <h3 class="vd-card-name">${v(c.name)}</h3> 155 <div class="vd-card-meta">${f.join("")}</div> 156 </button> 157 `}).join("");t.innerHTML=` 158 ${i} 159 <section class="vd-category-section"> 160 <header class="vd-category"> 161 <h2 class="vd-category-title">Open Panels</h2> 162 <span class="vd-category-count"> 163 ${e.length} of ${u.MAX_PANELS} 164 ${a>0?`\xB7 ${a} linked`:""} 165 </span> 166 <span class="vd-category-rule" aria-hidden="true"></span> 167 </header> 168 <div class="vd-grid">${l}</div> 169 </section> 170 `,_t(t),t.querySelectorAll(".vd-card[data-action='focus']").forEach(c=>{c.addEventListener("click",f=>{const b=f.target.closest('[data-action="close-panel"]');if(b){f.stopPropagation(),u.close(b.dataset.panelId);return}u.focus(c.dataset.panelId)})})}s(pt,"renderOpenPanelsList");function _t(t){t.querySelectorAll(".vd-toolbar-btn").forEach(e=>{e.addEventListener("click",async()=>{switch(e.dataset.tool){case"tile":u.tileAll();break;case"cascade":u.cascadeAll();break;case"link-all":u.linkAll(!0);break;case"unlink-all":u.linkAll(!1);break;case"close-all":window.confirm("Close all unpinned floating panels?")&&u.closeAll();break;case"export-grid":{e.disabled=!0;const n=e.textContent;e.textContent="\u23F3 Composing\u2026";try{await u.exportComparisonGrid()}finally{e.disabled=!1,e.textContent=n}break}case"restore-session":ie();break;case"dismiss-session":u.clearSession(),p===$&&pt(t);break}})})}s(_t,"bindToolbar");function ie(){const t=u.readSession();if(!t?.slugs?.length)return;const e=[];for(const a of t.slugs.slice(0,u.MAX_PANELS)){const n=k.find(l=>l.slug===a);if(!n)continue;const i=u.open({slug:n.slug,name:n.name,category:n.category,categoryName:K(n.category),prefix:n.prefix,bespoke:n.bespoke,models:n.models,complexity:n.complexity,legacyHref:n.legacyHref,modulePath:n.modulePath});i&&e.push({inst:i,slug:a})}for(const{inst:a,slug:n}of e)t.linkedSlugs?.includes(n)&&u.setLink(a.id,!0),t.pinnedSlugs?.includes(n)&&a.pin(!0)}s(ie,"restoreSession");function Ft(){const t=d("vd-open-count");if(t){const e=u.count();t.textContent=String(e),t.classList.toggle("zero",e===0)}if(p===$){const e=d("vd-grid");e&&pt(e)}
170else A(".vd-card").forEach(e=>{const a=e.dataset.slug;if(!a)return;const n=e.querySelector(".vd-card-meta");if(!n)return;const i=u.has(a),l=n.querySelector(".vd-card-tag--open");i&&!l?n.insertAdjacentHTML("beforeend",'<span class="vd-card-tag vd-card-tag--open">\u25CF Open</span>'):!i&&l&&l.remove()})}s(Ft,"updateOpenPanelsBadge");let I="all";function vt(t){I=["all","colour","field"].includes(t)?t:"all",A("[data-kind]",d("vd-app")).forEach(e=>{if(!e.classList.contains("vd-kind-btn"))return;const a=e.dataset.kind===I;e.classList.toggle("active",a),e.setAttribute("aria-pressed",a?"true":"false")}),B(N)}s(vt,"setKindFilter");function B(t){N=(t||"").trim().toLowerCase();const e=d("vd-grid"),a=d("vd-empty");if(!e)return;let n=0;e.querySelectorAll(".vd-category-section").forEach(i=>{let l=0;i.querySelectorAll(".vd-card").forEach(c=>{const f=(c.textContent||"").toLowerCase(),b=!N||f.includes(N),h=I==="all"||c.dataset.kind===I;c.classList.toggle("is-search-hidden",!(b&&h)),b&&h&&l++}),i.classList.toggle("is-search-hidden",l===0),n+=l}),at(n),a&&p!==$&&(a.hidden=n>0,n||re())}s(B,"applySearchFilter");function ft(t){return![$,q,U,T,F].includes(t)}s(ft,"isBrowseView");function at(t){const e=d("vd-count");if(!e)return;const a=ft(p);e.hidden=!a,a&&(e.innerHTML=`<b>${t}</b> of ${k.length}`)}s(at,"updateCount");function re(){const t=document.querySelector("[data-vd-empty-why]");if(!t)return;const e=p===x?"the catalogue":p===E?"your favourites":K(p),a=I==="colour"?"per-colour transforms":"field effects";p===E?t.textContent="You have not starred anything yet \u2014 the \u2605 on any card saves it here.":N?t.textContent=`Nothing in ${e} matches \u201C${N}\u201D.`:I!=="all"?t.textContent=`${e[0].toUpperCase()}${e.slice(1)} has no ${a}${R()!=="both"?" at this level":""}.`:t.textContent="No condition matches every filter you have on."}s(re,"explainEmpty");function le(){const t=d("vd-search");t&&(t.value=""),xt("both"),vt("all"),S(x),B("")}s(le,"resetFilters");let Pt;function ce(){const t=d("vd-search"),e=d("vd-clear");t&&(t.addEventListener("input",()=>{clearTimeout(Pt),Pt=setTimeout(()=>B(t.value),ae)}),e&&e.addEventListener("click",()=>{t.value="",B(""),t.focus()}),document.addEventListener("keydown",a=>{a.key==="Escape"&&document.activeElement===t&&(t.value="",B("")),a.key==="/"&&document.activeElement?.tagName!=="INPUT"&&document.activeElement?.tagName!=="TEXTAREA"&&(a.preventDefault(),t.focus())}))}s(ce,"bindSearch");function S(t){p=t||x;try{localStorage.setItem(wt,p)}catch{}Lt(p),et(),gt()}s(S,"switchCategory");const Ot=["browse","open","arrange","compare","export"];function de(){return p===T?"export":p===F?"compare":p===$?"arrange":u.count()>0?"open":"browse"}s(de,"flowStepForState");function gt(){const t=Ot.indexOf(de());A("#vd-flow .anz-flow-step").forEach((a,n)=>{a.classList.toggle("active",n===t),a.classList.toggle("done",n<t)});const e=d("vd-progress-meter");e&&(e.style.width=`${t/(Ot.length-1)*100}%`)}s(gt,"syncFlow");function ue(){const t={browse:s(()=>{S(x),d("vd-search")?.focus()},"browse"),open:s(()=>S(x),"open"),arrange:s(()=>S($),"arrange"),compare:s(()=>S(F),"compare"),export:s(()=>S(T),"export")};A("[data-flow-step]").forEach(e=>{e.addEventListener("click",()=>(t[e.dataset.flowStep]||(()=>{}))())})}s(ue,"bindFlow");function pe(){try{const t=localStorage.getItem(wt);if(!t)return;(t===x||t===$||t===q||t===T||t===F||t===E||L().some(e=>e.slug===t))&&(p=t)}catch{}}s(pe,"restoreCategory");function Nt(t=R()){A(".anz-mode-btn",d("vd-app")).forEach(e=>{const a=e.dataset.mode===t;e.classList.toggle("active",a),e.setAttribute("aria-pressed",a?"true":"false")})}s(Nt,"syncModeButtons");function ve(){A(".anz-mode-btn",d("vd-app")).forEach(t=>{t.addEventListener("click",()=>{const e=t.dataset.mode;e&&xt(e)})}),window.addEventListener(Gt,t=>{const e=t?.detail?.mode||R();Nt(e),Ct(),et(),mt()}),Nt()}s(ve,"bindModeSwitch");function D(){[["vd-scope-menu","vd-scope"],["vd-info-pop","vd-info"]].forEach(([a,n])=>{const i=d(a),l=d(n);i&&(i.hidden=!0),l&&l.setAttribute("aria-expanded","false")});const t=d("vd-filters"),e=d("vd-filter-toggle");t&&t.classList.remove("is-open"),e&&e.setAttribute("aria-expanded","fal
170se")}s(D,"closePopovers");function fe(t,e){const a=d("vd-app");if(!a)return;if(window.matchMedia&&window.matchMedia("(max-width: 720px)").matches){t.style.left="",t.style.right="",t.style.top="";return}const n=a.getBoundingClientRect(),i=e.getBoundingClientRect();if(t.style.top=`${Math.round(i.bottom-n.top+a.scrollTop+6)}px`,t.id==="vd-info-pop"){const f=Math.max(0,Math.round(n.right-i.right));t.style.left="auto",t.style.right=`${f}px`;return}const l=t.offsetWidth||336;let c=i.left-n.left+a.scrollLeft;c=Math.min(c,a.clientWidth-l),t.style.right="auto",t.style.left=`${Math.round(Math.max(0,c))}px`}s(fe,"placePopover");function zt(t,e){const a=d(t),n=d(e);if(!a||!n)return;const i=!a.hidden;D(),i||(a.hidden=!1,n.setAttribute("aria-expanded","true"),fe(a,n))}s(zt,"togglePopover");function mt(){const t=document.querySelector("[data-vd-filter-count]");if(!t)return;const e=(I!=="all"?1:0)+(R()!=="both"?1:0);t.hidden=e===0,t.textContent=String(e),d("vd-filter-toggle")?.classList.toggle("active",e>0)}s(mt,"syncFilterCount");function ge(){const t=d("vd-app");t&&(d("vd-scope")?.addEventListener("click",e=>{e.stopPropagation(),zt("vd-scope-menu","vd-scope")}),d("vd-info")?.addEventListener("click",e=>{e.stopPropagation(),zt("vd-info-pop","vd-info")}),d("vd-filter-toggle")?.addEventListener("click",e=>{e.stopPropagation();const a=d("vd-filters"),n=a?.classList.contains("is-open");D(),a&&!n&&(a.classList.add("is-open"),d("vd-filter-toggle")?.setAttribute("aria-expanded","true"))}),t.querySelectorAll("[data-vd-close-sheet]").forEach(e=>{e.addEventListener("click",D)}),t.querySelectorAll(".vd-kind-btn").forEach(e=>{e.addEventListener("click",()=>{vt(e.dataset.kind),mt()})}),document.querySelector("[data-vd-reset]")?.addEventListener("click",le),document.addEventListener("click",e=>{e.target.closest(".vd-pop, .vd-scope, #vd-info, #vd-filter-toggle, .vd-filters")||D()}),document.addEventListener("keydown",e=>{e.key==="Escape"&&D()}),vt("all"),mt())}s(ge,"bindOneBar");function me(){const t=d("vd-guide"),e=d("vd-guide-dismiss");if(!(!t||!e)){try{localStorage.getItem(Et)==="1"&&(t.hidden=!0)}catch{}e.addEventListener("click",()=>{t.hidden=!0;try{localStorage.setItem(Et,"1")}catch{}})}}s(me,"bindGuide");function It(){ye(),Se(),pe(),Ct(),et(),ce(),ve(),ge(),me(),ue(),Te(),Jt(),St(),gt(),window.addEventListener(u.EVENT_NAME,()=>{Ft();const t=document.querySelector(`.vd-scope-row[data-cat="${$}"] em`);t&&(t.textContent=String(u.count())),gt()}),Ft(),Dt(),ee(),globalThis.AAVisionLab=Object.assign(globalThis.AAVisionLab||{},{switchCategory:S,openPanel:s(t=>M({dataset:{slug:t}}),"openPanel"),currentCategory:s(()=>p,"currentCategory")}),window.AAVisionSim={sims:k,open:s(t=>M({dataset:{slug:t}}),"open"),restoreState(t,e={}){if(!k.find(l=>l.slug===t))return!1;const n=u.findBySlug&&u.findBySlug(t);if(n)try{u.close(n.id)}catch{}M({dataset:{slug:t}});const i=s(()=>{const l=u.findBySlug?u.findBySlug(t):null;if(!l||!l.body)return;const c=e&&(e.inputs||e.settings)||{};if(Object.entries(c).forEach(([f,b])=>{if(!f)return;const h=l.body.querySelector(`#${CSS.escape(f)}`);if(h)try{h.type==="checkbox"||h.type==="radio"?h.checked=!!b:h.tagName==="SELECT"?Array.from(h.options).some(P=>P.value===String(b))&&(h.value=String(b)):h.value=b==null?"":String(b),h.dispatchEvent(new Event("input",{bubbles:!0})),h.dispatchEvent(new Event("change",{bubbles:!0}))}catch{}}),e.reference){const f=l.body.querySelector(`#${l.prefix}-sim-ref`)||l.body.querySelector(`#${l.prefix}-ref-hex`);f&&(f.value=e.reference,f.dispatchEvent(new Event("input",{bubbles:!0})),f.dispatchEvent(new Event("change",{bubbles:!0})))}},"apply");return requestAnimationFrame(()=>requestAnimationFrame(i)),!0}}}s(It,"init");const U="__audit__",T="__analytics__",F="__compare__",E="__favorites__",Rt="aa_vd_favorites",Ht="aa_vd_recents",he=12,be='<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m12 3.6 2.6 5.3 5.8.85-4.2 4.1 1 5.75L12 16.9l-5.2 2.7 1-5.75-4.2-4.1 5.8-.85z"/></svg>',qt=["#d3af37","#4299e1","#48bb78","#ed8936","#9f7aea","#ed64a6","#38b2ac","#e53e3e","#667eea","#f6ad55","#68d391"];let C=new Set;function ye(){try{C=new Set(JSON.parse(localStorage.getItem(Rt))||[])}catch{}}s(ye,"loadFavorites");function ke(){try{localStorage.setItem(Rt,JSON.stringify([...C]))}catch{}}s(ke,"saveFavorites");function $e(t,e){e&&(e.stopPropagation(),e.preventDefault()),C.has(t)?C.delete(t):C.add(t),ke(),xe(),Dt(),p===E&&et()}s($e,"toggleFavorite");function nt(t){return C.has(t)}s(nt,"isFavorite");function xe(){A(".vd-card[data-slug]").forEach(t=>{const e=t.querySelector(".vd-fav-btn");e&&e.classList.toggle("is-fav",nt(t.dataset.slug))})}s(xe,"updateFavoriteIndicators");function Bt(){return C.size}s(Bt,"favoriteCount");function Dt(){const t=d("vd-fav-count");t&&(t.textContent=String(C.size),t.classList.toggle("zero",C.size===0));const e=document.querySelector(`.vd-scope-row[data-cat="${E}"] em`);e&&(e.textContent=String(C.size)),p===E&&dt(p)}s(Dt,"updateFavoritesBadge");let Y=[];function Se(){try{Y=JSON.parse(localStorage.getItem(Ht))||[]}catch{}}s(Se,"loadRecents");function Ee(){try{localStorage.setItem(Ht,JSON.stringify(Y))}catch{}}s(Ee,"saveRecents");function we(t){Y=[t,...Y.filter(e=>e!==t)].slice(0,he),Ee()}s(we,"addRecent");function Ce(t){const e=Math.max(0,Math.min(10,t))/10;if(e<.5){const n=e*2;return`rgb(${Math.round(66+170*n)},${Math.round(153+48*n)},${Math.round(225+-150*n)})`}const a=(e-.5)*2;return`rgb(${Math.round(236+-7*a)},${Math.round(201+-139*a)},${Math.round(75+-13*a)})`}s(Ce,"heatColor");function Le(t){t.innerHTML=` 171 <div class="vd-mindmap-wrap"> 172 <div class="vd-mindmap-controls"> 173 <button type="button" class="vd-toolbar-btn" id="vd-mm-reset">\u27F3 Reset View</button>
174 <span class="vd-mindmap-hint">Drag to pan \xB7 Scroll to zoom \xB7 Click node to open simulation</span> 175 </div> 176 <svg class="vd-mindmap-svg" id="vd-mindmap-svg" viewBox="0 0 1000 700" role="img" 177 aria-label="Force-directed mind map of vision deficiency simulations"> 178 <g id="vd-mm-vp"> 179 <g id="vd-mm-edges"></g> 180 <g id="vd-mm-nodes"></g> 181 </g> 182 </svg> 183 </div> 184 `;const e=d("vd-mindmap-svg"),a=d("vd-mm-vp"),n=d("vd-mm-edges"),i=d("vd-mm-nodes"),l=L(),c=z(),f=1e3,b=700,h=f/2,P=b/2,G=l.map((o,r)=>{const g=r/l.length*Math.PI*2-Math.PI/2;return{id:`cat:${o.slug}`,type:"cat",label:o.name,slug:o.slug,color:qt[r%qt.length],x:h+Math.cos(g)*240,y:P+Math.sin(g)*200,vx:0,vy:0,r:26}}),st=c.map(o=>{const r=G.find(y=>y.slug===o.category),g=Math.random()*Math.PI*2,m=H[o.slug]?.score??5;return{id:`sim:${o.slug}`,type:"sim",label:o.name,slug:o.slug,category:o.category,color:r?.color??"#888",x:(r?.x??h)+Math.cos(g)*55,y:(r?.y??P)+Math.sin(g)*55,vx:0,vy:0,r:5+m*.65,sev:m}}),j=[...G,...st],ht=st.map(o=>({src:o,tgt:G.find(r=>r.slug===o.category)})).filter(o=>o.tgt);for(let o=0;o<150;o++){for(let r=0;r<j.length;r++)for(let g=r+1;g<j.length;g++){const m=j[r],y=j[g],_=y.x-m.x,w=y.y-m.y,yt=_*_+w*w+1,ct=Math.sqrt(yt),kt=m.r+y.r+(m.type==="cat"||y.type==="cat"?36:18);if(ct<kt){const tt=(kt-ct)/ct*.28;m.vx-=_*tt,m.vy-=w*tt,y.vx+=_*tt,y.vy+=w*tt}const Z=(m.type==="cat"?7e3:1800)/yt;m.vx-=_*Z*1e-4,m.vy-=w*Z*1e-4,y.vx+=_*Z*1e-4,y.vy+=w*Z*1e-4}for(const r of ht){const g=r.tgt.x-r.src.x,m=r.tgt.y-r.src.y,y=Math.sqrt(g*g+m*m)||1,_=r.tgt.r+r.src.r+44,w=(y-_)/y*.05;r.src.vx+=g*w,r.src.vy+=m*w,r.tgt.vx-=g*w*.1,r.tgt.vy-=m*w*.1}for(const r of j)r.vx+=(h-r.x)*.001,r.vy+=(P-r.y)*.001,r.x=Math.max(r.r+8,Math.min(f-r.r-8,r.x+r.vx)),r.y=Math.max(r.r+8,Math.min(b-r.r-8,r.y+r.vy)),r.vx*=.82,r.vy*=.82}n.innerHTML=ht.map(o=>` 185 <line x1="${o.src.x.toFixed(1)}" y1="${o.src.y.toFixed(1)}" 186 x2="${o.tgt.x.toFixed(1)}" y2="${o.tgt.y.toFixed(1)}" 187 stroke="${o.tgt.color}" stroke-width="0.8" stroke-opacity="0.3"/> 188 `).join("");let ot="";for(const o of G){const r=o.label.length>14?o.label.slice(0,12)+"\u2026":o.label;ot+=` 189 <g class="vd-mm-cat-node" data-slug="${v(o.slug)}"> 190 <circle cx="${o.x.toFixed(1)}" cy="${o.y.toFixed(1)}" r="${o.r}" 191 fill="${o.color}" fill-opacity="0.15" 192 stroke="${o.color}" stroke-width="1.5"/> 193 <text x="${o.x.toFixed(1)}" y="${(o.y+o.r+13).toFixed(1)}" 194 text-anchor="middle" class="vd-mm-cat-label" fill="${o.color}"> 195 ${v(r)}</text> 196 <title>${v(o.label)}</title> 197 </g>`}for(const o of st)ot+=` 198 <g class="vd-mm-sim-node" data-slug="${v(o.slug)}" 199 role="button" tabindex="0" aria-label="Open ${v(o.label)}"> 200 <circle cx="${o.x.toFixed(1)}" cy="${o.y.toFixed(1)}" r="${o.r}" 201 fill="${o.color}" fill-opacity="${(.4+o.sev*.05).toFixed(2)}" 202 stroke="${o.color}" stroke-width="0.8"/> 203 <title>${v(o.label)} \u2014 Severity ${o.sev}/10</title> 204 </g>`;i.innerHTML=ot;const bt=t.querySelector(".vd-mindmap-wrap"),O=Object.assign(document.createElement("div"),{className:"vd-mm-tooltip"});O.hidden=!0,bt.appendChild(O),i.querySelectorAll(".vd-mm-sim-node").forEach(o=>{o.addEventListener("mouseenter",()=>{const r=o.dataset.slug,g=k.find(y=>y.slug===r),m=H[r]||{};g&&(O.innerHTML=` 205 <strong>${v(g.name)}</strong> 206 <span>${v(m.desc||"")}</span> 207 <span>Severity ${m.score??"?"}/10 \xB7 ${v(m.prev||"")}</span> 208 <em>Click to open</em>`,O.hidden=!1)}),o.addEventListener("mousemove",r=>{const g=bt.getBoundingClientRect();O.style.left=r.clientX-g.left+16+"px",O.style.top=r.clientY-g.top-10+"px"}),o.addEventListener("mouseleave",()=>{O.hidden=!0}),o.addEventListener("click",()=>{const r=k.find(g=>g.slug===o.dataset.slug);r&&M({dataset:{slug:r.slug}})}),o.addEventListener("keydown",r=>{if(r.key==="Enter"||r.key===" "){r.preventDefault();const g=k.find(m=>m.slug===o.dataset.slug);g&&M({dataset:{slug:g.slug}})}})});let J=0,W=0,Q=1,it=!1,rt={x:0,y:0};const lt=s(()=>a.setAttribute("transform",`translate(${J},${W}) scale(${Q})`),"applyVP");e.addEventListener("mousedown",o=>{o.target.closest(".vd-mm-sim-node,.vd-mm-cat-node")||(it=!0,rt={x:o.clientX-J,y:o.clientY-W},e.style.cursor="grabbing",o.preventDefault())}),window.addEventListener("mousemove",o=>{it&&(J=o.clientX-rt.x,W=o.clientY-rt.y,lt())}),window.addEventListener("mouseup",()=>{it=!1,e.style.cursor=""}),e.addEventListener("wheel",o=>{o.preventDefault(),Q=Math.max(.3,Math.min(4,Q*(o.deltaY>0?.9:1.1))),lt()},{passive:!1}),d("vd-mm-reset")?.addEventListener("click",()=>{J=0,W=0,Q=1,lt()})}s(Le,"renderMindMap");function Ae(){const t={meta:{title:"Auric Artisan \u2014 Color Blindness Simulator Catalog",exported:new Date().toISOString(),version:"1.0",total:k.length},simulations:k.map(e=>({slug:e.slug,name:e.name,category:e.category,complexity:e.complexity,bespoke:e.bespoke,models:e.models?[...e.models]:null,severity:H[e.slug]??null,moduleUrl:e.modulePath}))};Kt(new Blob([JSON.stringify(t,null,2)],{type:"application/json"}),`vd-catalog-${jt()}.json`)}s(Ae,"exportCatalogJson");function Me(){const t="slug,name,category,complexity,severity_score,description,prevalence",e=k.map(a=>{const n=H[a.slug]||{score:"",desc:"",prev:""};
208return[X(a.slug),X(a.name),X(a.category),a.complexity,n.score,X(n.desc),X(n.prev)].join(",")});Kt(new Blob([[t,...e].join(` 209`)],{type:"text/csv;charset=utf-8"}),`vd-severity-${jt()}.csv`)}s(Me,"exportSeverityCsv");function X(t){return`"${String(t??"").replace(/"/g,'""')}"`}s(X,"csvQ");function jt(){return new Date().toISOString().slice(0,10)}s(jt,"fmtDate");function Kt(t,e){const a=URL.createObjectURL(t),n=Object.assign(document.createElement("a"),{href:a,download:e});document.body.appendChild(n),n.click(),n.remove(),setTimeout(()=>URL.revokeObjectURL(a),5e3)}s(Kt,"dlBlob");function Vt(){const t=z().filter(e=>!e.bespoke);t.length&&M({dataset:{slug:t[Math.floor(Math.random()*t.length)].slug}})}s(Vt,"openRandomSimulation");function Ut(){let t=d("vd-shortcuts-ov");if(t){t.hidden=!t.hidden;return}t=document.createElement("div"),t.id="vd-shortcuts-ov",t.className="vd-shortcuts-ov",t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),t.setAttribute("aria-label","Keyboard shortcuts"),t.innerHTML=` 210 <div class="vd-shortcuts-dialog"> 211 <div class="vd-shortcuts-hdr"> 212 <strong>Keyboard Shortcuts</strong> 213 <button type="button" class="vd-panel-btn vd-panel-btn-close" 214 id="vd-shortcuts-cls" aria-label="Close shortcuts">\xD7</button> 215 </div> 216 <div class="vd-shortcuts-body"> 217 <div class="vd-shortcuts-group"> 218 <h4 class="vd-shortcuts-group-title">Navigation</h4> 219 <div class="vd-shortcuts-row"><kbd>/</kbd><span>Focus search</span></div> 220 <div class="vd-shortcuts-row"><kbd>Esc</kbd><span>Clear search</span></div> 221 <div class="vd-shortcuts-row"><kbd>?</kbd><span>This overlay</span></div> 222 <div class="vd-shortcuts-row"><kbd>F</kbd><span>Favourites tab</span></div> 223 <div class="vd-shortcuts-row"><kbd>A</kbd><span>Analytics tab</span></div> 224 <div class="vd-shortcuts-row"><kbd>C</kbd><span>Compare tab</span></div> 225 </div> 226 <div class="vd-shortcuts-group"> 227 <h4 class="vd-shortcuts-group-title">Panels</h4> 228 <div class="vd-shortcuts-row"><kbd>R</kbd><span>Random simulation</span></div> 229 <div class="vd-shortcuts-row"><kbd>T</kbd><span>Tile all panels</span></div> 230 <div class="vd-shortcuts-row"><kbd>1\u20135</kbd><span>Focus panel by index</span></div> 231 <div class="vd-shortcuts-row"><kbd>Shift+Click</kbd><span>Duplicate panel</span></div> 232 <div class="vd-shortcuts-row"><kbd>Ctrl+Click</kbd><span>Duplicate panel</span></div> 233 </div> 234 </div> 235 </div> 236 `,document.body.appendChild(t),d("vd-shortcuts-cls").addEventListener("click",()=>{t.hidden=!0}),t.addEventListener("click",e=>{e.target===t&&(t.hidden=!0)})}s(Ut,"showKeyboardShortcuts");function Te(){document.addEventListener("keydown",t=>{const e=document.activeElement?.tagName;if(!(e==="INPUT"||e==="TEXTAREA"||e==="SELECT")&&!(t.ctrlKey||t.metaKey||t.altKey))switch(t.key){case"?":t.preventDefault(),Ut();break;case"r":case"R":t.preventDefault(),Vt();break;case"f":case"F":t.preventDefault(),S(E);break;case"a":case"A":t.preventDefault(),S(T);break;case"c":case"C":t.preventDefault(),S(F);break;case"t":case"T":t.preventDefault(),u.tileAll();break;case"1":case"2":case"3":case"4":case"5":{t.preventDefault();const a=u.list()[parseInt(t.key)-1];a&&u.focus(a.id);break}}})}s(Te,"bindKeyboardShortcuts"),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",It,{once:!0}):It();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.