feat: build step 1 — scaffold, layout, header, footer, SEO; zero JavaScript

Build order step 1 (docs/01): scaffold, tokens, base layout, header,
footer, SEO component, plus a temporary /type-scale/ proof sheet that
step 2 deletes.

THE FONTS WERE NEVER ON DISK. global.css declared six @font-face rules
pointing at /fonts/*.woff2 and public/fonts/ did not exist, so every
face had been silently falling back to Georgia and the system sans.
Six cuts committed, 123,804 bytes, SIL OFL 1.1, provenance in
docs/reference/fonts-provenance.md. ?v=1 on every URL because the
deploy script serves them immutable for a year.

ZERO JAVASCRIPT. The reveal was an inline IntersectionObserver in
<head>; docs/05 specifies script-src 'self' with no unsafe-inline, so
the only script on the site was the one thing the site's own CSP would
refuse to execute. Replaced with animation-timeline: view() behind
@supports. 0 script tags and 0 .js files in dist.

The infinity mark is lifted verbatim from the deployed site's own
smlMark loading thumbnail, not redrawn (Q32 asks whether a canonical
vector exists). The proof sheet computes its contrast table from
tokens.css rather than restating docs/02 — all eleven ratios reproduce
the measured table exactly.

Register: Canadian Tax Foundation added (§4, R10 widened); Q30 closed
— SML Company Ltd is federally incorporated under the CBCA, and the
footer publishes neither that nor the place of business; Q31 closed —
Plausible, on EU-only data residency (D15 amended). ROLE constants
added for "Director of Firm Operations" and "active litigation
exposure" so step 3 does not hand-type them.

Lighthouse unavailability now stated in six places rather than left as
a control that had silently stopped existing (§7, R11).

Both review agents ran twice. The second pass found four defects in
the first pass's fixes, including the minifier bug written back into
its own fix and a colour-alone repair that used the banned gold-on-
cream pairing at 2.10:1. Measured in headless Chrome at thirteen
widths with a seventh nav item injected: 0 overflow, 0 tap targets
under 44x44, 0 focus-order inversions, state indicators at 12.29:1,
755 words of body text with no JavaScript.

Opened: Q32-Q37. Closed: Q30, Q31.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XquaEq4BgWMCwUqLEyNkF
This commit is contained in:
Pouya Lajevardi
2026-08-26 15:57:02 -04:00
co-authored by Claude Opus 5
parent 8f1df2c27c
commit 8134709548
33 changed files with 2575 additions and 147 deletions
+97 -20
View File
@@ -12,12 +12,30 @@ export const SITE = {
url: 'https://adr.smlcompany.ca',
locale: 'en_CA',
/**
* TODO(pouya): AGENTS.md Q30 — §4 verifies "Operator of SML Company Ltd."
* but nothing verifies the company's jurisdiction of incorporation, and this
* string is destined for the public footer. Jurisdiction dropped until
* confirmed; the operator fact itself is verified and stays.
* The footer's copyright line, in full. Q30 is CLOSED.
*
* Two facts were being conflated in the string this replaces
* (`'SML Company Ltd. · Ontario, Canada'`), which read as a jurisdiction of
* incorporation and named the wrong one:
*
* - Jurisdiction of incorporation — **federal, under the CBCA**
* `[verified 2026-08-26 — Pouya]`, recorded in AGENTS.md §4.
* - Place of business — Toronto, Ontario. That is `CONTACT.location`,
* and it belongs in the contact block, not in the entity line.
*
* **Neither appears in the footer.** Pouya's direction, 2026-08-26: the line
* is `© <year> SML Company Ltd` and nothing else. The incorporation fact is
* verified and available — it is simply not published. Do not "complete" this
* line by adding it back.
*
* No corporation number: we do not have one and the line does not need one.
*
* Spelling note so it does not read as a typo and get "fixed": AGENTS.md §4
* writes *SML Company Ltd.* with a terminal period. Pouya specified the
* rendered footer string twice, both times without it. His wording governs
* what ships.
*/
entity: 'SML Company Ltd.',
entity: 'SML Company Ltd',
} as const;
/**
@@ -38,38 +56,97 @@ export const CREDENTIALS = {
'Stitt Feld Handy — negotiation and ADR workshop series',
],
languages: ['English', 'Farsi'],
/** [verified 2026-08-26 — Pouya, AGENTS.md Q28] — and FOR NOW: OBA section
* membership renews yearly, so this is a fact with a shelf life (AGENTS.md
* R10). Re-confirm at renewal. NOT OCNI (lapsed) and NOT the Law Society —
* listing the LSO implies licensure, which D13 bars. Do not add either. */
/** [verified 2026-08-26 — Pouya, AGENTS.md Q28 and the CTF addition of the
* same date] — and FOR NOW. Both the OBA sections and the Canadian Tax
* Foundation renew yearly, so every line below is a fact with a shelf life
* (AGENTS.md R10). Re-confirm at renewal, and before any page that lists
* memberships ships. NOT OCNI (lapsed) and NOT the Law Society — listing the
* LSO implies licensure, which D13 bars. Do not add either. */
memberships: [
'ADR Institute of Canada (ADRIC)',
'ADR Institute of Ontario (ADRIO)',
'Ontario Bar Association — Construction & Infrastructure, ADR, and Civil Litigation sections',
'Canadian Tax Foundation',
],
} as const;
/** The three credential slots. Never matter counts — AGENTS.md §4. */
export const CREDENTIAL_ROW = [
{ value: 'Q.Med', label: 'ADRIC / ADRIO designation' },
{ value: 'JD + ML', label: 'Law and engineering' },
{ value: 'EN · FA', label: 'Bilingual practice' },
] as const;
/**
* The Toronto boutique is NEVER named — AGENTS.md D16. Use this string.
* Do not infer a name from an email domain or anywhere else.
*/
export const BOUTIQUE = 'a Toronto litigation and ADR boutique' as const;
/**
* The boutique role and the litigation line — the two highest-risk strings on
* the site, so they live here rather than being typed into a page.
*
* Neither had a constant until 2026-08-26, which meant `/about/` (step 3) and
* the `Person` JSON-LD (docs/04) were both going to hand-type them. A claim
* written by hand in a component is a claim nobody re-checks against §4 — and
* these are the two where the wording IS the compliance.
*/
export const ROLE = {
/** §4 verbatim. docs/04: this is `jobTitle` in the Person JSON-LD, and
* `worksFor` is OMITTED — populating it either names the boutique (D16) or
* misstates the employer. */
title: 'Director of Firm Operations', // [verified 2026-08-25 — strategy brief §I]
/** Always rendered with BOUTIQUE, never with a firm name (D16). */
at: BOUTIQUE,
/**
* D13's approved phrasing, and the only approved phrasing. The alternative
* he approved is 'involvement in litigation and ADR matters'.
*
* NEVER "practice" in this context — that is the exact word D13 bars in the
* exact context it bars it, and §4 records that this register itself once
* carried the wrong word here while quoting the strategy brief verbatim.
* "Practice" describing Pouya's OWN ADR practice is correct and unaffected.
*
* Explicitly interim — AGENTS.md R1. Raise it; do not let it settle in.
*/
litigationLine: 'active litigation exposure', // [verified 2026-08-26 — D13]
/** The matter types behind that exposure. §4 verbatim; do not extend this
* list without a §4 row to extend it from. */
litigationAreas: [
'personal injury',
'construction',
'regulatory (POA)',
'insurance (SABS)',
],
} as const;
/** The three credential slots. Never matter counts — AGENTS.md §4. */
export const CREDENTIAL_ROW = [
{ value: 'Q.Med', label: 'ADRIC / ADRIO designation' },
/**
* TODO(pouya): AGENTS.md Q37 — is "Law and engineering" the right label?
*
* §4's substitution principle supplies the three VALUES (`Q.Med / JD + ML /
* EN · FA`); the labels come from docs/03 and are not themselves registered.
* `claims-auditor` reads this one as a D13 implication risk: "engineering" is
* shorthand for a verified *practising* claim, so the parallel invites "Law"
* to be read the same way — and D13 bars implication as hard as assertion.
*
* Left as written, because it is docs/03's approved copy and changing
* approved copy is not an implementer's call. Nothing renders it yet. Answer
* before step 2 builds the credential row.
*/
{ value: 'JD + ML', label: 'Law and engineering' },
{ value: 'EN · FA', label: 'Bilingual practice' },
] as const;
/** Analytics: privacy-first and cookieless (D15). No GA4, no consent banner. */
export const ANALYTICS = {
/**
* TODO(pouya): AGENTS.md Q31 — D15 records the choice as "Plausible **or**
* Fathom", i.e. undecided. `'plausible'` was a guessed value, which is what
* the header of this file tells you not to do. Null until you pick one.
* Q31 CLOSED — **Plausible**, decided rather than defaulted. Pouya checked
* 2026-08-26: Fathom is Canadian-owned but stores non-EU traffic on US
* servers, isolating in the EU only for EU visitors; Plausible keeps all data
* in the EU. For a practice whose privacy posture is part of the offer,
* EU-only beats US-hosted. D15 amended to match.
*
* The union type stays — `/legal/privacy/` has to name the processor, and a
* change of processor is a copy change on that page, not just a config edit.
*/
provider: null as 'plausible' | 'fathom' | null,
provider: 'plausible' as 'plausible' | 'fathom',
domain: 'adr.smlcompany.ca',
} as const;