Talk to the Director →
designesy.

Verification transparency

Methodology

The full scoring methodology behind the Designesy 34-check engine. Deterministic, no LLM, no human judgment. Every check is a regex or token-resolution test against the live fetched CSS and HTML. This page documents exactly what the engine measures, how the score is computed, and what it cannot measure.

At a glance

34Total checks
31Scored (PASS/WARN/FAIL)
3SKIP (needs browser)
10Categories
100%Weight total

Scoring math

The engine fetches the target URL’s HTML and all linked CSS, parses :root custom properties, and runs 34 deterministic checks across 10 weighted categories. Each check returns PASS, WARN, FAIL, or SKIP. The score is a weighted average — not a simple count.

SKIP checks are excluded from both numerator and denominator (Lighthouse precedent: manual/N/A audits excluded). This means a site is not penalized for checks the static engine cannot run. The 3 SKIP checks require a browser viewport trace, CDP performance trace, or live DOM interaction.

# Per-check weight = category weight / checks in that category
checkWeight = CATEGORY_WEIGHTS[category] / count(scored checks in category)

# Status scoring
PASS → 1.0 × checkWeight
WARN → 0.5 × checkWeight
FAIL → 0
SKIP → excluded (weight × 0, not counted in total)

# Composite score
score = round( ∑(weightedPoints) / ∑(weightedTotal) × 1000 ) / 10

# Per-category sub-score (same math, scoped to one category)
categoryScore = round( ∑(catPoints) / ∑(catWeight) × 1000 ) / 10

The round(… × 1000) / 10 pattern produces a one-decimal-place score (e.g. 95.2, not 95.2347). The same math runs per-category, producing the constellation breakdown shown on the leaderboard and score pages.

Category weights

Weights follow the contract’s section emphasis — the contractis the scoring basis. Cadence (typography) carries the highest weight at 18% because it has the most checks (11) and typography discipline is the loudest craft signal. Accessibility carries 15% and the a11y floor. Semantic/identity, motion, and tokens follow. Performance and responsive are lowest-weighted because their checks are SKIP in the static engine.

CategoryWeightChecksScored
Cadence18%1212
Accessibility15%66
Semantic12%22
Motion10%44
Tokens9%22
Takt8%22
Poise7%32
Interaction6%11
Performance6%10
Responsive3%10
Total100%3431

Grade bands

The letter grade is a simple threshold on the numeric score. The bands are deliberately demanding — a site must score 90+ to earn an A. Most sites land in D or F because the contract requires primitives (token systems, reduced-motion blocks, font-synthesis rules) that most sites do not ship.

A90Reference-tier craft. The site ships the contract primitives at :root and passes the majority of checks across all categories.
B80Strong. A few checks are missing or WARN, but the foundation is solid.
C70Acceptable. Notable gaps in cadence, motion, or accessibility. The a11y floor caps here if accessibility < 60%.
D60Below standard. Significant gaps across multiple categories. Most sites land here — the contract is demanding.
F0Needs work. The site does not ship the contract primitives. Common for sites with no :root token system, no reduced-motion block, no font-synthesis rule.

Accessibility floor

The a11y floor: if the accessibility category scores below 60%, the overall grade is capped at C (70) — no matter how high the weighted score is. This prevents “perfect tokens, zero a11y = A” dishonesty. A site with beautiful typography and no contrast or touch targets cannot earn above C.

The floor is a softer version of the DSAF enterprise-grade precedent (DSAF enforces A8 Accessibility ≥75%). Designesy applies 60% as the floor — strict enough to prevent the “all tokens, no a11y” failure mode, lenient enough that a site with 3 of 6 accessibility checks passing is not auto-capped. The cap only triggers if the weighted score is above 70 — if the score is already below 70, the floor does not change it.

What the engine measures

The engine fetches the target URL, extracts all CSS (inline <style> blocks + linked <link rel="stylesheet"> files), parses :root custom properties, and runs each check as a regex or token-resolution test. It does not render the page, execute JavaScript, or interact with the DOM. This means:

