@wcag-checkr/ci 1.0.14 → 1.0.16

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.
@@ -0,0 +1 @@
1
+ import{c as U}from"./crash-reporter-DAZnNefT.js";const I="autoExportSettings",f="lastAutoExportAt",be=["deposition-packet","defense-bundle","html-print","ai-prompt"],v={enabled:!1,formats:["defense-bundle"]};function C(o){return o==="deposition-packet"||o==="defense-bundle"||o==="html-print"||o==="ai-prompt"}async function ye(){var l;if(typeof chrome>"u"||!((l=chrome.storage)!=null&&l.local))return{...v,formats:[...v.formats]};const e=(await chrome.storage.local.get(I))[I];if(!e||typeof e!="object")return{...v,formats:[...v.formats]};const n=typeof e.enabled=="boolean"?e.enabled:!1;let a=[];return Array.isArray(e.formats)?a=e.formats.filter(C):C(e.format)&&(a=[e.format]),a.length===0&&(a=[...v.formats]),{enabled:n,formats:a}}async function Ae(o){var e;typeof chrome>"u"||!((e=chrome.storage)!=null&&e.local)||await chrome.storage.local.set({[I]:o})}async function we(o){var a;return typeof chrome>"u"||!((a=chrome.storage)!=null&&a.local)?null:((await chrome.storage.local.get(f))[f]??{})[o]??null}async function Ie(o){var a;if(typeof chrome>"u"||!((a=chrome.storage)!=null&&a.local))return;const n=(await chrome.storage.local.get(f))[f]??{};n[o.url]=o,await chrome.storage.local.set({[f]:n})}const S="autoDownloadReports";async function Se(){return(await chrome.storage.local.get(S))[S]===!0}const xe=S;function M(o,e){const a=/^text\/(markdown|plain|csv)\b/i.test(e)?"\uFEFF"+o:o,l=/charset=/i.test(e)?e:`${e};charset=utf-8`;return{body:a,type:l}}function ke(o,e,n="text/html"){const a=(e.split(".").pop()??"").toLowerCase(),l=n==="text/html"&&(a==="md"||a==="markdown")?"text/markdown":n==="text/html"&&a==="txt"?"text/plain":n,{body:r,type:t}=M(o,l),d=new Blob([r],{type:t}),i=URL.createObjectURL(d),s=document.createElement("a");s.href=i,s.download=e,document.body.appendChild(s),s.click(),document.body.removeChild(s),setTimeout(()=>URL.revokeObjectURL(i),5e3)}function De(o){var e;typeof chrome<"u"&&((e=chrome.tabs)!=null&&e.create)?chrome.tabs.create({url:o,active:!0}).catch(n=>{console.warn("[download-helper] chrome.tabs.create failed; falling back to window.open",n),window.open(o,"_blank","noopener,noreferrer")}):window.open(o,"_blank","noopener,noreferrer")}function Ce(o,e="text/html"){var l;const n=new Blob([o],{type:e}),a=URL.createObjectURL(n);return typeof chrome<"u"&&((l=chrome.tabs)!=null&&l.create)?chrome.tabs.create({url:a,active:!0}).catch(r=>{console.warn("[download-helper] chrome.tabs.create failed; falling back to window.open",r),window.open(a,"_blank","noopener,noreferrer")}):window.open(a,"_blank","noopener,noreferrer"),setTimeout(()=>URL.revokeObjectURL(a),6e4),a}function qe(o,e){const n=new Date().toISOString().slice(0,10),a=(e??"audit").replace(/[^a-z0-9]/gi,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").slice(0,24).toLowerCase()||"audit";return`wcagcheckr-${o}-${n}-${a}.${o==="ai-prompt"?"md":"html"}`}function Re(o){return o<1024?`${o} B`:o<1024*1024?`${Math.round(o/1024)} KB`:`${(o/(1024*1024)).toFixed(1)} MB`}const x="tierConfig:cache",P=60*60*1e3,N=24*60*60*1e3,W=7*24*60*60*1e3;async function Te(){return(await chrome.storage.local.get(x))[x]??null}async function Oe(o){await chrome.storage.local.set({[x]:o})}function Ee(o,e=Date.now()){const n=e-o.fetchedAt;return n<P?"fresh":n<N?"stale":n<W?"grace":"expired"}function Le(o,e){const n={...o},a=s=>{if(typeof s=="number")return s===-1?1/0:s},l=s=>typeof s=="boolean"?s:void 0,r=s=>{if(s==="all"||s==="configurable"||s==="default-only")return s},t=(s,c)=>{const u=l(c);u!==void 0&&(n[s]=u)},d=(s,c)=>{const u=a(c);u!==void 0&&(n[s]=u)};d("maxComponents",e.maxComponents),d("maxBaselines",e.maxBaselines);const i=r(e.stateMatrix);return i!==void 0&&(n.stateMatrix=i),d("siteCrawlMaxPages",e.siteCrawlMaxPages),d("scheduledAuditsMaxCount",e.scheduledAuditsMaxCount),d("aiCostCapDefaultUsd",e.aiCostCapDefaultUsd),d("aiMaxCandidatesPerCheck",e.aiMaxCandidatesPerCheck),t("storybookAutoIterate",e.storybookAutoIterate),t("parallelScan",e.parallelScan),t("allFramesAudit",e.allFramesAudit),t("siteCrawl",e.siteCrawl),t("scheduledAudits",e.scheduledAudits),t("emailAlerts",e.emailAlerts),t("webhookAlerts",e.webhookAlerts),t("autoExportAuditReports",e.autoExportAuditReports),t("aiJudgment",e.aiJudgment),t("aiWalkthroughs",e.aiWalkthroughs),t("aiCopilot",e.aiCopilot),t("aiColorFix",e.aiColorFix),t("aiComplianceSummary",e.aiComplianceSummary),t("aiIncompleteResolver",e.aiIncompleteResolver),t("aiConsistencySuppression",e.aiConsistencySuppression),t("visualizers",e.visualizers),t("flowRecorder",e.flowRecorder),t("igtWorkflows",e.igtWorkflows),t("axTreeViewer",e.axTreeViewer),t("pdfAudit",e.pdfAudit),t("exportJson",e.exportJson),t("exportSarif",e.exportSarif),t("exportJunit",e.exportJunit),t("exportHtmlPrint",e.exportHtmlPrint),t("exportVpat",e.exportVpat),t("exportDefenseBundle",e.exportDefenseBundle),t("exportEvidenceBundle",e.exportEvidenceBundle),t("exportDeveloperLetter",e.exportDeveloperLetter),t("exportOwnerReport",e.exportOwnerReport),t("exportAiPrompts",e.exportAiPrompts),t("exportDepositionPacket",e.exportDepositionPacket),t("exportMethodologyDoc",e.exportMethodologyDoc),t("exportConformanceCrosswalk",e.exportConformanceCrosswalk),t("exportEaaStatement",e.exportEaaStatement),t("exportTicketBundle",e.exportTicketBundle),t("exportExecutiveReport",e.exportExecutiveReport),t("exportPreLitigationReport",e.exportPreLitigationReport),t("forensicLog",e.forensicLog),t("forensicAnchoring",e.forensicAnchoring),t("wcagEmReport",e.wcagEmReport),t("wcagEmAnchor",e.wcagEmAnchor),t("statusBadge",e.statusBadge),t("riskDashboard",e.riskDashboard),t("lawfareRisk",e.lawfareRisk),t("wcag3Preview",e.wcag3Preview),t("cloudSync",e.cloudSync),t("issueTrackers",e.issueTrackers),t("cliRunner",e.cliRunner),t("mcpServer",e.mcpServer),t("vscodeExtension",e.vscodeExtension),t("devtoolsPanel",e.devtoolsPanel),t("designSystemAudit",e.designSystemAudit),t("customRules",e.customRules),n}function Fe(o,e){const n=e.plans.find(a=>a.code===o||a.code.startsWith(o+"-"));return(n==null?void 0:n.features)??null}const w=[{id:"mobile",label:"Mobile (375×667)",width:375,height:667,deviceScaleFactor:2,mobile:!0},{id:"tablet",label:"Tablet (768×1024)",width:768,height:1024,deviceScaleFactor:2,mobile:!0},{id:"desktop",label:"Desktop (1280×800)",width:1280,height:800,deviceScaleFactor:1,mobile:!1}],T={pseudoStates:["default","hover","focus","focus-visible","active","disabled"],ariaVariations:[],themes:["light","dark","forced-colors-active","forced-colors-none"],directions:["ltr"],breakpoints:["desktop","mobile","tablet"],breakpointPresets:w},O={pseudoStates:["default","hover","focus","focus-visible","active","disabled"],ariaVariations:[],themes:["light","dark","forced-colors-active","forced-colors-none"],directions:["ltr","rtl"],breakpoints:["desktop","mobile","tablet"],breakpointPresets:w},V={pseudoStates:["default"],ariaVariations:[],themes:["light"],directions:["ltr"],breakpoints:["desktop"],breakpointPresets:w},$=[{id:"default-subset",name:"Default subset",matrix:T},{id:"full-matrix",name:"Full matrix",matrix:O}],_e=Object.freeze(Object.defineProperty({__proto__:null,BUILT_IN_PRESETS:$,DEFAULT_BREAKPOINT_PRESETS:w,DEFAULT_STATE_MATRIX_SETTINGS:T,FULL_STATE_MATRIX_SETTINGS:O,QUICK_SCAN_MATRIX_SETTINGS:V},Symbol.toStringTag,{value:"Module"})),z={id:"keyboard",name:"Keyboard navigation",blurb:"Verify everyone who relies on the keyboard can reach, operate, and escape every interactive element. WCAG 2.1.1, 2.1.2, 2.4.3, 2.4.7.",steps:[{id:"tab-reaches-all",prompt:"Tab through the component from start to finish. Compare against the Tab-order overlay.",question:"Did Tab reach every interactive element (button, link, form field, custom widget)?",wcag:"2.1.1",visualizer:"tab-order",severity:"required"},{id:"tab-order-logical",prompt:"Watch the focus indicator as you Tab. Compare visual order vs the Tab-order numbered overlay.",question:"Does focus move in a logical order matching the visual layout (left-to-right, top-to-bottom)? Red badges indicate visual mismatches.",wcag:"2.4.3",visualizer:"tab-order",severity:"required",autoDismissActivity:"tab-order"},{id:"focus-visible",prompt:"On each focused element, confirm a visible focus indicator (outline, ring, color change).",question:"Is the focus indicator clearly visible on every interactive element?",wcag:"2.4.7",relatedAxeRule:"focus-order-semantics",severity:"required"},{id:"no-trap",prompt:"Tab forward and Shift+Tab backward through any modal, dropdown, or custom widget.",question:"Can you escape the widget with Tab/Shift+Tab/Esc — no trapping?",wcag:"2.1.2",severity:"required"},{id:"enter-activates",prompt:"Focus a button or link and press Enter (and Space for buttons).",question:"Did Enter/Space activate the control as expected?",wcag:"2.1.1",severity:"required"},{id:"esc-closes",prompt:"Open any modal, dropdown, or popover and press Escape.",question:"Did Escape close the overlay and return focus to the trigger?",wcag:"2.1.2",severity:"required"},{id:"arrow-keys-grouped",prompt:"For grouped widgets (radio, tabs, listbox, menu): focus into the group, then use arrow keys.",question:"Do arrow keys move within the group as expected (and Tab moves out of it)?",wcag:"2.1.1",severity:"advisory"},{id:"character-key-shortcuts",prompt:'Identify any single-character keyboard shortcuts (e.g., "S" to open search, "/" to focus the search box, J/K for next/prev). If none exist, mark N/A.',question:"For every single-character shortcut: can it be turned off, remapped to a modifier-key combo, OR is it only active when the relevant control has focus? (Prevents accidental activation by speech-input users.)",wcag:"2.1.4",severity:"required"}]},K={id:"screen-reader",name:"Screen reader readiness",blurb:"Verify the component is operable and meaningful via a screen reader. Use NVDA (Windows), VoiceOver (macOS/iOS), or TalkBack (Android). WCAG 1.3.1, 4.1.2.",steps:[{id:"sr-announces-on-focus",prompt:"Activate your screen reader and Tab to each interactive element.",question:"Does the SR announce a meaningful name + role + state for every focused element?",wcag:"4.1.2",relatedAxeRule:"aria-required-attr",severity:"required"},{id:"sr-headings-navigate",prompt:"Use the SR's heading-navigation shortcut (NVDA: H, VoiceOver: VO+Cmd+H). Compare against the Outline overlay.",question:"Are all logical sections reachable via heading navigation, in correct hierarchy order?",wcag:"1.3.1",relatedAxeRule:"heading-order",visualizer:"outline",severity:"required"},{id:"sr-reading-order",prompt:"Read the page top-to-bottom using the SR's read-all command (NVDA: NumPad+Down, VoiceOver: VO+A). Compare against the Reading-order numbered overlay.",question:"Does the SR read content in the meaningful order implied by the visual layout (1.3.2 Meaningful Sequence)? Red badges in the Reading-order overlay show DOM-vs-visual divergences.",wcag:"1.3.2",visualizer:"reading-order",severity:"required",autoDismissActivity:"reading-order"},{id:"sr-landmarks",prompt:"Use the SR's landmark-navigation shortcut (NVDA: D, VoiceOver: VO+U → Landmarks). Compare against the Outline overlay.",question:"Can the user jump to main, nav, banner, contentinfo via landmark navigation?",wcag:"1.3.1",relatedAxeRule:"region",visualizer:"outline",severity:"required"},{id:"sr-live-region",prompt:"Trigger any dynamic update (form submission, status change, toast).",question:'Does the SR announce the change automatically (via aria-live or role="status"/role="alert")?',wcag:"4.1.3",severity:"required"},{id:"sr-form-errors",prompt:"Submit a form with an invalid field.",question:"Does the SR announce the error and which field it relates to?",wcag:"3.3.1",severity:"required"},{id:"sr-images-meaningful",prompt:"Navigate over each image (NVDA: G, VoiceOver: VO+Cmd+G).",question:"Does each meaningful image have descriptive alt text? Are decorative images silent?",wcag:"1.1.1",relatedAxeRule:"image-alt",severity:"required"}]},G={id:"focus-management",name:"Focus management",blurb:"Verify focus moves and restores correctly across overlays, navigations, and dynamic content. WCAG 2.4.3, 2.4.7, 3.2.2.",steps:[{id:"modal-initial-focus",prompt:"Open a modal/dialog.",question:"Did focus move into the modal automatically (typically to the first focusable element or a heading)?",severity:"required"},{id:"modal-restored-on-close",prompt:"Close a modal/dialog (via close button or Esc).",question:"Was focus restored to the element that opened it?",severity:"required"},{id:"modal-trap-while-open",prompt:"While a modal is open, Tab/Shift+Tab through it.",question:"Is focus trapped inside the modal until it closes?",severity:"required"},{id:"route-change-focus",prompt:"Trigger a client-side route change.",question:"Did focus move sensibly (to the new page heading, or main landmark) — not to <body>?",severity:"required"},{id:"expanded-focus",prompt:"Open an expandable section (accordion, dropdown, collapsible).",question:"Is focus moved into or near the newly-revealed content (or kept on the trigger appropriately)?",severity:"advisory"},{id:"no-unexpected-focus-move",prompt:"Type or click in form fields without explicitly tabbing.",question:"Does focus stay where you put it (no auto-jump on input)?",wcag:"3.2.2",severity:"required"},{id:"no-context-change-on-focus",prompt:"Tab into each interactive element on the page.",question:"Does merely RECEIVING focus on an element NOT trigger a context change (auto-submit, open modal, navigate elsewhere, change focus to a different field)? (Context change on focus violates 3.2.1; activating a control via click/Enter is fine.)",wcag:"3.2.1",severity:"required"}]},B={id:"forms",name:"Forms",blurb:"Verify form fields are properly labeled, errors are clear, and the experience works for assistive technology. WCAG 1.3.1, 3.3.1, 3.3.2, 4.1.2.",steps:[{id:"visible-labels",prompt:"Look at every form field.",question:"Does every field have a visible label (not just placeholder text)?",wcag:"3.3.2",relatedAxeRule:"label",severity:"required"},{id:"label-association",prompt:"Click each visible label.",question:"Did clicking the label focus the associated input?",wcag:"1.3.1",relatedAxeRule:"label",severity:"required"},{id:"required-marked",prompt:"Identify required fields.",question:"Are required fields marked both visually AND programmatically (aria-required or required attribute)?",wcag:"3.3.2",severity:"required"},{id:"autocomplete-set",prompt:"For personal-info fields (name, email, phone, address): inspect the autocomplete attribute.",question:'Is autocomplete set with a valid HTML5 token (e.g., "email", "given-name", "tel")?',wcag:"1.3.5",relatedAxeRule:"autocomplete-valid",severity:"required"},{id:"error-text",prompt:"Submit with invalid input.",question:'Are error messages specific (not just "invalid"), shown near the field, and programmatically associated (aria-describedby)?',wcag:"3.3.1",severity:"required"},{id:"no-color-only-error",prompt:"Look at how errors are signaled.",question:"Is the error indicated by more than just color (also icon, text, or border style)?",wcag:"1.4.1",severity:"required"},{id:"success-announced",prompt:"Submit a form successfully.",question:'Is the success state announced to screen readers (via aria-live or role="status")?',wcag:"4.1.3",severity:"advisory"},{id:"error-suggestion",prompt:"Submit a form with an obvious invalid input (wrong email format, password too short, missing required field).",question:'Does the error message INCLUDE a specific suggestion for fixing it (not just "invalid")?',wcag:"3.3.3",severity:"required"},{id:"redundant-entry",prompt:"Identify any multi-step or multi-form flow where the user re-enters previously provided information (shipping = billing, profile data repeated in another form).",question:"Is previously-entered information auto-populated, selectable from a list, or otherwise NOT manually re-entered?",wcag:"3.3.7",severity:"required"},{id:"accessible-authentication",prompt:"Identify the site's authentication flow (login, password reset, multi-factor).",question:'Does auth NOT require a cognitive function test (e.g., remembering / transcribing characters), OR is an accessible alternative offered (passkey, magic link, password-manager autofill, "show password" toggle)?',wcag:"3.3.8",severity:"required"}]},H={id:"page-structure",name:"Page structure",blurb:"Verify the page declares its language, has a meaningful title, and exposes a sensible heading + landmark hierarchy. WCAG 2.4.2, 3.1.1, 3.1.2, 1.3.1, 2.4.6.",steps:[{id:"page-title",prompt:"Look at the browser tab — is the page title set and meaningful?",question:'Does the title describe the page topic / purpose (not just "Untitled" or the site name)?',wcag:"2.4.2",relatedAxeRule:"document-title",severity:"required"},{id:"page-lang",prompt:"Inspect the <html> element's lang attribute.",question:'Is lang set to a valid language code (e.g., "en", "es-MX")?',wcag:"3.1.1",relatedAxeRule:"html-has-lang",severity:"required"},{id:"lang-of-parts",prompt:"For any text not in the page's primary language (foreign quote, brand name in another language), inspect the parent element.",question:"Is lang attribute set on those elements to indicate the language change?",wcag:"3.1.2",severity:"advisory"},{id:"h1-present",prompt:"Use the Outline visualizer or SR heading shortcut to find the h1.",question:"Is there exactly one h1, and does it describe the main content of the page?",wcag:"1.3.1",relatedAxeRule:"page-has-heading-one",visualizer:"outline",severity:"required"},{id:"descriptive-headings",prompt:"Read each heading. Imagine someone listening only to the heading text.",question:"Does each heading describe its section meaningfully on its own?",wcag:"2.4.6",severity:"required"},{id:"main-landmark",prompt:"Use the Outline visualizer or SR landmark shortcut.",question:"Is there exactly one <main> landmark wrapping the page's primary content?",wcag:"1.3.1",relatedAxeRule:"landmark-one-main",visualizer:"outline",severity:"required"},{id:"parsing-well-formed",prompt:"Open DevTools → Console. Reload the page and check for HTML parse errors. Or run W3C validator on the URL.",question:"Is the page's markup well-formed (no duplicate IDs in scope, no invalid nesting, no missing required attributes)? WCAG 4.1.1 was obsoleted in 2.2 but still applies to 2.1 conformance claims.",wcag:"4.1.1",severity:"required"}]},j={id:"visual-indicators",name:"Visual indicators",blurb:"Verify nothing relies on color/shape/position alone, and non-text contrast meets thresholds for UI components and focus rings. WCAG 1.3.3, 1.4.1, 1.4.11.",steps:[{id:"no-color-only-info",prompt:"Scan instructions, error messages, charts, status indicators.",question:"Is information conveyed by something OTHER than color alone (text, icon, pattern, label)?",wcag:"1.4.1",severity:"required"},{id:"no-sensory-only",prompt:'Look for instructions referencing shape ("the round button"), location ("on the left"), sound ("the chime"), or visual cues alone.',question:"Are those instructions backed up by a programmatic identifier (label, role, accessible name)?",wcag:"1.3.3",severity:"required"},{id:"non-text-contrast",prompt:"For UI components (form-field borders, focus rings, icons-as-buttons), verify contrast vs adjacent colors. Use a contrast checker if needed.",question:"Do non-text UI components meet ≥3:1 contrast against adjacent colors?",wcag:"1.4.11",severity:"required"},{id:"focus-ring-contrast",prompt:"Tab through; for each focused element, verify the focus ring is visible against both the element and the page background.",question:"Does the focus ring meet ≥3:1 contrast on every focusable surface?",wcag:"1.4.11",visualizer:"tab-order",severity:"required"},{id:"state-changes-visible",prompt:"For toggleable controls (checkboxes, switches, expanded states): change them and observe.",question:"Is the state change conveyed visibly AND programmatically (aria-pressed/expanded/checked)?",wcag:"4.1.2",severity:"required"}]},Y={id:"reflow",name:"Reflow & text spacing",blurb:"Verify the layout survives narrow viewports, browser zoom, and user-overridden text spacing. WCAG 1.4.4, 1.4.10, 1.4.12.",steps:[{id:"resize-320",prompt:"Resize the browser to 320px wide (or set DevTools device toolbar to 320×256).",question:"Does content reflow without two-dimensional scrolling? (Vertical scroll OK; horizontal scroll within content blocks NOT OK.)",wcag:"1.4.10",relatedAxeRule:"wcagcheckr-reflow",severity:"required"},{id:"zoom-200",prompt:"In a desktop viewport, zoom the browser to 200%.",question:"Is all content + functionality available, with no text clipping or unusable controls?",wcag:"1.4.4",severity:"required"},{id:"text-spacing-override",prompt:"Apply text-spacing override (line-height: 1.5, paragraph spacing 2x font-size, letter-spacing 0.12em, word-spacing 0.16em) via a bookmarklet or DevTools.",question:"Does content stay readable with no overlap or clipping?",wcag:"1.4.12",severity:"required"},{id:"no-fixed-pixel-text",prompt:"Inspect text styles for fixed px-based font sizes, line-heights.",question:"Are text dimensions set in relative units (rem/em/%) so they scale with user settings?",severity:"advisory"},{id:"orientation-not-locked",prompt:"Rotate a mobile device (or use DevTools device toolbar to rotate) between portrait and landscape.",question:"Does the layout adapt to both orientations? (Content not locked to one orientation unless essential.)",wcag:"1.3.4",severity:"required"},{id:"images-of-text",prompt:"Look for marketing banners, hero images, or any image that contains substantial text content as part of the raster.",question:"Is real HTML text used in preference to images-of-text, except for logos / decorative purposes? (Images-of-text fail to scale with zoom, can't be selected, and don't respect user text settings.)",wcag:"1.4.5",severity:"required"}]},J={id:"hover-focus-content",name:"Content on hover or focus",blurb:"Tooltips, dropdown previews, and any content revealed on hover or focus must be dismissable, hoverable, and persistent. WCAG 1.4.13.",steps:[{id:"dismissable",prompt:"Hover or focus to reveal a tooltip / popover. Press Escape.",question:"Did Escape dismiss the revealed content without moving pointer or focus?",wcag:"1.4.13",severity:"required"},{id:"hoverable",prompt:"Hover to reveal a tooltip. Move the pointer over the tooltip itself (without losing the trigger's hover).",question:"Does the revealed content stay visible when the pointer enters it?",wcag:"1.4.13",severity:"required"},{id:"persistent",prompt:"Reveal a tooltip and don't do anything else.",question:"Does the content remain visible until the user dismisses it, moves focus/pointer away, or the trigger info is no longer valid?",wcag:"1.4.13",severity:"required"}]},X={id:"pointer",name:"Pointer interactions",blurb:"Verify gestures, target sizes, and pointer cancellation respect users with motor limitations. WCAG 2.5.1, 2.5.2, 2.5.5/2.5.8.",steps:[{id:"no-multi-point-gesture",prompt:"Identify any feature that requires a multi-point gesture (pinch, two-finger swipe) or path-based gesture (drag along a line).",question:"Is there a single-tap / single-click alternative for that feature?",wcag:"2.5.1",severity:"required"},{id:"pointer-cancellation",prompt:"Mouse-down on a button, drag the pointer OFF the button, then release.",question:"Was the action canceled (the button did NOT activate)? Activation should fire on up-event over the target, not down-event.",wcag:"2.5.2",severity:"required"},{id:"target-size-aa",prompt:"Toggle the Targets visualizer. Look for any red overlays (≥24×24 fail).",question:"Are all interactive targets ≥24×24 CSS px (or have sufficient spacing per WCAG 2.5.8)?",wcag:"2.5.8",relatedAxeRule:"target-size",visualizer:"targets",severity:"required"},{id:"label-in-name",prompt:"For every visually-labeled control (button, link), inspect its accessible name (use the SR or DevTools).",question:"Does the accessible name START with — or fully contain — the visible label text?",wcag:"2.5.3",relatedAxeRule:"label-content-name-mismatch",severity:"required"},{id:"motion-actuation-alt",prompt:"Identify any feature that triggers on device motion (shake to undo, tilt to scroll, step counter).",question:"Is there a non-motion alternative (button / control) for every motion-triggered function, AND can motion be disabled?",wcag:"2.5.4",severity:"required"},{id:"dragging-alternative",prompt:"Identify any feature that requires a dragging movement (slider thumb, drag-to-rearrange, swipe-to-delete).",question:"Is there a single-tap / single-click alternative for every dragging action (e.g., +/- buttons next to a slider, up/down buttons next to draggable list items)?",wcag:"2.5.7",severity:"required"}]},Q={id:"time-based",name:"Time-based behaviors",blurb:"Verify time limits, auto-updating content, and motion can be controlled by users. WCAG 2.2.1, 2.2.2, 2.3.1.",steps:[{id:"time-limits-adjustable",prompt:"Identify any time-limited interaction (session timeout, form auto-submit, OTP expiration).",question:"Can the user turn off, adjust, or extend the time limit before it expires (warning + control before the deadline)?",wcag:"2.2.1",severity:"required"},{id:"pause-moving-content",prompt:"Look for content that moves, blinks, scrolls, or auto-updates for >5 seconds (carousels, animated banners, news tickers, auto-refreshing feeds).",question:"Is there a control to pause / stop / hide the moving content?",wcag:"2.2.2",severity:"required"},{id:"no-flash",prompt:"Identify any flashing or blinking content (>3 flashes per second).",question:"Is flashing absent, OR limited below the general/red flash thresholds?",wcag:"2.3.1",severity:"required"},{id:"reduced-motion-honored",prompt:'Enable system "reduce motion" preference. Reload the page.',question:"Does the site honor prefers-reduced-motion (parallax / animations / spinners minimized or disabled)?",wcag:"2.3.3",severity:"advisory"}]},Z={id:"error-prevention",name:"Error prevention",blurb:"Verify destructive, financial, or legal actions are reversible, checked, or confirmed. WCAG 3.3.4, 3.3.6.",steps:[{id:"destructive-confirm",prompt:"Identify destructive actions (delete account, cancel subscription, destroy data, send irreversible message).",question:'Is each destructive action reversible (undo), or checked (validation), or confirmed (explicit "Are you sure?" dialog)?',wcag:"3.3.4",severity:"required"},{id:"financial-confirm",prompt:"Identify financial / legal commitments (purchase, contract sign, transfer).",question:"Before submission, does the user see a review screen and an explicit confirmation step?",wcag:"3.3.4",severity:"required"},{id:"undo-available",prompt:'Test "destructive" actions on user content (delete a note, archive an item).',question:'Is there an undo / restore mechanism, even briefly (toast with "undo" button)?',wcag:"3.3.6",severity:"advisory"}]},ee={id:"consistency",name:"Consistency",blurb:"Verify navigation, identification, and user paths are consistent across pages. WCAG 2.4.5, 3.2.3, 3.2.4.",steps:[{id:"consistent-nav",prompt:"Compare the primary navigation across 3+ pages.",question:"Does the same navigation appear in the same order on every page?",wcag:"3.2.3",severity:"required"},{id:"consistent-id",prompt:'Compare the same UI element appearing on multiple pages (e.g., a search icon, a "Help" link).',question:"Does the same component have the same accessible name everywhere it appears?",wcag:"3.2.4",severity:"required"},{id:"multiple-ways",prompt:"Beyond the primary navigation, is there a second way to find a page (search, sitemap, related links, breadcrumbs)?",question:"Are there at least 2 ways to locate any page (single-process pages exempt)?",wcag:"2.4.5",severity:"required"},{id:"skip-link",prompt:"Tab once when the page loads.",question:'Does the first focusable element offer a "Skip to main content" link (or equivalent bypass)?',wcag:"2.4.1",relatedAxeRule:"bypass",severity:"required"},{id:"consistent-help",prompt:"Identify pages that surface a help mechanism (contact info, help link, FAQ link, chatbot trigger). Compare position + order across pages.",question:"When the same help mechanism appears on multiple pages, does it appear in the same relative order (e.g., always last in the header)?",wcag:"3.2.6",severity:"required"}]},te={id:"time-based-media",name:"Time-based media",blurb:'Verify audio + video have the alternatives required by WCAG. If the site has no time-based media, mark every step "Not applicable." WCAG 1.2.1, 1.2.2, 1.2.3, 1.2.4, 1.2.5, 1.4.2.',steps:[{id:"prerecorded-audio-only-alt",prompt:"Identify any prerecorded audio-only content (podcast embed, audio quote, voice message).",question:"Does each prerecorded audio-only file have a text transcript readable on the page (or linked from it)?",wcag:"1.2.1",severity:"required"},{id:"prerecorded-video-only-alt",prompt:"Identify any prerecorded silent video (animated GIF with content, silent screencast, animated explainer).",question:"Does each prerecorded video-only file have an equivalent text or audio description?",wcag:"1.2.1",severity:"required"},{id:"prerecorded-captions",prompt:"Identify any prerecorded video that includes audio (interviews, tutorials, marketing videos).",question:"Does each video provide synchronized captions for ALL spoken content + meaningful non-speech sound?",wcag:"1.2.2",severity:"required"},{id:"prerecorded-alt-for-video",prompt:"For each prerecorded video with audio, check if there's a full text transcript on the page (covering both audio dialog AND visual action) OR if audio description is provided.",question:"Does each prerecorded video have either a full text alternative OR an audio-description track?",wcag:"1.2.3",severity:"required"},{id:"prerecorded-audio-description",prompt:"Watch each prerecorded video without looking at it. Listen only.",question:"Is all visually-conveyed information also conveyed in the audio (either built into the narration OR via a separate audio-description track)?",wcag:"1.2.5",severity:"required"},{id:"live-captions",prompt:"Identify any LIVE audio/video stream (live shopping, webinar, conference broadcast).",question:"Does each live broadcast provide real-time captions?",wcag:"1.2.4",severity:"required"},{id:"audio-control",prompt:"Reload the page. Listen for audio that starts automatically and plays for >3 seconds (background music, autoplay video with sound).",question:"Is there a mechanism to pause / stop the audio, OR can the volume be controlled INDEPENDENTLY from the system volume?",wcag:"1.4.2",severity:"required"}]},oe=[z,K,G,B,H,j,Y,J,X,Q,te,Z,ee];function Ue(o,e){let n=0,a=0,l=0,r=0,t=0;for(const d of e.steps){const i=o.steps[d.id];if(!i){t++;continue}i.status==="pass"?n++:i.status==="fail"?a++:i.status==="not-applicable"?r++:i.status==="skip"?l++:t++}return{passed:n,failed:a,skipped:l,notApplicable:r,unanswered:t,total:e.steps.length,fullyAnswered:t===0}}const ie=[{id:"1.1.1",title:"Non-text Content",level:"A",addedIn:"2.0",understandingSlug:"non-text-content",shortDescription:"All non-text content has a text alternative."},{id:"1.2.1",title:"Audio-only and Video-only (Prerecorded)",level:"A",addedIn:"2.0",understandingSlug:"audio-only-and-video-only-prerecorded",shortDescription:"Alternatives for prerecorded audio-only or video-only."},{id:"1.2.2",title:"Captions (Prerecorded)",level:"A",addedIn:"2.0",understandingSlug:"captions-prerecorded",shortDescription:"Captions for prerecorded audio in synchronized media."},{id:"1.2.3",title:"Audio Description or Media Alternative (Prerecorded)",level:"A",addedIn:"2.0",understandingSlug:"audio-description-or-media-alternative-prerecorded",shortDescription:"Alternative for time-based media (prerecorded)."},{id:"1.2.4",title:"Captions (Live)",level:"AA",addedIn:"2.0",understandingSlug:"captions-live",shortDescription:"Captions for live synchronized media."},{id:"1.2.5",title:"Audio Description (Prerecorded)",level:"AA",addedIn:"2.0",understandingSlug:"audio-description-prerecorded",shortDescription:"Audio description for prerecorded video in synchronized media."},{id:"1.2.6",title:"Sign Language (Prerecorded)",level:"AAA",addedIn:"2.0",understandingSlug:"sign-language-prerecorded",shortDescription:"Sign-language interpretation for prerecorded audio."},{id:"1.2.7",title:"Extended Audio Description (Prerecorded)",level:"AAA",addedIn:"2.0",understandingSlug:"extended-audio-description-prerecorded",shortDescription:"Extended audio description for prerecorded video."},{id:"1.2.8",title:"Media Alternative (Prerecorded)",level:"AAA",addedIn:"2.0",understandingSlug:"media-alternative-prerecorded",shortDescription:"Alternative for time-based media (prerecorded)."},{id:"1.2.9",title:"Audio-only (Live)",level:"AAA",addedIn:"2.0",understandingSlug:"audio-only-live",shortDescription:"Alternative for live audio-only content."},{id:"1.3.1",title:"Info and Relationships",level:"A",addedIn:"2.0",understandingSlug:"info-and-relationships",shortDescription:"Information and structural relationships are programmatically determinable."},{id:"1.3.2",title:"Meaningful Sequence",level:"A",addedIn:"2.0",understandingSlug:"meaningful-sequence",shortDescription:"Reading sequence is programmatically determinable."},{id:"1.3.3",title:"Sensory Characteristics",level:"A",addedIn:"2.0",understandingSlug:"sensory-characteristics",shortDescription:"Instructions don't rely solely on shape, color, size, or sound."},{id:"1.3.4",title:"Orientation",level:"AA",addedIn:"2.1",understandingSlug:"orientation",shortDescription:"Content doesn't restrict view to portrait or landscape."},{id:"1.3.5",title:"Identify Input Purpose",level:"AA",addedIn:"2.1",understandingSlug:"identify-input-purpose",shortDescription:"Purpose of input fields is programmatically identifiable."},{id:"1.3.6",title:"Identify Purpose",level:"AAA",addedIn:"2.1",understandingSlug:"identify-purpose",shortDescription:"Purpose of UI components, icons, and regions is identifiable."},{id:"1.4.1",title:"Use of Color",level:"A",addedIn:"2.0",understandingSlug:"use-of-color",shortDescription:"Color is not the only means of conveying information."},{id:"1.4.2",title:"Audio Control",level:"A",addedIn:"2.0",understandingSlug:"audio-control",shortDescription:"Mechanism to pause/stop auto-playing audio over 3s."},{id:"1.4.3",title:"Contrast (Minimum)",level:"AA",addedIn:"2.0",understandingSlug:"contrast-minimum",shortDescription:"Text has 4.5:1 contrast (3:1 for large text)."},{id:"1.4.4",title:"Resize Text",level:"AA",addedIn:"2.0",understandingSlug:"resize-text",shortDescription:"Text resizable to 200% without loss of content/function."},{id:"1.4.5",title:"Images of Text",level:"AA",addedIn:"2.0",understandingSlug:"images-of-text",shortDescription:"Text used in preference to images of text where possible."},{id:"1.4.6",title:"Contrast (Enhanced)",level:"AAA",addedIn:"2.0",understandingSlug:"contrast-enhanced",shortDescription:"Text has 7:1 contrast (4.5:1 for large text)."},{id:"1.4.7",title:"Low or No Background Audio",level:"AAA",addedIn:"2.0",understandingSlug:"low-or-no-background-audio",shortDescription:"Background audio at least 20dB lower than speech."},{id:"1.4.8",title:"Visual Presentation",level:"AAA",addedIn:"2.0",understandingSlug:"visual-presentation",shortDescription:"Configurable visual presentation for blocks of text."},{id:"1.4.9",title:"Images of Text (No Exception)",level:"AAA",addedIn:"2.0",understandingSlug:"images-of-text-no-exception",shortDescription:"Images of text used only for decoration / essential."},{id:"1.4.10",title:"Reflow",level:"AA",addedIn:"2.1",understandingSlug:"reflow",shortDescription:"Content reflows at 320 CSS px without 2D scrolling."},{id:"1.4.11",title:"Non-text Contrast",level:"AA",addedIn:"2.1",understandingSlug:"non-text-contrast",shortDescription:"UI components and graphical objects have 3:1 contrast."},{id:"1.4.12",title:"Text Spacing",level:"AA",addedIn:"2.1",understandingSlug:"text-spacing",shortDescription:"Text spacing overrides don't cause content loss."},{id:"1.4.13",title:"Content on Hover or Focus",level:"AA",addedIn:"2.1",understandingSlug:"content-on-hover-or-focus",shortDescription:"Hover/focus tooltips are dismissible, hoverable, persistent."},{id:"2.1.1",title:"Keyboard",level:"A",addedIn:"2.0",understandingSlug:"keyboard",shortDescription:"All functionality available from the keyboard."},{id:"2.1.2",title:"No Keyboard Trap",level:"A",addedIn:"2.0",understandingSlug:"no-keyboard-trap",shortDescription:"Keyboard focus can move away from any component."},{id:"2.1.3",title:"Keyboard (No Exception)",level:"AAA",addedIn:"2.0",understandingSlug:"keyboard-no-exception",shortDescription:"All functionality is keyboard-operable without timing."},{id:"2.1.4",title:"Character Key Shortcuts",level:"A",addedIn:"2.1",understandingSlug:"character-key-shortcuts",shortDescription:"Single-key shortcuts can be turned off or remapped."},{id:"2.2.1",title:"Timing Adjustable",level:"A",addedIn:"2.0",understandingSlug:"timing-adjustable",shortDescription:"User can turn off, adjust, or extend time limits."},{id:"2.2.2",title:"Pause, Stop, Hide",level:"A",addedIn:"2.0",understandingSlug:"pause-stop-hide",shortDescription:"Moving/blinking/scrolling content can be paused."},{id:"2.2.3",title:"No Timing",level:"AAA",addedIn:"2.0",understandingSlug:"no-timing",shortDescription:"No timing essential to content/function (with exceptions)."},{id:"2.2.4",title:"Interruptions",level:"AAA",addedIn:"2.0",understandingSlug:"interruptions",shortDescription:"User can postpone/suppress non-emergency interruptions."},{id:"2.2.5",title:"Re-authenticating",level:"AAA",addedIn:"2.0",understandingSlug:"re-authenticating",shortDescription:"Authenticated session can be resumed without data loss."},{id:"2.2.6",title:"Timeouts",level:"AAA",addedIn:"2.1",understandingSlug:"timeouts",shortDescription:"Inactivity timeouts warned in advance."},{id:"2.3.1",title:"Three Flashes or Below Threshold",level:"A",addedIn:"2.0",understandingSlug:"three-flashes-or-below-threshold",shortDescription:"No content flashes more than 3 times per second."},{id:"2.3.2",title:"Three Flashes",level:"AAA",addedIn:"2.0",understandingSlug:"three-flashes",shortDescription:"No content flashes more than 3 times per second (no exceptions)."},{id:"2.3.3",title:"Animation from Interactions",level:"AAA",addedIn:"2.1",understandingSlug:"animation-from-interactions",shortDescription:"Motion animation from interactions can be disabled."},{id:"2.4.1",title:"Bypass Blocks",level:"A",addedIn:"2.0",understandingSlug:"bypass-blocks",shortDescription:"Mechanism to skip blocks of repeated content."},{id:"2.4.2",title:"Page Titled",level:"A",addedIn:"2.0",understandingSlug:"page-titled",shortDescription:"Pages have titles that describe topic/purpose."},{id:"2.4.3",title:"Focus Order",level:"A",addedIn:"2.0",understandingSlug:"focus-order",shortDescription:"Components receive focus in a meaningful order."},{id:"2.4.4",title:"Link Purpose (In Context)",level:"A",addedIn:"2.0",understandingSlug:"link-purpose-in-context",shortDescription:"Link purpose is clear from the link text + context."},{id:"2.4.5",title:"Multiple Ways",level:"AA",addedIn:"2.0",understandingSlug:"multiple-ways",shortDescription:"Two or more ways to locate a page within a set."},{id:"2.4.6",title:"Headings and Labels",level:"AA",addedIn:"2.0",understandingSlug:"headings-and-labels",shortDescription:"Headings and labels describe topic or purpose."},{id:"2.4.7",title:"Focus Visible",level:"AA",addedIn:"2.0",understandingSlug:"focus-visible",shortDescription:"Keyboard focus indicator is visible."},{id:"2.4.8",title:"Location",level:"AAA",addedIn:"2.0",understandingSlug:"location",shortDescription:"Information about user's location within a set is available."},{id:"2.4.9",title:"Link Purpose (Link Only)",level:"AAA",addedIn:"2.0",understandingSlug:"link-purpose-link-only",shortDescription:"Link purpose clear from the link text alone."},{id:"2.4.10",title:"Section Headings",level:"AAA",addedIn:"2.0",understandingSlug:"section-headings",shortDescription:"Section headings are used to organize content."},{id:"2.4.11",title:"Focus Not Obscured (Minimum)",level:"AA",addedIn:"2.2",understandingSlug:"focus-not-obscured-minimum",shortDescription:"Focused component not entirely hidden by other content."},{id:"2.4.12",title:"Focus Not Obscured (Enhanced)",level:"AAA",addedIn:"2.2",understandingSlug:"focus-not-obscured-enhanced",shortDescription:"Focused component fully visible."},{id:"2.4.13",title:"Focus Appearance",level:"AAA",addedIn:"2.2",understandingSlug:"focus-appearance",shortDescription:"Focus indicator meets specific size/contrast requirements."},{id:"2.5.1",title:"Pointer Gestures",level:"A",addedIn:"2.1",understandingSlug:"pointer-gestures",shortDescription:"Multi-point or path-based gestures have single-pointer alternatives."},{id:"2.5.2",title:"Pointer Cancellation",level:"A",addedIn:"2.1",understandingSlug:"pointer-cancellation",shortDescription:"Pointer actions can be aborted or undone."},{id:"2.5.3",title:"Label in Name",level:"A",addedIn:"2.1",understandingSlug:"label-in-name",shortDescription:"Accessible name includes the visible label text."},{id:"2.5.4",title:"Motion Actuation",level:"A",addedIn:"2.1",understandingSlug:"motion-actuation",shortDescription:"Motion-triggered functions have UI alternatives + can be disabled."},{id:"2.5.5",title:"Target Size (Enhanced)",level:"AAA",addedIn:"2.1",understandingSlug:"target-size-enhanced",shortDescription:"Pointer target size at least 44×44 CSS px."},{id:"2.5.6",title:"Concurrent Input Mechanisms",level:"AAA",addedIn:"2.1",understandingSlug:"concurrent-input-mechanisms",shortDescription:"Content doesn't restrict input modality."},{id:"2.5.7",title:"Dragging Movements",level:"AA",addedIn:"2.2",understandingSlug:"dragging-movements",shortDescription:"Dragging actions have single-pointer alternatives."},{id:"2.5.8",title:"Target Size (Minimum)",level:"AA",addedIn:"2.2",understandingSlug:"target-size-minimum",shortDescription:"Pointer target size at least 24×24 CSS px."},{id:"3.1.1",title:"Language of Page",level:"A",addedIn:"2.0",understandingSlug:"language-of-page",shortDescription:"Default human language of the page is programmatically set."},{id:"3.1.2",title:"Language of Parts",level:"AA",addedIn:"2.0",understandingSlug:"language-of-parts",shortDescription:"Language of each passage is programmatically set."},{id:"3.1.3",title:"Unusual Words",level:"AAA",addedIn:"2.0",understandingSlug:"unusual-words",shortDescription:"Definitions provided for jargon, idioms, etc."},{id:"3.1.4",title:"Abbreviations",level:"AAA",addedIn:"2.0",understandingSlug:"abbreviations",shortDescription:"Expanded form or meaning of abbreviations is available."},{id:"3.1.5",title:"Reading Level",level:"AAA",addedIn:"2.0",understandingSlug:"reading-level",shortDescription:"Supplemental content provided for advanced reading levels."},{id:"3.1.6",title:"Pronunciation",level:"AAA",addedIn:"2.0",understandingSlug:"pronunciation",shortDescription:"Mechanism for pronunciation of words where meaning is ambiguous."},{id:"3.2.1",title:"On Focus",level:"A",addedIn:"2.0",understandingSlug:"on-focus",shortDescription:"Focus does not trigger an unexpected context change."},{id:"3.2.2",title:"On Input",level:"A",addedIn:"2.0",understandingSlug:"on-input",shortDescription:"Input does not trigger an unexpected context change."},{id:"3.2.3",title:"Consistent Navigation",level:"AA",addedIn:"2.0",understandingSlug:"consistent-navigation",shortDescription:"Navigation is consistent across a set of pages."},{id:"3.2.4",title:"Consistent Identification",level:"AA",addedIn:"2.0",understandingSlug:"consistent-identification",shortDescription:"Components with the same function are identified consistently."},{id:"3.2.5",title:"Change on Request",level:"AAA",addedIn:"2.0",understandingSlug:"change-on-request",shortDescription:"Changes of context only on user request."},{id:"3.2.6",title:"Consistent Help",level:"A",addedIn:"2.2",understandingSlug:"consistent-help",shortDescription:"Help mechanisms appear in consistent order across pages."},{id:"3.3.1",title:"Error Identification",level:"A",addedIn:"2.0",understandingSlug:"error-identification",shortDescription:"Form errors are identified and described in text."},{id:"3.3.2",title:"Labels or Instructions",level:"A",addedIn:"2.0",understandingSlug:"labels-or-instructions",shortDescription:"Form fields have labels or instructions."},{id:"3.3.3",title:"Error Suggestion",level:"AA",addedIn:"2.0",understandingSlug:"error-suggestion",shortDescription:"Error suggestions provided when known."},{id:"3.3.4",title:"Error Prevention (Legal, Financial, Data)",level:"AA",addedIn:"2.0",understandingSlug:"error-prevention-legal-financial-data",shortDescription:"Submissions are reversible, checked, or confirmed."},{id:"3.3.5",title:"Help",level:"AAA",addedIn:"2.0",understandingSlug:"help",shortDescription:"Context-sensitive help is available."},{id:"3.3.6",title:"Error Prevention (All)",level:"AAA",addedIn:"2.0",understandingSlug:"error-prevention-all",shortDescription:"All submissions reversible, checked, or confirmed."},{id:"3.3.7",title:"Redundant Entry",level:"A",addedIn:"2.2",understandingSlug:"redundant-entry",shortDescription:"Previously-entered information is auto-populated or selectable."},{id:"3.3.8",title:"Accessible Authentication (Minimum)",level:"AA",addedIn:"2.2",understandingSlug:"accessible-authentication-minimum",shortDescription:"Auth doesn't require cognitive function test."},{id:"3.3.9",title:"Accessible Authentication (Enhanced)",level:"AAA",addedIn:"2.2",understandingSlug:"accessible-authentication-enhanced",shortDescription:"Auth doesn't require cognitive function test (no exceptions)."},{id:"4.1.1",title:"Parsing",level:"A",addedIn:"2.0",removedIn:"2.2",understandingSlug:"parsing",shortDescription:"Markup is well-formed (obsoleted in WCAG 2.2)."},{id:"4.1.2",title:"Name, Role, Value",level:"A",addedIn:"2.0",understandingSlug:"name-role-value",shortDescription:"UI components have programmatically determinable name + role + state."},{id:"4.1.3",title:"Status Messages",level:"AA",addedIn:"2.1",understandingSlug:"status-messages",shortDescription:"Status messages programmatically announced without focus change."}];function ne(o,e){const n={A:1,AA:2,AAA:3},a={"2.0":1,"2.1":2,"2.2":3};return ie.filter(l=>a[l.addedIn]>a[o]||l.removedIn&&a[l.removedIn]<=a[o]?!1:n[l.level]<=n[e])}function Me(o,e){return`https://www.w3.org/WAI/WCAG${e.replace(".","")}/Understanding/${o.understandingSlug}`}let y="2.1";const re="AA";function Pe(o){y=o}async function Ne(){var o,e;try{const a=(await chrome.storage.local.get("wcagTargetVersion")).wcagTargetVersion;(a==="2.1"||a==="2.2")&&(y=a),(e=(o=chrome.storage.onChanged)==null?void 0:o.addListener)==null||e.call(o,(l,r)=>{if(r!=="local")return;const t=l.wcagTargetVersion;if(!t)return;const d=t.newValue;(d==="2.1"||d==="2.2")&&(y=d)})}catch{}}const ae=["3.2.3","3.2.4","3.2.6","3.3.7"];function We(o){const e=ne(y,re),n=new Map;for(const r of e)n.set(r.id,{criterionId:r.id,level:r.level,title:r.title,state:"not-evaluated",evidence:[]});const a=new Map;function l(r,t){let d=a.get(r);return d||(d=new Set,a.set(r,d)),d.has(t)?!0:(d.add(t),!1)}for(const r of o.audits){const t=r.pageUrl??r.scope;for(const i of r.violations){if(!i.wcagCriterion)continue;const s=n.get(i.wcagCriterion);if(!s)continue;const c=i.ruleId.startsWith("ai-"),u=i.target.selector;if(o.acknowledgedMatchKeys.has(i.matchKey)){const h=`ack::${i.ruleId}::${t}::${u}`;if(l(i.wcagCriterion,h))continue;s.evidence.push({source:c?"ai":"axe",ruleOrStepId:i.ruleId,outcome:"ack",pageUrl:t,selector:u});continue}if(i.needsReview){const h=`needsReview::${i.ruleId}::${t}::${u}`;if(l(i.wcagCriterion,h))continue;s.evidence.push({source:"ai",ruleOrStepId:i.ruleId,outcome:"incomplete",pageUrl:t,selector:u,resolutionHint:"Acknowledge in the Matrix view if not an issue, or fix the underlying alt text."});continue}const p=`fail::${i.ruleId}::${t}::${u}`;l(i.wcagCriterion,p)||s.evidence.push({source:c?"ai":"axe",ruleOrStepId:i.ruleId,outcome:"fail",pageUrl:t,selector:u,resolutionHint:`Fix ${i.ruleId} on ${u}.`})}const d=r.axeRulesEvaluated;if(d){for(const i of d.passed){const s=n.get(i.wcagCriterion);if(!s)continue;const c=`axe::${i.ruleId}::${t}::pass`;l(i.wcagCriterion,c)||s.evidence.push({source:"axe",ruleOrStepId:i.ruleId,outcome:"pass",pageUrl:t})}for(const i of d.inapplicable){const s=n.get(i.wcagCriterion);if(!s)continue;const c=`axe::${i.ruleId}::${t}::inapplicable`;l(i.wcagCriterion,c)||s.evidence.push({source:"axe",ruleOrStepId:i.ruleId,outcome:"inapplicable",pageUrl:t})}for(const i of d.incomplete){const s=n.get(i.wcagCriterion);if(!s)continue;const c=`axe::${i.ruleId}::${t}::incomplete`,u=s.evidence.findIndex(p=>p.source==="axe"&&p.outcome==="incomplete"&&p.ruleOrStepId===i.ruleId&&p.pageUrl===t);if(u>=0){if(i.elements&&i.elements.length>0){const p=s.evidence[u],h=new Set((p.elements??[]).map(m=>m.selector));for(const m of i.elements)h.has(m.selector)||((p.elements??(p.elements=[])).push(m),h.add(m.selector))}continue}l(i.wcagCriterion,c)||s.evidence.push({source:"axe",ruleOrStepId:i.ruleId,outcome:"incomplete",pageUrl:t,elements:i.elements?[...i.elements]:void 0,resolutionHint:"axe-core couldn't fully determine. Common causes: text against an image/gradient background, or aria-role on a hidden element. Review the page manually."})}}}if(o.incompleteResolutions&&o.incompleteResolutions.length>0){const r=new Map;for(const t of o.incompleteResolutions)r.set(`${t.pageUrl}::${t.ruleId}::${t.selector}`,t);for(const t of n.values()){const d=[];for(const i of t.evidence){if(i.source!=="axe"||i.outcome!=="incomplete"||!i.elements||i.elements.length===0){d.push(i);continue}const s=[];for(const c of i.elements){const u=`${i.pageUrl}::${i.ruleOrStepId}::${c.selector}`,p=r.get(u);if(!p){s.push(c);continue}p.verdict==="pass"?d.push({source:"ai",ruleOrStepId:`ai-resolved::${i.ruleOrStepId}`,outcome:"pass",pageUrl:i.pageUrl,selector:c.selector,notes:p.reasoning}):p.verdict==="fail"?d.push({source:"ai",ruleOrStepId:`ai-resolved::${i.ruleOrStepId}`,outcome:"fail",pageUrl:i.pageUrl,selector:c.selector,notes:p.reasoning,resolutionHint:`AI determined ${i.ruleOrStepId} fails on this element. Review and fix or override.`}):s.push(c)}s.length>0&&d.push({...i,elements:s})}t.evidence=d}}if(o.interactiveAuditResults&&o.interactiveAuditResults.length>0)for(const r of o.interactiveAuditResults){const t=n.get(r.criterionId);t&&t.evidence.push({source:"ai",ruleOrStepId:r.ruleId,outcome:r.verdict==="pass"?"pass":r.verdict==="fail"?"fail":"incomplete",pageUrl:r.pageUrl,notes:r.reasoning,resolutionHint:r.verdict==="fail"?"Review the AI walkthrough in the Compliance tab; fix the underlying focus-order issue and re-run.":r.verdict==="uncertain"?"Re-run the interactive audit, or manually verify via Guided Tests.":void 0})}for(const r of o.workflows)for(const t of r.steps){if(!t.wcag)continue;const d=n.get(t.wcag);if(d)for(const i of o.igtRuns){if(i.workflowId!==r.id)continue;const s=i.steps[t.id],c=`${r.id}.${t.id}`;if(!s){d.evidence.push({source:"igt",ruleOrStepId:c,outcome:"skip",resolutionHint:`Open Guided Tests → ${r.name} → answer "${t.id}" as Pass / Fail / N/A.`});continue}s.status==="pass"?d.evidence.push({source:"igt",ruleOrStepId:c,outcome:"pass",notes:s.notes}):s.status==="fail"?d.evidence.push({source:"igt",ruleOrStepId:c,outcome:"fail",notes:s.notes,resolutionHint:`Address the failing manual check: ${t.question}`}):s.status==="not-applicable"?d.evidence.push({source:"igt",ruleOrStepId:c,outcome:"n/a",notes:s.notes}):s.status==="skip"&&d.evidence.push({source:"igt",ruleOrStepId:c,outcome:"skip",notes:s.notes,resolutionHint:`Open Guided Tests → ${r.name} → re-answer "${t.id}" as Pass / Fail / N/A.`})}}for(const r of n.values())r.state=se(r.evidence);if(o.auditScope==="single-page")for(const r of ae){const t=n.get(r);t&&t.state==="not-evaluated"&&(t.state="not-applicable",t.evidence.push({source:"axe",ruleOrStepId:"wcc-multi-page-only-na",outcome:"n/a",notes:"Single-page audit cannot evaluate this cross-page criterion. Treated as N/A for this audit; run Site Crawl to evaluate."}))}if(o.humanCriterionVerdicts&&o.humanCriterionVerdicts.length>0)for(const r of o.humanCriterionVerdicts){const t=n.get(r.criterionId);if(!t)continue;const d=r.verdict==="na"?"n/a":r.verdict,i=r.verdict==="na"?"not-applicable":r.verdict==="fail"?"fail":"pass";t.state=i,t.evidence.push({source:"human",ruleOrStepId:"human-criterion-verdict",outcome:d,notes:`Human verified ${r.verdict.toUpperCase()} on ${r.verifiedAt}: ${r.note}`})}return n}function se(o){return o.length===0?"not-evaluated":o.some(n=>n.outcome==="fail")?"fail":o.some(n=>n.outcome==="incomplete"||n.outcome==="skip")?"inconclusive":o.some(n=>n.outcome==="pass"||n.outcome==="inapplicable"||n.outcome==="ack")?"pass":"not-applicable"}function Ve(o){const e={pass:[],fail:[],inconclusive:[],notApplicable:[],notEvaluated:[]};for(const a of o.values())e[de(a.state)].push(a.criterionId);const n=o.size;return{pass:e.pass.length,fail:e.fail.length,inconclusive:e.inconclusive.length,notApplicable:e.notApplicable.length,notEvaluated:e.notEvaluated.length,totalApplicable:n,canClaimConformance:e.fail.length===0&&e.inconclusive.length===0&&e.notEvaluated.length===0,byState:e}}function de(o){return o==="not-applicable"?"notApplicable":o==="not-evaluated"?"notEvaluated":o}function $e(o,e=oe){const n=new Set,a=new Set,l=new Set;for(const t of o.values())for(const d of t.evidence)d.source==="axe"?n.add(t.criterionId):d.source==="ai"?a.add(t.criterionId):d.source==="igt"&&l.add(t.criterionId);for(const t of e)for(const d of t.steps)d.wcag&&o.has(d.wcag)&&l.add(d.wcag);function r(t,d){const i=Array.from(d).sort();let s=0;const c=[],u=[],p=[];for(const h of i){const m=o.get(h);if(!m)continue;const b=m.evidence.filter(g=>t==="automation"&&g.source==="axe"||t==="ai"&&g.source==="ai"||t==="human"&&g.source==="igt");if(b.length===0){p.push(h);continue}const L=b.some(g=>g.outcome==="fail"),F=b.some(g=>g.outcome==="incomplete"||g.outcome==="skip"),_=b.some(g=>g.outcome==="pass"||g.outcome==="inapplicable"||g.outcome==="ack"||g.outcome==="n/a");L?c.push(h):F?u.push(h):_?s++:p.push(h)}return{layer:t,coveredCriteria:i,cleared:s,failing:c,inconclusive:u,blocked:[...c,...u].sort(),unevaluated:p}}return{automation:r("automation",n),ai:r("ai",a),human:r("human",l)}}const k="auditCache:",le=24*60*60*1e3;async function D(o){const e=new TextEncoder().encode(o),n=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(n)).map(a=>a.toString(16).padStart(2,"0")).join("")}async function ce(o){const e=k+o,a=(await chrome.storage.local.get(e))[e];return!a||Date.now()-a.cachedAt>le?null:a}async function ue(o){const e=k+o.lookupKey;await chrome.storage.local.set({[e]:o})}async function pe(){const o=await chrome.storage.local.get(null),e=Object.keys(o).filter(n=>n.startsWith(k));e.length>0&&await chrome.storage.local.remove(e)}async function ge(o){return D(JSON.stringify(o))}async function he(o){return D(JSON.stringify([...o??[]].sort()))}const ze=Object.freeze(Object.defineProperty({__proto__:null,clearAllCachedAudits:pe,getCachedAudit:ce,hashDisabledRules:he,hashMatrixConfig:ge,setCachedAudit:ue,sha256Hex:D},Symbol.toStringTag,{value:"Module"}));function Ke(o){return{...q,...o??{},enabledChecks:{...q.enabledChecks,...(o==null?void 0:o.enabledChecks)??{}}}}const q={enabled:!1,provider:"anthropic",apiKey:"",costCapUsd:5,model:"",enabledChecks:{altText:!0,headings:!0,sensory:!0,aria:!0,imageOfText:!0,colorOnlyMeaning:!0,genericLinkText:!0,wallOfText:!0,languageMismatch:!0},imageOfTextMaxImages:5,maxCandidatesPerCheck:10},me=U("ai-usage-log"),A="aiUsageLog",R=200;async function Ge(o){try{const e=await E();e.unshift(o),e.length>R&&(e.length=R),await chrome.storage.local.set({[A]:e})}catch(e){me.warn("failed to append ai usage entry",e)}}async function E(){try{const e=(await chrome.storage.local.get(A))[A];return Array.isArray(e)?e:[]}catch{return[]}}function ve(o,e=10){const n=new Date,a=`${n.getUTCFullYear()}-${n.getUTCMonth()}`;let l=0,r=0,t=0;const d={};for(const i of o){l+=i.totalCostUsd,`${new Date(i.at).getUTCFullYear()}-${new Date(i.at).getUTCMonth()}`===a&&(r+=i.totalCostUsd,t++);for(const[c,u]of Object.entries(i.byCheck))u!=null&&(d[c]=(d[c]??0)+u)}return{totalSpentUsd:l,totalAudits:o.length,spentThisMonthUsd:r,auditsThisMonth:t,averageCostUsd:o.length===0?null:l/o.length,byCheck:d,recent:o.slice(0,e)}}async function Be(o=10){const e=await E();return ve(e,o)}async function He(){await chrome.storage.local.remove(A)}export{xe as A,$ as B,Ne as C,w as D,Ee as E,Oe as F,Pe as G,Fe as H,Le as I,Ve as J,D as K,ge as L,he as M,ce as N,ue as O,Ge as P,_e as Q,ze as R,re as T,ie as W,be as a,q as b,pe as c,He as d,T as e,qe as f,ye as g,$e as h,We as i,oe as j,Re as k,Be as l,Se as m,De as n,Ce as o,we as p,Ue as q,Ie as r,Ae as s,ke as t,M as u,ne as v,Me as w,y as x,Te as y,Ke as z};
@@ -1,5 +1,5 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ErrorBoundary-DSKtB-A5.js","assets/styles-DqLxz8Z7.js","assets/_commonjsHelpers-Cpj98o6Y.js","assets/crash-reporter-DAZnNefT.js","assets/ai-usage-log-C9Opn0x0.js","assets/styles-BwnbwQRf.css","assets/scheduled-audit-runner-CF1k2L-G.js","assets/preload-helper-D7HrI6pR.js","assets/diff-CECbooHD.js","assets/design-system-audit-DpxJrxnb.js"])))=>i.map(i=>d[i]);
2
- import{_ as l}from"./preload-helper-D7HrI6pR.js";import{r as v}from"./crash-reporter-DAZnNefT.js";async function C(e){var f,w,y,g;if(e.results.length===0)return;let d;if(e.componentId){const o=await chrome.storage.local.get("igtRuns"),a=((o==null?void 0:o.igtRuns)??{})[e.componentId]??{};d=Object.values(a)}let p,u;const i=((f=e.results[0])==null?void 0:f.pageUrl)??((w=e.results[0])==null?void 0:w.scope)??"";if(i){const{getDismissalsForUrl:o}=await l(async()=>{const{getDismissalsForUrl:t}=await import("./ErrorBoundary-DSKtB-A5.js").then(n=>n.o);return{getDismissalsForUrl:t}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9])),r=await o(i);p=Object.keys(r);const{getResolutionsForPage:a}=await l(async()=>{const{getResolutionsForPage:t}=await import("./scheduled-audit-runner-CF1k2L-G.js").then(n=>n.b6);return{getResolutionsForPage:t}},__vite__mapDeps([6,7,3,8,4])),c=await a(i),x=new Set;for(const t of e.results)for(const n of((y=t.axeRulesEvaluated)==null?void 0:y.incomplete)??[])for(const _ of n.elements??[])x.add(`${n.ruleId}::${_.selector}`);u=c.filter(t=>x.has(`${t.ruleId}::${t.selector}`))}let m;if(e.componentId){const{loadAcknowledgedKeysForComponent:o}=await l(async()=>{const{loadAcknowledgedKeysForComponent:a}=await import("./scheduled-audit-runner-CF1k2L-G.js").then(c=>c.b5);return{loadAcknowledgedKeysForComponent:a}},__vite__mapDeps([6,7,3,8,4])),r=await o(e.componentId);m=r.size>0?Array.from(r):void 0}const b=await v({type:"EXPORT_REQUEST",format:"ai-prompt",results:e.results,delta:e.delta??void 0,manualRuns:d,siteCrawlReport:e.siteCrawlReport??void 0,dismissedKeys:p,incompleteResolutions:u,acknowledgedKeys:m});try{await navigator.clipboard.writeText(b.content)}catch{}const h=`<!doctype html><html><head><meta charset="utf-8"><title>AI fix prompt</title>
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ErrorBoundary-BM308BG8.js","assets/styles-clWOl0K-.js","assets/_commonjsHelpers-Cpj98o6Y.js","assets/crash-reporter-DAZnNefT.js","assets/ai-usage-log-HdIilbbf.js","assets/styles-BwnbwQRf.css","assets/scheduled-audit-runner-DAaEDLPk.js","assets/preload-helper-D7HrI6pR.js","assets/diff-CECbooHD.js","assets/design-system-audit-DpxJrxnb.js"])))=>i.map(i=>d[i]);
2
+ import{_ as l}from"./preload-helper-D7HrI6pR.js";import{r as v}from"./crash-reporter-DAZnNefT.js";async function C(e){var f,w,y,g;if(e.results.length===0)return;let d;if(e.componentId){const o=await chrome.storage.local.get("igtRuns"),a=((o==null?void 0:o.igtRuns)??{})[e.componentId]??{};d=Object.values(a)}let p,u;const i=((f=e.results[0])==null?void 0:f.pageUrl)??((w=e.results[0])==null?void 0:w.scope)??"";if(i){const{getDismissalsForUrl:o}=await l(async()=>{const{getDismissalsForUrl:t}=await import("./ErrorBoundary-BM308BG8.js").then(n=>n.o);return{getDismissalsForUrl:t}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9])),r=await o(i);p=Object.keys(r);const{getResolutionsForPage:a}=await l(async()=>{const{getResolutionsForPage:t}=await import("./scheduled-audit-runner-DAaEDLPk.js").then(n=>n.b6);return{getResolutionsForPage:t}},__vite__mapDeps([6,7,3,8,4])),c=await a(i),x=new Set;for(const t of e.results)for(const n of((y=t.axeRulesEvaluated)==null?void 0:y.incomplete)??[])for(const _ of n.elements??[])x.add(`${n.ruleId}::${_.selector}`);u=c.filter(t=>x.has(`${t.ruleId}::${t.selector}`))}let m;if(e.componentId){const{loadAcknowledgedKeysForComponent:o}=await l(async()=>{const{loadAcknowledgedKeysForComponent:a}=await import("./scheduled-audit-runner-DAaEDLPk.js").then(c=>c.b5);return{loadAcknowledgedKeysForComponent:a}},__vite__mapDeps([6,7,3,8,4])),r=await o(e.componentId);m=r.size>0?Array.from(r):void 0}const b=await v({type:"EXPORT_REQUEST",format:"ai-prompt",results:e.results,delta:e.delta??void 0,manualRuns:d,siteCrawlReport:e.siteCrawlReport??void 0,dismissedKeys:p,incompleteResolutions:u,acknowledgedKeys:m});try{await navigator.clipboard.writeText(b.content)}catch{}const h=`<!doctype html><html><head><meta charset="utf-8"><title>AI fix prompt</title>
3
3
  <style>body{font:14px/1.5 ui-monospace,Menlo,monospace;max-width:920px;margin:24px auto;padding:0 16px;color:#0f172a;}
4
4
  .banner{background:#ecfdf5;border:1px solid #6ee7b7;padding:12px 14px;border-radius:6px;margin-bottom:16px;font-family:system-ui;}
5
5
  pre{white-space:pre-wrap;word-break:break-word;background:#f8fafc;border:1px solid #e2e8f0;padding:14px;border-radius:6px;font-size:13px;}
@@ -1 +1 @@
1
- import"./modulepreload-polyfill-B5Qt9EMX.js";import{c as s,j as e,R as n}from"./styles-DqLxz8Z7.js";import{E as i,u as a,n as l}from"./ErrorBoundary-DSKtB-A5.js";import{i as p,e as m}from"./crash-reporter-DAZnNefT.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./ai-usage-log-C9Opn0x0.js";import"./scheduled-audit-runner-CF1k2L-G.js";import"./preload-helper-D7HrI6pR.js";import"./diff-CECbooHD.js";import"./design-system-audit-DpxJrxnb.js";p("devtools-panel");function c(){const t=a(r=>r.tier);return m(t,"devtoolsPanel")?e.jsx(l,{}):e.jsxs("div",{style:{padding:24,fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif'},children:[e.jsx("h2",{style:{margin:0,fontSize:16,fontWeight:600,color:"#1f2923"},children:"DevTools panel isn’t available on your current plan"}),e.jsx("p",{style:{marginTop:8,fontSize:13,color:"#64748b"},children:"The wcagcheckr DevTools panel is part of a higher-tier plan. The extension’s side panel is still available — open it from the extensions menu."})]})}const o=document.getElementById("root");if(!o)throw new Error("devtools panel: #root not found");s(o).render(e.jsx(n.StrictMode,{children:e.jsx(i,{children:e.jsx(c,{})})}));
1
+ import"./modulepreload-polyfill-B5Qt9EMX.js";import{c as s,j as e,R as n}from"./styles-clWOl0K-.js";import{E as i,u as a,n as l}from"./ErrorBoundary-BM308BG8.js";import{i as p,e as m}from"./crash-reporter-DAZnNefT.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./ai-usage-log-HdIilbbf.js";import"./scheduled-audit-runner-DAaEDLPk.js";import"./preload-helper-D7HrI6pR.js";import"./diff-CECbooHD.js";import"./design-system-audit-DpxJrxnb.js";p("devtools-panel");function c(){const t=a(r=>r.tier);return m(t,"devtoolsPanel")?e.jsx(l,{}):e.jsxs("div",{style:{padding:24,fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif'},children:[e.jsx("h2",{style:{margin:0,fontSize:16,fontWeight:600,color:"#1f2923"},children:"DevTools panel isn’t available on your current plan"}),e.jsx("p",{style:{marginTop:8,fontSize:13,color:"#64748b"},children:"The wcagcheckr DevTools panel is part of a higher-tier plan. The extension’s side panel is still available — open it from the extensions menu."})]})}const o=document.getElementById("root");if(!o)throw new Error("devtools panel: #root not found");s(o).render(e.jsx(n.StrictMode,{children:e.jsx(i,{children:e.jsx(c,{})})}));
@@ -1,4 +1,4 @@
1
- import"./modulepreload-polyfill-B5Qt9EMX.js";import{a as q,R as D,u as z,j as e,b as X,r as i,d as fe,P as U,e as L,f as be,g as $e,h as Ge,i as ge,k as _,y as Be,C as Ke,A as Ve,c as He}from"./styles-DqLxz8Z7.js";import{c as ye,r as T,o as Je,T as Ye,a as ze,s as C,O as Z,b as We,l as qe,g as Qe,d as Xe}from"./crash-reporter-DAZnNefT.js";import{w as Ze,r as et}from"./tier-config-client-CGmK5CXV.js";import{D as tt,A as K,g as st,a as at,s as ee,c as nt,b as V,l as rt,d as ot,e as te}from"./ai-usage-log-C9Opn0x0.js";import{l as lt,s as se,v as it}from"./custom-rules-CAe0nbES.js";import"./_commonjsHelpers-Cpj98o6Y.js";function ct(t){const s=t+"CollectionProvider",[a,r]=q(s),[o,x]=a(s,{collectionRef:{current:null},itemMap:new Map}),c=N=>{const{scope:p,children:u}=N,f=D.useRef(null),y=D.useRef(new Map).current;return e.jsx(o,{scope:p,itemMap:y,collectionRef:f,children:u})};c.displayName=s;const n=t+"CollectionSlot",d=X(n),m=D.forwardRef((N,p)=>{const{scope:u,children:f}=N,y=x(n,u),k=z(p,y.collectionRef);return e.jsx(d,{ref:k,children:f})});m.displayName=n;const l=t+"CollectionItemSlot",h="data-radix-collection-item",b=X(l),g=D.forwardRef((N,p)=>{const{scope:u,children:f,...y}=N,k=D.useRef(null),F=z(p,k),R=x(l,u);return D.useEffect(()=>(R.itemMap.set(k,{ref:k,...y}),()=>void R.itemMap.delete(k))),e.jsx(b,{[h]:"",ref:F,children:f})});g.displayName=l;function j(N){const p=x(t+"CollectionConsumer",N);return D.useCallback(()=>{const f=p.collectionRef.current;if(!f)return[];const y=Array.from(f.querySelectorAll(`[${h}]`));return Array.from(p.itemMap.values()).sort((R,E)=>y.indexOf(R.ref.current)-y.indexOf(E.ref.current))},[p.collectionRef,p.itemMap])}return[{Provider:c,Slot:m,ItemSlot:g},j,r]}var dt=i.createContext(void 0);function ve(t){const s=i.useContext(dt);return t||s||"ltr"}var H="rovingFocusGroup.onEntryFocus",ut={bubbles:!1,cancelable:!0},O="RovingFocusGroup",[W,je,xt]=ct(O),[mt,Ne]=q(O,[xt]),[ht,pt]=mt(O),ke=i.forwardRef((t,s)=>e.jsx(W.Provider,{scope:t.__scopeRovingFocusGroup,children:e.jsx(W.Slot,{scope:t.__scopeRovingFocusGroup,children:e.jsx(ft,{...t,ref:s})})}));ke.displayName=O;var ft=i.forwardRef((t,s)=>{const{__scopeRovingFocusGroup:a,orientation:r,loop:o=!1,dir:x,currentTabStopId:c,defaultCurrentTabStopId:n,onCurrentTabStopIdChange:d,onEntryFocus:m,preventScrollOnEntryFocus:l=!1,...h}=t,b=i.useRef(null),g=z(s,b),j=ve(x),[N,p]=be({prop:c,defaultProp:n??null,onChange:d,caller:O}),[u,f]=i.useState(!1),y=$e(m),k=je(a),F=i.useRef(!1),[R,E]=i.useState(0);return i.useEffect(()=>{const w=b.current;if(w)return w.addEventListener(H,y),()=>w.removeEventListener(H,y)},[y]),e.jsx(ht,{scope:a,orientation:r,dir:j,loop:o,currentTabStopId:N,onItemFocus:i.useCallback(w=>p(w),[p]),onItemShiftTab:i.useCallback(()=>f(!0),[]),onFocusableItemAdd:i.useCallback(()=>E(w=>w+1),[]),onFocusableItemRemove:i.useCallback(()=>E(w=>w-1),[]),children:e.jsx(U.div,{tabIndex:u||R===0?-1:0,"data-orientation":r,...h,ref:g,style:{outline:"none",...t.style},onMouseDown:L(t.onMouseDown,()=>{F.current=!0}),onFocus:L(t.onFocus,w=>{const v=!F.current;if(w.target===w.currentTarget&&v&&!u){const S=new CustomEvent(H,ut);if(w.currentTarget.dispatchEvent(S),!S.defaultPrevented){const A=k().filter(P=>P.focusable),I=A.find(P=>P.active),Me=A.find(P=>P.id===N),Oe=[I,Me,...A].filter(Boolean).map(P=>P.ref.current);Te(Oe,l)}}F.current=!1}),onBlur:L(t.onBlur,()=>f(!1))})})}),Se="RovingFocusGroupItem",we=i.forwardRef((t,s)=>{const{__scopeRovingFocusGroup:a,focusable:r=!0,active:o=!1,tabStopId:x,children:c,...n}=t,d=fe(),m=x||d,l=pt(Se,a),h=l.currentTabStopId===m,b=je(a),{onFocusableItemAdd:g,onFocusableItemRemove:j,currentTabStopId:N}=l;return i.useEffect(()=>{if(r)return g(),()=>j()},[r,g,j]),e.jsx(W.ItemSlot,{scope:a,id:m,focusable:r,active:o,children:e.jsx(U.span,{tabIndex:h?0:-1,"data-orientation":l.orientation,...n,ref:s,onMouseDown:L(t.onMouseDown,p=>{r?l.onItemFocus(m):p.preventDefault()}),onFocus:L(t.onFocus,()=>l.onItemFocus(m)),onKeyDown:L(t.onKeyDown,p=>{if(p.key==="Tab"&&p.shiftKey){l.onItemShiftTab();return}if(p.target!==p.currentTarget)return;const u=yt(p,l.orientation,l.dir);if(u!==void 0){if(p.metaKey||p.ctrlKey||p.altKey||p.shiftKey)return;p.preventDefault();let y=b().filter(k=>k.focusable).map(k=>k.ref.current);if(u==="last")y.reverse();else if(u==="prev"||u==="next"){u==="prev"&&y.reverse();const k=y.indexOf(p.currentTarget);y=l.loop?vt(y,k+1):y.slice(k+1)}setTimeout(()=>Te(y))}}),children:typeof c=="function"?c({isCurrentTabStop:h,hasTabStop:N!=null}):c})})});we.displayName=Se;var bt={ArrowLeft:"prev",ArrowUp:"prev",ArrowRight:"next",ArrowDown:"next",PageUp:"first",Home:"first",PageDown:"last",End:"last"};function gt(t,s){return s!=="rtl"?t:t==="ArrowLeft"?"ArrowRight":t==="ArrowRight"?"ArrowLeft":t}function yt(t,s,a){const r=gt(t.key,a);if(!(s==="vertical"&&["ArrowLeft","ArrowRight"].includes(r))&&!(s==="horizontal"&&["ArrowUp","ArrowDown"].includes(r)))return bt[r]}function Te(t,s=!1){const a=document.activeElement;for(const r of t)if(r===a||(r.focus({preventScroll:s}),document.activeElement!==a))return}function vt(t,s){return t.map((a,r)=>t[(s+r)%t.length])}var jt=ke,Nt=we,B="Tabs",[kt]=q(B,[Ne]),Ce=Ne(),[St,Q]=kt(B),Ee=i.forwardRef((t,s)=>{const{__scopeTabs:a,value:r,onValueChange:o,defaultValue:x,orientation:c="horizontal",dir:n,activationMode:d="automatic",...m}=t,l=ve(n),[h,b]=be({prop:r,onChange:o,defaultProp:x??"",caller:B});return e.jsx(St,{scope:a,baseId:fe(),value:h,onValueChange:b,orientation:c,dir:l,activationMode:d,children:e.jsx(U.div,{dir:l,"data-orientation":c,...m,ref:s})})});Ee.displayName=B;var Ae="TabsList",Ie=i.forwardRef((t,s)=>{const{__scopeTabs:a,loop:r=!0,...o}=t,x=Q(Ae,a),c=Ce(a);return e.jsx(jt,{asChild:!0,...c,orientation:x.orientation,dir:x.dir,loop:r,children:e.jsx(U.div,{role:"tablist","aria-orientation":x.orientation,...o,ref:s})})});Ie.displayName=Ae;var Re="TabsTrigger",_e=i.forwardRef((t,s)=>{const{__scopeTabs:a,value:r,disabled:o=!1,...x}=t,c=Q(Re,a),n=Ce(a),d=De(c.baseId,r),m=Pe(c.baseId,r),l=r===c.value;return e.jsx(Nt,{asChild:!0,...n,focusable:!o,active:l,children:e.jsx(U.button,{type:"button",role:"tab","aria-selected":l,"aria-controls":m,"data-state":l?"active":"inactive","data-disabled":o?"":void 0,disabled:o,id:d,...x,ref:s,onMouseDown:L(t.onMouseDown,h=>{!o&&h.button===0&&h.ctrlKey===!1?c.onValueChange(r):h.preventDefault()}),onKeyDown:L(t.onKeyDown,h=>{[" ","Enter"].includes(h.key)&&c.onValueChange(r)}),onFocus:L(t.onFocus,()=>{const h=c.activationMode!=="manual";!l&&!o&&h&&c.onValueChange(r)})})})});_e.displayName=Re;var Le="TabsContent",Fe=i.forwardRef((t,s)=>{const{__scopeTabs:a,value:r,forceMount:o,children:x,...c}=t,n=Q(Le,a),d=De(n.baseId,r),m=Pe(n.baseId,r),l=r===n.value,h=i.useRef(l);return i.useEffect(()=>{const b=requestAnimationFrame(()=>h.current=!1);return()=>cancelAnimationFrame(b)},[]),e.jsx(Ge,{present:o||l,children:({present:b})=>e.jsx(U.div,{"data-state":l?"active":"inactive","data-orientation":n.orientation,role:"tabpanel","aria-labelledby":d,hidden:!b,id:m,tabIndex:0,...c,ref:s,style:{...t.style,animationDuration:h.current?"0s":void 0},children:b&&x})})});Fe.displayName=Le;function De(t,s){return`${t}-trigger-${s}`}function Pe(t,s){return`${t}-content-${s}`}var wt=Ee,Tt=Ie,Ct=_e,$=Fe;const Et=["default","hover","focus","focus-visible","active","disabled"],At=["light","dark","forced-colors-active","forced-colors-none"],It=["ltr","rtl"];function Rt({value:t,onChange:s}){function a(o,x){return o.includes(x)?o.filter(c=>c!==x):[...o,x]}function r(){const o=t.ariaVariations.length===0?1:t.ariaVariations.length;return t.pseudoStates.length*o*t.themes.length*t.directions.length*t.breakpoints.length}return e.jsxs("div",{className:"space-y-3 border border-slate-200 rounded p-3 bg-white",children:[e.jsx(G,{label:"Pseudo-states",all:Et,selected:t.pseudoStates,onToggle:o=>s({...t,pseudoStates:a(t.pseudoStates,o)})}),e.jsx(G,{label:"Themes",all:At,selected:t.themes,onToggle:o=>s({...t,themes:a(t.themes,o)})}),e.jsx(G,{label:"Directions",all:It,selected:t.directions,onToggle:o=>s({...t,directions:a(t.directions,o)})}),e.jsx(G,{label:"Breakpoints",all:t.breakpointPresets.map(o=>o.id),selected:t.breakpoints,onToggle:o=>s({...t,breakpoints:a(t.breakpoints,o)})}),e.jsxs("p",{className:"text-xs text-slate-500 pt-2 border-t border-slate-100",children:[e.jsx("strong",{children:r()})," audits per component"]})]})}function G({label:t,all:s,selected:a,onToggle:r}){return e.jsxs("div",{children:[e.jsx("div",{className:"text-xs font-medium mb-1.5",children:t}),e.jsx("div",{className:"flex flex-wrap gap-1.5",children:s.map(o=>{const x=a.includes(o);return e.jsx("button",{type:"button",onClick:()=>r(o),className:x?"text-xs px-2 py-1 rounded bg-brand-500 text-white":"text-xs px-2 py-1 rounded bg-slate-100 text-slate-700 hover:bg-slate-200",children:o},o)})})]})}function _t({value:t,onChange:s}){const[a,r]=i.useState(""),[o,x]=i.useState("");function c(m){m.preventDefault();const l=a.trim(),h=o.trim();!l||!h||(s({...t,[l]:h}),r(""),x(""))}function n(m){const l={...t};delete l[m],s(l)}const d=Object.entries(t);return e.jsxs("div",{className:"space-y-3 border border-slate-200 rounded p-3 bg-white",children:[d.length===0?e.jsx("p",{className:"text-xs text-slate-500 italic",children:"no aliases"}):e.jsx("ul",{className:"space-y-1",children:d.map(([m,l])=>e.jsxs("li",{className:"text-xs flex items-center justify-between gap-2 border border-slate-100 rounded p-1.5",children:[e.jsxs("span",{className:"font-mono truncate",title:`${m} → ${l}`,children:[m," ",e.jsx("span",{className:"text-slate-500",children:"→"})," ",l]}),e.jsx("button",{onClick:()=>n(m),className:"text-slate-500 hover:text-red-600 shrink-0","aria-label":`Remove alias ${m}`,children:"×"})]},m))}),e.jsxs("form",{onSubmit:c,className:"grid grid-cols-[1fr_1fr_auto] gap-2 items-end",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-slate-500 mb-1",children:"From"}),e.jsx("input",{type:"text",value:a,onChange:m=>r(m.target.value),placeholder:"https://example.com::testid:btn-a",className:"w-full text-xs border border-slate-300 rounded px-2 py-1 font-mono"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-slate-500 mb-1",children:"Treat as"}),e.jsx("input",{type:"text",value:o,onChange:m=>x(m.target.value),placeholder:"https://example.com::testid:btn-canonical",className:"w-full text-xs border border-slate-300 rounded px-2 py-1 font-mono"})]}),e.jsx("button",{type:"submit",className:"text-xs px-3 py-1 bg-brand-500 text-white rounded disabled:opacity-50",disabled:!a.trim()||!o.trim(),children:"Add"})]})]})}const ae=ye("billing-portal-client"),Lt="https://api.wcagcheckr.com",Ft="wcagcheckr",Dt=15e3;async function Pt(t){const s=`${Lt}/v1/products/${Ft}/billing-portal`;try{const a=await fetch(s,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({licenseToken:t.licenseToken}),signal:AbortSignal.timeout(Dt)}),r=await a.json().catch(()=>null);return a.ok?r!=null&&r.url?{ok:!0,url:r.url}:{ok:!1,error:"malformed response — no url",status:a.status}:(ae.warn(`billing portal HTTP ${a.status}`,r),{ok:!1,status:a.status,error:(r==null?void 0:r.hint)??(r==null?void 0:r.error)??`HTTP ${a.status}`})}catch(a){return ae.warn("billing portal request failed",a),{ok:!1,error:a instanceof Error?a.message:String(a)}}}const ne=ye("subscription-resume-client"),Ut="https://api.wcagcheckr.com",Mt="wcagcheckr",Ot=1e4;async function $t(t){try{const s=await fetch(`${Ut}/v1/products/${Mt}/subscription/resume`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({licenseToken:t.licenseToken}),signal:AbortSignal.timeout(Ot)}),a=await s.json().catch(()=>null);return s.ok?{ok:!0,alreadyActive:(a==null?void 0:a.alreadyActive)===!0}:(ne.warn(`resume http ${s.status}`,a),{ok:!1,status:s.status,error:(a==null?void 0:a.hint)??(a==null?void 0:a.error)??`HTTP ${s.status}`})}catch(s){return ne.warn("resume request failed",s),{ok:!1,error:s instanceof Error?s.message:String(s)}}}const Gt={free:"Free",solo:"Solo",team:"Team"},Bt={free:"Free",solo:"Solo (monthly)","solo-yearly":"Solo (yearly)","solo-single-month":"Solo (single month — non-recurring)",team:"Team (5 seats, monthly)","team-yearly":"Team (5 seats, yearly)","team-15":"Team (15 seats, monthly)","team-15-yearly":"Team (15 seats, yearly)"},Kt=new Set(["solo-single-month"]);function Vt(t){if(!t)return null;const s=new Date(t).getTime()-Date.now();return Number.isFinite(s)?Math.ceil(s/(24*60*60*1e3)):null}function M(t){return t?Bt[t]??t:"—"}function re(t){if(!t)return"no expiry on file";try{return new Date(t).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}catch{return t}}function Ht({tier:t,onTierChange:s}){const[a,r]=i.useState(null),[o,x]=i.useState(null),[c,n]=i.useState(!1),[d,m]=i.useState(""),[l,h]=i.useState(!1),[b,g]=i.useState(null),[j,N]=i.useState(!1),[p,u]=i.useState(!1),f=ge(),y=i.useCallback(async v=>{const A=(await chrome.storage.local.get("licenseToken")).licenseToken??null;if(r(A),!A){x(null);return}try{const I=await T({type:"LICENSE_VALIDATE_REQUEST",token:A,forceRefresh:(v==null?void 0:v.forceRefresh)===!0});x(I)}catch{x(null)}},[]);i.useEffect(()=>(y({forceRefresh:!0}),Je("LICENSE_CHANGED_EVENT",()=>{y()})),[y]);async function k(){if(d.trim()){h(!0),g(null);try{const v=await T({type:"LICENSE_SET_REQUEST",token:d.trim()}),S=await T({type:"LICENSE_VALIDATE_REQUEST",token:d.trim()});if(S.valid&&S.plan){const A=zt(S.plan);s(A);let I=`Activated as ${M(S.plan)}.`;v.seatClaim.ok?v.seatClaim.overCapacity&&(I=`Activated as ${M(S.plan)}. Note: this license is currently OVER its seat cap (${v.seatClaim.seatsUsed} of ${v.seatClaim.seatsTotal} seats). Release one or upgrade.`):v.seatClaim.reason==="cap-reached"?I=`Activated as ${M(S.plan)}, BUT this license is at its seat capacity (${v.seatClaim.seatsUsed} of ${v.seatClaim.seatsTotal} seats used). Release a seat from another device, or upgrade to a higher-seat plan. This device's seat won't be active until you do.`:v.seatClaim.reason==="network"&&(I=`Activated as ${M(S.plan)}. (Seat-tracking ping failed — retrying in the background.)`),g(I),v.seatClaim.ok&&!v.seatClaim.overCapacity?_.polite(I):_.assertive(I),m(""),n(!1),await y()}else{const A="Token did not validate. Check the value and try again.";g(A),_.assertive(A)}}catch(v){const S=v instanceof Error?v.message:String(v);g(S),_.assertive(S)}finally{h(!1)}}}async function F(){if(a)try{await navigator.clipboard.writeText(a),N(!0),setTimeout(()=>N(!1),2e3)}catch{}}async function R(){if(window.confirm(`Remove the active license token from this extension?
1
+ import"./modulepreload-polyfill-B5Qt9EMX.js";import{a as q,R as D,u as z,j as e,b as X,r as i,d as fe,P as U,e as L,f as be,g as $e,h as Ge,i as ge,k as _,y as Be,C as Ke,A as Ve,c as He}from"./styles-clWOl0K-.js";import{c as ye,r as T,o as Je,T as Ye,a as ze,s as C,O as Z,b as We,l as qe,g as Qe,d as Xe}from"./crash-reporter-DAZnNefT.js";import{w as Ze,r as et}from"./tier-config-client-D1GMRTQW.js";import{D as tt,A as K,g as st,a as at,s as ee,c as nt,b as V,l as rt,d as ot,e as te}from"./ai-usage-log-HdIilbbf.js";import{l as lt,s as se,v as it}from"./custom-rules-CAe0nbES.js";import"./_commonjsHelpers-Cpj98o6Y.js";function ct(t){const s=t+"CollectionProvider",[a,r]=q(s),[o,x]=a(s,{collectionRef:{current:null},itemMap:new Map}),c=N=>{const{scope:p,children:u}=N,f=D.useRef(null),y=D.useRef(new Map).current;return e.jsx(o,{scope:p,itemMap:y,collectionRef:f,children:u})};c.displayName=s;const n=t+"CollectionSlot",d=X(n),m=D.forwardRef((N,p)=>{const{scope:u,children:f}=N,y=x(n,u),k=z(p,y.collectionRef);return e.jsx(d,{ref:k,children:f})});m.displayName=n;const l=t+"CollectionItemSlot",h="data-radix-collection-item",b=X(l),g=D.forwardRef((N,p)=>{const{scope:u,children:f,...y}=N,k=D.useRef(null),F=z(p,k),R=x(l,u);return D.useEffect(()=>(R.itemMap.set(k,{ref:k,...y}),()=>void R.itemMap.delete(k))),e.jsx(b,{[h]:"",ref:F,children:f})});g.displayName=l;function j(N){const p=x(t+"CollectionConsumer",N);return D.useCallback(()=>{const f=p.collectionRef.current;if(!f)return[];const y=Array.from(f.querySelectorAll(`[${h}]`));return Array.from(p.itemMap.values()).sort((R,E)=>y.indexOf(R.ref.current)-y.indexOf(E.ref.current))},[p.collectionRef,p.itemMap])}return[{Provider:c,Slot:m,ItemSlot:g},j,r]}var dt=i.createContext(void 0);function ve(t){const s=i.useContext(dt);return t||s||"ltr"}var H="rovingFocusGroup.onEntryFocus",ut={bubbles:!1,cancelable:!0},O="RovingFocusGroup",[W,je,xt]=ct(O),[mt,Ne]=q(O,[xt]),[ht,pt]=mt(O),ke=i.forwardRef((t,s)=>e.jsx(W.Provider,{scope:t.__scopeRovingFocusGroup,children:e.jsx(W.Slot,{scope:t.__scopeRovingFocusGroup,children:e.jsx(ft,{...t,ref:s})})}));ke.displayName=O;var ft=i.forwardRef((t,s)=>{const{__scopeRovingFocusGroup:a,orientation:r,loop:o=!1,dir:x,currentTabStopId:c,defaultCurrentTabStopId:n,onCurrentTabStopIdChange:d,onEntryFocus:m,preventScrollOnEntryFocus:l=!1,...h}=t,b=i.useRef(null),g=z(s,b),j=ve(x),[N,p]=be({prop:c,defaultProp:n??null,onChange:d,caller:O}),[u,f]=i.useState(!1),y=$e(m),k=je(a),F=i.useRef(!1),[R,E]=i.useState(0);return i.useEffect(()=>{const w=b.current;if(w)return w.addEventListener(H,y),()=>w.removeEventListener(H,y)},[y]),e.jsx(ht,{scope:a,orientation:r,dir:j,loop:o,currentTabStopId:N,onItemFocus:i.useCallback(w=>p(w),[p]),onItemShiftTab:i.useCallback(()=>f(!0),[]),onFocusableItemAdd:i.useCallback(()=>E(w=>w+1),[]),onFocusableItemRemove:i.useCallback(()=>E(w=>w-1),[]),children:e.jsx(U.div,{tabIndex:u||R===0?-1:0,"data-orientation":r,...h,ref:g,style:{outline:"none",...t.style},onMouseDown:L(t.onMouseDown,()=>{F.current=!0}),onFocus:L(t.onFocus,w=>{const v=!F.current;if(w.target===w.currentTarget&&v&&!u){const S=new CustomEvent(H,ut);if(w.currentTarget.dispatchEvent(S),!S.defaultPrevented){const A=k().filter(P=>P.focusable),I=A.find(P=>P.active),Me=A.find(P=>P.id===N),Oe=[I,Me,...A].filter(Boolean).map(P=>P.ref.current);Te(Oe,l)}}F.current=!1}),onBlur:L(t.onBlur,()=>f(!1))})})}),Se="RovingFocusGroupItem",we=i.forwardRef((t,s)=>{const{__scopeRovingFocusGroup:a,focusable:r=!0,active:o=!1,tabStopId:x,children:c,...n}=t,d=fe(),m=x||d,l=pt(Se,a),h=l.currentTabStopId===m,b=je(a),{onFocusableItemAdd:g,onFocusableItemRemove:j,currentTabStopId:N}=l;return i.useEffect(()=>{if(r)return g(),()=>j()},[r,g,j]),e.jsx(W.ItemSlot,{scope:a,id:m,focusable:r,active:o,children:e.jsx(U.span,{tabIndex:h?0:-1,"data-orientation":l.orientation,...n,ref:s,onMouseDown:L(t.onMouseDown,p=>{r?l.onItemFocus(m):p.preventDefault()}),onFocus:L(t.onFocus,()=>l.onItemFocus(m)),onKeyDown:L(t.onKeyDown,p=>{if(p.key==="Tab"&&p.shiftKey){l.onItemShiftTab();return}if(p.target!==p.currentTarget)return;const u=yt(p,l.orientation,l.dir);if(u!==void 0){if(p.metaKey||p.ctrlKey||p.altKey||p.shiftKey)return;p.preventDefault();let y=b().filter(k=>k.focusable).map(k=>k.ref.current);if(u==="last")y.reverse();else if(u==="prev"||u==="next"){u==="prev"&&y.reverse();const k=y.indexOf(p.currentTarget);y=l.loop?vt(y,k+1):y.slice(k+1)}setTimeout(()=>Te(y))}}),children:typeof c=="function"?c({isCurrentTabStop:h,hasTabStop:N!=null}):c})})});we.displayName=Se;var bt={ArrowLeft:"prev",ArrowUp:"prev",ArrowRight:"next",ArrowDown:"next",PageUp:"first",Home:"first",PageDown:"last",End:"last"};function gt(t,s){return s!=="rtl"?t:t==="ArrowLeft"?"ArrowRight":t==="ArrowRight"?"ArrowLeft":t}function yt(t,s,a){const r=gt(t.key,a);if(!(s==="vertical"&&["ArrowLeft","ArrowRight"].includes(r))&&!(s==="horizontal"&&["ArrowUp","ArrowDown"].includes(r)))return bt[r]}function Te(t,s=!1){const a=document.activeElement;for(const r of t)if(r===a||(r.focus({preventScroll:s}),document.activeElement!==a))return}function vt(t,s){return t.map((a,r)=>t[(s+r)%t.length])}var jt=ke,Nt=we,B="Tabs",[kt]=q(B,[Ne]),Ce=Ne(),[St,Q]=kt(B),Ee=i.forwardRef((t,s)=>{const{__scopeTabs:a,value:r,onValueChange:o,defaultValue:x,orientation:c="horizontal",dir:n,activationMode:d="automatic",...m}=t,l=ve(n),[h,b]=be({prop:r,onChange:o,defaultProp:x??"",caller:B});return e.jsx(St,{scope:a,baseId:fe(),value:h,onValueChange:b,orientation:c,dir:l,activationMode:d,children:e.jsx(U.div,{dir:l,"data-orientation":c,...m,ref:s})})});Ee.displayName=B;var Ae="TabsList",Ie=i.forwardRef((t,s)=>{const{__scopeTabs:a,loop:r=!0,...o}=t,x=Q(Ae,a),c=Ce(a);return e.jsx(jt,{asChild:!0,...c,orientation:x.orientation,dir:x.dir,loop:r,children:e.jsx(U.div,{role:"tablist","aria-orientation":x.orientation,...o,ref:s})})});Ie.displayName=Ae;var Re="TabsTrigger",_e=i.forwardRef((t,s)=>{const{__scopeTabs:a,value:r,disabled:o=!1,...x}=t,c=Q(Re,a),n=Ce(a),d=De(c.baseId,r),m=Pe(c.baseId,r),l=r===c.value;return e.jsx(Nt,{asChild:!0,...n,focusable:!o,active:l,children:e.jsx(U.button,{type:"button",role:"tab","aria-selected":l,"aria-controls":m,"data-state":l?"active":"inactive","data-disabled":o?"":void 0,disabled:o,id:d,...x,ref:s,onMouseDown:L(t.onMouseDown,h=>{!o&&h.button===0&&h.ctrlKey===!1?c.onValueChange(r):h.preventDefault()}),onKeyDown:L(t.onKeyDown,h=>{[" ","Enter"].includes(h.key)&&c.onValueChange(r)}),onFocus:L(t.onFocus,()=>{const h=c.activationMode!=="manual";!l&&!o&&h&&c.onValueChange(r)})})})});_e.displayName=Re;var Le="TabsContent",Fe=i.forwardRef((t,s)=>{const{__scopeTabs:a,value:r,forceMount:o,children:x,...c}=t,n=Q(Le,a),d=De(n.baseId,r),m=Pe(n.baseId,r),l=r===n.value,h=i.useRef(l);return i.useEffect(()=>{const b=requestAnimationFrame(()=>h.current=!1);return()=>cancelAnimationFrame(b)},[]),e.jsx(Ge,{present:o||l,children:({present:b})=>e.jsx(U.div,{"data-state":l?"active":"inactive","data-orientation":n.orientation,role:"tabpanel","aria-labelledby":d,hidden:!b,id:m,tabIndex:0,...c,ref:s,style:{...t.style,animationDuration:h.current?"0s":void 0},children:b&&x})})});Fe.displayName=Le;function De(t,s){return`${t}-trigger-${s}`}function Pe(t,s){return`${t}-content-${s}`}var wt=Ee,Tt=Ie,Ct=_e,$=Fe;const Et=["default","hover","focus","focus-visible","active","disabled"],At=["light","dark","forced-colors-active","forced-colors-none"],It=["ltr","rtl"];function Rt({value:t,onChange:s}){function a(o,x){return o.includes(x)?o.filter(c=>c!==x):[...o,x]}function r(){const o=t.ariaVariations.length===0?1:t.ariaVariations.length;return t.pseudoStates.length*o*t.themes.length*t.directions.length*t.breakpoints.length}return e.jsxs("div",{className:"space-y-3 border border-slate-200 rounded p-3 bg-white",children:[e.jsx(G,{label:"Pseudo-states",all:Et,selected:t.pseudoStates,onToggle:o=>s({...t,pseudoStates:a(t.pseudoStates,o)})}),e.jsx(G,{label:"Themes",all:At,selected:t.themes,onToggle:o=>s({...t,themes:a(t.themes,o)})}),e.jsx(G,{label:"Directions",all:It,selected:t.directions,onToggle:o=>s({...t,directions:a(t.directions,o)})}),e.jsx(G,{label:"Breakpoints",all:t.breakpointPresets.map(o=>o.id),selected:t.breakpoints,onToggle:o=>s({...t,breakpoints:a(t.breakpoints,o)})}),e.jsxs("p",{className:"text-xs text-slate-500 pt-2 border-t border-slate-100",children:[e.jsx("strong",{children:r()})," audits per component"]})]})}function G({label:t,all:s,selected:a,onToggle:r}){return e.jsxs("div",{children:[e.jsx("div",{className:"text-xs font-medium mb-1.5",children:t}),e.jsx("div",{className:"flex flex-wrap gap-1.5",children:s.map(o=>{const x=a.includes(o);return e.jsx("button",{type:"button",onClick:()=>r(o),className:x?"text-xs px-2 py-1 rounded bg-brand-500 text-white":"text-xs px-2 py-1 rounded bg-slate-100 text-slate-700 hover:bg-slate-200",children:o},o)})})]})}function _t({value:t,onChange:s}){const[a,r]=i.useState(""),[o,x]=i.useState("");function c(m){m.preventDefault();const l=a.trim(),h=o.trim();!l||!h||(s({...t,[l]:h}),r(""),x(""))}function n(m){const l={...t};delete l[m],s(l)}const d=Object.entries(t);return e.jsxs("div",{className:"space-y-3 border border-slate-200 rounded p-3 bg-white",children:[d.length===0?e.jsx("p",{className:"text-xs text-slate-500 italic",children:"no aliases"}):e.jsx("ul",{className:"space-y-1",children:d.map(([m,l])=>e.jsxs("li",{className:"text-xs flex items-center justify-between gap-2 border border-slate-100 rounded p-1.5",children:[e.jsxs("span",{className:"font-mono truncate",title:`${m} → ${l}`,children:[m," ",e.jsx("span",{className:"text-slate-500",children:"→"})," ",l]}),e.jsx("button",{onClick:()=>n(m),className:"text-slate-500 hover:text-red-600 shrink-0","aria-label":`Remove alias ${m}`,children:"×"})]},m))}),e.jsxs("form",{onSubmit:c,className:"grid grid-cols-[1fr_1fr_auto] gap-2 items-end",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-slate-500 mb-1",children:"From"}),e.jsx("input",{type:"text",value:a,onChange:m=>r(m.target.value),placeholder:"https://example.com::testid:btn-a",className:"w-full text-xs border border-slate-300 rounded px-2 py-1 font-mono"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs text-slate-500 mb-1",children:"Treat as"}),e.jsx("input",{type:"text",value:o,onChange:m=>x(m.target.value),placeholder:"https://example.com::testid:btn-canonical",className:"w-full text-xs border border-slate-300 rounded px-2 py-1 font-mono"})]}),e.jsx("button",{type:"submit",className:"text-xs px-3 py-1 bg-brand-500 text-white rounded disabled:opacity-50",disabled:!a.trim()||!o.trim(),children:"Add"})]})]})}const ae=ye("billing-portal-client"),Lt="https://api.wcagcheckr.com",Ft="wcagcheckr",Dt=15e3;async function Pt(t){const s=`${Lt}/v1/products/${Ft}/billing-portal`;try{const a=await fetch(s,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({licenseToken:t.licenseToken}),signal:AbortSignal.timeout(Dt)}),r=await a.json().catch(()=>null);return a.ok?r!=null&&r.url?{ok:!0,url:r.url}:{ok:!1,error:"malformed response — no url",status:a.status}:(ae.warn(`billing portal HTTP ${a.status}`,r),{ok:!1,status:a.status,error:(r==null?void 0:r.hint)??(r==null?void 0:r.error)??`HTTP ${a.status}`})}catch(a){return ae.warn("billing portal request failed",a),{ok:!1,error:a instanceof Error?a.message:String(a)}}}const ne=ye("subscription-resume-client"),Ut="https://api.wcagcheckr.com",Mt="wcagcheckr",Ot=1e4;async function $t(t){try{const s=await fetch(`${Ut}/v1/products/${Mt}/subscription/resume`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({licenseToken:t.licenseToken}),signal:AbortSignal.timeout(Ot)}),a=await s.json().catch(()=>null);return s.ok?{ok:!0,alreadyActive:(a==null?void 0:a.alreadyActive)===!0}:(ne.warn(`resume http ${s.status}`,a),{ok:!1,status:s.status,error:(a==null?void 0:a.hint)??(a==null?void 0:a.error)??`HTTP ${s.status}`})}catch(s){return ne.warn("resume request failed",s),{ok:!1,error:s instanceof Error?s.message:String(s)}}}const Gt={free:"Free",solo:"Solo",team:"Team"},Bt={free:"Free",solo:"Solo (monthly)","solo-yearly":"Solo (yearly)","solo-single-month":"Solo (single month — non-recurring)",team:"Team (5 seats, monthly)","team-yearly":"Team (5 seats, yearly)","team-15":"Team (15 seats, monthly)","team-15-yearly":"Team (15 seats, yearly)"},Kt=new Set(["solo-single-month"]);function Vt(t){if(!t)return null;const s=new Date(t).getTime()-Date.now();return Number.isFinite(s)?Math.ceil(s/(24*60*60*1e3)):null}function M(t){return t?Bt[t]??t:"—"}function re(t){if(!t)return"no expiry on file";try{return new Date(t).toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}catch{return t}}function Ht({tier:t,onTierChange:s}){const[a,r]=i.useState(null),[o,x]=i.useState(null),[c,n]=i.useState(!1),[d,m]=i.useState(""),[l,h]=i.useState(!1),[b,g]=i.useState(null),[j,N]=i.useState(!1),[p,u]=i.useState(!1),f=ge(),y=i.useCallback(async v=>{const A=(await chrome.storage.local.get("licenseToken")).licenseToken??null;if(r(A),!A){x(null);return}try{const I=await T({type:"LICENSE_VALIDATE_REQUEST",token:A,forceRefresh:(v==null?void 0:v.forceRefresh)===!0});x(I)}catch{x(null)}},[]);i.useEffect(()=>(y({forceRefresh:!0}),Je("LICENSE_CHANGED_EVENT",()=>{y()})),[y]);async function k(){if(d.trim()){h(!0),g(null);try{const v=await T({type:"LICENSE_SET_REQUEST",token:d.trim()}),S=await T({type:"LICENSE_VALIDATE_REQUEST",token:d.trim()});if(S.valid&&S.plan){const A=zt(S.plan);s(A);let I=`Activated as ${M(S.plan)}.`;v.seatClaim.ok?v.seatClaim.overCapacity&&(I=`Activated as ${M(S.plan)}. Note: this license is currently OVER its seat cap (${v.seatClaim.seatsUsed} of ${v.seatClaim.seatsTotal} seats). Release one or upgrade.`):v.seatClaim.reason==="cap-reached"?I=`Activated as ${M(S.plan)}, BUT this license is at its seat capacity (${v.seatClaim.seatsUsed} of ${v.seatClaim.seatsTotal} seats used). Release a seat from another device, or upgrade to a higher-seat plan. This device's seat won't be active until you do.`:v.seatClaim.reason==="network"&&(I=`Activated as ${M(S.plan)}. (Seat-tracking ping failed — retrying in the background.)`),g(I),v.seatClaim.ok&&!v.seatClaim.overCapacity?_.polite(I):_.assertive(I),m(""),n(!1),await y()}else{const A="Token did not validate. Check the value and try again.";g(A),_.assertive(A)}}catch(v){const S=v instanceof Error?v.message:String(v);g(S),_.assertive(S)}finally{h(!1)}}}async function F(){if(a)try{await navigator.clipboard.writeText(a),N(!0),setTimeout(()=>N(!1),2e3)}catch{}}async function R(){if(window.confirm(`Remove the active license token from this extension?
2
2
 
3
3
  Your subscription stays active server-side — you can paste the same token back in any time. The extension will fall back to trial / free until then.`)){a&&await ze(a),await chrome.storage.local.remove("licenseToken"),r(null),x(null);try{const S=await T({type:"TIER_GET"});s(S.tier)}catch{s("free")}_.polite("License token removed.")}}const E=Ye[t],w=a!==null&&(o==null?void 0:o.valid)===!0;return e.jsxs("div",{className:"border border-slate-200 rounded p-3 bg-white space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-xs text-slate-500",children:"Current tier"}),e.jsx("span",{className:"text-xs px-2 py-0.5 rounded-full bg-slate-100 text-slate-700",children:Gt[t]})]}),e.jsxs("ul",{className:"text-xs text-slate-600 space-y-1",children:[e.jsxs("li",{children:["Components:"," ",Number.isFinite(E.maxComponents)?E.maxComponents:"unlimited"]}),e.jsxs("li",{children:["Baselines:"," ",Number.isFinite(E.maxBaselines)?E.maxBaselines:"unlimited"]}),e.jsxs("li",{children:["State matrix: ",E.stateMatrix]}),e.jsxs("li",{children:["Storybook auto-iterate: ",E.storybookAutoIterate?"yes":"no"]}),e.jsxs("li",{children:["JSON export: ",E.exportJson?"yes":"no"]}),e.jsxs("li",{children:["SARIF / JUnit export: ",E.exportSarif?"yes":"no"]})]}),w&&o?e.jsx(Jt,{token:a,info:o,copied:j,onCopy:F,onRemove:R,onUseDifferent:()=>n(!0),onManageSubscription:async()=>{const v=await Pt({licenseToken:a});v.ok?window.open(v.url,"_blank","noopener,noreferrer"):(g(`Couldn't open billing portal: ${v.error}`),_.assertive("Could not open billing portal."))},onResumeSubscription:async()=>{const v=await $t({licenseToken:a});if(v.ok){const S=v.alreadyActive?"Subscription was already active — no change needed.":"Subscription resumed. Cancellation has been reversed.";g(S),_.polite(S),await y({forceRefresh:!0})}else g(`Couldn't resume subscription: ${v.error}`),_.assertive("Could not resume subscription.")},onRenew:()=>u(!0),message:b}):a?e.jsx(Yt,{token:a,onRemove:R,onUseDifferent:()=>n(!0)}):e.jsx(oe,{token:d,onTokenChange:m,submitting:l,message:b,onSubmit:k}),w&&c&&e.jsx(oe,{token:d,onTokenChange:m,submitting:l,message:b,onSubmit:k,replacing:!0,onCancel:()=>{n(!1),m(""),g(null)}}),!w&&t==="free"&&e.jsxs("div",{className:"border-t border-slate-100 pt-3 space-y-2",children:[e.jsxs("p",{className:"text-xs text-slate-600",children:[e.jsx("strong",{children:"Solo"}),": $",f.solo.monthlyUsd,"/mo (recurring) ·"," ","$",f.solo.yearlyUsd,"/yr (save"," ",Be(f.solo.monthlyUsd,f.solo.yearlyUsd),"%) ·"," ","$",f.solo.singleMonthUsd," single month (no recurring) · single user."]}),e.jsxs("p",{className:"text-xs text-slate-600",children:[e.jsx("strong",{children:"Team"}),": $",f.team.fiveSeatMonthlyUsd,"/mo for 5 seats ·"," ","$",f.team.fifteenSeatMonthlyUsd,"/mo for 15 seats."]}),e.jsx("button",{type:"button",onClick:()=>u(!0),className:"inline-block text-xs px-3 py-1 bg-brand-500 text-white rounded hover:bg-brand-600",children:"Upgrade →"})]}),e.jsx(Ke,{open:p,onClose:()=>u(!1)})]})}function Jt({token:t,info:s,copied:a,onCopy:r,onRemove:o,onUseDifferent:x,onManageSubscription:c,onResumeSubscription:n,onRenew:d,message:m}){const l=s.features,h=typeof(l==null?void 0:l.seatsUsed)=="number"?l.seatsUsed:null,b=typeof(l==null?void 0:l.seatsTotal)=="number"?l.seatsTotal:null,g=b!==null,j=h!==null&&b!==null&&h>b,N=h!==null&&b!==null&&h===b,p=s.plan?Kt.has(s.plan):!1,u=Vt(s.expiresAt),f=p&&u!==null&&u<=7,y=ge();return e.jsxs("div",{className:"border-t border-slate-100 pt-3 space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs font-medium text-slate-700",children:"Active license"}),e.jsx("span",{className:s.cancelAtPeriodEnd?"text-[10px] px-1.5 py-0.5 rounded-full bg-amber-100 text-amber-900":"text-[10px] px-1.5 py-0.5 rounded-full bg-emerald-100 text-emerald-800",children:s.cancelAtPeriodEnd?"cancellation scheduled":s.status??"unknown"})]}),s.pastDueSince&&e.jsxs("div",{className:"bg-rose-50 border border-rose-200 rounded p-2 text-[11px] text-rose-900",children:[e.jsx("strong",{children:"Payment failed."})," Stripe couldn't charge your card. Access continues during the grace period (usually up to 7 days while Stripe retries), then this license will cancel automatically."," ",e.jsx("button",{type:"button",onClick:c,className:"font-medium underline-offset-2 hover:underline",children:"Update your card via the Stripe portal →"})]}),s.cancelAtPeriodEnd&&e.jsxs("div",{className:"bg-amber-50 border border-amber-200 rounded p-2 text-[11px] text-amber-900 space-y-1",children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Cancellation scheduled."})," Your subscription was cancelled via Stripe. Access continues until ",e.jsx("strong",{children:re(s.expiresAt)}),", then this license stops working."]}),e.jsx("button",{type:"button",onClick:n,className:"text-[11px] font-medium underline-offset-2 hover:underline",children:"Resume subscription →"})]}),j&&e.jsxs("div",{className:"bg-rose-50 border border-rose-200 rounded p-2 text-[11px] text-rose-900",children:[e.jsx("strong",{children:"Over seat capacity."})," This license has"," ",e.jsx("strong",{children:h})," seats in use but the plan only includes"," ",e.jsx("strong",{children:b}),". New devices will be rejected. Release a seat from another device, or upgrade to a higher-seat plan via Manage subscription below."]}),N&&!j&&e.jsxs("div",{className:"bg-amber-50 border border-amber-200 rounded p-2 text-[11px] text-amber-900",children:[e.jsx("strong",{children:"At seat capacity."})," All ",e.jsx("strong",{children:b})," seats are in use. The next new device that tries to activate this license will be rejected until a seat is released."]}),e.jsxs("dl",{className:"text-xs text-slate-600 grid grid-cols-[max-content_1fr] gap-x-3 gap-y-1",children:[e.jsx("dt",{className:"text-slate-500",children:"Plan"}),e.jsx("dd",{children:M(s.plan)}),e.jsx("dt",{className:"text-slate-500",children:"Email"}),e.jsx("dd",{className:"truncate",children:s.email??"—"}),e.jsx("dt",{className:"text-slate-500",children:p?"Expires":"Renews / ends"}),e.jsxs("dd",{children:[re(s.expiresAt),u!==null&&u>=0&&u<=14?e.jsx("span",{className:f?"ml-2 text-[10px] text-amber-900 bg-amber-100 rounded px-1.5 py-0.5":"ml-2 text-[10px] text-slate-500",children:u===0?"today":u===1?"1 day left":`${u} days left`}):null]}),g?e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-slate-500",children:"Seats"}),e.jsx("dd",{children:h!==null?`${h} of ${b} used`:`${b} total`})]}):null]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[11px] font-medium text-slate-500 mb-1",children:"Token"}),e.jsxs("div",{className:"flex items-stretch gap-1",children:[e.jsx("code",{className:"flex-1 font-mono text-[11px] bg-slate-100 border border-slate-200 rounded px-2 py-1.5 select-all break-all",children:t}),e.jsx("button",{type:"button",onClick:r,className:"text-[11px] px-2 py-1.5 border border-slate-300 rounded bg-white hover:bg-slate-50 shrink-0",children:a?"Copied ✓":"Copy"})]})]}),e.jsx("div",{className:"pt-1 flex flex-wrap gap-2",children:p?e.jsx("button",{type:"button",onClick:d,className:f?"text-xs px-3 py-1.5 bg-amber-500 text-white rounded hover:bg-amber-600":"text-xs px-3 py-1.5 bg-brand-500 text-white rounded hover:bg-brand-600",title:"Buy another month — extends your existing license, no new token to copy",children:f?`Renew now — $${y.solo.singleMonthUsd} →`:`Buy another month — $${y.solo.singleMonthUsd} →`}):e.jsx("button",{type:"button",onClick:c,className:"text-xs px-3 py-1.5 bg-brand-500 text-white rounded hover:bg-brand-600",title:"Open Stripe's billing portal — change plan or seat count, update card, view invoices, cancel",children:"Manage subscription →"})}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 pt-1",children:[e.jsx("button",{type:"button",onClick:x,className:"text-[11px] text-brand-600 hover:underline",children:"Use a different token"}),e.jsx("span",{className:"text-slate-300","aria-hidden":"true",children:"·"}),e.jsx("button",{type:"button",onClick:o,className:"text-[11px] text-rose-700 hover:underline",children:"Remove license from this extension"})]}),m&&e.jsx("p",{className:"text-xs text-slate-600 pt-1",children:m})]})}function Yt({token:t,onRemove:s,onUseDifferent:a}){return e.jsxs("div",{className:"border-t border-rose-100 pt-3 space-y-2 bg-rose-50/40 -mx-3 px-3 pb-2 rounded-b",children:[e.jsxs("p",{className:"text-xs text-rose-800",children:[e.jsx("strong",{children:"License token rejected by the server."})," The token may have been revoked, the subscription canceled, or the network is down. Verify your subscription and try a different token — or remove this one and continue on the trial / free tier."]}),e.jsx("p",{className:"text-[11px] text-rose-700 font-mono break-all",children:t}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("button",{type:"button",onClick:a,className:"text-[11px] text-brand-600 hover:underline",children:"Use a different token"}),e.jsx("span",{className:"text-slate-300","aria-hidden":"true",children:"·"}),e.jsx("button",{type:"button",onClick:s,className:"text-[11px] text-rose-700 hover:underline",children:"Remove and continue without a license"})]})]})}function oe({token:t,onTokenChange:s,submitting:a,message:r,onSubmit:o,replacing:x,onCancel:c}){return e.jsxs("div",{className:"border-t border-slate-100 pt-3 space-y-2",children:[e.jsx("label",{htmlFor:"opt-license-token",className:"block text-xs font-medium",children:x?"Replace with a different token":"Activate license token"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("input",{id:"opt-license-token",type:"text",value:t,onChange:n=>s(n.target.value),placeholder:"00000000-0000-0000-0000-000000000000",className:"flex-1 text-xs border border-slate-300 rounded px-2 py-1 font-mono"}),e.jsx("button",{onClick:o,disabled:a||!t.trim(),className:"text-xs px-3 py-1 bg-brand-500 text-white rounded disabled:opacity-50",children:a?"Validating…":x?"Replace":"Activate"}),x&&c&&e.jsx("button",{type:"button",onClick:c,className:"text-xs px-3 py-1 border border-slate-300 rounded text-slate-700 hover:bg-slate-50",children:"Cancel"})]}),r&&e.jsx("p",{className:"text-xs text-slate-600",children:r})]})}function zt(t){return t==="solo"||t==="solo-yearly"||t==="solo-single-month"?"solo":t==="team"||t==="team-15"||t==="team-yearly"||t==="team-15-yearly"?"team":"free"}const Wt=new Set(tt.map(t=>t.id));function qt({presets:t,onChange:s}){const[a,r]=i.useState({id:"",label:"",width:1024,height:768,deviceScaleFactor:1,mobile:!1});function o(n){n.preventDefault();const d=a.id.trim();!d||t.some(m=>m.id===d)||(s([...t,{...a,id:d,label:a.label.trim()||`${d} (${a.width}×${a.height})`}]),r({id:"",label:"",width:1024,height:768,deviceScaleFactor:1,mobile:!1}))}function x(n){s(t.filter(d=>d.id!==n))}function c(n,d){s(t.map(m=>m.id===n?{...m,...d}:m))}return e.jsxs("div",{className:"space-y-3 border border-slate-200 rounded p-3 bg-white",children:[t.length===0?e.jsx("p",{className:"text-xs text-slate-500 italic",children:"no breakpoints"}):e.jsx("ul",{className:"space-y-1.5",children:t.map(n=>{const d=Wt.has(n.id);return e.jsxs("li",{className:"grid grid-cols-[1fr_70px_70px_auto_auto] gap-2 items-center text-xs",children:[e.jsxs("span",{className:"font-medium truncate",title:n.id,children:[n.label,d&&e.jsx("span",{className:"text-slate-500 font-normal ml-1",children:"(default)"})]}),e.jsx("input",{type:"number",value:n.width,onChange:m=>c(n.id,{width:Number(m.target.value)||0}),className:"text-xs border border-slate-300 rounded px-1.5 py-1 w-full","aria-label":`Width for ${n.label}`,min:1}),e.jsx("input",{type:"number",value:n.height,onChange:m=>c(n.id,{height:Number(m.target.value)||0}),className:"text-xs border border-slate-300 rounded px-1.5 py-1 w-full","aria-label":`Height for ${n.label}`,min:1}),e.jsxs("label",{className:"flex items-center gap-1 text-slate-600",children:[e.jsx("input",{type:"checkbox",checked:n.mobile,onChange:m=>c(n.id,{mobile:m.target.checked})}),"mobile"]}),d?e.jsx("span",{className:"w-4","aria-hidden":"true"}):e.jsx("button",{onClick:()=>x(n.id),className:"text-slate-500 hover:text-red-600","aria-label":`Remove ${n.label}`,children:"×"})]},n.id)})}),e.jsxs("form",{onSubmit:o,className:"grid grid-cols-[1fr_1fr_70px_70px_auto] gap-2 items-end pt-3 border-t border-slate-100",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"bp-draft-id",className:"block text-xs text-slate-500 mb-1",children:"ID"}),e.jsx("input",{id:"bp-draft-id",type:"text",value:a.id,onChange:n=>r({...a,id:n.target.value}),placeholder:"laptop",className:"w-full text-xs border border-slate-300 rounded px-2 py-1"})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"bp-draft-label",className:"block text-xs text-slate-500 mb-1",children:"Label"}),e.jsx("input",{id:"bp-draft-label",type:"text",value:a.label,onChange:n=>r({...a,label:n.target.value}),placeholder:"Laptop (1440×900)",className:"w-full text-xs border border-slate-300 rounded px-2 py-1"})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"bp-draft-width",className:"block text-xs text-slate-500 mb-1",children:"W"}),e.jsx("input",{id:"bp-draft-width",type:"number",value:a.width,onChange:n=>r({...a,width:Number(n.target.value)||0}),min:1,className:"w-full text-xs border border-slate-300 rounded px-1.5 py-1"})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"bp-draft-height",className:"block text-xs text-slate-500 mb-1",children:"H"}),e.jsx("input",{id:"bp-draft-height",type:"number",value:a.height,onChange:n=>r({...a,height:Number(n.target.value)||0}),min:1,className:"w-full text-xs border border-slate-300 rounded px-1.5 py-1"})]}),e.jsx("button",{type:"submit",disabled:!a.id.trim()||t.some(n=>n.id===a.id.trim()),className:"text-xs px-3 py-1 bg-brand-500 text-white rounded disabled:opacity-50",children:"Add"})]})]})}function Qt({stateMatrix:t,componentIdAliases:s,onImport:a}){const r=i.useRef(null),[o,x]=i.useState(null);function c(){const d={schemaVersion:1,exportedAt:new Date().toISOString(),stateMatrix:t,componentIdAliases:s},m=new Blob([JSON.stringify(d,null,2)],{type:"application/json"}),l=URL.createObjectURL(m),h=document.createElement("a");h.href=l,h.download=`wcag-auditor-settings-${new Date().toISOString().slice(0,10)}.json`,h.click(),URL.revokeObjectURL(l),x("Exported.")}async function n(d){var m,l;x(null);try{const h=await d.text(),b=JSON.parse(h);if(b.schemaVersion!==1)throw new Error(`Unsupported schemaVersion: ${b.schemaVersion}`);if(!((m=b.stateMatrix)!=null&&m.pseudoStates)||!((l=b.stateMatrix)!=null&&l.breakpointPresets))throw new Error("stateMatrix is malformed");await C({type:"SETTINGS_SET",key:"stateMatrix",value:b.stateMatrix}),await C({type:"SETTINGS_SET",key:"componentIdAliases",value:b.componentIdAliases??{}}),a({stateMatrix:b.stateMatrix,componentIdAliases:b.componentIdAliases??{}}),x("Imported.")}catch(h){x(`Import failed: ${h instanceof Error?h.message:String(h)}`)}}return e.jsxs("div",{className:"border border-slate-200 rounded p-3 bg-white space-y-2",children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{onClick:c,className:"text-xs px-3 py-1 bg-slate-100 hover:bg-slate-200 rounded",children:"Export settings"}),e.jsx("button",{onClick:()=>{var d;return(d=r.current)==null?void 0:d.click()},className:"text-xs px-3 py-1 bg-slate-100 hover:bg-slate-200 rounded",children:"Import settings…"}),e.jsx("input",{ref:r,type:"file",accept:"application/json,.json",className:"hidden",onChange:d=>{var l;const m=(l=d.target.files)==null?void 0:l[0];m&&n(m),d.target.value=""}})]}),o&&e.jsx("p",{className:"text-xs text-slate-600",children:o})]})}function Xt(){const[t,s]=i.useState(null);i.useEffect(()=>{chrome.storage.local.get(Z).then(r=>s(r[Z]===!0))},[]);async function a(){const r=!t;s(r),await We(r)}return t===null?e.jsx("p",{className:"text-xs text-slate-500",children:"Loading…"}):e.jsx("div",{className:"border border-slate-200 rounded p-3 bg-white space-y-2",children:e.jsxs("label",{className:"flex items-start gap-2 text-xs cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:t,onChange:a,className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium",children:"Send anonymized crash reports"}),e.jsx("span",{className:"block text-slate-500 mt-0.5",children:"When the extension hits an unexpected error, send the error message + redacted stack trace + extension version. URLs, emails, and license tokens are stripped before sending. No audit data, page content, or browsing history is included."})]})]})})}function Zt(){const[t,s]=i.useState(null);i.useEffect(()=>{chrome.storage.local.get(K).then(r=>s(r[K]===!0))},[]);async function a(){const r=!t;s(r),await chrome.storage.local.set({[K]:r})}return t===null?e.jsx("p",{className:"text-xs text-slate-500",children:"Loading…"}):e.jsx("div",{className:"border border-slate-200 rounded p-3 bg-white space-y-2",children:e.jsxs("label",{className:"flex items-start gap-2 text-xs cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:t,onChange:a,className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium",children:"Skip the download confirmation"}),e.jsx("span",{className:"block text-slate-500 mt-0.5",children:"By default, generating a defense or evidence bundle pops up a small confirmation asking whether to download or preview. Enable this to skip the prompt and have the file land directly in your Downloads folder. Keep it off if you'd rather decide each time (recommended for non-technical users — surprise downloads can be alarming)."})]})]})})}const es={"deposition-packet":{name:"Deposition packet",description:"Court-grade HTML with VPS-anchored RFC 3161 timestamp. Use for active litigation / regulatory submission."},"defense-bundle":{name:"Defense bundle",description:"Locally anchored attorney-ready HTML. The everyday remediation-trail artifact — exec summary, findings, screenshots, VPAT, methodology. Recommended baseline."},"html-print":{name:"Printable HTML",description:"Simple print-ready HTML for sharing with stakeholders. No anchoring, no legal framing — just the findings."},"ai-prompt":{name:"AI fix prompt (markdown)",description:"Markdown prompt for Claude / Cursor / Copilot Chat. Includes fix recipes per violation + acknowledged-findings context. Use for dev handoff after each audit."}};function ts(){const[t,s]=i.useState(null);if(i.useEffect(()=>{let o=!1;return(async()=>{const x=await st();o||s(x)})(),()=>{o=!0}},[]),!t)return e.jsx("p",{className:"text-xs text-slate-500",children:"Loading…"});async function a(){const o={...t,enabled:!t.enabled};s(o),await ee(o)}async function r(o){const x=t.formats.includes(o);let c;x?(c=t.formats.filter(d=>d!==o),c.length===0&&t.enabled&&(c=t.formats)):c=[...t.formats,o];const n={...t,formats:c};s(n),await ee(n)}return e.jsxs("div",{className:"border border-slate-200 rounded p-3 bg-white space-y-3",children:[e.jsxs("label",{className:"flex items-start gap-2 text-xs cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:t.enabled,onChange:()=>void a(),className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium",children:"Auto-export every audit"}),e.jsxs("span",{className:"block text-slate-500 mt-0.5",children:["Each completed audit silently downloads the formats checked below. Same setting applies to both manual and scheduled audits. Scheduled audits land in ",e.jsx("span",{className:"font-mono",children:"Downloads/wcagcheckr/{domain}/"}),"; scheduled audits only fire while Chrome is running."]})]})]}),t.enabled&&e.jsxs("fieldset",{className:"pl-6 space-y-2",children:[e.jsx("legend",{className:"text-xs font-medium text-slate-700",children:"Formats to export"}),at.map(o=>{const x=t.formats.includes(o),c=es[o];return e.jsxs("label",{className:"flex items-start gap-2 text-xs cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:x,onChange:()=>void r(o),className:"mt-0.5"}),e.jsxs("span",{className:"leading-snug",children:[e.jsx("span",{className:"font-medium",children:c.name}),e.jsx("span",{className:"block text-slate-500 mt-0.5",children:c.description})]})]},o)})]})]})}function ss(){const[t,s]=i.useState(null),[a,r]=i.useState(!1);async function o(){const c=await chrome.storage.local.get(null),n=Object.keys(c).filter(d=>d.startsWith("auditCache:"));s(n.length)}i.useEffect(()=>{o()},[]);async function x(){r(!0);try{await nt(),await o()}finally{r(!1)}}return e.jsxs("div",{className:"border border-slate-200 rounded p-3 bg-white space-y-2",children:[e.jsxs("div",{className:"text-xs",children:[e.jsx("span",{className:"font-medium",children:"Audit cache"}),e.jsx("span",{className:"block text-slate-500 mt-0.5",children:"Repeat audits of the same component skip the state-matrix iteration when the DOM is unchanged from the last audit (10-50× faster). The fingerprint is DOM-only — if you change ONLY CSS, the cache won't notice and will return stale results. Clear it here when that happens."})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:x,disabled:a||(t??0)===0,className:"text-xs px-3 py-1 bg-slate-100 hover:bg-slate-200 disabled:opacity-50 disabled:cursor-not-allowed border border-slate-300 rounded",children:a?"Clearing…":"Clear audit cache"}),e.jsx("span",{className:"text-xs text-slate-500",children:t===null?"Loading…":t===0?"Cache is empty.":`${t} cached audit${t===1?"":"s"}.`})]})]})}const le="licenseToken";function ie(t){const s=Date.now()-new Date(t).getTime(),a=Math.floor(s/6e4);if(a<1)return"just now";if(a<60)return`${a} min ago`;const r=Math.floor(a/60);if(r<24)return`${r}h ago`;const o=Math.floor(r/24);return o<30?`${o}d ago`:new Date(t).toLocaleDateString()}function as(t){return t.slice(0,8)+"…"}function ns(t){return t?/Edg\//.test(t)?"Edge":/Chrome\//.test(t)?"Chrome":/Firefox\//.test(t)?"Firefox":/Safari\//.test(t)?"Safari":t.slice(0,30):"unknown"}function rs(){const[t,s]=i.useState(null),[a,r]=i.useState(null),[o,x]=i.useState(null),[c,n]=i.useState(0),[d,m]=i.useState(null),[l,h]=i.useState(!1),[b,g]=i.useState(null),j=i.useCallback(async()=>{h(!0),g(null);try{const u=(await chrome.storage.local.get(le))[le]??null;if(s(u),!u){r(null);return}const f=await qe(u);if(!f){g("Could not load seats — check network or license validity.");return}r(f.seats),x(f.seatsTotal),n(f.seatsUsed),m(await Qe())}finally{h(!1)}},[]);i.useEffect(()=>{j()},[j]);async function N(p){if(!t)return;const f=p===d?"Revoke THIS device? You will have to re-claim a seat on the next audit (if a seat is available).":"Revoke this seat? The device will be denied audits until it re-claims a seat (subject to the seat cap).";if(window.confirm(f)){h(!0);try{if(!await Xe(t,p)){g("Revoke failed — try again or check network.");return}await j()}finally{h(!1)}}}return t?o===null?e.jsx("div",{className:"text-xs text-slate-500",children:"This license has no seat cap (Solo / single-month / free / trial). Upgrade to a Team plan to see and manage seats here."}):e.jsxs("div",{className:"border border-slate-200 rounded p-3 bg-white space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"text-xs",children:[e.jsx("span",{className:"font-medium",children:"Team seats"}),e.jsxs("span",{className:"text-slate-500 ml-2",children:[c," of ",o," used",c>o&&e.jsx("span",{className:"ml-2 text-amber-700",children:"(over capacity — release to bring under limit)"})]})]}),e.jsx("button",{onClick:j,disabled:l,className:"text-xs px-2 py-0.5 border border-slate-300 rounded hover:bg-slate-50 disabled:opacity-50",children:l?"Loading…":"Refresh"})]}),b&&e.jsx("p",{className:"text-xs text-red-700",children:b}),a&&a.length>0?e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-left text-slate-500",children:[e.jsx("th",{className:"font-normal py-1",children:"Device"}),e.jsx("th",{className:"font-normal py-1",children:"Browser"}),e.jsx("th",{className:"font-normal py-1",children:"Claimed"}),e.jsx("th",{className:"font-normal py-1",children:"Last active"}),e.jsx("th",{className:"font-normal py-1"})]})}),e.jsx("tbody",{children:a.map(p=>e.jsxs("tr",{className:"border-t border-slate-100",children:[e.jsxs("td",{className:"py-1",children:[e.jsx("code",{className:"text-[10px] text-slate-600",children:as(p.deviceId)}),p.deviceId===d&&e.jsx("span",{className:"ml-1 text-[10px] text-brand-700",children:"(this device)"})]}),e.jsx("td",{className:"py-1 text-slate-700",children:ns(p.userAgent)}),e.jsx("td",{className:"py-1 text-slate-500",children:ie(p.claimedAt)}),e.jsx("td",{className:"py-1 text-slate-500",children:ie(p.lastSeenAt)}),e.jsx("td",{className:"py-1 text-right",children:e.jsx("button",{onClick:()=>N(p.deviceId),disabled:l,className:"text-[11px] px-2 py-0.5 border border-slate-300 rounded hover:bg-red-50 hover:text-red-800 hover:border-red-300 disabled:opacity-50",children:"Revoke"})})]},p.deviceId))})]}):e.jsx("p",{className:"text-xs text-slate-500",children:"No seats claimed yet."})]}):e.jsx("div",{className:"text-xs text-slate-500",children:"Activate a Team license to manage seats here."})}const os=[{id:"use-our-button",description:"Use the design-system Button, not raw <button>.",impact:"moderate",selector:"button:not([data-component='Button']):not([data-component^='ds-'])",check:{type:"fail-on-match",message:"Replace raw <button> with the design-system Button component."},enabled:!0},{id:"no-inline-styles",description:"Inline style attribute escapes the design tokens.",impact:"minor",selector:"[style]",check:{type:"fail-on-match",message:"Move this style into a design-token-aware CSS class."},enabled:!0},{id:"cta-needs-testid",description:"Every call-to-action button must have data-testid for E2E.",impact:"serious",selector:'button.cta, [data-component="Button"][data-variant="primary"]',check:{type:"attribute-required",attribute:"data-testid",message:"Add a data-testid attribute so QA can target this element."},enabled:!1}];function ls(){const[t,s]=i.useState(""),[a,r]=i.useState([]),[o,x]=i.useState(!1),[c,n]=i.useState(null);i.useEffect(()=>{lt().then(l=>{s(l.length>0?JSON.stringify(l,null,2):""),x(!0)})},[]);function d(){if(t.trim().length===0){se([]),r([]),n(Date.now());return}let l;try{l=JSON.parse(t)}catch(g){r([`Invalid JSON: ${g instanceof Error?g.message:String(g)}`]);return}const{valid:h,errors:b}=it(l);if(b.length>0){r(b);return}r([]),se(h),n(Date.now()),s(JSON.stringify(h,null,2))}function m(){s(JSON.stringify(os,null,2)),r([])}return o?e.jsxs("div",{className:"space-y-2",children:[e.jsxs("p",{className:"text-xs text-slate-500",children:["Custom rules check your design-system contracts during every audit. Three check types supported:"," ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"fail-on-match"})," (every element matching the selector is a violation),"," ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"attribute-required"})," ","(the named attribute must be present), and"," ",e.jsx("code",{className:"bg-slate-100 px-1 rounded",children:"attribute-equals"})," ","(attribute must equal a specific value). Output appears in audit results alongside built-in WCAG rules."]}),e.jsx("textarea",{value:t,onChange:l=>s(l.target.value),rows:14,spellCheck:!1,placeholder:"[]",className:"w-full text-xs font-mono border border-slate-300 rounded p-2 resize-y"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:d,className:"text-xs px-3 py-1 bg-brand-500 text-white rounded hover:bg-brand-600",children:"Save"}),e.jsx("button",{onClick:m,className:"text-xs px-3 py-1 border border-slate-300 rounded hover:bg-slate-50",children:"Load example rules"}),c&&a.length===0&&e.jsxs("span",{className:"text-[11px] text-slate-500",children:["Saved at ",new Date(c).toLocaleTimeString(),"."]})]}),a.length>0&&e.jsx("div",{className:"border border-red-200 bg-red-50 rounded p-2 text-xs text-red-800 space-y-1",children:a.map((l,h)=>e.jsx("div",{children:l},h))})]}):e.jsx("div",{className:"text-xs text-slate-500",children:"Loading…"})}const ce="disabledRules";function is(){const[t,s]=i.useState(""),[a,r]=i.useState(!1),[o,x]=i.useState(null);i.useEffect(()=>{T({type:"SETTINGS_GET",key:ce}).then(n=>{const d=Array.isArray(n.data)?n.data:[];s(d.join(`
4
4
  `)),r(!0)})},[]);function c(n){const d=n.split(`
@@ -1 +1 @@
1
- import{b0 as p,b1 as g,b2 as $,b3 as v}from"./scheduled-audit-runner-CF1k2L-G.js";import{k as w,c as E,h as T}from"./crash-reporter-DAZnNefT.js";import"./preload-helper-D7HrI6pR.js";import"./diff-CECbooHD.js";import"./ai-usage-log-C9Opn0x0.js";const m=E("parallel-tab-flow");async function _(s){const n=performance.now(),a=p(s.matrix),o=Math.max(1,Math.min(s.parallelism??4,8)),i=[];for(let e=0;e<o;e++)i.push([]);a.forEach((e,b)=>{i[b%o].push(e)}),m.info(`parallel-tab audit starting: ${a.length} states across ${o} tabs (~${Math.ceil(a.length/o)} states/tab)`);const r=a.length;let t=0;a[0]&&w({type:"AUDIT_PROGRESS_EVENT",current:0,total:r,currentState:a[0]});const l=e=>{t++,w({type:"AUDIT_PROGRESS_EVENT",current:t,total:r,currentState:e})},d=i.map((e,b)=>e.length===0?Promise.resolve({results:[],failed:!1}):y(s.targetUrl,s.scope,e,b,s.cancel,l)),h=await Promise.all(d),c=[];let u=0,f=0;for(const e of h)e.failed?f++:u++,c.push(...e.results);return{results:c,parallelDurationMs:performance.now()-n,tabsCompleted:u,tabsFailed:f}}async function y(s,n,a,o,i,r){let t;const l=[];try{const d=await chrome.tabs.create({url:s,active:!1});if(!d.id)throw new Error("chrome.tabs.create returned no id");if(t=d.id,m.debug(`worker ${o}: opened tab ${t}`),await U(t),i.isCanceled())throw new Error("canceled");const h=await g(t,0);if(!h.ok)throw new Error(`content script unreachable: ${h.reason}`);for(let c=0;c<a.length&&!i.isCanceled();c++){const u=a[c];try{if(!(await $(t,u,n)).success){m.warn(`worker ${o} state ${c+1}/${a.length} drive failed`),r==null||r(u);continue}const e=await T(t,{type:"AUDIT_REQUEST",selector:n,currentState:u});e.success&&e.result&&l.push({...e.result,violations:e.result.violations})}catch(f){m.debug(`worker ${o} state ${c+1} error`,f)}finally{r==null||r(u)}}try{await v(t,n)}catch{}return{results:l,failed:!1}}catch(d){return m.warn(`worker ${o} failed`,d),{results:l,failed:!0}}finally{if(t!==void 0)try{await chrome.tabs.remove(t)}catch{}}}function U(s,n=3e4){return new Promise((a,o)=>{const i=setTimeout(()=>{chrome.tabs.onUpdated.removeListener(r),o(new Error(`tab ${s} load timed out after ${n}ms`))},n),r=(t,l)=>{t===s&&l.status==="complete"&&(clearTimeout(i),chrome.tabs.onUpdated.removeListener(r),a())};chrome.tabs.onUpdated.addListener(r),chrome.tabs.get(s).then(t=>{t.status==="complete"&&(clearTimeout(i),chrome.tabs.onUpdated.removeListener(r),a())})})}export{_ as runParallelTabAudit};
1
+ import{b0 as p,b1 as g,b2 as $,b3 as v}from"./scheduled-audit-runner-DAaEDLPk.js";import{k as w,c as E,h as T}from"./crash-reporter-DAZnNefT.js";import"./preload-helper-D7HrI6pR.js";import"./diff-CECbooHD.js";import"./ai-usage-log-HdIilbbf.js";const m=E("parallel-tab-flow");async function _(s){const n=performance.now(),a=p(s.matrix),o=Math.max(1,Math.min(s.parallelism??4,8)),i=[];for(let e=0;e<o;e++)i.push([]);a.forEach((e,b)=>{i[b%o].push(e)}),m.info(`parallel-tab audit starting: ${a.length} states across ${o} tabs (~${Math.ceil(a.length/o)} states/tab)`);const r=a.length;let t=0;a[0]&&w({type:"AUDIT_PROGRESS_EVENT",current:0,total:r,currentState:a[0]});const l=e=>{t++,w({type:"AUDIT_PROGRESS_EVENT",current:t,total:r,currentState:e})},d=i.map((e,b)=>e.length===0?Promise.resolve({results:[],failed:!1}):y(s.targetUrl,s.scope,e,b,s.cancel,l)),h=await Promise.all(d),c=[];let u=0,f=0;for(const e of h)e.failed?f++:u++,c.push(...e.results);return{results:c,parallelDurationMs:performance.now()-n,tabsCompleted:u,tabsFailed:f}}async function y(s,n,a,o,i,r){let t;const l=[];try{const d=await chrome.tabs.create({url:s,active:!1});if(!d.id)throw new Error("chrome.tabs.create returned no id");if(t=d.id,m.debug(`worker ${o}: opened tab ${t}`),await U(t),i.isCanceled())throw new Error("canceled");const h=await g(t,0);if(!h.ok)throw new Error(`content script unreachable: ${h.reason}`);for(let c=0;c<a.length&&!i.isCanceled();c++){const u=a[c];try{if(!(await $(t,u,n)).success){m.warn(`worker ${o} state ${c+1}/${a.length} drive failed`),r==null||r(u);continue}const e=await T(t,{type:"AUDIT_REQUEST",selector:n,currentState:u});e.success&&e.result&&l.push({...e.result,violations:e.result.violations})}catch(f){m.debug(`worker ${o} state ${c+1} error`,f)}finally{r==null||r(u)}}try{await v(t,n)}catch{}return{results:l,failed:!1}}catch(d){return m.warn(`worker ${o} failed`,d),{results:l,failed:!0}}finally{if(t!==void 0)try{await chrome.tabs.remove(t)}catch{}}}function U(s,n=3e4){return new Promise((a,o)=>{const i=setTimeout(()=>{chrome.tabs.onUpdated.removeListener(r),o(new Error(`tab ${s} load timed out after ${n}ms`))},n),r=(t,l)=>{t===s&&l.status==="complete"&&(clearTimeout(i),chrome.tabs.onUpdated.removeListener(r),a())};chrome.tabs.onUpdated.addListener(r),chrome.tabs.get(s).then(t=>{t.status==="complete"&&(clearTimeout(i),chrome.tabs.onUpdated.removeListener(r),a())})})}export{_ as runParallelTabAudit};
@@ -1 +1 @@
1
- import{m as t,n as i,o as e,aW as n}from"./scheduled-audit-runner-CF1k2L-G.js";import{c as o}from"./crash-reporter-DAZnNefT.js";const c=o("rubric-config-client"),f="wcagcheckr",u=`https://api.wcagcheckr.com/v1/products/${f}/rubrics`,h=1e4,s="rubric-config-refresh",d=60;async function R(){const r=await t();if(!r){e(null);return}if(i(r)==="expired"){c.warn("cached rubrics are expired (>7d); falling back to bundled defaults"),e(null);return}e(r.config)}async function g(){try{const r=await fetch(u,{signal:AbortSignal.timeout(h),headers:{accept:"application/json"}});if(!r.ok)throw new Error(`http ${r.status}`);const a=await r.json();await n({fetchedAt:Date.now(),config:a}),e(a),c.info("rubrics refreshed from server")}catch(r){c.warn("rubric refresh failed; keeping prior cache",r)}}function b(){chrome.alarms.create(s,{periodInMinutes:d}),chrome.alarms.onAlarm.addListener(r=>{r.name===s&&g()})}export{b as a,g as r,R as w};
1
+ import{m as t,n as i,o as e,aW as n}from"./scheduled-audit-runner-DAaEDLPk.js";import{c as o}from"./crash-reporter-DAZnNefT.js";const c=o("rubric-config-client"),f="wcagcheckr",u=`https://api.wcagcheckr.com/v1/products/${f}/rubrics`,h=1e4,s="rubric-config-refresh",d=60;async function R(){const r=await t();if(!r){e(null);return}if(i(r)==="expired"){c.warn("cached rubrics are expired (>7d); falling back to bundled defaults"),e(null);return}e(r.config)}async function g(){try{const r=await fetch(u,{signal:AbortSignal.timeout(h),headers:{accept:"application/json"}});if(!r.ok)throw new Error(`http ${r.status}`);const a=await r.json();await n({fetchedAt:Date.now(),config:a}),e(a),c.info("rubrics refreshed from server")}catch(r){c.warn("rubric refresh failed; keeping prior cache",r)}}function b(){chrome.alarms.create(s,{periodInMinutes:d}),chrome.alarms.onAlarm.addListener(r=>{r.name===s&&g()})}export{b as a,g as r,R as w};