// Font weights: which weights the templates ask for, how to get them from Google Fonts, and whether a rendered title // got the weight it asked for. The @font-face rules use font-synthesis: none, so a face that lacks a weight is drawn // at the nearest weight it has (a 750 headline from a 400-only face renders thin), never faked bolder. // shots fonts: per role (title / body) the weights of the style's templates (templateWeights); a Google family is // fetched as the full wght axis when it is variable, else the range the templates use, else those weights one by // one (static families), else the default instance (fetchFaces). // shots render: the title's computed weight vs. the weights the loaded faces serve (report.json `weights`); // shots check warns when the browser fell back to another weight (weightIssues). /** Weights a page's CSS asks for, per role: rules that use var(--tf) are title text, the rest body text (the body * default 400 included). Literal font-weight values plus the numbers set on --tw by the page script. Pure. */ export function templateWeights(html: string): { title: number[]; body: number[] } { const tw = [...html.matchAll(/setProperty\('--tw',([^;]+)\)/g)].flatMap(m => [...m[1]!.matchAll(/\b([1-9]00|[1-9][0-9]0)\b/g)].map(x => +x[1]!)); const title = new Set(), body = new Set([400]); const style = /