It measures what is shipped, not what is documented. A design-system site can publish a rich token taxonomy in Storybook and still score low if the marketing surface doesn’t expose those tokens at :root. That gap — between documented and shipped — is exactly what the leaderboard surfaces.

It is deterministic. No LLM, no human judgment, no roast. The same URL always produces the same score (within the 24-hour cache window). If a site changes its CSS, the score changes on the next run.

What the engine skips

3 checks are marked SKIP because they require a capability the static engine does not have:

SKIP checks are excluded from both numerator and denominator — a site is not penalized for them. Future versions of the engine may run these via a Playwright/CDP trace integration.

Cadence

18% weight · 12 checks · 12 scored

Typography rendering discipline — font smoothing, rem scales, line-height, text-wrap, tabular nums, selection styling, font-synthesis, underline-position, skip-ink. The contract section with the most checks (11), weighted highest at 18%.

v14Cadence typography rules match live CSS and contract.cadence

Checks for the Cadence rule set: font-synthesis: none, text-underline-position: from-font, text-decoration-skip-ink: auto, -webkit-font-smoothing: antialiased, -moz-osx-font-smoothing: grayscale, root font-size: 16px, all sizes in rem. PASS if all present.

v15Font smoothing: antialiased + grayscale on :root confirmed

Searches :root or html for -webkit-font-smoothing: antialiased and -moz-osx-font-smoothing: grayscale. PASS if both are present. Prevents subpixel rendering artifacts on dark backgrounds.

v16Rem-based scale: all text sizes in rem, root at 16px confirmed

Counts rem-based vs px-based font-size declarations. PASS if the majority are rem and root is 16px. The 16px root is the Cadence floor — iOS Safari auto-zooms inputs below 16px.

v17Line-height by role: headings 1.08, body 1.55 confirmed

Extracts line-height values from heading and body selectors. PASS if heading line-heights cluster near 1.08 and body line-heights near 1.55. Tight headings read as deliberate; relaxed body copy reads as confident.

v18text-wrap: balance + pretty both present in live CSS

Searches for text-wrap: balance (headings) and text-wrap: pretty (paragraphs). PASS if both are present. Progressive enhancement — unsupported browsers ignore them.

v19tabular-nums: 8 instances across the live CSS

Counts font-feature-settings: "tnum" or font-variant-numeric: tabular-nums declarations. PASS if ≥ 8 instances (threshold for a site that takes numeric display seriously). Prevents digits from shifting width as values change.

v20::selection styled with var(--signal) — not browser default

Searches for ::selection rules using var(--signal). PASS if the selection color is the signal token, not the browser default. The selection color is a small but loud brand surface.

v26Font family count ≤3 (body + heading + mono)

Parses all font-family declarations and counts distinct families. PASS if ≤ 3. WARN if 4-5. FAIL if 6+. More than 3 families signals inconsistency and hurts performance.

v28Reading width 45-75ch on prose containers

Searches for max-width declarations in the 45-75ch range (66ch ideal). PASS if at least one measure is in range. Lines longer than 75ch are hard to track; shorter than 45ch feels choppy.

x01font-synthesis: none set (Cadence resolved tension)

Searches for font-synthesis: none. PASS if declared. WARN if font-synthesis is declared but not set to none, or if no rule is found. Prevents the browser from synthesizing bold/italic faces when the real weights are not loaded — a common cause of blurry headlines on Windows.

x02text-underline-position: from-font set (Cadence resolved tension)

Searches for text-underline-position: from-font or under. PASS if declared. Uses the font designer’s built-in underline position rather than the browser default, which is usually too low and clips descenders.

x03text-decoration-skip-ink: auto set

Searches for text-decoration-skip-ink: auto or none. PASS if declared. Makes underlines skip the rounded parts of letters (g, j, p, q, y) — a small typographic refinement that signals attention to craft.

Accessibility

15% weight · 6 checks · 6 scored

WCAG 2.2 AA primitives — contrast, touch targets, heading hierarchy, input font floor, button-text contrast, forced-colors readiness. Carries the a11y floor: if this category scores below 60%, the overall grade is capped at C.

