@wcag-checkr/ci 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ai-usage-log-CYyG5MT2.js","assets/crash-reporter-KD5f4utB.js","assets/scheduled-audit-runner-ZCuDk8-r.js","assets/preload-helper-D7HrI6pR.js","assets/diff-RnwNJg4F.js"])))=>i.map(i=>d[i]);
2
- import{_ as F}from"./preload-helper-D7HrI6pR.js";import{ai as v,aj as U,g as J,D as Z,ak as ee,al as te,am as re,an as ae,ao as ne,ap as oe,aq as se,ar as ie,as as le,at as ce,au as de,av as ue,aw as fe,ac as ge,ax as pe,ay as he,az as Ee,aA as me,aB as Se,aC as Te,v as C,aD as k,aE as ye,aF as Re,aG as j,aH as Ie,aI as we,aJ as Ae,aK as Ce}from"./scheduled-audit-runner-ZCuDk8-r.js";import{m as G,a as m,r as _e}from"./diff-RnwNJg4F.js";import{w as be,r as Pe,a as ke}from"./tier-config-client-85XOCE5d.js";import{w as Oe,r as ve,a as Ue}from"./rubric-config-client-DvjbA4nG.js";import{o as g,m as Ne,n as xe,c as h,f as _,i as Le,p as De,h as B,k as $e}from"./crash-reporter-KD5f4utB.js";import{y as A,z as Fe}from"./ai-usage-log-CYyG5MT2.js";const Ge=h("support-messenger"),Me="https://api.wcagcheckr.com/v1/products/wcagcheckr/support",O="support:rate-window",Ve=5,He=10*60*1e3,We=2,Ke="wcagcheckr",M="storybook:lastDetected";async function je(e){if(!e)return;const t=await chrome.runtime.getPlatformInfo(),a=(await chrome.storage.local.get(M))[M];return{extensionVersion:chrome.runtime.getManifest().version,platform:t,storybookDetected:a!=null&&a.detected?a.version??"detected":"none",licenseTier:await m(),logTail:Ne(xe())}}async function Be(e=Date.now()){const r=((await chrome.storage.local.get(O))[O]??[]).filter(a=>e-a<He);return r.length>=Ve?!1:(r.push(e),await chrome.storage.local.set({[O]:r}),!0)}async function q(e,t=0){try{const r=await fetch(Me,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok)throw new Error(`http ${r.status}`);const a=await r.json();if(!a.success)throw new Error(a.error??"server returned success=false");return{ticketRef:a.ticketRef??""}}catch(r){if(t<We){const a=(t+1)*1e3;return await new Promise(n=>setTimeout(n,a)),q(e,t+1)}throw r}}function qe(){return g("SUPPORT_MESSAGE_REQUEST",async e=>{if(!await Be())return{type:"SUPPORT_MESSAGE_RESPONSE",success:!1,error:G("NETWORK","Rate limit reached. Try again in 10 minutes.",!0)};try{const t=await je(e.includeContext);return{type:"SUPPORT_MESSAGE_RESPONSE",success:!0,ticketRef:(await q({productSlug:Ke,subject:e.subject,body:e.body,replyEmail:e.replyEmail,context:t,extensionVersion:chrome.runtime.getManifest().version,timestamp:new Date().toISOString()})).ticketRef}}catch(t){Ge.error("send failed",t);const r=t instanceof Error?t.message:String(t);return{type:"SUPPORT_MESSAGE_RESPONSE",success:!1,error:G("NETWORK",r,!0)}}})}const Q=h("ai-color-suggester");async function Qe(e,t,r=[]){if(!t.enabled||e.length===0)return{results:[],totalCostUsd:0,capExceeded:!1};const a=v(t);if(!a.ok)return{results:[],totalCostUsd:0,capExceeded:!1};const n=a.client,o=U(t.costCapUsd),i=[];for(const l of e){if(!o.canCharge())break;try{const d=await n.suggestColorFix({foreground:l.foreground,background:l.background,fontSize:l.fontSize,fontWeight:l.fontWeight,targetLevel:l.targetLevel,paletteHints:r});o.recordCharge(d.costUsd),d.verdict==="suggested"&&d.candidates.length>0&&i.push({matchKey:l.matchKey,suggestions:d.candidates,reasoning:d.reasoning,costUsd:d.costUsd})}catch(d){Q.warn(`color-fix suggestion failed for ${l.matchKey}`,d)}}return{results:i,totalCostUsd:o.state.spentUsd,capExceeded:o.state.exceeded}}async function Xe(){const e=await chrome.storage.local.get("aiConfig");return A(e.aiConfig)}function ze(){return g("AI_COLOR_SUGGEST_REQUEST",async e=>{const t=await m();if(!_(t,"aiColorFix"))return{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:"AI color-fix suggester is not available on your current plan."};const r=await Xe();if(!r.enabled)return{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:"AI augmentation is disabled in Settings → AI augmentation."};if(!r.apiKey)return{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:"No AI API key configured. Add one in Settings → AI augmentation."};try{const{results:a,totalCostUsd:n,capExceeded:o}=await Qe(e.inputs,r,e.paletteHints);return{type:"AI_COLOR_SUGGEST_RESPONSE",results:a,totalCostUsd:n,capExceeded:o}}catch(a){return Q.warn("color-suggest handler failed",a),{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:a instanceof Error?a.message:String(a)}}})}function V(e){if(!e)return null;const t=e.match(/rgba?\(\s*([0-9.]+)\s*,?\s*([0-9.]+)\s*,?\s*([0-9.]+)(?:\s*[,/]\s*([0-9.]+))?\s*\)/i);return t?{r:Math.round(parseFloat(t[1])),g:Math.round(parseFloat(t[2])),b:Math.round(parseFloat(t[3])),a:t[4]!==void 0?parseFloat(t[4]):1}:null}function H(e){const t=r=>{const a=r/255;return a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)};return .2126*t(e.r)+.7152*t(e.g)+.0722*t(e.b)}function Ye(e,t){const r=H(e),a=H(t),n=Math.max(r,a),o=Math.min(r,a);return(n+.05)/(o+.05)}function Je(e,t){const r=Math.max(0,Math.min(1,e.a));return{r:Math.round(e.r*r+t.r*(1-r)),g:Math.round(e.g*r+t.g*(1-r)),b:Math.round(e.b*r+t.b*(1-r))}}function Ze(e,t){var $;if(e!=="color-contrast"&&e!=="color-contrast-enhanced")return null;const r=t.styles;if(!r)return null;const a=(($=r.effectiveBackground)==null?void 0:$.color)??r.background,n=r.foreground;if(!n||!a)return null;const o=V(n),i=V(a);if(!o||!i||i.a<.999)return null;const l=o.a<.999?Je(o,i):{r:o.r,g:o.g,b:o.b},d=Ye(l,i),c=r.fontSize??16,s=r.fontWeight??400,u=c>=24||c>=18.5&&s>=700,y=e==="color-contrast-enhanced"?u?4.5:7:u?3:4.5,L=d>=y?"pass":"fail",D=P=>`rgb(${P.r}, ${P.g}, ${P.b})`,Y=`Deterministic WCAG contrast measurement (no AI guessing, no pixel sampling). Foreground ${D(l)}${o.a<.999?` (originally rgba with alpha=${o.a}, composited over background)`:""} against background ${D(i)} yields contrast ratio ${d.toFixed(2)}:1. Text is ${c}px at font-weight ${s}; ${u?"qualifies as large text (threshold 3:1 for AA)":"normal text (threshold 4.5:1 for AA)"}. ${L==="pass"?`Passes AA at ${y}:1.`:`Falls below the ${y}:1 threshold.`}`;return{verdict:L,ratio:d,threshold:y,reasoning:Y}}async function et(e,t,r){var l,d,c,s,u;const a=JSON.stringify({ruleId:e,selector:t,styles:{fg:((l=r.styles)==null?void 0:l.foreground)??null,bg:((d=r.styles)==null?void 0:d.background)??null,fs:((c=r.styles)==null?void 0:c.fontSize)??null,fw:((s=r.styles)==null?void 0:s.fontWeight)??null,ts:((u=r.styles)==null?void 0:u.textSample)??null},failureSummary:r.failureSummary??null}),n=new TextEncoder().encode(a),o=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(o)).map(T=>T.toString(16).padStart(2,"0")).join("")}const w=h("ai-incomplete-resolver");function W(e,t){if(!e)return t;const r=e.toLowerCase(),a=/verdict\s+corrected\s+to\s+pass|verdict:\s*pass\s+\(corrected\)/i,n=/verdict\s+corrected\s+to\s+fail|verdict:\s*fail\s+\(corrected\)/i,o=R(r,a),i=R(r,n);if(o>i&&o>=0)return"pass";if(i>o&&i>=0)return"fail";const l=/actually\s+passes|in\s+fact\s+passes|passes\s+AA/gi,d=/actually\s+fails|in\s+fact\s+fails|fails\s+AA/gi,c=R(r,l),s=R(r,d);return c<0&&s<0?t:c>s&&c/r.length>=.5?"pass":s>c&&s/r.length>=.5?"fail":t}function R(e,t){let r=-1;const a=t.flags.includes("g")?t.flags:t.flags+"g",n=new RegExp(t.source,a);let o;for(;(o=n.exec(e))!==null;)r=o.index,o.index===n.lastIndex&&n.lastIndex++;return r}async function tt(){const e=await chrome.storage.local.get("aiConfig");return A(e.aiConfig)}async function rt(e){if(!e.aiConfig.enabled||e.elements.length===0)return{resolutions:[],totalCostUsd:0};const t=v(e.aiConfig);if(!t.ok)return{resolutions:[],totalCostUsd:0};const r=t.client,a=U(e.aiConfig.costCapUsd),n=[],o=await J(e.pageUrl),i=new Map;for(const l of o)i.set(`${l.ruleId}::${l.selector}`,l);for(const l of e.elements){if(!a.canCharge())break;const d=await et(e.ruleId,l.selector,l),c=i.get(`${e.ruleId}::${l.selector}`),s=Ze(e.ruleId,l);if(s){w.info(`Deterministic verdict for ${e.ruleId} on ${l.selector}: ${s.verdict} (${s.ratio.toFixed(2)}:1 vs ${s.threshold}:1) — math overrides cache + AI`),n.push({pageUrl:e.pageUrl,ruleId:e.ruleId,selector:l.selector,verdict:s.verdict,reasoning:s.reasoning,resolvedAt:new Date().toISOString(),costUsd:0,wcagCriterion:e.wcagCriterion,inputHash:d});continue}if(c&&c.inputHash===d&&c.verdict!=="uncertain"){w.info(`Reusing cached resolution for ${e.ruleId} on ${l.selector} (hash match, verdict=${c.verdict})`);const u=W(c.reasoning,c.verdict);n.push({...c,verdict:u,resolvedAt:new Date().toISOString(),costUsd:0,inputHash:d});continue}try{const u=await r.resolveAxeIncomplete({ruleId:e.ruleId,element:l,pageUrl:e.pageUrl,targetLevel:e.targetLevel});a.recordCharge(u.costUsd);const T=W(u.reasoning,u.verdict);n.push({pageUrl:e.pageUrl,ruleId:e.ruleId,selector:l.selector,verdict:T,reasoning:u.reasoning,resolvedAt:new Date().toISOString(),costUsd:u.costUsd,wcagCriterion:e.wcagCriterion,inputHash:d})}catch(u){w.warn(`resolveAxeIncomplete failed for ${l.selector}`,u)}}return n.length>0&&await Z(n),{resolutions:n,totalCostUsd:a.state.spentUsd}}function at(){return g("AI_RESOLVE_INCOMPLETE_REQUEST",async e=>{const t=await m();if(!_(t,"aiIncompleteResolver"))return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:"AI resolver for axe-incomplete elements is not available on your current plan."};const r=await tt();if(!r.enabled)return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:"AI augmentation is disabled in Settings → AI augmentation."};if(!r.apiKey)return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:"No AI API key configured. Add one in Settings → AI augmentation."};try{const{resolutions:a,totalCostUsd:n}=await rt({ruleId:e.ruleId,pageUrl:e.pageUrl,wcagCriterion:e.wcagCriterion,elements:e.elements,targetLevel:e.targetLevel,aiConfig:r});return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:a,totalCostUsd:n}}catch(a){return w.warn("ai-incomplete-resolver failed",a),{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:a instanceof Error?a.message:"Unknown error during AI resolution."}}})}function nt(){return g("INTERACTIVE_AUDIT_REQUEST",async e=>{try{switch(e.criterionId){case"2.4.3":{const t=await oe({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"2.1.2":{const t=await ne({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"2.4.7":{const t=await ae({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"1.4.11":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=(r==null?void 0:r.results)??[];if(a.length===0)return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:"No audit results available. Run an audit first; 1.4.11 needs the page screenshot."};const n=await re({componentId:e.componentId,pageUrl:e.pageUrl,results:a});return n.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:n.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:n.error}}case"1.3.2":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=(r==null?void 0:r.results)??[];if(a.length===0)return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:"No audit results available. Run an audit first, then the 1.3.2 walkthrough can judge its reading-order findings."};const n=await te({componentId:e.componentId,pageUrl:e.pageUrl,results:a});return n.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:n.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:n.error}}case"2.5.3":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=await ee({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl,results:r==null?void 0:r.results});return a.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:a.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:a.error}}default:return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:`Interactive audit for criterion ${e.criterionId} not yet implemented.`}}}catch(t){return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}})}async function ot(){var t;if(typeof chrome>"u"||!((t=chrome.storage)!=null&&t.local))return A(void 0);const e=await chrome.storage.local.get("aiConfig");return A(e.aiConfig)}async function st(e){const t=await ot();if(!t.enabled)return{findings:[],totalCostUsd:0,capExceeded:!1,errors:[],skipReason:"disabled"};if(!t.apiKey)return{findings:[],totalCostUsd:0,capExceeded:!1,errors:[],skipReason:"no-key"};const r=v(t);if(!r.ok)return{findings:[],totalCostUsd:0,capExceeded:!1,errors:[`AI client unavailable: ${r.reason}`],skipReason:"client-error"};const a=r.client,n=U(t.costCapUsd),o=[],i=[],l=Math.max(1,t.maxCandidatesPerCheck??10);if(t.enabledChecks.altText){const d=e.figureAltTexts.slice(0,l);for(const c of d){if(!n.canCharge())break;try{const s=await a.judgeGenericLinkText({linkText:c.alt,surroundingText:`(This is an alt text on a PDF Figure tag, page ${c.pageNum}.)`});n.recordCharge(s.costUsd),s.verdict==="fail"&&s.confidence>=.6&&o.push({ruleId:"pdf-alt-text-not-descriptive",impact:"moderate",wcagCriterion:"1.1.1",description:`Figure on page ${c.pageNum} has alt text "${c.alt}" that doesn't describe the figure's content. ${s.reasoning} A screen-reader user hears the literal alt and gets no useful information about what the figure shows.`,failureSummary:'Replace generic alt text with a description of what the figure actually shows. For data charts: include the key data point. For decorative images: use alt="" so the screen reader skips them. PDF/UA-1 §7.4 / WCAG 1.1.1.'})}catch(s){i.push(`alt-text page ${c.pageNum}: ${s instanceof Error?s.message:String(s)}`)}}}else i.push("altText AI check disabled in user settings");if(t.enabledChecks.altText&&e.formLabels&&e.formLabels.length>0){const d=s=>{switch(s){case"Tx":return"text input";case"Btn":return"button / checkbox / radio";case"Ch":return"choice / dropdown";case"Sig":return"signature field";default:return s||"unknown"}},c=e.formLabels.slice(0,l);for(const s of c){if(!n.canCharge())break;try{const u=await a.judgeGenericLinkText({linkText:s.tooltip,surroundingText:`(This is the screen-reader tooltip for a PDF form field on page ${s.pageNum}. Field type: ${d(s.fieldType)}. Internal field name: "${s.fieldName||"(none)"}".)`});n.recordCharge(u.costUsd),u.verdict==="fail"&&u.confidence>=.6&&o.push({ruleId:"pdf-form-label-not-descriptive",impact:"serious",wcagCriterion:"3.3.2",description:`Form field on page ${s.pageNum} (${d(s.fieldType)}) has tooltip "${s.tooltip}" that doesn't convey what the user should enter. ${u.reasoning} Screen-reader users hear the tooltip as the field's accessible name; generic tooltips fail to identify the field's purpose.`,failureSummary:'Replace the generic tooltip with one that names what the field is for. "Field 1" → "Mailing address." "Text input" → "Email address." In Acrobat: Tools → Prepare Form → right-click field → Properties → General → Tooltip. WCAG 3.3.2 (Labels or Instructions) requires labels that describe purpose, not just type.'})}catch(u){i.push(`form-label page ${s.pageNum}: ${u instanceof Error?u.message:String(u)}`)}}}if(t.enabledChecks.headings&&e.headings&&e.headings.length>0){const d=e.headings.slice(0,l);for(const c of d){if(!n.canCharge())break;try{const s=await a.judgeHeading({headingText:c.headingText,sectionContent:c.sectionContent});n.recordCharge(s.costUsd),s.verdict==="fail"&&s.confidence>=.6&&o.push({ruleId:"pdf-heading-not-descriptive",impact:"moderate",wcagCriterion:"2.4.6",description:`Heading on page ${c.pageNum} "${c.headingText}" doesn't describe the content of its section. ${s.reasoning} Screen-reader users navigating by heading hear titles that don't help them locate the section they want.`,failureSummary:`Rewrite the heading to describe what the section is about. "Section 1" → "Q3 financial summary." "More info" → "How to apply for benefits." Generic, recycled, or placeholder heading text wastes the SR user's heading-navigation feature.`})}catch(s){i.push(`heading page ${c.pageNum}: ${s instanceof Error?s.message:String(s)}`)}}}return{findings:o,totalCostUsd:n.state.spentUsd,capExceeded:n.state.exceeded,errors:i}}function it(e){return g("PDF_AUDIT_REQUEST",async t=>{const r=await e();if(!_(r,"pdfAudit"))return{type:"PDF_AUDIT_RESPONSE",ok:!1,source:t.url,findings:[],pageCount:null,fatalError:`PDF accessibility audit is not enabled on the ${r} tier. Upgrade or contact your admin to enable the pdfAudit feature.`};try{const a=await se(t.url,{maxBytes:t.maxBytes});let n=[];if(a.aiCandidates)try{const o=await st(a.aiCandidates);if(n=o.findings,o.skipReason&&(a.aiCandidates.figureAltTexts.length>0||a.aiCandidates.headings.length>0||a.aiCandidates.formLabels.length>0)){const i=o.skipReason==="no-key"?"No Anthropic API key configured. AI quality checks (alt-text descriptiveness, heading clarity, form-label match) did NOT run on this PDF.":o.skipReason==="disabled"?"AI augmentation is disabled in Settings → AI. AI quality checks did NOT run on this PDF.":"AI client could not be constructed. AI quality checks did NOT run on this PDF.";n=[...n,{ruleId:"pdf-ai-quality-skipped",impact:"minor",wcagCriterion:"1.1.1",description:i+` (${a.aiCandidates.figureAltTexts.length} figure alts, ${a.aiCandidates.headings.length} headings, ${a.aiCandidates.formLabels.length} form labels would have been judged.)`,failureSummary:"Configure an Anthropic API key in Settings → AI augmentation to enable PDF semantic-quality checks. The structural audit ran normally; this informational finding is dismissible."}]}}catch{}return{type:"PDF_AUDIT_RESPONSE",ok:a.ok,source:a.source,findings:[...a.findings,...n],pageCount:a.pageCount,...a.fatalError?{fatalError:a.fatalError}:{},...a._perPageContrast?{_perPageContrast:a._perPageContrast}:{},...a.aiCandidates?{aiCandidates:a.aiCandidates}:{}}}catch(a){return{type:"PDF_AUDIT_RESPONSE",ok:!1,source:t.url,findings:[],pageCount:null,fatalError:`PDF audit handler threw: ${a instanceof Error?a.message:String(a)}`}}})}const lt=h("ax-tree-snapshot"),ct="1.3";function dt(e){var r,a,n;const t=[];for(const o of e.properties??[]){const i=(r=o.value)==null?void 0:r.value;i!==void 0&&(typeof i=="string"||typeof i=="number"||typeof i=="boolean"||i===null)&&t.push({name:o.name,value:i})}return{nodeId:e.nodeId,parentId:e.parentId,childIds:e.childIds??[],role:typeof((a=e.role)==null?void 0:a.value)=="string"?e.role.value:"unknown",name:typeof((n=e.name)==null?void 0:n.value)=="string"?e.name.value:"",ignored:!!e.ignored,properties:t,backendDomNodeId:e.backendDOMNodeId}}async function ut(e){let t=!1;try{try{await chrome.debugger.attach({tabId:e},ct),t=!0}catch(n){if(!(n instanceof Error?n.message:String(n)).includes("Another debugger"))throw lt.warn("chrome.debugger.attach failed",n),n}await chrome.debugger.sendCommand({tabId:e},"Accessibility.enable");const r=await chrome.debugger.sendCommand({tabId:e},"Accessibility.getFullAXTree");return((r==null?void 0:r.nodes)??[]).map(dt)}finally{if(t)try{await chrome.debugger.detach({tabId:e})}catch{}}}const X=h("perf-throttle"),ft="1.3",gt={none:{label:"No throttling",network:null,cpuRate:1},"3g-slow":{label:"Slow 3G",network:{offline:!1,latency:400,downloadThroughput:500*1024/8,uploadThroughput:500*1024/8},cpuRate:6},"3g-fast":{label:"Fast 3G",network:{offline:!1,latency:150,downloadThroughput:1.5*1024*1024/8,uploadThroughput:750*1024/8},cpuRate:4},"4g":{label:"4G LTE",network:{offline:!1,latency:20,downloadThroughput:4*1024*1024/8,uploadThroughput:3*1024*1024/8},cpuRate:2},"cpu-2x":{label:"CPU 2× slowdown (no network throttle)",network:null,cpuRate:2},"cpu-4x":{label:"CPU 4× slowdown (no network throttle)",network:null,cpuRate:4}};async function pt(e){try{return await chrome.debugger.attach({tabId:e},ft),!0}catch(t){if((t instanceof Error?t.message:String(t)).includes("Another debugger"))return!1;throw t}}async function ht(e,t){const r=gt[t];await pt(e),await chrome.debugger.sendCommand({tabId:e},"Network.enable"),r.network?await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",r.network):await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",{offline:!1,latency:0,downloadThroughput:-1,uploadThroughput:-1}),await chrome.debugger.sendCommand({tabId:e},"Emulation.setCPUThrottlingRate",{rate:r.cpuRate}),X.info(`applied ${t} (label="${r.label}", cpu×${r.cpuRate})`)}async function Et(e){try{await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",{offline:!1,latency:0,downloadThroughput:-1,uploadThroughput:-1}),await chrome.debugger.sendCommand({tabId:e},"Emulation.setCPUThrottlingRate",{rate:1})}catch(t){X.debug("throttle reset commands failed (debugger may not be attached)",t)}}const f=h("service-worker");Le("service-worker");ie();var I,K;(K=(I=chrome.sidePanel)==null?void 0:I.setPanelBehavior)==null||K.call(I,{openPanelOnActionClick:!0}).catch(e=>f.warn("setPanelBehavior failed",e));le();ce();_e();de().catch(e=>f.warn("initial cloud pull failed",e));(async()=>(await Fe(),await be(),Pe(),await Oe(),ve(),ue(),fe(),ge()))();chrome.alarms.onAlarm.addListener(e=>{const t=pe(e.name);t!==null&&he(t).catch(r=>f.warn(`scheduled audit ${t} threw at top level`,r))});ke();Ue();Ee();me();qe();ze();Se();at();nt();it(m);self.addEventListener("unhandledrejection",e=>{const t=e.reason;De(t instanceof Error?t:new Error(String(t)))});let E=!1;chrome.runtime.onConnect.addListener(e=>{if(e.name==="audit-keepalive"){f.debug("keepalive connected"),e.onDisconnect.addListener(async()=>{f.debug("keepalive disconnected"),await Te()});return}if(e.name==="sidepanel-tracker"){E=!0,f.debug("chrome.sidePanel opened"),e.onDisconnect.addListener(async()=>{E=!1,f.debug("chrome.sidePanel closed — restoring in-page overlay"),await b()});return}});let N=!1;const p={isCanceled:()=>N};async function x(){const e=await C();if(e)try{await B(e,{type:"SIDEBAR_HIDE_REQUEST"})}catch(t){f.warn("sidebar hide failed",t)}}async function b(){const e=await C();if(e)try{await B(e,{type:"SIDEBAR_SHOW_REQUEST"})}catch(t){f.warn("sidebar show failed",t)}}g("START_AUDIT",async e=>{N=!1,await x();const t=await C();let r;const a={verifyFixesOnly:e.verifyFixesOnly};if(e.mode==="single-element"){if(!e.scope)throw new Error("START_AUDIT single-element requires scope");r=k(e.scope,p,e.frameId,e.matrixOverride,a)}else if(e.mode==="full-page")r=k("html",p,0,e.matrixOverride,a);else if(e.mode==="quick-scan"){const{QUICK_SCAN_MATRIX_SETTINGS:n}=await F(async()=>{const{QUICK_SCAN_MATRIX_SETTINGS:o}=await import("./ai-usage-log-CYyG5MT2.js").then(i=>i.P);return{QUICK_SCAN_MATRIX_SETTINGS:o}},__vite__mapDeps([0,1]));r=k(e.scope??"html",p,e.frameId??0,n,a)}else if(e.mode==="all-frames")r=ye(p);else if(e.mode==="parallel-scan"){const{runParallelScan:n}=await F(async()=>{const{runParallelScan:o}=await import("./scheduled-audit-runner-ZCuDk8-r.js").then(i=>i.aV);return{runParallelScan:o}},__vite__mapDeps([2,3,1,4,0]));r=n(p)}else r=Re(p);r.catch(n=>{f.error("audit failed",n);const o=n instanceof Error?n.message:String(n),i=/no audit target tab/i.test(o);$e({type:"AUDIT_FAILED_EVENT",error:{code:i?"RESTRICTED_URL":"UNKNOWN",message:i?"No audit target tab found. Open a regular http(s) page (not chrome:// or about:blank) and try again.":`Audit failed: ${o}`,recoverable:!0}})}).finally(()=>{t!=null&&j(t).catch(n=>f.debug("post-audit debugger release failed (best-effort)",n)),E||b()})});g("CANCEL_AUDIT",async()=>{N=!0,f.info("cancel requested")});let S=!1;const z={isCanceled:()=>S};g("START_SITE_CRAWL",async e=>{S=!1,await x();const t=await C();Ie(e.startUrl,{maxPages:e.maxPages,includeRegex:e.includeRegex,excludeRegex:e.excludeRegex,verifyFixesOnly:e.verifyFixesOnly,urls:e.urls},z).catch(r=>f.error("site crawl failed",r)).finally(()=>{t!=null&&j(t).catch(r=>f.debug("post-crawl debugger release failed (best-effort)",r)),E||b()})});g("CANCEL_SITE_CRAWL",async()=>{S=!0,f.info("site crawl cancel requested")});g("START_CRAWL_DISCOVERY",async e=>{S=!1,await x(),we(e.startUrl,{maxPages:e.maxPages,includeRegex:e.includeRegex,excludeRegex:e.excludeRegex},z).catch(t=>f.error("crawl discovery failed",t)).finally(()=>{E||b()})});g("CANCEL_CRAWL_DISCOVERY",async()=>{S=!0,f.info("crawl discovery cancel requested")});g("REGRADE_SITE_CRAWL",async()=>{try{const e=await Ae();return{type:"REGRADE_SITE_CRAWL_RESPONSE",ok:e.ok,...e.reason?{reason:e.reason}:{}}}catch(e){return{type:"REGRADE_SITE_CRAWL_RESPONSE",ok:!1,reason:e instanceof Error?e.message:String(e)}}});g("OPEN_SETTINGS",()=>{chrome.runtime.openOptionsPage()});g("PERF_THROTTLE_APPLY_REQUEST",async e=>{try{return await ht(e.tabId,e.profile),{type:"PERF_THROTTLE_APPLY_RESPONSE",ok:!0}}catch(t){return{type:"PERF_THROTTLE_APPLY_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}});g("PERF_THROTTLE_CLEAR_REQUEST",async e=>{try{return await Et(e.tabId),{type:"PERF_THROTTLE_CLEAR_RESPONSE",ok:!0}}catch(t){return{type:"PERF_THROTTLE_CLEAR_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}});g("SITE_CLAIM_GET_REQUEST",async e=>({type:"SITE_CLAIM_GET_RESPONSE",claim:await Ce(e.domain)}));g("AX_TREE_SNAPSHOT_REQUEST",async e=>{const t=await m();if(!_(t,"axTreeViewer"))return{type:"AX_TREE_SNAPSHOT_RESPONSE",ok:!1,error:"AX-tree viewer is not available on your current plan."};try{return{type:"AX_TREE_SNAPSHOT_RESPONSE",ok:!0,nodes:await ut(e.tabId)}}catch(r){return f.warn("ax-tree snapshot failed",r),{type:"AX_TREE_SNAPSHOT_RESPONSE",ok:!1,error:r instanceof Error?r.message:String(r)}}});f.info("service worker ready");
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ai-usage-log-CYyG5MT2.js","assets/crash-reporter-KD5f4utB.js","assets/scheduled-audit-runner-BALgZTaj.js","assets/preload-helper-D7HrI6pR.js","assets/diff-RnwNJg4F.js"])))=>i.map(i=>d[i]);
2
+ import{_ as F}from"./preload-helper-D7HrI6pR.js";import{ai as v,aj as U,g as J,D as Z,ak as ee,al as te,am as re,an as ae,ao as ne,ap as oe,aq as se,ar as ie,as as le,at as ce,au as de,av as ue,aw as fe,ac as ge,ax as pe,ay as he,az as Ee,aA as me,aB as Se,aC as Te,v as C,aD as k,aE as ye,aF as Re,aG as j,aH as Ie,aI as we,aJ as Ae,aK as Ce}from"./scheduled-audit-runner-BALgZTaj.js";import{m as G,a as m,r as _e}from"./diff-RnwNJg4F.js";import{w as be,r as Pe,a as ke}from"./tier-config-client-85XOCE5d.js";import{w as Oe,r as ve,a as Ue}from"./rubric-config-client-DTzQUfN_.js";import{o as g,m as Ne,n as xe,c as h,f as _,i as Le,p as De,h as B,k as $e}from"./crash-reporter-KD5f4utB.js";import{y as A,z as Fe}from"./ai-usage-log-CYyG5MT2.js";const Ge=h("support-messenger"),Me="https://api.wcagcheckr.com/v1/products/wcagcheckr/support",O="support:rate-window",Ve=5,He=10*60*1e3,We=2,Ke="wcagcheckr",M="storybook:lastDetected";async function je(e){if(!e)return;const t=await chrome.runtime.getPlatformInfo(),a=(await chrome.storage.local.get(M))[M];return{extensionVersion:chrome.runtime.getManifest().version,platform:t,storybookDetected:a!=null&&a.detected?a.version??"detected":"none",licenseTier:await m(),logTail:Ne(xe())}}async function Be(e=Date.now()){const r=((await chrome.storage.local.get(O))[O]??[]).filter(a=>e-a<He);return r.length>=Ve?!1:(r.push(e),await chrome.storage.local.set({[O]:r}),!0)}async function q(e,t=0){try{const r=await fetch(Me,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok)throw new Error(`http ${r.status}`);const a=await r.json();if(!a.success)throw new Error(a.error??"server returned success=false");return{ticketRef:a.ticketRef??""}}catch(r){if(t<We){const a=(t+1)*1e3;return await new Promise(n=>setTimeout(n,a)),q(e,t+1)}throw r}}function qe(){return g("SUPPORT_MESSAGE_REQUEST",async e=>{if(!await Be())return{type:"SUPPORT_MESSAGE_RESPONSE",success:!1,error:G("NETWORK","Rate limit reached. Try again in 10 minutes.",!0)};try{const t=await je(e.includeContext);return{type:"SUPPORT_MESSAGE_RESPONSE",success:!0,ticketRef:(await q({productSlug:Ke,subject:e.subject,body:e.body,replyEmail:e.replyEmail,context:t,extensionVersion:chrome.runtime.getManifest().version,timestamp:new Date().toISOString()})).ticketRef}}catch(t){Ge.error("send failed",t);const r=t instanceof Error?t.message:String(t);return{type:"SUPPORT_MESSAGE_RESPONSE",success:!1,error:G("NETWORK",r,!0)}}})}const Q=h("ai-color-suggester");async function Qe(e,t,r=[]){if(!t.enabled||e.length===0)return{results:[],totalCostUsd:0,capExceeded:!1};const a=v(t);if(!a.ok)return{results:[],totalCostUsd:0,capExceeded:!1};const n=a.client,o=U(t.costCapUsd),i=[];for(const l of e){if(!o.canCharge())break;try{const d=await n.suggestColorFix({foreground:l.foreground,background:l.background,fontSize:l.fontSize,fontWeight:l.fontWeight,targetLevel:l.targetLevel,paletteHints:r});o.recordCharge(d.costUsd),d.verdict==="suggested"&&d.candidates.length>0&&i.push({matchKey:l.matchKey,suggestions:d.candidates,reasoning:d.reasoning,costUsd:d.costUsd})}catch(d){Q.warn(`color-fix suggestion failed for ${l.matchKey}`,d)}}return{results:i,totalCostUsd:o.state.spentUsd,capExceeded:o.state.exceeded}}async function Xe(){const e=await chrome.storage.local.get("aiConfig");return A(e.aiConfig)}function ze(){return g("AI_COLOR_SUGGEST_REQUEST",async e=>{const t=await m();if(!_(t,"aiColorFix"))return{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:"AI color-fix suggester is not available on your current plan."};const r=await Xe();if(!r.enabled)return{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:"AI augmentation is disabled in Settings → AI augmentation."};if(!r.apiKey)return{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:"No AI API key configured. Add one in Settings → AI augmentation."};try{const{results:a,totalCostUsd:n,capExceeded:o}=await Qe(e.inputs,r,e.paletteHints);return{type:"AI_COLOR_SUGGEST_RESPONSE",results:a,totalCostUsd:n,capExceeded:o}}catch(a){return Q.warn("color-suggest handler failed",a),{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:a instanceof Error?a.message:String(a)}}})}function V(e){if(!e)return null;const t=e.match(/rgba?\(\s*([0-9.]+)\s*,?\s*([0-9.]+)\s*,?\s*([0-9.]+)(?:\s*[,/]\s*([0-9.]+))?\s*\)/i);return t?{r:Math.round(parseFloat(t[1])),g:Math.round(parseFloat(t[2])),b:Math.round(parseFloat(t[3])),a:t[4]!==void 0?parseFloat(t[4]):1}:null}function H(e){const t=r=>{const a=r/255;return a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)};return .2126*t(e.r)+.7152*t(e.g)+.0722*t(e.b)}function Ye(e,t){const r=H(e),a=H(t),n=Math.max(r,a),o=Math.min(r,a);return(n+.05)/(o+.05)}function Je(e,t){const r=Math.max(0,Math.min(1,e.a));return{r:Math.round(e.r*r+t.r*(1-r)),g:Math.round(e.g*r+t.g*(1-r)),b:Math.round(e.b*r+t.b*(1-r))}}function Ze(e,t){var $;if(e!=="color-contrast"&&e!=="color-contrast-enhanced")return null;const r=t.styles;if(!r)return null;const a=(($=r.effectiveBackground)==null?void 0:$.color)??r.background,n=r.foreground;if(!n||!a)return null;const o=V(n),i=V(a);if(!o||!i||i.a<.999)return null;const l=o.a<.999?Je(o,i):{r:o.r,g:o.g,b:o.b},d=Ye(l,i),c=r.fontSize??16,s=r.fontWeight??400,u=c>=24||c>=18.5&&s>=700,y=e==="color-contrast-enhanced"?u?4.5:7:u?3:4.5,L=d>=y?"pass":"fail",D=P=>`rgb(${P.r}, ${P.g}, ${P.b})`,Y=`Deterministic WCAG contrast measurement (no AI guessing, no pixel sampling). Foreground ${D(l)}${o.a<.999?` (originally rgba with alpha=${o.a}, composited over background)`:""} against background ${D(i)} yields contrast ratio ${d.toFixed(2)}:1. Text is ${c}px at font-weight ${s}; ${u?"qualifies as large text (threshold 3:1 for AA)":"normal text (threshold 4.5:1 for AA)"}. ${L==="pass"?`Passes AA at ${y}:1.`:`Falls below the ${y}:1 threshold.`}`;return{verdict:L,ratio:d,threshold:y,reasoning:Y}}async function et(e,t,r){var l,d,c,s,u;const a=JSON.stringify({ruleId:e,selector:t,styles:{fg:((l=r.styles)==null?void 0:l.foreground)??null,bg:((d=r.styles)==null?void 0:d.background)??null,fs:((c=r.styles)==null?void 0:c.fontSize)??null,fw:((s=r.styles)==null?void 0:s.fontWeight)??null,ts:((u=r.styles)==null?void 0:u.textSample)??null},failureSummary:r.failureSummary??null}),n=new TextEncoder().encode(a),o=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(o)).map(T=>T.toString(16).padStart(2,"0")).join("")}const w=h("ai-incomplete-resolver");function W(e,t){if(!e)return t;const r=e.toLowerCase(),a=/verdict\s+corrected\s+to\s+pass|verdict:\s*pass\s+\(corrected\)/i,n=/verdict\s+corrected\s+to\s+fail|verdict:\s*fail\s+\(corrected\)/i,o=R(r,a),i=R(r,n);if(o>i&&o>=0)return"pass";if(i>o&&i>=0)return"fail";const l=/actually\s+passes|in\s+fact\s+passes|passes\s+AA/gi,d=/actually\s+fails|in\s+fact\s+fails|fails\s+AA/gi,c=R(r,l),s=R(r,d);return c<0&&s<0?t:c>s&&c/r.length>=.5?"pass":s>c&&s/r.length>=.5?"fail":t}function R(e,t){let r=-1;const a=t.flags.includes("g")?t.flags:t.flags+"g",n=new RegExp(t.source,a);let o;for(;(o=n.exec(e))!==null;)r=o.index,o.index===n.lastIndex&&n.lastIndex++;return r}async function tt(){const e=await chrome.storage.local.get("aiConfig");return A(e.aiConfig)}async function rt(e){if(!e.aiConfig.enabled||e.elements.length===0)return{resolutions:[],totalCostUsd:0};const t=v(e.aiConfig);if(!t.ok)return{resolutions:[],totalCostUsd:0};const r=t.client,a=U(e.aiConfig.costCapUsd),n=[],o=await J(e.pageUrl),i=new Map;for(const l of o)i.set(`${l.ruleId}::${l.selector}`,l);for(const l of e.elements){if(!a.canCharge())break;const d=await et(e.ruleId,l.selector,l),c=i.get(`${e.ruleId}::${l.selector}`),s=Ze(e.ruleId,l);if(s){w.info(`Deterministic verdict for ${e.ruleId} on ${l.selector}: ${s.verdict} (${s.ratio.toFixed(2)}:1 vs ${s.threshold}:1) — math overrides cache + AI`),n.push({pageUrl:e.pageUrl,ruleId:e.ruleId,selector:l.selector,verdict:s.verdict,reasoning:s.reasoning,resolvedAt:new Date().toISOString(),costUsd:0,wcagCriterion:e.wcagCriterion,inputHash:d});continue}if(c&&c.inputHash===d&&c.verdict!=="uncertain"){w.info(`Reusing cached resolution for ${e.ruleId} on ${l.selector} (hash match, verdict=${c.verdict})`);const u=W(c.reasoning,c.verdict);n.push({...c,verdict:u,resolvedAt:new Date().toISOString(),costUsd:0,inputHash:d});continue}try{const u=await r.resolveAxeIncomplete({ruleId:e.ruleId,element:l,pageUrl:e.pageUrl,targetLevel:e.targetLevel});a.recordCharge(u.costUsd);const T=W(u.reasoning,u.verdict);n.push({pageUrl:e.pageUrl,ruleId:e.ruleId,selector:l.selector,verdict:T,reasoning:u.reasoning,resolvedAt:new Date().toISOString(),costUsd:u.costUsd,wcagCriterion:e.wcagCriterion,inputHash:d})}catch(u){w.warn(`resolveAxeIncomplete failed for ${l.selector}`,u)}}return n.length>0&&await Z(n),{resolutions:n,totalCostUsd:a.state.spentUsd}}function at(){return g("AI_RESOLVE_INCOMPLETE_REQUEST",async e=>{const t=await m();if(!_(t,"aiIncompleteResolver"))return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:"AI resolver for axe-incomplete elements is not available on your current plan."};const r=await tt();if(!r.enabled)return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:"AI augmentation is disabled in Settings → AI augmentation."};if(!r.apiKey)return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:"No AI API key configured. Add one in Settings → AI augmentation."};try{const{resolutions:a,totalCostUsd:n}=await rt({ruleId:e.ruleId,pageUrl:e.pageUrl,wcagCriterion:e.wcagCriterion,elements:e.elements,targetLevel:e.targetLevel,aiConfig:r});return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:a,totalCostUsd:n}}catch(a){return w.warn("ai-incomplete-resolver failed",a),{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:a instanceof Error?a.message:"Unknown error during AI resolution."}}})}function nt(){return g("INTERACTIVE_AUDIT_REQUEST",async e=>{try{switch(e.criterionId){case"2.4.3":{const t=await oe({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"2.1.2":{const t=await ne({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"2.4.7":{const t=await ae({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"1.4.11":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=(r==null?void 0:r.results)??[];if(a.length===0)return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:"No audit results available. Run an audit first; 1.4.11 needs the page screenshot."};const n=await re({componentId:e.componentId,pageUrl:e.pageUrl,results:a});return n.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:n.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:n.error}}case"1.3.2":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=(r==null?void 0:r.results)??[];if(a.length===0)return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:"No audit results available. Run an audit first, then the 1.3.2 walkthrough can judge its reading-order findings."};const n=await te({componentId:e.componentId,pageUrl:e.pageUrl,results:a});return n.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:n.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:n.error}}case"2.5.3":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=await ee({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl,results:r==null?void 0:r.results});return a.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:a.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:a.error}}default:return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:`Interactive audit for criterion ${e.criterionId} not yet implemented.`}}}catch(t){return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}})}async function ot(){var t;if(typeof chrome>"u"||!((t=chrome.storage)!=null&&t.local))return A(void 0);const e=await chrome.storage.local.get("aiConfig");return A(e.aiConfig)}async function st(e){const t=await ot();if(!t.enabled)return{findings:[],totalCostUsd:0,capExceeded:!1,errors:[],skipReason:"disabled"};if(!t.apiKey)return{findings:[],totalCostUsd:0,capExceeded:!1,errors:[],skipReason:"no-key"};const r=v(t);if(!r.ok)return{findings:[],totalCostUsd:0,capExceeded:!1,errors:[`AI client unavailable: ${r.reason}`],skipReason:"client-error"};const a=r.client,n=U(t.costCapUsd),o=[],i=[],l=Math.max(1,t.maxCandidatesPerCheck??10);if(t.enabledChecks.altText){const d=e.figureAltTexts.slice(0,l);for(const c of d){if(!n.canCharge())break;try{const s=await a.judgeGenericLinkText({linkText:c.alt,surroundingText:`(This is an alt text on a PDF Figure tag, page ${c.pageNum}.)`});n.recordCharge(s.costUsd),s.verdict==="fail"&&s.confidence>=.6&&o.push({ruleId:"pdf-alt-text-not-descriptive",impact:"moderate",wcagCriterion:"1.1.1",description:`Figure on page ${c.pageNum} has alt text "${c.alt}" that doesn't describe the figure's content. ${s.reasoning} A screen-reader user hears the literal alt and gets no useful information about what the figure shows.`,failureSummary:'Replace generic alt text with a description of what the figure actually shows. For data charts: include the key data point. For decorative images: use alt="" so the screen reader skips them. PDF/UA-1 §7.4 / WCAG 1.1.1.'})}catch(s){i.push(`alt-text page ${c.pageNum}: ${s instanceof Error?s.message:String(s)}`)}}}else i.push("altText AI check disabled in user settings");if(t.enabledChecks.altText&&e.formLabels&&e.formLabels.length>0){const d=s=>{switch(s){case"Tx":return"text input";case"Btn":return"button / checkbox / radio";case"Ch":return"choice / dropdown";case"Sig":return"signature field";default:return s||"unknown"}},c=e.formLabels.slice(0,l);for(const s of c){if(!n.canCharge())break;try{const u=await a.judgeGenericLinkText({linkText:s.tooltip,surroundingText:`(This is the screen-reader tooltip for a PDF form field on page ${s.pageNum}. Field type: ${d(s.fieldType)}. Internal field name: "${s.fieldName||"(none)"}".)`});n.recordCharge(u.costUsd),u.verdict==="fail"&&u.confidence>=.6&&o.push({ruleId:"pdf-form-label-not-descriptive",impact:"serious",wcagCriterion:"3.3.2",description:`Form field on page ${s.pageNum} (${d(s.fieldType)}) has tooltip "${s.tooltip}" that doesn't convey what the user should enter. ${u.reasoning} Screen-reader users hear the tooltip as the field's accessible name; generic tooltips fail to identify the field's purpose.`,failureSummary:'Replace the generic tooltip with one that names what the field is for. "Field 1" → "Mailing address." "Text input" → "Email address." In Acrobat: Tools → Prepare Form → right-click field → Properties → General → Tooltip. WCAG 3.3.2 (Labels or Instructions) requires labels that describe purpose, not just type.'})}catch(u){i.push(`form-label page ${s.pageNum}: ${u instanceof Error?u.message:String(u)}`)}}}if(t.enabledChecks.headings&&e.headings&&e.headings.length>0){const d=e.headings.slice(0,l);for(const c of d){if(!n.canCharge())break;try{const s=await a.judgeHeading({headingText:c.headingText,sectionContent:c.sectionContent});n.recordCharge(s.costUsd),s.verdict==="fail"&&s.confidence>=.6&&o.push({ruleId:"pdf-heading-not-descriptive",impact:"moderate",wcagCriterion:"2.4.6",description:`Heading on page ${c.pageNum} "${c.headingText}" doesn't describe the content of its section. ${s.reasoning} Screen-reader users navigating by heading hear titles that don't help them locate the section they want.`,failureSummary:`Rewrite the heading to describe what the section is about. "Section 1" → "Q3 financial summary." "More info" → "How to apply for benefits." Generic, recycled, or placeholder heading text wastes the SR user's heading-navigation feature.`})}catch(s){i.push(`heading page ${c.pageNum}: ${s instanceof Error?s.message:String(s)}`)}}}return{findings:o,totalCostUsd:n.state.spentUsd,capExceeded:n.state.exceeded,errors:i}}function it(e){return g("PDF_AUDIT_REQUEST",async t=>{const r=await e();if(!_(r,"pdfAudit"))return{type:"PDF_AUDIT_RESPONSE",ok:!1,source:t.url,findings:[],pageCount:null,fatalError:`PDF accessibility audit is not enabled on the ${r} tier. Upgrade or contact your admin to enable the pdfAudit feature.`};try{const a=await se(t.url,{maxBytes:t.maxBytes});let n=[];if(a.aiCandidates)try{const o=await st(a.aiCandidates);if(n=o.findings,o.skipReason&&(a.aiCandidates.figureAltTexts.length>0||a.aiCandidates.headings.length>0||a.aiCandidates.formLabels.length>0)){const i=o.skipReason==="no-key"?"No Anthropic API key configured. AI quality checks (alt-text descriptiveness, heading clarity, form-label match) did NOT run on this PDF.":o.skipReason==="disabled"?"AI augmentation is disabled in Settings → AI. AI quality checks did NOT run on this PDF.":"AI client could not be constructed. AI quality checks did NOT run on this PDF.";n=[...n,{ruleId:"pdf-ai-quality-skipped",impact:"minor",wcagCriterion:"1.1.1",description:i+` (${a.aiCandidates.figureAltTexts.length} figure alts, ${a.aiCandidates.headings.length} headings, ${a.aiCandidates.formLabels.length} form labels would have been judged.)`,failureSummary:"Configure an Anthropic API key in Settings → AI augmentation to enable PDF semantic-quality checks. The structural audit ran normally; this informational finding is dismissible."}]}}catch{}return{type:"PDF_AUDIT_RESPONSE",ok:a.ok,source:a.source,findings:[...a.findings,...n],pageCount:a.pageCount,...a.fatalError?{fatalError:a.fatalError}:{},...a._perPageContrast?{_perPageContrast:a._perPageContrast}:{},...a.aiCandidates?{aiCandidates:a.aiCandidates}:{}}}catch(a){return{type:"PDF_AUDIT_RESPONSE",ok:!1,source:t.url,findings:[],pageCount:null,fatalError:`PDF audit handler threw: ${a instanceof Error?a.message:String(a)}`}}})}const lt=h("ax-tree-snapshot"),ct="1.3";function dt(e){var r,a,n;const t=[];for(const o of e.properties??[]){const i=(r=o.value)==null?void 0:r.value;i!==void 0&&(typeof i=="string"||typeof i=="number"||typeof i=="boolean"||i===null)&&t.push({name:o.name,value:i})}return{nodeId:e.nodeId,parentId:e.parentId,childIds:e.childIds??[],role:typeof((a=e.role)==null?void 0:a.value)=="string"?e.role.value:"unknown",name:typeof((n=e.name)==null?void 0:n.value)=="string"?e.name.value:"",ignored:!!e.ignored,properties:t,backendDomNodeId:e.backendDOMNodeId}}async function ut(e){let t=!1;try{try{await chrome.debugger.attach({tabId:e},ct),t=!0}catch(n){if(!(n instanceof Error?n.message:String(n)).includes("Another debugger"))throw lt.warn("chrome.debugger.attach failed",n),n}await chrome.debugger.sendCommand({tabId:e},"Accessibility.enable");const r=await chrome.debugger.sendCommand({tabId:e},"Accessibility.getFullAXTree");return((r==null?void 0:r.nodes)??[]).map(dt)}finally{if(t)try{await chrome.debugger.detach({tabId:e})}catch{}}}const X=h("perf-throttle"),ft="1.3",gt={none:{label:"No throttling",network:null,cpuRate:1},"3g-slow":{label:"Slow 3G",network:{offline:!1,latency:400,downloadThroughput:500*1024/8,uploadThroughput:500*1024/8},cpuRate:6},"3g-fast":{label:"Fast 3G",network:{offline:!1,latency:150,downloadThroughput:1.5*1024*1024/8,uploadThroughput:750*1024/8},cpuRate:4},"4g":{label:"4G LTE",network:{offline:!1,latency:20,downloadThroughput:4*1024*1024/8,uploadThroughput:3*1024*1024/8},cpuRate:2},"cpu-2x":{label:"CPU 2× slowdown (no network throttle)",network:null,cpuRate:2},"cpu-4x":{label:"CPU 4× slowdown (no network throttle)",network:null,cpuRate:4}};async function pt(e){try{return await chrome.debugger.attach({tabId:e},ft),!0}catch(t){if((t instanceof Error?t.message:String(t)).includes("Another debugger"))return!1;throw t}}async function ht(e,t){const r=gt[t];await pt(e),await chrome.debugger.sendCommand({tabId:e},"Network.enable"),r.network?await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",r.network):await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",{offline:!1,latency:0,downloadThroughput:-1,uploadThroughput:-1}),await chrome.debugger.sendCommand({tabId:e},"Emulation.setCPUThrottlingRate",{rate:r.cpuRate}),X.info(`applied ${t} (label="${r.label}", cpu×${r.cpuRate})`)}async function Et(e){try{await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",{offline:!1,latency:0,downloadThroughput:-1,uploadThroughput:-1}),await chrome.debugger.sendCommand({tabId:e},"Emulation.setCPUThrottlingRate",{rate:1})}catch(t){X.debug("throttle reset commands failed (debugger may not be attached)",t)}}const f=h("service-worker");Le("service-worker");ie();var I,K;(K=(I=chrome.sidePanel)==null?void 0:I.setPanelBehavior)==null||K.call(I,{openPanelOnActionClick:!0}).catch(e=>f.warn("setPanelBehavior failed",e));le();ce();_e();de().catch(e=>f.warn("initial cloud pull failed",e));(async()=>(await Fe(),await be(),Pe(),await Oe(),ve(),ue(),fe(),ge()))();chrome.alarms.onAlarm.addListener(e=>{const t=pe(e.name);t!==null&&he(t).catch(r=>f.warn(`scheduled audit ${t} threw at top level`,r))});ke();Ue();Ee();me();qe();ze();Se();at();nt();it(m);self.addEventListener("unhandledrejection",e=>{const t=e.reason;De(t instanceof Error?t:new Error(String(t)))});let E=!1;chrome.runtime.onConnect.addListener(e=>{if(e.name==="audit-keepalive"){f.debug("keepalive connected"),e.onDisconnect.addListener(async()=>{f.debug("keepalive disconnected"),await Te()});return}if(e.name==="sidepanel-tracker"){E=!0,f.debug("chrome.sidePanel opened"),e.onDisconnect.addListener(async()=>{E=!1,f.debug("chrome.sidePanel closed — restoring in-page overlay"),await b()});return}});let N=!1;const p={isCanceled:()=>N};async function x(){const e=await C();if(e)try{await B(e,{type:"SIDEBAR_HIDE_REQUEST"})}catch(t){f.warn("sidebar hide failed",t)}}async function b(){const e=await C();if(e)try{await B(e,{type:"SIDEBAR_SHOW_REQUEST"})}catch(t){f.warn("sidebar show failed",t)}}g("START_AUDIT",async e=>{N=!1,await x();const t=await C();let r;const a={verifyFixesOnly:e.verifyFixesOnly};if(e.mode==="single-element"){if(!e.scope)throw new Error("START_AUDIT single-element requires scope");r=k(e.scope,p,e.frameId,e.matrixOverride,a)}else if(e.mode==="full-page")r=k("html",p,0,e.matrixOverride,a);else if(e.mode==="quick-scan"){const{QUICK_SCAN_MATRIX_SETTINGS:n}=await F(async()=>{const{QUICK_SCAN_MATRIX_SETTINGS:o}=await import("./ai-usage-log-CYyG5MT2.js").then(i=>i.P);return{QUICK_SCAN_MATRIX_SETTINGS:o}},__vite__mapDeps([0,1]));r=k(e.scope??"html",p,e.frameId??0,n,a)}else if(e.mode==="all-frames")r=ye(p);else if(e.mode==="parallel-scan"){const{runParallelScan:n}=await F(async()=>{const{runParallelScan:o}=await import("./scheduled-audit-runner-BALgZTaj.js").then(i=>i.aV);return{runParallelScan:o}},__vite__mapDeps([2,3,1,4,0]));r=n(p)}else r=Re(p);r.catch(n=>{f.error("audit failed",n);const o=n instanceof Error?n.message:String(n),i=/no audit target tab/i.test(o);$e({type:"AUDIT_FAILED_EVENT",error:{code:i?"RESTRICTED_URL":"UNKNOWN",message:i?"No audit target tab found. Open a regular http(s) page (not chrome:// or about:blank) and try again.":`Audit failed: ${o}`,recoverable:!0}})}).finally(()=>{t!=null&&j(t).catch(n=>f.debug("post-audit debugger release failed (best-effort)",n)),E||b()})});g("CANCEL_AUDIT",async()=>{N=!0,f.info("cancel requested")});let S=!1;const z={isCanceled:()=>S};g("START_SITE_CRAWL",async e=>{S=!1,await x();const t=await C();Ie(e.startUrl,{maxPages:e.maxPages,includeRegex:e.includeRegex,excludeRegex:e.excludeRegex,verifyFixesOnly:e.verifyFixesOnly,urls:e.urls},z).catch(r=>f.error("site crawl failed",r)).finally(()=>{t!=null&&j(t).catch(r=>f.debug("post-crawl debugger release failed (best-effort)",r)),E||b()})});g("CANCEL_SITE_CRAWL",async()=>{S=!0,f.info("site crawl cancel requested")});g("START_CRAWL_DISCOVERY",async e=>{S=!1,await x(),we(e.startUrl,{maxPages:e.maxPages,includeRegex:e.includeRegex,excludeRegex:e.excludeRegex},z).catch(t=>f.error("crawl discovery failed",t)).finally(()=>{E||b()})});g("CANCEL_CRAWL_DISCOVERY",async()=>{S=!0,f.info("crawl discovery cancel requested")});g("REGRADE_SITE_CRAWL",async()=>{try{const e=await Ae();return{type:"REGRADE_SITE_CRAWL_RESPONSE",ok:e.ok,...e.reason?{reason:e.reason}:{}}}catch(e){return{type:"REGRADE_SITE_CRAWL_RESPONSE",ok:!1,reason:e instanceof Error?e.message:String(e)}}});g("OPEN_SETTINGS",()=>{chrome.runtime.openOptionsPage()});g("PERF_THROTTLE_APPLY_REQUEST",async e=>{try{return await ht(e.tabId,e.profile),{type:"PERF_THROTTLE_APPLY_RESPONSE",ok:!0}}catch(t){return{type:"PERF_THROTTLE_APPLY_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}});g("PERF_THROTTLE_CLEAR_REQUEST",async e=>{try{return await Et(e.tabId),{type:"PERF_THROTTLE_CLEAR_RESPONSE",ok:!0}}catch(t){return{type:"PERF_THROTTLE_CLEAR_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}});g("SITE_CLAIM_GET_REQUEST",async e=>({type:"SITE_CLAIM_GET_RESPONSE",claim:await Ce(e.domain)}));g("AX_TREE_SNAPSHOT_REQUEST",async e=>{const t=await m();if(!_(t,"axTreeViewer"))return{type:"AX_TREE_SNAPSHOT_RESPONSE",ok:!1,error:"AX-tree viewer is not available on your current plan."};try{return{type:"AX_TREE_SNAPSHOT_RESPONSE",ok:!0,nodes:await ut(e.tabId)}}catch(r){return f.warn("ax-tree snapshot failed",r),{type:"AX_TREE_SNAPSHOT_RESPONSE",ok:!1,error:r instanceof Error?r.message:String(r)}}});f.info("service worker ready");