# PURE page compliance — the 10-point standard

> **Generated file.** The standard lives in `pure_memory` under `design.compliance_standard`
> and is read by `mcp_compliance_standard()`. Edit the row, then run
> `node tools/compliance-doc.mjs --write`. Editing this file by hand creates a second
> standard, and the day the two disagree nobody can tell which one the scorer enforces.

**Why 10.** It was published as the eight-point rule on 8/16 and the scorer measured SIX — points 7 (responsive) and 8 (no floating UI) were written into the standard and never checked, so two of the eight were memos. They are measured now. Points 9 and 10 are new and are here only because a script can decide them; the rule stays script-checkable by construction, and anything not measurable still does not belong in it.

Set: 2026-08-16 CT; extended to ten measured points 2026-08-18

Adopted by: Mike (exemplars A/B/C adopted 8/16: pure-deal-cockpit = workflow, navigation-management = admin console, pure-property-search = data-browse; property.html = detail). Points 9 and 10 added 8/18 from this month's shipped work.

## The points

### 1. Mounts the shell

Chrome comes from pure-shell.js resolution, never hand-rolled. No page-local brand bar, Home link or identity chip (design.one_chrome_rule).

*How it is measured:* the loader tag is present, or the page is in the canonically chromeless public/auth family, or it is a boneyard tombstone

### 2. Every number from a definer RPC

Live data, never literals or localStorage. An unbound stat shows an em-dash — never a fake number. Sample data is allowed only when it is labelled as sample.

*How it is measured:* a live read path exists (mcp_* / PureLive.rpc / pure-livebind), or the row is marked static_ok. A static scan cannot prove this semantically, so it tests the necessary condition and says so.

### 3. Token pairs only

card/ink · chip-bg/chip-fg · field-bg/field-ph · wash/hair. Never a background token under an unrelated ink token; never a hardcoded surface under theme text. Flip to Midnight — anything that does not move is hardcoded.

*How it is measured:* no raw brand hex outside the page's own :root block, inline identity SVG, meta theme-color, script bodies, or a var() fallback

### 4. Semantic tables

Real <table>/thead/tbody so pure-table.js can enhance it — sortable, searchable, readable by assistive tech. A div grid drawn to look like a table is a fake table. Full standard: /brand-standards#tables.

*How it is measured:* no header-row + row-list div pattern; corroborated repo-wide by tools/table-audit.mjs

### 5. System icons

Files from assets/icons/** (img or currentColor mask) or a <use> from the pack. Never inline one-off SVG copies, never emoji, never imported substitutes.

*How it is measured:* the page defines no <symbol> set of its own, and either references the pack or draws almost no raw paths

### 6. No page-local chrome

A page-local bar is allowed only for what the shell does not provide: page actions and page state.

*How it is measured:* no pure-topnav.js and no hand-rolled .top/.tb/.topbar element; markup hidden by the runtime guard satisfies the intent (Design ruling 2, 8/16)

### 7. Responsive, never width-capped

Fills wide desktops with a fluid cap like min(1320px,94vw), collapses cleanly on phones, no fixed column stranding whitespace (pref.always_responsive).

*How it is measured:* NEW 8/18 — a top-level wrapper (.wrap/.container/.main/.content) pinned to a fixed px max-width with no min()/clamp() fails; any fluid cap on the page credits it

### 8. No floating UI

Status labels live in the page header; promos live inline. Fixed corners belong to shell chrome. Scrims, toasts, modals, drawers and sticky bars are the named exceptions.

*How it is measured:* NEW 8/18 — position:fixed in the page's own CSS on a selector outside that exception list

### 9. Waiting and failing are components, not strings

A hand-typed "Loading…" cannot be told apart from a failed read. data-pure-loading fills the wait and names the failure; "no rows yet", "nothing matches" and "we could not ask" are three different facts and must read as three different things.

*How it is measured:* NEW 8/18 — hand-rolled loading text present while data-pure-loading is absent

### 10. State that matters is in the URL

A hand-rolled tab strip is a place you cannot send anyone, and almost none of them are operable by keyboard. data-pure-tabs makes the state linkable (#tab=<id> / #tab-<group>=<id>) and accessible by construction. A page with no tabs passes — this asks nobody to add tabs, only to stop rolling their own.

*How it is measured:* NEW 8/18 — a tab-strip class vocabulary present with no data-pure-tabs

## Exemplars

- **admin** — `/pure-admin/governance/navigation-management`
- **browse** — `/pure-property-search.html`
- **detail** — `/property.html`
- **workflow** — `/pure-deal-cockpit.html`

## New pages

_template-page.html scores 10/10 — new pages start born compliant on every point

## Stub pages

A small page whose only scripts are pure-boot/pure-shell renders everything at runtime from one source: its surface IS the shell config, and it is scored as such rather than as a static page.

## Enforcement

tools/page-compliance.mjs scores every page; pure_page_compliance + mcp_page_compliance_get read it back; nightly re-score cron; surfaced in Site Control and on /brand-standards#compliance, which renders these points from THIS row rather than from markup.

## The learning loop

Each per-page fix that reveals a new anti-pattern adds a lesson.* row and, when script-checkable, a new signature to the scorer — the standard is a ratchet, not a snapshot. The worst-first queue cut moves with the total, so raising the bar never reports "nothing to fix".