v06Contrast remains readable for ink, muted, and accent on paper (WCAG 2.1 + APCA)

Resolves --paper, --ink, --muted, --muted-dim to RGB and computes WCAG 2.1 contrast ratios. PASS if all clear 4.5:1 (AA body text). WARN if any clear 3:1 but not 4.5:1. FAIL if any below 3:1. APCA Lc values are reported alongside.

v22Primary button text passes WCAG AA contrast against --signal fill

Resolves --signal to RGB, then tests --ink and --paper against it. PASS if the best ratio ≥ 4.5:1. WARN if ≥ 3:1 (large-text pass). FAIL if below 3:1. SKIP if --signal is not declared or unresolvable.

v24Touch targets ≥44px on interactive elements (WCAG 2.5.8)

Searches CSS for min-height or min-width ≥ 44px on button/a/input/select selectors. PASS if found. This is the WCAG 2.2 Target Size Minimum (AA). Full verification needs a browser to measure rendered dimensions.

v25Heading hierarchy: single h1, no skipped levels

Parses the HTML for h1-h6 elements. PASS if exactly one h1 and no skipped levels (no h1→h3 jumps). Screen readers and SEO both rely on a logical heading outline.

v27Input font-size ≥16px (prevents iOS Safari auto-zoom)

Searches CSS for input/textarea/select font-size declarations ≥ 16px (or 1rem). PASS if the floor is detected. Inputs below 16px trigger a layout-shift zoom on iPhone that breaks mobile UX.

v35Forced-colors readiness: @media (forced-colors: active) block present

Searches CSS for @media (forced-colors: active) and forced-color-adjust. PASS if both are present. Windows High Contrast Mode and Chrome forced-colors recolor the page — without this media query, critical UI becomes illegible.

Semantic

12% weight · 2 checks · 2 scored

HTML semantic foundation — single h1, meta description, landmark elements, AI-disclosure readiness (EU AI Act Art 50). Labeled "semantic" in the engine; maps to the contract.identity section.

v07Semantic HTML foundation: single h1, title, meta description, landmark

Parses HTML for: exactly one h1, a descriptive <title>, <meta name="description">, and at least one <main>/<header>/<nav> landmark. PASS if all 4 are present. WARN if 1-2 missing. FAIL if 3+ missing.

v34AI-Disclosure Readiness (EU AI Act Art 50, effective 2026-08-02)

Detects AI-interactive surfaces (chatbots, AI assistants) in the HTML. If detected, checks for disclosure signals (visible "AI" text, aria-label, meta generator, C2PA). PASS if no AI surface is detected (disclosure not required) or if disclosure is present. FAIL if an AI surface is detected without disclosure.

Motion

10% weight · 4 checks · 4 scored

Motion hygiene — no transition:all, will-change restricted to transform/opacity, prefers-reduced-motion block, duration tokens present. 4 checks, 10% weight.

v05prefers-reduced-motion disables entrance and wordmark breath

Regex-searches for @media (prefers-reduced-motion: reduce). PASS if the media query is declared. This is the vestibular-safety primitive — without it, motion-sensitive users cannot use the site.

v11No transition:all in the live stylesheet

Regex-searches for transition: all (case-insensitive). FAIL if found. transition: all causes layout-thrash and surprises — the contract requires named properties only.

v12will-change restricted to transform and opacity only

Parses every will-change declaration. If any value contains anything other than transform or opacity (including auto), it WARNs. will-change on non-transform/opacity properties forces unnecessary layer promotion.

v23Duration tokens --duration-quick through --duration-slow present in :root

Checks :root for the 5 duration tokens: --duration, --duration-quick, --duration-fast, --duration-medium, --duration-slow. PASS if all 5 are declared. Hardcoded ms values in component CSS are the anti-pattern.

Tokens

9% weight · 2 checks · 2 scored

Token architecture — --paper foundation present, token layer depth (primitive → semantic → component). 2 scored checks, 9% weight.

