fix: replace the traced infinity mark with the real artwork; add §4 Offerings

Q32 — the traced mark was a WRONG SHAPE and had shipped. Pouya compared
it against the master and rejected it. Two grounds reproduce from the
path and are verified here: all four cubic branches meet the origin at
exactly 90 degrees, so the loops are tangent rather than crossing and at
stroke-width 28 render as two kissing circles (signed crossing number 0;
the strokes fuse across 61% of the mark's height at 2rem); and the
master's ink bbox is 2668x1704 = 1.5657:1. The path is deleted, not kept
as a fallback.

Pouya's 1.23:1 figure is reconciled rather than left dangling: it is the
bounding box of the path's COORDINATES, not the curve. Control points sit
at y +/-160 where the curve reaches +/-120, so the hull is 400x320 and
with stroke 428x348 = 1.2299. A trap rather than a slip — x is monotone,
so the control points give the right width and a 33% inflated height, and
the "does the width look right" check passes.

The real artwork is now in the repo: master, tight crop (the render
source, so the file's aspect ratio IS the mark's), full lockup, and the
SVG. InfinityMark renders AVIF/WebP; a Retina device takes 3,063 B.
Favicons regenerated; favicon.svg deleted.

Q33/Q36 — Pouya accepts arbitration appointments now. §4 gains an
Offerings category: competence for an offering, permission for a
credential, with an explicit boundary so it cannot become a route around
D13. The masthead tagline is restored, and the footer designation strip
now carries "Q.Arb — commenced August 2026" so §4's paired-disclosure
condition is actually met on every page rather than only asserted.

Two conventions added to CLAUDE.md, both earned this session: anything a
spec makes a claim about must be reachable from the repo (R14 — the
traced mark survived two review passes because the artwork was not here
to compare against); and a command that did not run is not evidence of
absence (`timeout` is not installed on macOS, so four Drive reads never
executed and were reported as an empty directory).

Reviews: claims-auditor FAIL/13 and adversarial-reviewer 2 blocking, all
resolved. The severe one was self-inflicted — `flex: none` landed on the
<img> while <Picture>'s <picture> wrapper is the flex item, so the logo
compressed to 28.5x32 at 1024px with seven nav items. The page-level
overflow check passed throughout because the brand block absorbed the
deficit by crushing the mark. Harness now asserts rendered aspect ratio.

Opened: Q38, Q39. Closed: Q32, Q33, Q36. Narrowed: Q35. Added: R13, R14.
AGENTS.md entry (v) carries a RESUME HERE section.

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 17:30:19 -04:00
co-authored by Claude Opus 5
parent 8134709548
commit 364b09632e
20 changed files with 764 additions and 117 deletions
+408 -4
View File
@@ -189,6 +189,140 @@ since May.
| LinkedIn: `https://www.linkedin.com/in/pouyalajevardi/` | `[verified 2026-08-26 — Pouya]` |
| ~~The boutique may be named on the site~~ | **STRUCK 2026-08-26 (Q25).** Superseded by **D16 — never named.** Pouya said it *could* be named, then reversed; the permission survived the reversal and sat in the Verified table authorising exactly what D16 bars. Refer to it only as *a Toronto litigation and ADR boutique* |
### Offerings — what the practice offers, as distinct from what Pouya holds
**Added 2026-08-26 on Pouya's ruling (Q33, Q36).** Everything above this point
answers one question: *is this claim about Pouya true?* That is a question about
**credentials**. It turns out the register also has to answer a second, different
question: *does the practice offer this?* — and applying the credential test to
an offering produced a wrong answer twice in one session.
**What went wrong, because it explains the rule — stated correctly on the second
attempt.** `co-arbitration available now` was flagged across three specs on the
reasoning that §4 records the Q.Arb pathway as merely *commenced* and therefore
could not support an arbitration offering. **That** reasoning was wrong at the
root: it silently treated a **designation** as though it were a **licence**.
*The masthead objection was a different one, and this paragraph originally
misdescribed it.* Q33-orig did not say Pouya was not entitled to arbitrate. It
said the line had been **promoted to a masthead under his name on every page,
where nothing qualifies it and it reads as a designation strip** — an objection
about **placement and implication**, not entitlement. Answering the entitlement
objection does not answer the placement one, and the first version of this
section quietly substituted the easier question. `claims-auditor` caught the
substitution. The placement objection is answered by the paired-disclosure
condition below, which is a **condition**, not a formality.
**Pouya's ruling, and the reasoning to keep.** His stated basis: ADRIC and ADRIO
designations — Q.Med, Q.Arb, C.Med-Arb — are **voluntary credentials, not
licences**, and **commercial arbitral appointment in Ontario is not gated behind
a designation**. So the constraint on offering arbitration was never *may he
act* — only *will parties appoint someone at this stage of the arc*, which is
**positional** and his to answer. He answers it: **he accepts arbitration
appointments now**, and that — his acceptance — is what the rows below record.
> ⚠️ **The legal proposition underneath is the architect's, not this register's,
> and it is deliberately NOT stamped `[verified]`.** `[verified — Pouya]` means
> *the subject reported it*, which can establish what he offers and cannot
> establish a proposition of Ontario law. No statute or regulation is cited here
> and none is in the repo, so **no reviewer can check it** — R14 again, in a
> place that matters more than a logo.
>
> It is also **not a universal, and must never be restated as one.** An earlier
> draft of this paragraph wrote "Anyone may be appointed an arbitrator in
> Ontario. Nothing in law gates the role behind a designation." `claims-auditor`
> produced a counter-example from inside this repo: the site ships a
> **Shareholder & Family Business** practice area, and **family** arbitration in
> Ontario is understood to be one of the places where arbitrator qualification
> *is* prescribed. This record does not resolve that — it is **Q39** — but it
> will not carry an unqualified universal that the site's own nav may already
> contradict. The rows below are scoped to **commercial** arbitration for that
> reason.
### The offering test
> **For an offering, ask about COMPETENCE. For a credential, ask about
> PERMISSION.** A credential claim needs a row in the Verified table because it
> asserts a fact about Pouya that is either true or false. An offering needs two
> things, and they are answered by different people:
>
> 1. **Is the activity gated?** — *a question for THIS REGISTER, not for the
> subject.* It needs a source that a reviewer can check, and it is answered
> per activity and per jurisdiction, never as a class. Until it is answered,
> the offering does not ship.
> 2. **Is he competent to do it?** — *his call, and only his.* Not the
> register's, not an implementer's, not a reviewer's.
>
> **Question 1 is not his to answer**, and an earlier draft of this test said it
> was: it ended "That is his call, not the register's, and not an implementer's"
> attached to the *whole* preceding question, gating included. That hands a
> future writer the sentence *"he says this one is ungated, and §4 says that is
> his call"* — which is the walk-through the boundary below exists to prevent.
> Split, on `claims-auditor`'s finding, 2026-08-26.
### What counts as an offering, and the rule for publishing one
> **An offering may not be published until it has a row in "Offered now" below.**
> Same force as the governing rule for the Verified table. The register created
> this category; it has to gate it too, or it is a category that authorises
> everything by saying nothing.
**Scope: an offering is a PROCESS the practice conducts** — mediation,
arbitration, med-arb, early neutral evaluation, settlement counsel,
dispute-system design, pre-dispute technical advisory. Each needs its own row.
**A subject-matter area is NOT an offering.** *Construction*, *technology*,
*energy*, *insurance*, *shareholder*, *cross-cultural* are the contexts in which
the processes are conducted, not additional things offered. They are governed by
`docs/03`'s framing rule instead — *"Frame as positioning, not as history"* — and
the open half of **Q35** asks whether a one-word nav label can carry even that.
Do not read this scope note as clearing them; it says only which rule applies.
*Added 2026-08-26 on `claims-auditor`'s finding that the section had created a
category without defining either its extent or its gate — so `Med-Arb` was
sitting in the site-wide footer as an offering with no row, three sentences
below a paragraph saying not to infer exactly that. It has been removed from the
footer pending Q35(a).*
**THE BOUNDARY, AND IT IS NOT NEGOTIABLE.** This test applies **only where no
licence gates the activity.** It is not a general licence-free zone, and it must
never be read as one:
- **Mediation and arbitration are ungated.** No designation is required to be
appointed. The offering test governs, and Pouya has answered it.
- **Legal services are gated.** Providing legal services and practising law in
Ontario are restricted activities. For anything on that side of the line the
binding question is **permission**, the answer is **not established** (see the
**Licence status — NOT ESTABLISHED** row above), and **D13 bars the claim
outright.** "I offer legal representation — that is competence, not
permission" is exactly the misreading this paragraph exists to foreclose.
- **The test never converts a credential into an offering.** Q.Arb is still
*commenced August 2026* and must still never read as held. Offering
arbitration and holding Q.Arb are two different statements, and the site makes
the first while stating the second plainly.
### Offered now — may be published
| Offering | Status |
|---|---|
| **Mediation** — sole mediator | `[verified 2026-08-26 — Pouya]`. Q.Med held; §4 also verifies multiple completed sole mediations |
| **Arbitration — sole arbitrator** (commercial) | `[verified 2026-08-26 — Pouya, Q33/Q36]`. Offered **now**. Not gated by Q.Arb. **Commercial** — see Q39 on family arbitration |
| **Arbitration — party-appointed** | `[verified 2026-08-26 — Pouya, Q33/Q36]`. Offered **now** |
| **Arbitration — co-arbitration** | `[verified 2026-08-26 — Pouya, Q33/Q36]`. Offered **now**. This closes Q36, which had flagged the claim as asserted in three specs and resting on no §4 row — the row is here |
| ~~Tribunal secretary~~ | **Not offered.** D14 removed the rate and bars offering it |
**How the arbitration page must read** (`docs/01` §`/arbitration/`, step 4):
it offers all three today **and states plainly that the Q.Arb pathway commenced
August 2026, with C.Med-Arb as the endpoint.** Pouya's instruction: *being open
about the stage is the differentiator — do not hedge it into vagueness.* So
neither half may be dropped. Naming the stage is not a disclaimer bolted onto an
offering; it is the reason a sophisticated reader believes the offering.
**Still unanswered — do not infer from this section.** Whether **Med-Arb** is
offered now is not recorded here; Pouya named the three arbitration forms and
mediation, and nothing else. Med-Arb is ungated by the same reasoning, so the
question is his competence call alone — but it is still a question. See Q35.
### Forbidden — must not appear on the site
**Scope, clarified 2026-08-26.** This table governs **published pages** — anything
@@ -353,12 +487,18 @@ Nothing below can be invented. Each needs an answer from Pouya.
| ~~Q29~~ | **ANSWERED 2026-08-26 by implementation.** Guard widened on both counts: the two secrets are checked (emptiness only, never echoed), and `INTAKE_ENDPOINT` is promoted to job-level `env:` and guarded. Every `vars.*` and `secrets.*` the workflow consumes is now covered except `BOOKING_URL`, empty by decision (R6) | — |
| ~~Q30~~ | **ANSWERED 2026-08-26 — federally, under the CBCA**, and it does **not** appear in the footer. Recorded in §4 with the caution that it implies nothing about licensure or about where the practice may operate. The footer reads `© <year> SML Company Ltd` and stops there (Pouya's direction, given twice). `src/data/site.ts` un-nulled, `TODO(pouya)` removed. Note the spelling: §4 writes *SML Company Ltd.* with a terminal period; the rendered string has none, because that is how Pouya specified it | — |
| ~~Q31~~ | **ANSWERED 2026-08-26 — Plausible**, and decided rather than defaulted. Pouya checked and found his own assumption wrong: Fathom is Canadian-owned but stores non-EU traffic on US servers, isolating in the EU only for EU visitors; Plausible holds everything in the EU. D15 amended with that reasoning. The value that was guessed and nulled is now the value that was chosen — which is not the same thing, and the difference is why it was nulled | — |
| **Q35** | **May the header nav and footer sitemap name a service or practice area the register does not establish as a present capability, before the page that qualifies it exists?** This is the architecture-versus-register question that `claims-auditor` has now raised twice, and it is not one an implementer should settle. The nav and footer ship on all nineteen pages and today carry **`Arbitration`**, **`Med-Arb`**, **`Energy, Grid & Regulatory`** and **`Shareholder & Family Business`** — none of which trace to a §4 row. Every one of them is also **locked architecture**: D5 and §6 fix the sitemap, and `docs/01` specifies each page. The specs already anticipate the tension and answer it at page level — `docs/03`: *"Frame as positioning, not as history"*; `docs/01` on energy: *"Write it as a genuine position, not a claim of existing volume"* — so the question is precisely whether a **one-word nav label**, which has no room to frame anything, inherits that licence. Three ways out: accept the labels as taxonomy and rely on the pages to qualify (status quo), rename toward capability-neutral wording, or hold items out of the nav until their page ships. **Claude Code declined to act unilaterally on either audit pass**; recorded so the judgement is visible rather than missed | The header and footer on every page; sharpest at step 5 |
| **Q36** | **Is co-arbitration work available now?** Asserted in three specs — `docs/01` §`/arbitration/`, `docs/03` §Voice as model copy, and `docs/07-fees.md`, which instructs *"The page must say so"* — and **it is in no §4 row.** §4 records the Q.Arb pathway as commenced August 2026 and nothing about what is available in the meantime. The sentence is offered under the heading *"Name the limits"*, so the unverified half travels inside advice about honesty, which is how it survived. All three files now cite this question; none has been deleted, because the *shape* of the sentence is right and only its second clause is unsourced. Raised by `claims-auditor`, 2026-08-26 | `/arbitration/` (step 4) and `/fees/` (step 9) |
| **Q35** | **NARROWED 2026-08-26 — two of the four items are resolved; two are not.** `Arbitration` is answered (Q33) and is now a **§4 Offerings** row. What remains: **(a) Med-Arb** — ungated by the same reasoning, so it is purely a competence call, and Pouya named mediation and the three arbitration forms without naming it. Do not infer it. **(b) `Energy, Grid & Regulatory` and `Shareholder & Family Business`** — subject-matter areas rather than gated activities, so the offering test asks only whether he is competent to mediate or arbitrate in them, which is his answer to give. `docs/03` already fixes how the pages must read once answered — *"Frame as positioning, not as history"* — so this is not a blocker on writing them, only on claiming capability in a one-word nav label before the page exists. Original framing follows | Med-Arb (step 4); the practice pages (step 5) |
| ~~Q35-orig~~ | **May the header nav and footer sitemap name a service or practice area the register does not establish as a present capability, before the page that qualifies it exists?** This is the architecture-versus-register question that `claims-auditor` has now raised twice, and it is not one an implementer should settle. The nav and footer ship on all nineteen pages and today carry **`Arbitration`**, **`Med-Arb`**, **`Energy, Grid & Regulatory`** and **`Shareholder & Family Business`** — none of which trace to a §4 row. Every one of them is also **locked architecture**: D5 and §6 fix the sitemap, and `docs/01` specifies each page. The specs already anticipate the tension and answer it at page level — `docs/03`: *"Frame as positioning, not as history"*; `docs/01` on energy: *"Write it as a genuine position, not a claim of existing volume"* — so the question is precisely whether a **one-word nav label**, which has no room to frame anything, inherits that licence. Three ways out: accept the labels as taxonomy and rely on the pages to qualify (status quo), rename toward capability-neutral wording, or hold items out of the nav until their page ships. **Claude Code declined to act unilaterally on either audit pass**; recorded so the judgement is visible rather than missed | The header and footer on every page; sharpest at step 5 |
| ~~Q36~~ | **ANSWERED 2026-08-26 — yes, and so are sole-arbitrator and party-appointed appointments.** Now a row in **§4 Offerings** rather than an unsourced assertion in three specs. `docs/01`, `docs/03` and `docs/07-fees.md` no longer need to cite an open question against it. Original text follows | — |
| ~~Q36-orig~~ | **Is co-arbitration work available now?** Asserted in three specs — `docs/01` §`/arbitration/`, `docs/03` §Voice as model copy, and `docs/07-fees.md`, which instructs *"The page must say so"* — and **it is in no §4 row.** §4 records the Q.Arb pathway as commenced August 2026 and nothing about what is available in the meantime. The sentence is offered under the heading *"Name the limits"*, so the unverified half travels inside advice about honesty, which is how it survived. All three files now cite this question; none has been deleted, because the *shape* of the sentence is right and only its second clause is unsourced. Raised by `claims-auditor`, 2026-08-26 | `/arbitration/` (step 4) and `/fees/` (step 9) |
| **Q37** | **Is "Law and engineering" the right label under `JD + ML`?** §4's substitution principle supplies the three credential-row **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 — it is approved copy and changing approved copy is not an implementer's call — with a `TODO(pouya)` on it in `src/data/site.ts`. Nothing renders it yet. Raised by `claims-auditor`, 2026-08-26 | The credential row on `/` (step 2) and `/about/` (step 3) |
| **Q33** | **How is arbitration described in site-wide copy before Q.Arb is conferred?** Not a wording question — a positioning one, and it recurs on every page. §4 records the Q.Arb pathway as **commenced August 2026**, "never as held or nearing completion". `SITE.tagline` reads `Mediation · Arbitration · Toronto`, and `docs/01` specifies that exact string as the **Home hero eyebrow** — where the hero copy beneath it can qualify it. Build step 1 promoted it to a masthead line under Pouya's name on every page, where nothing qualifies it and it reads as a designation strip; `claims-auditor` flagged it and **it has been removed from the header**. But the question it exposed is still open and lands at build step 2: does the hero eyebrow keep `Arbitration` as specified, qualify it, or hold it until designation? `/arbitration/` (step 4) is separately specced to state the position plainly, which is the honest model — the issue is the one-line forms that have no room to. **Second pass, same day:** the removal from the header did not sweep the proof sheet, where the same string was **hand-typed** as a type specimen and rendered ten times at up to 96px. Both defects fixed — the specimen is now a neutral pangram — and the lesson is the sweep rule again: a removal is a `grep`, not a memory. The nav item `Arbitration` also survives, deliberately; that is Q35. Raised by `claims-auditor`, 2026-08-26 | The Home hero (step 2); `docs/04`'s specified home `<title>`; any bio or one-line descriptor |
| ~~Q33~~ | **ANSWERED 2026-08-26 — the question rested on a false premise.** It assumed the constraint on describing arbitration was about *entitlement*. ADR designations are voluntary credentials, not licences, and **anyone may be appointed an arbitrator in Ontario** — so the constraint was always positional, never legal, and it was Pouya's to answer. He accepts arbitration appointments now. `Mediation · Arbitration · Toronto` is **restored to the masthead one-liner**, and `docs/04`'s specified home `<title>` stands as written. See **§4 Offerings**, added for exactly this class of statement. The original question text follows for the record | — |
| ~~Q33-orig~~ | **How is arbitration described in site-wide copy before Q.Arb is conferred?** Not a wording question — a positioning one, and it recurs on every page. §4 records the Q.Arb pathway as **commenced August 2026**, "never as held or nearing completion". `SITE.tagline` reads `Mediation · Arbitration · Toronto`, and `docs/01` specifies that exact string as the **Home hero eyebrow** — where the hero copy beneath it can qualify it. Build step 1 promoted it to a masthead line under Pouya's name on every page, where nothing qualifies it and it reads as a designation strip; `claims-auditor` flagged it and **it has been removed from the header**. But the question it exposed is still open and lands at build step 2: does the hero eyebrow keep `Arbitration` as specified, qualify it, or hold it until designation? `/arbitration/` (step 4) is separately specced to state the position plainly, which is the honest model — the issue is the one-line forms that have no room to. **Second pass, same day:** the removal from the header did not sweep the proof sheet, where the same string was **hand-typed** as a type specimen and rendered ten times at up to 96px. Both defects fixed — the specimen is now a neutral pangram — and the lesson is the sweep rule again: a removal is a `grep`, not a memory. The nav item `Arbitration` also survives, deliberately; that is Q35. Raised by `claims-auditor`, 2026-08-26 | The Home hero (step 2); `docs/04`'s specified home `<title>`; any bio or one-line descriptor |
| **Q34** | **Do §2's measurements of the previous build still hold, and were they measured against the deployed file?** Two of `claims-auditor`'s findings were unverified old-site assertions published in copy, which sent Claude Code to measure the live URL on 2026-08-26. What came back does not straightforwardly match §2. **Reproduced:** the response is a single **2,206,032-byte** file, and `<title>` is still `SML Company · Dispute Resolution`. **Could not be reproduced from the served HTML:** there are **zero** `base64,` occurrences anywhere in it — §2 records "two logo PNGs ~1 MB, base64-inlined" — and no reference to `unpkg` or a React development build. **Why this is a question and not a correction:** the served document is a *bundler harness*. 2,210,921 bytes of it are inline `<script>`, the real `<head>` sits JSON-escaped inside a `<script type="__bundler/template">`, and the application is loaded from **nine UUID-named script files that were not fetched**. The logos and the CDN references may well be in those bundles. So §2 may be right, may be stale, or may have been measured against the local source rather than the deployment — this record cannot tell which. **Why it matters beyond tidiness:** `docs/02` and `CLAUDE.md` both cite the base64-logo figure as the *reason* for a standing convention, and §12 R8 exists because unverified premises propagate. Nobody should quote these numbers in public copy until the question closes. Raised by Claude Code, 2026-08-26 | Nothing structural. It governs whether §2's figures may be cited as fact |
| **Q32** | **Is there a canonical vector file for the SML infinity mark?** `src/components/InfinityMark.astro` is built from geometry lifted verbatim from the deployed site's own loading-thumbnail SVG — the element it labels `smlMark`, fetched from `https://adr.smlcompany.ca/` on 2026-08-26. Path, both stroke widths (28 / 6) and the 0.7 inner opacity are the source's; the only change is folding a `translate(60 0)` into the coordinates. So it is SML's own artwork rather than a redrawing — but a loading placeholder is not necessarily the canonical file, and D7 says the mark carries over *unchanged*. If a master SVG or AI/EPS exists, supply it and the component gets replaced. Raised by Claude Code, 2026-08-26 | Nothing — the mark renders. This is about fidelity, not a blocker |
| **Q39** | **Does the arbitration offering extend to FAMILY arbitration, and is that activity gated?** Raised by `claims-auditor` 2026-08-26 as a counter-example from inside this repo, and it is a good one. §4 Offerings rests on the proposition that arbitral appointment in Ontario is not gated behind a designation. The site ships a **`Shareholder & Family Business`** practice area — and **family** arbitration in Ontario is understood to be one of the places where arbitrator qualification *is* prescribed by statute and regulation. If so, the offering test's own boundary applies: where an activity is gated, the question is **permission**, and permission is not established. **This record does not resolve it** — Claude Code will not assert a proposition of Ontario law, and neither may a self-report. What is needed: (a) does the practice-area page contemplate family-law arbitration at all, or only shareholder, partnership and family-*business* disputes, which is a different thing; and (b) if it does, the gating question needs a checkable source in the repo, per R14. **Interim:** §4's arbitration rows are scoped to **commercial** arbitration and the universal has been removed from the reasoning. Nothing ships that turns on it | The `Shareholder & Family Business` page (step 5); `/arbitration/` (step 4) |
| **Q38** | **A true vector master for the infinity mark.** The mark is a shaded ribbon — variable-width band, maroon flowing into champagne, twisting in three dimensions and passing over itself at the crossing. That is gradient-mesh artwork, and there is no honest way to express it as the flat vector paths `docs/02` assumes. An SVG **is** held — `src/assets/brand/sml-logo-source.svg` — and **it renders faithfully**: rasterised at 8333 px it reproduces the master exactly, at the same 1.566:1 `[verified 2026-08-26 — rendered and measured]`. *An earlier draft of this row called it "a raster in a vector wrapper", which was unfair and is corrected.* What rules it out is **payload and composition**: 257,278 bytes against **3,063** for the AVIF a Retina browser actually takes — 84× — plus **seven embedded base64 PNGs** and a 1,225-stop gradient mesh, so inlining it would breach `CLAUDE.md`'s rule against base64-inlining images. What is wanted is a master that is faithful **and** light. **Pouya is commissioning a proper vector master.** Until it lands, `InfinityMark.astro` renders an optimised raster and that is a **documented, temporary exception to `docs/02`'s inline-SVG rule** (R13 keeps it from becoming permanent). When the master arrives: replace the component's `<Picture>` with inline SVG, regenerate the favicons from it, and delete the exception from `docs/02` and this row. Raised by Claude Code 2026-08-26; scoped by Pouya the same day | Nothing — the mark renders correctly. This is fidelity and payload, not function |
| ~~Q32~~ | **ANSWERED 2026-08-26 — and the answer was that the reconstruction was WRONG.** Pouya rendered the committed path against the master (`SML Company Just Logo Transparent.png`, 3000×3000) and rejected it on three counts. Two reproduce from the path alone: **(a) TANGENT, NOT CROSSING** — all four cubic branches meet the origin at exactly 90°, so the loops are mutually tangent on a vertical line and at stroke-width 28 render as *two kissing circles*, the one thing an infinity mark must not be `[verified 2026-08-26 — tangent vectors computed per segment, independently reproduced]`. Both lobes are strictly confined to their own half-plane (x is monotone on every segment), so the signed crossing number is **0** — they cannot cross anywhere, not merely at the node. Worse at the size actually shipped: the two strokes stay fused into one mass wherever the centreline separation `y²/192` is under 28, i.e. across **61% of the mark's height** — at 2rem that is a 16.8px blob out of a 27.4px-tall mark. No stroke-width, viewBox or scale change can produce a crossing from this centreline; **(b) WRONG PROPORTION** — the master's ink bounding box is **2668 × 1704 = 1.5657:1** `[verified 2026-08-26 — measured]`, and **(c)** the master is a shaded ribbon where the trace was two flat uniform strokes. ***1.23:1 — RECONCILED, and it was a real measurement, not a slip.*** It is the bounding box of the path's **coordinates** rather than of the **curve**. The control points sit at y = ±160 while the curve only reaches ±120 — the standard 3/4 pull-in of a cubic — so a coordinate-hull box is 400 × 320 = 1.2500, and with stroke-width 28 applied on all four sides it is **428 × 348 = 1.2299**. Pouya's figure to four significant figures, from one method applied consistently `[verified 2026-08-26 — derived]`. **It is a trap rather than a slip:** because x is monotone on every segment, the control points give the *correct* width (±200) and a 33% inflated height, so the obvious sanity check — "does the width look right?" — passes. Any tool that reads a bbox from parsed coordinates lands here; `getBBox()` would have returned 400 × 240. **And the direction is inverted from how it read:** measured from the curve, the traced path is 6.4% *wider and flatter* than the master, not squatter. **Consequence worth keeping:** the declared viewBox 440:280 = 1.5714 is within **0.35%** of the master's 1.566, so re-tuning the layout to the true ratio was ~0.18px of work at the shipped 2rem — and **re-tuning to 1.23 would have actively broken it** — at any given width 1.2299 allocates 1.5657/1.2299 = **27% more height** than the mark occupies, so the header would have been rebuilt around a box a quarter too tall. The ratio was never sufficient grounds on its own; **(a) tangency is, and it is exact.** **The traced path is deleted, not kept as a fallback**, on Pouya's instruction: *a wrong mark that renders is worse than a missing one, because it stops looking wrong.* Now closed by Q38 for the vector master | — |
| ~~Q32-orig~~ | *(superseded — the original wording of this question is preserved in entry (v))* | `src/components/InfinityMark.astro` is built from geometry lifted verbatim from the deployed site's own loading-thumbnail SVG — the element it labels `smlMark`, fetched from `https://adr.smlcompany.ca/` on 2026-08-26. Path, both stroke widths (28 / 6) and the 0.7 inner opacity are the source's; the only change is folding a `translate(60 0)` into the coordinates. So it is SML's own artwork rather than a redrawing — but a loading placeholder is not necessarily the canonical file, and D7 says the mark carries over *unchanged*. If a master SVG or AI/EPS exists, supply it and the component gets replaced. Raised by Claude Code, 2026-08-26 | Nothing — the mark renders. This is about fidelity, not a blocker |
| **Q23** | **Is a Gitea `act_runner` registered, and are Actions enabled in `app.ini`?** *The version half is closed:* the instance reports **1.27.2** `[verified 2026-08-26 — /api/v1/version]`, so the `vars` context is supported and the first-step guard is belt-and-braces rather than load-bearing. **What remains is not a fact to look up but a dependency on a person:** git.larsnolden.com is **jointly administered**, and both enabling Actions and registering a runner need the second administrator. Until then `npm run deploy` is the path, and it is documented rather than treated as a workaround | How deploys are triggered — not what they do |
## 10. Risks
@@ -418,6 +558,8 @@ never being raised again.
| R10 | **Annually-renewing memberships.** §4 verifies the **OBA sections** (Construction & Infrastructure, ADR, Civil Litigation) and the **Canadian Tax Foundation** as of 2026-08-26 — *for now*. Both renew yearly. *Widened 2026-08-26 when CTF was added; it was OBA-only before* | 2026-08-26 | A credential that lapses quietly is the failure mode §4 exists to prevent, and OCNI already did exactly this (§4 records it as "not current, do not publish"). Re-confirm at each renewal, and before any page listing memberships ships — `/about/` at build step 3 is the first one that will |
| R11 | **Re-check dependency currency at every phase boundary in the build order** (`docs/01-architecture.md` §Build order, 11 steps). Run `npm view <pkg> version` across **every** pin in `package.json` and compare; do not wait for something to break. Verified does not mean latest — record the reason for any deliberate hold in §7. **Carries one specific re-add trigger: at step 7, put `@lhci/cli` back.** Check for a patched release — do not assume `0.15.1` is still the ceiling just because it was on 2026-08-26 — pin it against `npm view` that day, write a `lighthouserc` with the budgets from `docs/04-seo-spec.md`, and delete the UNAVAILABLE notices this repo now carries in six places (§7 lists them). If the advisories are still unfixed, that is a decision to take deliberately, not a reason to leave the gap unstated | 2026-08-26 | `astro: "^5.0.0"` was recalled rather than checked and was two majors stale the day it was written, which meant a framework carrying high-severity XSS advisories. Between phases is cheap; after a phase of pages is written is not. The build order has ten more boundaries |
| R12 | **`compressHTML: true` is a deliberate deviation from the Astro 7 default (`'jsx'`).** Measured 2026-08-26: in an `.astro` template an inline pair split across two lines renders as `<em>a</em><strong>b</strong>` under the default — the space is silently deleted. MDX prose is unaffected | 2026-08-26 | It is a deviation, and undocumented deviations become folklore. Revisit **with a measurement**, not a preference — and re-measure after any Astro major, since the behaviour could change again |
| R13 | **The infinity mark ships as a RASTER, and that is temporary.** `InfinityMark.astro` renders an optimised AVIF/WebP from `src/assets/brand/sml-infinity-mark.png` — a deliberate, documented exception to `docs/02`'s "inline SVG, never a PNG", because the mark is gradient-mesh artwork and no true vector master exists yet (Q38). **Removal trigger: the commissioned vector master lands.** Then replace the `<Picture>` with inline SVG, regenerate `favicon.ico` and `apple-touch-icon.png` from it, and delete the exception from `docs/02`, from the component, and from Q38 | 2026-08-26 | Pouya flagged this himself when he made the ruling: *an interim raster is exactly the kind of temporary measure that becomes permanent by never being raised.* It costs ~8 KB and works, which is precisely why nobody will notice it again. There is no build error to prompt anyone — only this row |
| R14 | **Anything a spec makes a claim about must be reachable from the repository.** If the artefact lives only in Drive, in a console, or on someone's disk, no reviewer can check the claim and the claim is unverifiable by construction — see the rule now in `CLAUDE.md` | 2026-08-26 | **This has now cost twice.** Q24 was `AWS-Hosting-Guide.md`, the only record of how the infrastructure was hand-built, living outside the repo. Q32 was the infinity mark: Claude Code traced it from the old site's *loading placeholder*, wrote a scrupulous provenance comment recording exactly that doubt — and **two adversarial review passes still could not catch it**, because the artwork they would have had to compare against was not in the repo. The doubt was correctly stated and structurally uncheckable. That is the failure mode: not a missing warning, a missing artefact |
| ~~R7~~ | **RATIFIED / SUPERSEDED 2026-08-26.** (a) Cache-policy table matching the pipeline — **accepted**; documenting what the pipeline does beats documenting an intention. (b) `s3:AbortMultipartUpload` omitted — **accepted, reasoning corrected**: the lifecycle rule does not exist and is therefore not the cover; the actual cover is that `aws s3 sync` only goes multipart above 8 MB and the largest asset is a 357 KB portrait. Recorded in `docs/06-deployment.md` with a revisit trigger. (c) The `aws s3 ls` pre-flight — **superseded** by the variable guard now running as the workflow's first step | 2026-08-26 | — |
| ~~R8~~ | **PROMOTED TO A RULE 2026-08-26.** A reminder was too weak for a pattern that survived three entries. *A sweep is a command, not a claim* now sits in `CLAUDE.md` under Conventions, in `/build` Phase 6, and in `/wrap` step 3: any claim that a change was applied across files must cite the command and be written only after reading its output | 2026-08-26 | — |
@@ -425,6 +567,268 @@ never being raised again.
# Change Log
## 2026-08-26 (v) — The mark was wrong; §4 gains an Offerings category; and two of my own tools lied to me
**Who:** Pouya ruled on the mark (Q32), on arbitration (Q33, Q36), and on the
asset convention. Claude Code implemented; `adversarial-reviewer` and
`claims-auditor` ran on the result. **The claims audit returned FAIL with 13
findings, and the sharpest of them were against text written an hour earlier in
this same entry's work.** Most of what follows is those findings.
### Q32 — the infinity mark was a wrong shape, and it had shipped
Pouya rendered the committed path against the master and rejected it. Two of his
three grounds reproduce from the path alone and are now verified here:
- **TANGENT, NOT CROSSING.** All four cubic branches meet the origin at exactly
90°, so the loops are mutually tangent on a vertical line rather than crossing.
At stroke-width 28 that renders as **two kissing circles** — the one thing an
infinity mark must not be `[verified 2026-08-26 — tangent vector computed per
segment]`. This alone disqualifies the shape.
- **WRONG PROPORTION.** The master's ink bounding box is **2668 × 1704 =
1.5657:1** `[verified 2026-08-26 — measured]`.
- **FLAT.** Two uniform strokes standing in for a shaded ribbon: a band of
variable width twisting in three dimensions, maroon into champagne, passing
over itself at the crossing.
**The 1.23:1 figure is reconciled, and it was a real measurement.** It is the
bounding box of the path's **coordinates**, not of the **curve**: control points
sit at y = ±160 where the curve reaches only ±120, so the coordinate hull is
400 × 320, and with stroke-width 28 on all four sides **428 × 348 = 1.2299**.
Pouya's number exactly. It is a trap rather than a slip — x is monotone on every
segment, so the control points give the *right* width and a 33% inflated height,
and the usual "does the width look right?" check passes.
Two consequences worth keeping. **The direction was inverted:** measured from the
curve, the traced path is 6.4% *wider* than the master, not squatter. And the
declared viewBox 440:280 = 1.5714 sits within **0.35%** of 1.566 — so step 3 of
the ruling, re-tune the layout to the true aspect, was **0.18px of work at the
shipped 2rem**, and re-tuning to 1.23 would have *broken* it: for any
given width, 1.2299 allocates 1.5657/1.2299 = **27% more height** than the mark
actually occupies, so the header would have been rebuilt around a box a quarter
too tall. Where 1.566 does matter is step 2: a tight crop to ink is
exactly the measurement where 1.667 and 1.566 differ visibly, which is why the
render source is cropped to the master's ink box and pinned at `667 / 426` rather
than inheriting 11:7. **The ratio was never sufficient grounds on its own.
Tangency was, and it is exact** — both lobes are confined to their own
half-plane, so the signed crossing number is 0, and at 2rem the strokes fuse into
a single mass across 61% of the mark's height.
**The traced path is deleted, not kept as a fallback**, on Pouya's instruction:
*a wrong mark that renders is worse than a missing one, because it stops looking
wrong.* `public/favicon.svg` deleted with it; the favicon chain is regenerated
from the real artwork.
### Why two review passes could not catch it — and the rule that follows
`InfinityMark.astro` carried a scrupulous provenance comment stating that the
path was traced from the **old site's loading placeholder** and that a
placeholder is not necessarily canonical. It was correct, it was prominent, and
**it did not help**, because the artwork it would have to be checked against was
not in the repository. The doubt was stated and structurally uncheckable.
**New rule in `CLAUDE.md`, and R14:** *anything a spec makes a claim about must
be reachable from the repository.* If the artefact lives only in Drive, in a
console, or on a laptop, the claim is **unverifiable by construction**, not
merely unverified. Second occurrence — Q24 was `AWS-Hosting-Guide.md`, the only
record of how the infrastructure was built, living outside the repo.
### Two process failures of my own, both in the same shape
1. **I reported the brand assets unreachable. They never were.** Four commands of
the form `timeout 60 ls "$DRIVE"` returned empty output; I read that as an
empty directory and told Pouya the ruling could not be executed. **`timeout`
is not installed on macOS** — the commands had never run. The Drive was fully
readable the whole time and the masters were found within a minute of using a
tool that exists.
2. **I reported malformed HTML**`<picture="true">` and
`style="block-size:2rem"="true"` — and rewrote a component around it. It was
**my own regex**, stripping an attribute's name and leaving its value. The
markup was always valid. The rewrite was reverted.
Both are the same failure as *a sweep is a command, not a claim*: an assertion
resting on output that was never produced, or was produced by my own filter.
**New rule in `CLAUDE.md`:** *a command that did not run is not evidence of
absence* — check the tool exists, read exit status, not just stdout.
### What the mark is now
`src/assets/brand/` holds the master (3000 × 3000, alpha), the tight crop that is
the render source (2668 × 1704, so **the file's aspect ratio is the mark's**),
the full lockup, and the SVG Pouya added. `InfinityMark.astro` renders it through
Astro's `<Picture>`; a browser downloads **3,063 bytes** of AVIF on a Retina device.
**Correction inside this entry.** The SVG was first described here and in three
files as "a raster in a vector wrapper". That was unfair: rasterised at 8333 px
it **reproduces the master exactly, at the same 1.566:1** `[verified 2026-08-26]`.
What rules it out is **payload and composition** — 257,278 bytes against 9,468,
plus seven embedded base64 PNGs that would breach `CLAUDE.md`'s no-base64 rule.
Corrected in the component, `docs/02`, Q38 and `docs/reference/brand-assets.md`.
**`width={320}` on `<Picture>` is load-bearing.** Without it Astro emits the
untouched 2668 px master as the `<img src>` fallback — **1,146,406 bytes** — sitting
in `dist` looking like an optimisation had happened.
**Documented, temporary exception to `docs/02`'s "inline SVG, never a PNG"**,
tracked as **Q38** (a vector master that is faithful *and* light) with **R13** so
it cannot become permanent by neglect — Pouya's own warning when he made the
ruling.
### Q33 and Q36 — arbitration, and a new §4 category
**Both answered: Pouya accepts arbitration appointments now** — sole,
party-appointed and co-arbitration. His reasoning: ADR designations are
**voluntary credentials, not licences**, so the constraint was always
**positional**, never legal. `Mediation · Arbitration · Toronto` is **restored to
the masthead**; `docs/04`'s home `<title>` stands as specified.
**§4 gains an Offerings subsection** — a second category beside the credential
register, with the test: **competence for an offering, permission for a
credential.** Three specs that asserted the converse were swept
(`docs/01`, `docs/03`, `docs/07-fees.md`) — and that sweep had been *claimed* in
the Q36 closure before it was *run*, which `claims-auditor` caught. `docs/03`'s
model sentence was wrong in **both** halves and in opposite directions, which is
why it had survived two audits.
### What the claims audit found in the new section, and how it was resolved
Four structural defects in text written the same hour:
- **The masthead justification answered the wrong objection.** Q33-orig had
objected to **placement** — a line under his name on every page *"where nothing
qualifies it"* — not to entitlement. The section refuted an entitlement
objection nobody raised. Corrected, and the substitution is recorded rather
than tidied away.
- **§4's own paired-disclosure condition was unmet by the shipped build.** The
section says the site *"makes the first while stating the second plainly"* and
*"neither half may be dropped"* — yet the masthead shipped on every page while
the Q.Arb stage shipped on none, and `CREDENTIALS.inProgress` existed in
`site.ts` rendered nowhere. **The footer designation strip now reads
`Q.Med (ADRIC / ADRIO) · Q.Arb — commenced August 2026` on every page.**
- **The offering test handed the gating question to the subject.** Its closing
sentence, *"that is his call, not the register's"*, attached to the whole
preceding question including *whether the activity is gated* — a clean
walk-through for a future writer. Split in two: **gating is this register's
question and needs a checkable source; competence is his and only his.**
- **The category had no gate and no defined extent.** No rule said an offering
needs a row before it may be published, and `Med-Arb` was sitting in the
site-wide footer as an offering three sentences below a paragraph saying not to
infer exactly that. Both fixed: the publication rule is stated, scope is
defined (**an offering is a PROCESS; a subject-matter area is not**), and
**Med-Arb is removed from the footer pending Q35(a)**.
**And the finding that matters most: four unsourced propositions of Ontario
law.** *"Anyone may be appointed an arbitrator in Ontario. Nothing in law gates
the role behind a designation."* `[verified — Pouya]` means *the subject reported
it*, which can establish what he offers and **cannot establish a proposition of
law**. The auditor produced a counter-example from inside the repo: the site
ships a **Shareholder & Family Business** practice area, and **family**
arbitration in Ontario is understood to be one of the places where arbitrator
qualification *is* prescribed. §4 now carries the proposition as **the
architect's stated basis, deliberately unstamped**, scoped to **commercial**
arbitration, with the universal removed — and **Q39** opened. This record will
not assert Ontario law, and neither will a self-report.
### Questions and reminders
**Closed:** Q32 (the reconstruction was wrong), Q33, Q36.
**Narrowed:** Q35 — `Arbitration` resolved; **Med-Arb** and the two
subject-matter labels remain, now under the scope note that says which rule
governs them.
**Opened:** **Q38** (vector master), **Q39** (family arbitration and gating).
**§12:** **R13** (the raster is temporary), **R14** (assets must be in-repo).
### Verification — run, not asserted
`npm run check` 0/0/0 · `npm run lint` clean · `npm run build` 0 errors ·
`npm audit` **0 vulnerabilities**.
Measured in headless Chrome at 320/375/640/768/1000/1023/1024/1100/1199/1200/1201/1279/1280/1281/1440/1600,
**with a seventh nav item injected** for the step-7 state:
- **0 overflow, 0 focus-order inversions, 0 tap targets under 44 × 44** at every
width; closed `<details>` panels contribute 0 hidden tab stops
- Header a constant **81px** at every sticky width — 32 padding + 48 reserved
brand block + **the 1px border I had forgotten**, which is why `--header-h` is
measured rather than added up
- Restoring the tagline **broke the 64rem fit** (84px past the content box at
1024 with seven items) and was re-tuned: tagline gated at 75rem, nav gap moved
to **80rem so two things do not grow at one breakpoint** — 4px of spill at
exactly 1200px caught that
- **0 `<script>` tags, 0 `.js` files**; both scroll-driven animations attach live
- Print: all four revealed cards present · **760 words** with no JavaScript
### ⏸ RESUME HERE — session ended mid-flight, 2026-08-26
Pouya went mobile. The tree is committed and green; nothing is half-applied.
**Pick up at the numbered list below.**
**State:** `npm run check` 0/0/0 · `npm run lint` clean · `npm run build` 0
errors · `npm audit` 0 vulnerabilities. Both `adversarial-reviewer` blocking
findings on the mark are fixed and re-measured. Build step 1 is complete; step 2
is `/` (`docs/01` §Build order).
**Waiting on Pouya — nothing proceeds on these without a ruling:**
1. **Q35** — may the nav and footer name `Med-Arb`, `Energy, Grid & Regulatory`
and `Shareholder & Family Business`? Both halves go to him **together**;
`Med-Arb` was removed from the footer for a few hours and restored, because
acting on one half unilaterally was wrong and orphaned the page.
2. **Q39** — family arbitration. §4's arbitration rows are scoped to
**commercial** pending an answer. This one has a legal dimension the register
cannot resolve from a self-report.
3. **Q37** — is `JD + ML → "Law and engineering"` the right label? Answer before
step 2 renders the credential row.
4. **Q38 / R13** — the commissioned vector master. Until it lands the mark ships
as a raster under a documented exception.
5. **R1** — the licensure framing is interim and now carried by shipped pages.
**Unresolved review findings, all non-blocking, none shipped-defect:**
- `adversarial-reviewer` #7: `gap: 2px` and `font-size: 0.6875rem` in
`SiteHeader` are magic numbers; add `--text-2xs` / `--space-05` or record the
deviation.
- #8: Astro's `<Picture>` + `densities` emits a duplicate `1x` descriptor in
`srcset` — an HTML conformance error, harmless in browsers. Do not claim
"validator clean" on a page carrying it.
- #9: `--header-h` has 0.81 px of headroom at ≥76 rem. A font-metric change
pushes the brand past its 48 px reservation with no build error.
- #10: the masthead tagline duplicates the home hero eyebrow, so `/` will open
with the same words twice. Decide at step 2.
- #11: ~3.16 MB of brand binaries; the 1.1 MB derived crop is reproducible from
the committed master and could go if Astro could crop at build time.
- #12: `InfinityMark`'s `label` and `class` props have no call site.
**One correction owed to the record.** Entry (v)'s verification section says
"0 overflow at every width". That was true and **misleading** — the page-level
check passed *because* the brand block absorbed the deficit by crushing the
logo. The harness now asserts the rendered aspect ratio of every mark instance,
not just document overflow. Measure the elements, not only the page.
### Declined and deferred
- **The remaining Q35 labels** — locked architecture; not an implementer's call.
- **A verification workflow was run and half of it was wasted, which is worth
recording rather than hiding.** It was launched while the artwork was believed
unreachable, and briefed accordingly; the premise died four minutes later when
the assets were found. Its *design* strand — three proposals for coping without
the artwork — was answered by reality and discarded. Its *geometry* strand did
not depend on that premise at all, and it is what **reconciled 1.23:1** above,
proved the zero crossing number, and computed the fused-waist figure. The
lesson is not "don't delegate" but "scope a brief to what cannot change under
it": a premise about the environment goes stale, a question about the contents
of a committed file does not.
- **`Technology, AI & Data` and the other three practice labels**, raised as
offering claims with no rows: answered structurally rather than individually —
subject-matter areas are **not** offerings, so the Offerings table is not the
rule that governs them. `docs/03`'s framing rule and Q35 are.
- **`docs/reference/brand-assets.md` reproducing R14** — the auditor was right
that every measurement derived from a master outside the repo. **Fixed, not
declined:** the uncropped master is now committed, so the crop is re-derivable
in-repo, and every figure carries a stamp.
---
## 2026-08-26 (u) — Build step 1. Zero JavaScript, and both review passes found defects in the first pass's fixes
**Who:** Pouya ruled on CTF, Q30, Q31 and the Lighthouse gap, and set the
+24
View File
@@ -152,6 +152,30 @@ interactive elements reachable by keyboard, `prefers-reduced-motion` honoured on
every animation. Gold `#c9a876` never sits on cream — it fails contrast at
2.10:1. See `docs/02-design-system.md`.
**Anything a spec makes a claim about must be reachable from the repository.**
If the artefact lives only in Drive, in a console, or on someone's laptop, no
reviewer can compare the claim against it and the claim is **unverifiable by
construction** — not merely unverified. Commit the artefact, or commit a faithful
extract with its provenance and the command that produced it.
This has cost twice. `AGENTS.md` Q24 was the AWS hosting guide, the only record
of how the infrastructure was hand-built, living outside the repo. Q32 was the
infinity mark: it was traced from the old site's *loading placeholder*, the
source comment said so in as many words — and **two adversarial review passes
still could not catch that the shape was wrong**, because the real artwork was
not in the repo to compare against. Stating a doubt is not enough when the thing
that would resolve it is unreachable. Tracked as R14.
**A command that did not run is not evidence of absence.** Check that a tool
exists before trusting its silence, and read exit status, not just stdout. This
project ran `timeout 60 ls "$DRIVE"` four times, got empty output each time, and
reported the brand assets unreachable — `timeout` is not installed on macOS, so
the command had never executed and the directory was fully readable all along.
Empty output from a command that failed to start looks exactly like empty output
from a command that found nothing. Same family as *a sweep is a command, not a
claim*: the claim must rest on output you actually read, from a command that
actually ran.
**A parent cannot style a child component's root element.** Astro does not pass
a parent's scope attribute down, so `<Button class="header-cta" />` compiles the
parent's rule to `.header-cta[data-astro-cid-<parent>]` while the rendered `<a>`
+10 -7
View File
@@ -193,14 +193,17 @@ neutral.
3. **Rules:** ADRIC, ADR Chambers, ad hoc.
4. Awards — form, reasoning, timing.
5. **Credentialing status, stated plainly.** The Q.Arb pathway is in progress;
the page says so and describes what is available now versus what follows
designation. Honesty here is a differentiator, not a weakness — and
misstating it is a conduct problem. **What "available now" consists of is
`AGENTS.md` Q36 and is NOT yet in §4** — this line, `03-content-spec.md`, and
`07-fees.md` all assert co-arbitration availability off the same unverified
premise. Do not write it onto the page until Q36 closes.
the page says so. **What is available now is all three forms — sole,
party-appointed and co-arbitration** — and `AGENTS.md` §4 Offerings carries a
row for each `[verified 2026-08-26 — Pouya]`. The page states that alongside
the credentialing stage: Q.Arb commenced August 2026, C.Med-Arb is the
endpoint. §4 Offerings: **neither half may be dropped.** Honesty here is a
differentiator, not a weakness — and misstating it in either direction is a
conduct problem.
*(This paragraph read "(co-arbitration, co-arbitration)" until 2026-08-26 —
edited without being re-read, which is how the unverified half travelled.)*
edited without being re-read — and then carried a caveat against Q36 for
several hours after Q36 closed. Both are recorded because the pattern is the
same one: an edit that was not re-read against the register.)*
6. Fees, booking.
### `/med-arb/`
+8 -2
View File
@@ -11,6 +11,12 @@ system that preserves it while fixing what the old build got wrong.
- The **palette**: cream, ink, maroon, gold.
- The **infinity mark** — SML Company Ltd.'s actual logo, and the metaphor holds:
a dispute is a loop, and the work is redrawing the loop into a line.
**It is a shaded ribbon, not a stroked curve**: a band of variable width that
twists in three dimensions, maroon flowing into champagne, passing over itself
at the crossing. Ink bounding box **2668 × 1704 = 1.5657:1**
`[verified 2026-08-26 — measured against the master]`. Source of truth:
`src/assets/brand/sml-infinity-mark.png`; provenance in
`docs/reference/brand-assets.md`.
- The **type pairing**: Instrument Serif for display, Geist for text, Geist Mono
for eyebrows and labels.
- The **editorial register** — generous whitespace, restrained colour, serif
@@ -177,8 +183,8 @@ except the reveal of the hero.
| Component | Notes |
|---|---|
| `InfinityMark` | Inline SVG, `currentColor`, `aria-hidden` when decorative. Never a PNG |
| `SiteHeader` | **Sticky from 64rem (1024 px) up; static below it.** Practice dropdown as CSS-only `<details>`. *Amended 2026-08-26, both halves by measurement:* **(a)** the one-row header has to hold the brand, **seven** nav items and the CTA — Insights is the seventh and arrives on its own at build step 7 — and it does that at 1024 px with 32 px of clearance, not below. Under 64 rem the nav takes its own row and the header measures **137 px** at tablet widths and **185 px** at 320375 px, which is more of a small viewport than a sticky header is worth, so it scrolls away there. *(This row first said 60 rem and "~115 px". Both were wrong — the threshold moved when the seven-item case was measured, and 115 px was never a height the header took at any width. Corrected against headless-Chrome measurements at thirteen widths.)* **(b)** "Condenses on scroll" is now **a hairline rule and a shadow, not a size change.** A `position: sticky` header stays in normal flow, so its layout box sits at the top of the document whatever the viewport shows; shrinking its padding shortens that box and lifts every page below it — a scroll-linked layout shift on every page, against the CLS < 0.05 budget in `04-seo-spec.md`. Implemented with `animation-timeline: scroll()`, **longhands only** — see the note in the component about what the minifier does to the `animation` shorthand |
| `InfinityMark` | ⚠️ **Currently a raster — a documented, temporary exception to this rule** (`AGENTS.md` Q38, R13). The mark is gradient-mesh artwork rather than flat vector paths. An SVG *is* held and it renders faithfully — but at 257,278 bytes against 3,063 for the AVIF a Retina browser takes, carrying seven embedded base64 PNGs that would breach `CLAUDE.md`'s no-base64-images rule. The exception is about payload and composition, not about fidelity. It renders AVIF/WebP with a PNG fallback; a Retina device takes 3,063 B of AVIF, `alt=""` when decorative, aspect ratio pinned to `667 / 426`. **Restore this rule the moment the commissioned vector master lands.** Until then the rule stands unchanged for every other mark or icon: inline SVG, `currentColor`, `aria-hidden` when decorative, never a PNG |
| `SiteHeader` | **Sticky from 66 rem (1056 px) up; static below it.** Practice dropdown as CSS-only `<details>`. **(a)** The one-row header holds the brand, **seven** nav items and the CTA — Insights is the seventh, arriving on its own at build step 7. Binary search on the built page puts the true fit at **1047 px**; 66 rem is the clean token above it. Below 66 rem the nav takes its own row and the header measures **141 px** at tablet widths and **189 px** at 320375 px. **(b)** "Condenses on scroll" is a hairline rule and a shadow, **not a size change** — a `position: sticky` header stays in normal flow, so shrinking its padding lifts every page below it, against the CLS < 0.05 budget. Longhands only; see the component on what the minifier does to the `animation` shorthand. *(This row has been wrong twice, instructively. It first said 60 rem / "~115 px", a height the header never took. It then said 64 rem "with 32 px of clearance" — that 32 px was `.header-inner`'s own `column-gap` mistaken for slack; the real figure at 1024 px with seven items was **21.6 px**, and nothing overflowed only because flexbox crushed the logo inside the brand block. **Measure slack, not gaps.**)* |
| `SiteFooter` | Three-column sitemap, contact block, designations, entity line |
| `Eyebrow` | Mono label with optional maroon dot |
| `SectionHeading` | Eyebrow + display heading + optional lede, one measure |
+15 -5
View File
@@ -28,11 +28,21 @@ detect padding instantly and discount everything after it.
practice". The old site's "we" implied a firm that does not exist.
- Concrete nouns. *Lien claim. Change order. System Impact Assessment. Model
card. Minutes of settlement.* Specificity is the credential.
- Name the limits. "Sole-arbitrator appointments follow the Q.Arb designation;
co-arbitration work is available now." **The first half traces to §4; the
second does not — `AGENTS.md` Q36.** Keep the shape of the sentence, which is
the point being made here, and do not publish the second clause until Q36
closes. (**No tribunal-secretary work** — D14
- Name the limits — but name the *right* ones. This bullet carried the model
sentence *"Sole-arbitrator appointments follow the Q.Arb designation;
co-arbitration work is available now"* until 2026-08-26. **Both halves were
wrong and they were wrong in opposite directions**, which is why it survived
two audits: the first half understated (sole-arbitrator appointments are
offered **now** and are not gated by Q.Arb — §4 Offerings), and the second was
unsourced when written. §4 now carries rows for all three forms.
The shape of the bullet still stands, so here is a sentence that fits it and
clears the register: *"I accept sole, party-appointed and co-arbitration
appointments. The Q.Arb designation commenced in August 2026; C.Med-Arb is the
endpoint."* The limit being named is the **stage of the arc**, stated plainly —
Pouya's instruction is that being open about it is the differentiator, so do
not hedge it into vagueness and do not drop it. (**No tribunal-secretary
work** — D14
removed the rate and bars offering it; see `docs/07-fees.md`.) Precision about
what you cannot yet do makes the rest believable.
- Plain words over Latin. "Without prejudice" survives because it is a term of
+8 -4
View File
@@ -104,10 +104,14 @@ All figures **plus HST**.
### Arbitration
Available now as co-arbitrator; sole appointments follow the Q.Arb designation
**the co-arbitrator half is `AGENTS.md` Q36 and is not in §4.** Do not publish
it on `/fees/` until Q36 closes,
commenced August 2026. The page must say so — see `03-content-spec.md`.
Sole, party-appointed and co-arbitration appointments are all accepted now —
`AGENTS.md` §4 Offerings carries a row for each `[verified 2026-08-26 — Pouya]`.
*(This line previously read "sole appointments follow the Q.Arb designation",
which understated the offering, and carried a caveat against a since-closed
Q36.)* Whatever `/fees/` says about arbitration must state the Q.Arb stage
plainly alongside it — §4 Offerings, "neither half may be dropped": the Q.Arb
designation commenced August 2026, with C.Med-Arb as the endpoint. See
`03-content-spec.md` for the wording.
| Item | Fee |
|---|---|
+92
View File
@@ -0,0 +1,92 @@
# Brand assets — provenance
The repository holds the artwork it makes claims about. That is not tidiness: it
is `CLAUDE.md`'s rule and `AGENTS.md` R14, and this file exists because the
infinity mark was reconstructed wrongly and **two adversarial review passes could
not catch it**, since the real artwork was not in the repo to compare against.
**Every measurement below is `[verified 2026-08-26]`** — computed with `sharp`
against the files in this repository, and re-derivable by anyone from the
commands given. Nothing here is quoted from an external source.
## Files
| File | What it is | Use |
|---|---|---|
| `src/assets/brand/sml-infinity-mark-master.png` | The mark as supplied: **3000 × 3000, alpha**, mark inset within the canvas | **The master.** Committed so the crop below can be re-derived and checked in-repo, not taken on trust |
| `src/assets/brand/sml-infinity-mark.png` | The same mark tight-cropped to its ink bounding box: **2668 × 1704, alpha, 1.5657:1** | **The render source.** `InfinityMark.astro` feeds it to Astro's `<Picture>` |
| `src/assets/brand/sml-logo-full.png` | Mark **plus** the "SML Company" wordmark, 3000 × 3000, alpha; ink bbox 2414 × 1440 = 1.676:1 | Not currently rendered. Held for the OG-image template (`docs/04`) and print |
| `src/assets/brand/sml-logo-source.svg` | 1500 × 1500 viewBox, **257,278 bytes** | Reference. Faithful, but not what is served — see below |
## Reproducing the crop, in-repo
The crop is derived, so it is re-derivable — and now from a file that is here,
which is the whole point of R14. Scan the master for the first and last pixel
that is neither transparent (`alpha < 24`) nor near-white (`r,g,b > 243`):
```
ink bbox of sml-infinity-mark-master.png -> 2668 x 1704 at (159, 646)
sharp(master).extract({ left: 159, top: 646, width: 2668, height: 1704 })
```
Crop to that box and the file's own aspect ratio becomes the mark's, so layout
can be tuned against the asset directly rather than against a number written
down beside it. `InfinityMark.astro` pins `aspect-ratio: 667 / 426`, which is
`2668 / 1704` reduced — **1.56573**.
## Why the SVG is held but not served
It renders **faithfully**. Rasterised at 8333 px it reproduces the master
exactly, at the same **1.566:1**. It is not bad artwork, and an earlier version
of this file implied it was; that was wrong.
What rules it out is weight and composition:
- **257,278 bytes**, against **9,468 bytes** for the AVIF a browser actually
takes at the size the mark renders. **27×.**
- **7 embedded base64 PNGs** (`<image>` elements), so it is a hybrid rather than
pure vector — inlining it would breach `CLAUDE.md`'s rule against
base64-inlining images, which is one of the specific faults of the build this
project replaces.
- 10 `<linearGradient>` carrying **1,225 `<stop>`** elements, 64 `<path>`,
59 `<clipPath>`, 23 `<mask>`, 1 `<filter>`. Expensive to rasterise.
What `AGENTS.md` Q38 asks for is a master that is faithful **and** light.
## What the browser actually downloads
`<Picture>` emits AVIF, WebP and a PNG fallback at 1× and 2× of a 320 px
intrinsic width:
| | 1× (64 px) | 2× (128 px) | 3× (192 px) |
|---|---|---|---|
| AVIF | **1,720 B** | **3,063 B** | **4,843 B** |
| WebP | 2,368 B | 5,368 B | 8,664 B |
| PNG (fallback) | 6,137 B | 16,996 B | 29,780 B |
A Retina device takes **3,063 B**. The first attempt sized the ladder at 320 px
— justified by a 4 rem sample on the proof sheet, a page step 2 deletes — and
stacked `densities` on top, so every DPR-2 device pulled a 640 px image into a
56 px slot: **20,629 B**, and the docs claimed 9 KB because that is what DPR 1
takes. Size to the largest render that survives, and quote the figure for the
devices the budget targets.
Passing an explicit `width` is load-bearing: without it Astro emits the
untouched 2668 px master as the `<img src>` fallback — **1,146,406 bytes**
which any client without AVIF or WebP support would actually download.
## The colours are the artwork's, not the palette's
`tokens.css` is not involved. The ribbon carries its own gradient and it is
close to but not identical with `--maroon` `#5a1a1c` and `--gold` `#c9a876`.
Do not "correct" the artwork toward the tokens, and do not derive tokens from
the artwork — D7 keeps the palette *and* the mark, as they are.
## Where these came from
Supplied by Pouya. `sml-logo-source.svg` was added by him directly to the repo;
the PNGs were taken from the `smlcompany.ca` Google Drive, under `SML/Designs/`
and `Research/Law/ADR Personal Branding Project/`. **The Drive copies are not the
record — these files are.** That is the point of R14: an artefact that lives only
in Drive cannot be compared against a claim by any reviewer, which is exactly how
the traced mark survived two review passes.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

-17
View File
@@ -1,17 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-232 -232 464 464">
<!-- The SML infinity mark. Geometry and colours match
src/components/InfinityMark.astro — see the provenance note there.
Kept as its own file rather than imported: the browser requests a favicon
at a fixed path before any stylesheet resolves.
SQUARE viewBox, deliberately. The mark is 11:7; browsers render an SVG
favicon into a square slot with xMidYMid meet, so an 11:7 viewBox
letterboxes — the cream ground becomes a floating stripe with transparent
bars above and below, which on a dark tab strip reads as a graphical
artefact rather than a logo. The square ground fills the slot. -->
<rect x="-232" y="-232" width="464" height="464" fill="#faf7f2"/>
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M -200 0 C -200 -160, 0 -160, 0 0 C 0 160, 200 160, 200 0 C 200 -160, 0 -160, 0 0 C 0 160, -200 160, -200 0 Z" stroke="#5a1a1c" stroke-width="34"/>
<path d="M -200 0 C -200 -160, 0 -160, 0 0 C 0 160, 200 160, 200 0 C 200 -160, 0 -160, 0 0 C 0 160, -200 160, -200 0 Z" stroke="#c9a876" stroke-width="7" opacity="0.7"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 251 KiB

+95 -43
View File
@@ -1,29 +1,53 @@
---
/**
* The SML infinity mark. AGENTS.md D7 keeps it unchanged; docs/02 requires it
* be inline SVG rather than a raster. (The "~470 KB PNG" this comment used to
* cite had no source anywhere in the repo — see AGENTS.md Q34. The mark is
* geometry, which is reason enough without a number.)
* The SML infinity mark.
*
* PROVENANCE — read before editing the path. This geometry is lifted verbatim
* from the deployed site's own loading-thumbnail SVG (the element it labels
* `smlMark`), fetched from https://adr.smlcompany.ca/ on 2026-08-26. The only
* change is arithmetic: the source drew the path offset by `translate(60 0)`
* inside a 1200×800 frame, and that offset is folded into the coordinates here
* so the curve is symmetric about the origin. Stroke widths (28 outer, 6 inner)
* and the 0.7 inner opacity are the source's.
* ⚠️ DELIBERATE, TEMPORARY EXCEPTION TO docs/02's "inline SVG, never a PNG".
* Tracked as AGENTS.md Q38, with a standing reminder (R13) so it cannot become
* permanent by neglect. Read both before changing this file.
*
* It is therefore SML's own artwork, not a redrawing — but it came from a
* loading placeholder, which is not necessarily the canonical file. See
* AGENTS.md Q32.
* WHY A RASTER — and the reason is PAYLOAD, not fidelity. The mark is not a
* stroked curve; it is a shaded ribbon of variable width that twists in three
* dimensions, maroon flowing into champagne, passing over itself at the
* crossing. That is gradient-mesh artwork, not the flat vector paths docs/02
* assumes.
*
* Two-tone by design: the outer stroke takes `currentColor` so the mark sits
* correctly on cream, ink, and maroon; the inner hairline is gold. Gold as an
* icon stroke is explicitly allowed — the rule it must never break is gold as
* TEXT on cream, which measures 2.10:1 (docs/02).
* We do hold an SVG — src/assets/brand/sml-logo-source.svg — and **it renders
* faithfully**: rasterised at 8333px it reproduces the master exactly, at the
* same 1.566:1 [verified 2026-08-26]. An earlier version of this comment implied
* it was inadequate artwork. It is not; that was unfair and is corrected here.
* What rules it out is weight and composition: 257,278 bytes against 3,063 for
* the AVIF a Retina browser takes — 84× — and SEVEN embedded base64 PNGs plus
* a 1,225-stop gradient mesh, so inlining it would breach CLAUDE.md's rule
* against base64-inlining images. The exception ends when a vector master lands
* that is both faithful AND light.
*
* WHAT THIS REPLACES, and why it had to go. Until 2026-08-26 this component
* drew a hand-traced cubic path lifted from the old site's loading thumbnail.
* Pouya compared it against the master and it was wrong in three ways; two are
* reproducible from the path itself:
*
* 1. TANGENT, NOT CROSSING. All four branches met the origin at exactly 90°,
* so the loops were mutually tangent on a vertical line rather than
* crossing. At stroke-width 28 that renders as two circles kissing — the
* one thing an infinity mark must not be. Verified by computing the
* tangent vector of every segment at the origin.
* 2. WRONG PROPORTION. The real mark's ink bounding box is 2668 × 1704 =
* 1.5657:1. The traced path measured 1.667:1 ink / 1.597:1 stroked.
* 3. FLAT. Two uniform strokes standing in for a shaded ribbon.
*
* It is deleted rather than kept as a fallback, on Pouya's instruction: a wrong
* mark that renders is worse than a missing one, because it stops looking wrong.
*
* SOURCE OF TRUTH. src/assets/brand/sml-infinity-mark.png is the master tight-
* cropped to its ink bounding box, so the file's aspect ratio IS the mark's and
* layout can be tuned to it directly. Provenance: docs/reference/brand-assets.md.
*/
import { Picture } from 'astro:assets';
import mark from '../assets/brand/sml-infinity-mark.png';
interface Props {
/** Rendered height. Width follows the 11:7 aspect ratio. */
/** Rendered height. Width follows 1.5657:1. */
size?: string;
/** Accessible name. Omit for decorative use — the default. */
label?: string;
@@ -31,36 +55,64 @@ interface Props {
}
const { size = '1.75rem', label, class: className } = Astro.props;
const decorative = label === undefined;
const PATH = `M -200 0
C -200 -160, 0 -160, 0 0
C 0 160, 200 160, 200 0
C 200 -160, 0 -160, 0 0
C 0 160, -200 160, -200 0 Z`;
// Sized to the largest render that SURVIVES, which is the footer at 2.25rem =
// 56.4 CSS px wide. The first attempt used 320px, justified by the 4rem sample
// on the proof sheet — a page step 2 deletes — and then stacked densities on
// top, so the ladder double-counted its own headroom and every Retina device
// pulled a 640px image into a 56px slot.
//
// PASSING A WIDTH EXPLICITLY IS STILL THE POINT. Without it Astro emits the
// untouched 2668px master as the <img src> fallback: 1,146,406 bytes, which any
// client without AVIF or WebP support would actually download, sitting in dist
// looking like an optimisation had happened.
const INTRINSIC_WIDTH = 64;
---
<svg
<Picture
src={mark}
width={INTRINSIC_WIDTH}
densities={[1, 2, 3]}
formats={['avif', 'webp']}
fallbackFormat="png"
alt={label ?? ''}
loading="eager"
decoding="async"
class:list={['mark', className]}
viewBox="-220 -140 440 280"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
role={decorative ? undefined : 'img'}
aria-hidden={decorative ? 'true' : undefined}
aria-label={label}
focusable="false"
style={`block-size:${size}`}
>
<path d={PATH} stroke="currentColor" stroke-width="28"></path>
<path d={PATH} stroke="var(--rule)" stroke-width="6" opacity="0.7"></path>
</svg>
pictureAttributes={{ style: `block-size:${size}` }}
/>
<style>
.mark {
/* 440 : 280 — the viewBox. Height is set inline; width follows. */
aspect-ratio: 11 / 7;
inline-size: auto;
/* THE FLEX ITEM IS THE <picture>, NOT THE <img>.
`class:list` lands on the <img>, which Astro's <Picture> wraps in a
<picture> — and that wrapper is what `.brand`'s flex layout actually sizes.
So `flex: none` on .mark reached the wrong box entirely and the mark was
free to be squeezed: measured 28.52 x 32 at 1024px with seven nav items,
against a correct 50.09 x 32 — an aspect of 0.891 where it should be 1.5657.
This is the SAME defect CLAUDE.md already records for <Button> in
SiteHeader — a parent cannot style a child component's root — reintroduced
inside the fix for it, one round later. The bare `picture` selector below is
scoped by Astro's cid, which the emitted markup does carry, and the height
now goes on the wrapper via `pictureAttributes` rather than on the image.
Worse than the bug: the page-level overflow check passed throughout, because
the brand block absorbed the deficit by crushing the logo. "0 overflow at
every width" was true and misleading — it measured the document, not the
elements inside it. The harness now asserts the rendered aspect ratio. */
picture {
display: block;
flex: none;
aspect-ratio: 667 / 426;
inline-size: auto;
}
.mark {
/* 2668 / 1704 reduced — the master's exact ink bounding box, so the box the
layout reserves is the shape that fills it. */
inline-size: 100%;
block-size: 100%;
/* Belt and braces: if anything ever squeezes the box again, the artwork
letterboxes instead of distorting. */
object-fit: contain;
}
</style>
+23 -1
View File
@@ -27,6 +27,17 @@ import InfinityMark from './InfinityMark.astro';
// deployed, which is the same cadence everything else here updates on.
const year = new Date().getFullYear();
// Med-Arb was filtered out of this column for a few hours on 2026-08-26 and is
// RESTORED, because removing it was wrong on three counts and `adversarial-
// reviewer` caught all three. (1) docs/01 specifies this footer as the FULL
// sitemap and lists /med-arb/ as deliberately out of the primary nav, "linked
// contextually" — so dropping it here left the page with no site-wide link at
// all, on a project whose entire premise is crawlability. (2) The label names a
// PAGE, and docs/01 frames that page around the C.Med-Arb arc rather than as a
// present offering, so listing it is not the §4 inference it looked like.
// (3) It settled half of Q35 unilaterally while the other half — Energy and
// Shareholder — stayed in both nav and footer, and the record claimed no
// unilateral action had been taken. Both halves of Q35 go to Pouya together.
const processLinks = [
{ href: '/mediation/', label: 'Mediation' },
{ href: '/arbitration/', label: 'Arbitration' },
@@ -48,8 +59,19 @@ const aboutLinks = [
<InfinityMark size="2.25rem" />
<span class="footer-brand-name">{SITE.name}</span>
</a>
{
/* The designation strip carries the credentialing STAGE, not just the
held designation, and that is a §4 Offerings condition rather than a
flourish. The masthead says "Mediation · Arbitration · Toronto" on
every page; §4 permits the arbitration half on the condition that the
site "makes the first while stating the second plainly", and
"neither half may be dropped". Before this line rendered
CREDENTIALS.inProgress, that condition was unmet on every page that
ships — the constant existed in site.ts and was rendered nowhere.
Q.Arb reads as commenced, never as held (§4). */
}
<p class="footer-designation">
{CREDENTIALS.designations.join(' · ')}
{[...CREDENTIALS.designations, ...CREDENTIALS.inProgress].join(' · ')}
</p>
</div>
+65 -23
View File
@@ -38,7 +38,10 @@ const inSection = (href: string) => path === href || path.startsWith(href);
<div class="wrap header-inner">
<a class="brand" href="/">
<InfinityMark size="2rem" />
<span class="brand-text">
<span class="brand-name">{SITE.name}</span>
<span class="eyebrow brand-tagline">{SITE.tagline}</span>
</span>
</a>
<nav class="nav" aria-label="Primary">
@@ -131,22 +134,44 @@ const inSection = (href: string) => path === href || path.startsWith(href);
/* --- Brand --------------------------------------------------------------- */
/* No tagline under the name. `SITE.tagline` reads "Mediation · Arbitration ·
Toronto", and docs/01 specifies that string as the HOME HERO EYEBROW —
nothing asks for a header tagline. Set under the name on every page it
stops being page copy and becomes a designation strip, with `Arbitration`
unqualified beside a name. AGENTS.md §4 records Q.Arb as commenced August
2026 and requires it never read as held. See AGENTS.md Q33. */
/* The tagline is BACK, and the reasoning is worth keeping rather than just
the outcome. It was removed on 2026-08-26 because `Arbitration` under
Pouya's name read as a held capability, and §4 records Q.Arb as merely
commenced. Q33 answered that the same day, and the premise was wrong:
ADR designations are voluntary credentials, not licences. Anyone may be
appointed an arbitrator in Ontario, so the constraint was always
positional, never legal — Pouya accepts sole, party-appointed and
co-arbitration work today. See §4 Offerings, which is where the register
now draws the line between a CREDENTIAL claim and an OFFERING. */
.brand {
display: flex;
align-items: center;
gap: var(--space-3);
/* 44px floor — this is the tap target that goes home. */
min-block-size: 44px;
/* 48px, not 44. Still clears the touch floor, and it reserves the height the
two-line brand takes at >=76rem so the sticky header is one constant 81px
across every width where it is sticky — which is what --header-h and
scroll-padding-top are keyed to. One number instead of two bands. */
min-block-size: 48px;
color: var(--accent);
text-decoration: none;
margin-inline-end: auto;
}
.brand-text {
display: flex;
flex-direction: column;
gap: 2px;
}
/* The tagline appears only where there is room for it — see the 76rem block.
Measured: at 11px with 0.18em tracking the string is ~285px wide, and
restoring it under the name pushed the one-row header past its content box
by 18px at 1024 with six items and 84px with seven. The brand name carries
the identity on its own; the tagline is a flourish, and `/` opens with the
same words as the hero eyebrow (docs/01). */
.brand-tagline {
display: none;
font-size: 0.6875rem; /* 11px — the eyebrow floor in docs/02 */
white-space: nowrap;
}
.brand-name {
font-family: var(--font-serif);
font-size: var(--text-xl);
@@ -255,7 +280,7 @@ const inSection = (href: string) => path === href || path.startsWith(href);
color: var(--accent);
}
/* Nav takes its own row below 64rem. No `order` anywhere: reordering flex
/* Nav takes its own row below 66rem. No `order` anywhere: reordering flex
items moved the CTA onto row one visually while it stayed last in the DOM,
so a keyboard user tabbed off the brand, down through all 13 nav links
including the practice panel, and back UP to the CTA. WCAG 2.4.3, and
@@ -267,17 +292,17 @@ const inSection = (href: string) => path === href || path.startsWith(href);
/* `white-space` INHERITS into the Button, which is how a parent reaches a
child component's root at all here — see the note on why this wrapper
exists. Without it the label wrapped to two lines, standing the header up
at 93px instead of 77px. `flex: none` stops the row squeezing it. */
taller than it needed to be. `flex: none` stops the row squeezing it. */
.header-cta {
flex: none;
white-space: nowrap;
}
/* Below 64rem the CTA is dropped, not shrunk — and that is the whole reason
/* Below 66rem the CTA is dropped, not shrunk — and that is the whole reason
no `order` is needed. Wherever the nav has its own row, `/contact/` is
already on it, so the button is a duplicate link paying for itself in
header height. It was previously dropped only below 40rem and reordered in
between, which is what put focus order out of step with visual order. */
@media (max-width: 63.999rem) {
@media (max-width: 65.999rem) {
.header-cta {
display: none;
}
@@ -285,12 +310,19 @@ const inSection = (href: string) => path === href || path.startsWith(href);
/* --- Desktop ------------------------------------------------------------- */
/* --- Desktop: 64rem (1024px) ---------------------------------------------
The threshold is measured, not conventional. The one-row header has to hold
the brand, seven nav items and the CTA side by side, and **at 1024px it
does, with 32px of clearance between the nav and the CTA — measured in
headless Chrome with a seventh nav item injected.** Below that it does not,
which is why the nav takes its own row there.
/* --- Desktop: 66rem (1024px) ---------------------------------------------
The threshold is measured, and the first measurement was WRONG — worth
recording, because of how it was wrong. It read "32px of clearance at
1024px". That 32px was `.header-inner`'s own `column-gap`, i.e. exactly
zero slack, mistaken for headroom. The true max-content sum at seven items
is 48 + 184.3 brand + 24 margin + 32 gap + 480.1 nav + 32 gap + 197.2 CTA
+ 48 = **1045.6px — 21.6px OVER a 1024px viewport.** Nothing overflowed
only because flexbox shrank the brand and crushed the mark inside it.
Binary search on the built page with a seventh item gives the real
thresholds: the row fits from **1047px**, and the tagline from **1207px**.
66rem (1056) and 76rem (1216) are the clean tokens above each. Below 66rem
the nav takes its own row.
Insights is the seventh item and arrives by itself at build step 7
(SiteHeader gates it on the collection), so a breakpoint verified only
@@ -305,7 +337,7 @@ const inSection = (href: string) => path === href || path.startsWith(href);
Sticky only from here up, too. Below this the nav takes a second row and
the header stands at 137px, which is more of a small viewport than a
sticky header is worth. Deviation from docs/02 "Sticky"; recorded there. */
@media (min-width: 64rem) {
@media (min-width: 66rem) {
.site-header {
position: sticky;
inset-block-start: 0;
@@ -321,11 +353,11 @@ const inSection = (href: string) => path === href || path.startsWith(href);
}
/* nowrap, and flex:none so the nav is never squeezed below its content
width. Measured before this: at 960-1250px the seven-item nav broke to
two rows and the header stood at 142px instead of 80px. */
two rows and the header stood at 141px instead of 81px. */
.nav-list {
flex-wrap: nowrap;
flex: none;
/* 16px from 64rem, widening to 24px at 75rem where there is room for it.
/* 16px from 66rem, widening to 24px at 76rem where there is room for it.
Measured with seven items at every width from 1024px up. */
column-gap: var(--space-4);
}
@@ -372,14 +404,24 @@ const inSection = (href: string) => path === href || path.startsWith(href);
you scroll off the top. That is a smaller effect than docs/02's "condenses
on scroll", and docs/02 has been amended to say so and why. */
@media (min-width: 75rem) {
/* The tagline arrives at 76rem. The nav gap does NOT widen here as well:
measured, doing both at one breakpoint put the row 4px past its content box
at exactly 1200px with seven items. Two things growing at the same width is
how a breakpoint gets over-subscribed. */
@media (min-width: 76rem) {
.brand-tagline {
display: block;
}
}
@media (min-width: 80rem) {
.nav-list {
column-gap: var(--space-5);
}
}
@supports (animation-timeline: scroll()) {
@media (min-width: 64rem) and (prefers-reduced-motion: no-preference) {
@media (min-width: 66rem) and (prefers-reduced-motion: no-preference) {
.site-header {
animation-name: header-lift;
animation-duration: 1ms;
+5 -4
View File
@@ -26,11 +26,12 @@ const lang = SITE.locale.replace('_', '-');
<SEO {...Astro.props} />
{
/* .ico first for clients that ignore the SVG, and because some crawlers
request /favicon.ico at the root regardless of what is declared here. */
/* No SVG favicon. The mark is a shaded ribbon, not flat vector paths, so
there is no honest SVG of it to serve — see InfinityMark.astro and
AGENTS.md Q38. The .ico carries 16/32/48, and is what crawlers request
at the root regardless of what is declared here. */
}
<link rel="icon" href="/favicon.ico" sizes="48x48" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="icon" href="/favicon.ico" sizes="16x16 32x32 48x48" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
{
+3 -3
View File
@@ -113,16 +113,16 @@
html {
-webkit-text-size-adjust: 100%;
scroll-behavior: smooth;
/* No offset by default: below 64rem the header is not sticky, so nothing is
/* No offset by default: below 66rem the header is not sticky, so nothing is
covering the target. See the media query below. */
scroll-padding-top: var(--space-4);
}
/* The header is sticky from 64rem up, and `scroll-padding-top` has to clear it
/* The header is sticky from 66rem up, and `scroll-padding-top` has to clear it
or "Skip to content" drops the reader behind it — the one control that exists
specifically for keyboard users, landing them on content they cannot see.
--header-h is defined in tokens.css beside the value it has to match. */
@media (min-width: 64rem) {
@media (min-width: 66rem) {
html {
scroll-padding-top: calc(var(--header-h) + var(--space-4));
}
+6 -3
View File
@@ -112,13 +112,16 @@
/* --- Layout ------------------------------------------------------------ */
/* Sticky-header height at >= 64rem, where the header IS sticky. global.css
/* Sticky-header height at >= 66rem, where the header IS sticky. global.css
drives `scroll-padding-top` off this, so the skip link does not drop the
reader behind the header. If SiteHeader's padding or nav sizing changes,
re-measure and change this with it — one fact living in two files.
[measured 2026-08-26 — headless Chrome at 1024/1100/1280/1440px, with six
nav items and with a seventh injected: 77px at every one] */
--header-h: 4.8125rem; /* 77 — measured, not chosen */
nav items and with a seventh injected. 81px at every one: 32 padding + 48
reserved brand block + the 1px bottom border, which is easy to forget and
is why this is measured rather than added up. The brand reserves 48px so
the height does not change when the tagline appears at 76rem] */
--header-h: 5.0625rem; /* 81 — measured, not chosen */
--width-content: 80rem; /* 1280 */
--width-wide: 90rem; /* 1440 */