import {readFileSync,writeFileSync} from 'node:fs'; const tokens=JSON.parse(readFileSync(new URL('tokens.json',import.meta.url),'utf8')); function luminance(hex){ if(!/^#[0-9a-f]{6}$/i.test(hex))throw new Error(`Expected opaque sRGB hex: ${hex}`); const c=[1,3,5].map(i=>parseInt(hex.slice(i,i+2),16)/255).map(v=>v<=0.04045?v/12.92:((v+0.055)/1.055)**2.4); return .2126*c[0]+.7152*c[1]+.0722*c[2]; } const resolve=k=>tokens.color[k]??k; const rows=tokens.contrastPairs.map(p=>{ const foreground=resolve(p.fg),background=resolve(p.bg),a=luminance(foreground),b=luminance(background); const ratio=(Math.max(a,b)+.05)/(Math.min(a,b)+.05); return {...p,foreground,background,ratio,pass:p.minimum===null?null:ratio>=p.minimum}; }); writeFileSync(new URL('contrast-audit.json',import.meta.url),JSON.stringify({method:'WCAG relative luminance, opaque sRGB; threshold checked without rounding; does not validate all composed/animated UI states',rows},null,2)+'\n'); console.table(rows.map(r=>({pair:r.name,foreground:r.foreground,background:r.background,ratio:r.ratio.toFixed(3),minimum:r.minimum,result:r.pass===null?'diagnostic':r.pass?'pass':'FAIL'}))); if(rows.some(r=>r.pass===false))process.exitCode=1;