v01Token values match live site :root foundation

Parses :root custom properties from the fetched CSS. Looks for --paper specifically — the contract names --paper, --ink, --muted, --surface, --surface-raised, --line, --signal, --signal-light, --signal-dim as the required foundation. PASS if --paper resolves to a value.

v29Token architecture: primitive → semantic → component layers

Counts how many tokens are referenced via var() (aliasing) vs. raw values. A 2-tier or 3-tier aliasing structure (primitive → semantic → component) signals a mature token system. PASS if at least 2 layers are detected.

Takt

8% weight · 2 checks · 2 scored

Interaction feel — press scales above the 0.95 floor (0.96 cells, 0.985 cards, 0.995 surfaces). Named after the German word for precise, musical timing.

v10Takt interface-feel rules match live CSS and contract.takt

Verifies the static half: stagger enter animation-delay, soften exit transform ease-out, concentric border-radius set. Press-behavior and hit-area require a browser.

v13Press scale 0.96 on cells, 0.985 on cards/rows — both above 0.95 floor

Extracts every transform: scale() value in :active contexts. FAIL if any scale is 0 (glitch, not a press) or below 0.95. PASS if real press scales are found above 0.95. The 0.95 floor is the contract minimum — lower reads as a glitch.

Poise

7% weight · 3 checks · 2 scored

Interaction poise — hover lifts, press-settle, keyboard-path documentation, sound-toggle aria-pressed. Static half verified from CSS; interaction half requires a browser (SKIP).

v04Sound toggle flips aria-pressed and applies the audio preference

Requires clicking a sound toggle and verifying aria-pressed flips and a [data-audio] attribute is applied. The static engine cannot interact with the DOM.

SKIP — Requires live DOM interaction — the engine does not execute JavaScript or click elements.
v08Poise interaction rules match live /labs/poise and contract.interaction

Verifies the static half: fine-pointer hover guard (@media hover: hover), press-settle scale ~0.97, opacity-only mark breath. The interaction-feel half requires a browser.

v09Poise keyboard-path verification remains published and current

Verifies the static half: 4 keyboard-affordance signals in the HTML/CSS (tabindex, accesskey, key bindings, focus management). Tab-order traversal requires a browser.

Interaction

6% weight · 1 check · 1 scored

Focus visibility — :focus-visible rings declared. 1 scored check, 6% weight.

v03Primary interactive elements show focus-visible rings

Regex-searches the CSS for :focus-visible declarations. PASS if any :focus-visible rule is found. This is the keyboard-navigation visibility primitive — without it, Tab users cannot see where they are.

Performance

6% weight · 1 check · 0 scored

Core Web Vitals — LCP, INP, CLS. Requires a CDP/Playwright trace (SKIP in the static engine). 6% weight, 0 scored checks in the current engine.

v21Core Web Vitals plausible: LCP < 2.5s, INP < 200ms, CLS < 0.1

Requires a CDP/Playwright trace to measure LCP, INP, and CLS against the Google thresholds. The static engine cannot do this.

SKIP — Requires a CDP trace — the engine fetches HTML/CSS, not a rendered page with timing data.

Responsive

3% weight · 1 check · 0 scored

Viewport overflow — horizontal overflow at 375/720/860/1080px+. Requires a browser viewport trace (SKIP in the static engine). 3% weight, 0 scored checks.

v02Routes render without horizontal overflow at 375px, 720px, 860px, 1080px+

Requires rendering the page at four viewport widths and measuring scrollWidth > clientWidth. The static engine cannot do this.

SKIP — Requires a browser viewport trace — the engine fetches CSS, not a rendered DOM.

Data exports

The leaderboard data is available in two machine-readable formats for agents and researchers:

/api/leaderboard — JSON with full per-site categoryScores. CORS-enabled.
/api/leaderboard.csv — RFC 4180 CSV with a header row. Spreadsheet-friendly.

Methodology v1 · 34 checks · 10 categories · deterministic, no LLM · engine source at /api/score · contract at /contracts/design-system.json