feat: build step 6 — /process/ and /for-parties/, the first step under D20
Build and deploy / build-and-deploy (push) Failing after 4s
Build and deploy / build-and-deploy (push) Failing after 4s
Two pages, 14 in dist/ (was 12), zero JavaScript, one <h1> each, no skipped heading levels. Both were dangling links in SECONDARY_NAV since step 1; the footer is now whole on every page. /process/ — the five steps from intake to minutes of settlement or an award, with PROCESS_FRAMING rendered adjacent to the timings rather than in a section lede above them, which is the condition Q43 attached to publishing them at all. Conflicts says WHEN the check runs and WHAT it needs, and then stops: any sentence naming the outcome would be a seventh conduct undertaking, and §4's gate requires that Pouya has made it in terms. Logged as Q57. /for-parties/ — second person, grade 9, for a party arriving without counsel. NEUTRAL_ROLE_LINE gets its own section above the FAQ rather than a slot in it. Eight questions in one array feeding both the visible page and the FAQPage node, so a question cannot reach the structured data without appearing on the page. The word "lawyer" appears nowhere, deliberately, and the reason is in the file header. Three defects worth recording. The link colour on a dark band measured 1.88:1, and 1.10:1 on hover. `--link` is documented at 8.95:1 ON CREAM and was never overridden for an inverse ground; SiteFooter sets its own colour, which is the only reason this had not fired before — /process/ shipped the site's first body link on a dark band. That is worse than the gold-on-cream 2.10:1 this project treats as canonical. Fixed in global.css, where the next inverse-ground link will hit the same hole. The `:not(.btn)` guard is load-bearing, not tidiness: the new rule's specificity (0,2,1) beats `.btn-gold`'s (0,2,0), so without it the repair would have recoloured every gold button on a dark band. The fee shipped as "with preparation included", which docs/07 forbids in terms: the allowance is CAPPED, so the unqualified form sells an uncapped one, and /mediation/ already promises the site does the opposite. `prepIncluded` had been declared in site.ts with no consumer anywhere. /process/ §Confidentiality asserted that confidentiality is settled in the terms of appointment — a claim about Pouya's engagement documents that §4 does not row and no reader can check. Replaced with ADRIC's Code of Ethics quoted from the committed extract, plus the §4-verified membership rendered from MEMBERSHIP_ORGS. The replacement then said "on this it is one sentence", a completeness claim about a third party's Code that the extract cannot support — the same file records a separate instrument eighteen lines above. The cited source supplied its own counter-example. check:claims failed the build on compliant copy: five uses of "lawyer" about the READER, which §4 permits since it bars the word used OF Pouya. There is no allowlist, and the freeze bars narrowing the pattern, so the copy moved — the same call and the same direction as "my client" to "our client" on /med-arb/. Both replacements are better than what they replaced. Q58 opened rather than guessed: docs/07 reads "up to 3.5 h, INCLUDING 2 h preparation", which makes 3.5 the billed envelope and the room time 1.5 h, against which 3.5 and 7 being exactly 2x makes no sense. A draft had answered "What happens on the day?" with "about 3.5 hours" — the envelope presented as the day, to the reader least able to check it. The sentence was removed. Two review rounds, 16 findings, all applied. Verified: check 0 errors, lint 0, build 0 (14 pages), check:claims 0, npm audit 0, minifier tripwire clean. Lighthouse not run — tool unavailable until build step 7. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
co-authored by
Claude Opus 5
parent
2ea4c0f8ac
commit
13b97841b9
@@ -0,0 +1,250 @@
|
||||
---
|
||||
/**
|
||||
* `/for-parties/` — build step 6. Spec: docs/01 §`/for-parties/`, docs/03 §For
|
||||
* parties. The one page written in the second person, at a grade-9 reading
|
||||
* level, for a party who may be arriving without counsel.
|
||||
*
|
||||
* ⚠️ THIS IS THE PAGE `docs/03` NAMES AS THE PLACE THE BARRED PHRASING FEELS
|
||||
* MOST NATURAL AND IS MOST WRONG. Two forms are struck and must never come
|
||||
* back: *"the mediator is not your lawyer"* — which presupposes lawyer status,
|
||||
* and D13 treats implication as hard as assertion — and *"cannot give you legal
|
||||
* advice"*, a denial of a capacity §4 records as `[unestablished]` and
|
||||
* instructs this repository to answer neither way. `NEUTRAL_ROLE_LINE` is the
|
||||
* ratified pattern: role, then consequence for the reader, no verb of capacity.
|
||||
* It is rendered, never retyped, and it took three attempts and two audits.
|
||||
*
|
||||
* ⚠️ AND THE WORD "LAWYER" DOES NOT APPEAR ON THIS PAGE, DELIBERATELY. §4 bars
|
||||
* it *used of Pouya*, and every natural use here is about the READER — "do I
|
||||
* need my own lawyer", "coming without a lawyer". Those are compliant on §4's
|
||||
* wording and `check:claims` still fails the build on them, because a bare
|
||||
* `\blawyer\b` cannot tell whose. The gate is not wrong: this is the page
|
||||
* `docs/03` names as where the barred phrasing is most tempting, and a broad
|
||||
* pattern is the right shape there. The copy moved instead — "your own legal
|
||||
* advice", which is `NEUTRAL_ROLE_LINE`'s own wording. Same call, and the same
|
||||
* direction, as "my client" → "our client" on `/med-arb/`.
|
||||
*
|
||||
* ⚠️ THE FAQ ARRAY IS THE ONLY SOURCE. It is rendered visibly AND fed to the
|
||||
* `FAQPage` node, because docs/04 allows the node here "only where the visible
|
||||
* page genuinely is Q&A" — so a question cannot reach the structured data
|
||||
* without appearing on the page, and the two cannot drift.
|
||||
*
|
||||
* ⚠️ THE FEE FIGURES ARE INTERPOLATED FROM `FEES`, NOT TYPED. D14's card is one
|
||||
* source; a second hand-typed copy on the page a party reads is the copy that
|
||||
* goes stale, and it goes stale silently.
|
||||
*
|
||||
* ⚠️ AND THE BUNDLED PREPARATION IS STATED IN HOURS, NEVER AS "PREPARATION
|
||||
* INCLUDED". `docs/07` §All parameters confirmed is explicit: *"Preparation time
|
||||
* is bundled and MUST be stated on the page — 'including 2 hours of
|
||||
* preparation'… Do not quietly fold it into the hours figure."* The allowance is
|
||||
* CAPPED, so the unqualified form sells an uncapped one. This page shipped
|
||||
* "with preparation included" for one pass; `adversarial-reviewer` found it, and
|
||||
* `prepIncluded` had been declared in `site.ts` with no consumer anywhere.
|
||||
*
|
||||
* ⚠️ AND THIS PAGE DOES NOT STATE HOW LONG A MEDIATION DAY IS — see §9 Q58.
|
||||
* `docs/07`'s card reads *"Half day — up to 3.5 h, INCLUDING 2 h preparation"*,
|
||||
* which makes 3.5 the billed envelope and the room time 1.5 h. `FEES.mediation
|
||||
* .halfDay.hours` documents neither reading. A draft answered "what happens on
|
||||
* the day" with "about 3.5 hours", which is the envelope presented as the day,
|
||||
* to the reader least able to check it. Do not restore a duration here until
|
||||
* Q58 is answered.
|
||||
*/
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import Button from '../components/Button.astro';
|
||||
import ContactBand from '../components/ContactBand.astro';
|
||||
import Eyebrow from '../components/Eyebrow.astro';
|
||||
import SectionHeading from '../components/SectionHeading.astro';
|
||||
import Undertaking from '../components/Undertaking.astro';
|
||||
import { getImage } from 'astro:assets';
|
||||
import ogDefault from '../assets/og-portrait.jpg';
|
||||
import { forPartiesGraph } from '../data/schema';
|
||||
import { CONDUCT_UNDERTAKINGS, FEES, NEUTRAL_ROLE_LINE } from '../data/site';
|
||||
|
||||
const ldImage = await getImage({
|
||||
src: ogDefault,
|
||||
format: 'jpeg',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
});
|
||||
|
||||
const money = (amount: number) =>
|
||||
new Intl.NumberFormat('en-CA', {
|
||||
style: 'currency',
|
||||
currency: FEES.currency,
|
||||
maximumFractionDigits: 0,
|
||||
}).format(amount);
|
||||
|
||||
const FAQ = [
|
||||
{
|
||||
q: 'What is a mediation?',
|
||||
a: 'It is a meeting to try to settle a dispute without a hearing. Everyone involved comes. I run the meeting. I do not decide who is right.',
|
||||
},
|
||||
{
|
||||
q: 'Are you on anyone’s side?',
|
||||
a: 'No. I run the process for everyone in the room at once. If I ran it for one side it would settle nothing, and the other side would be right not to come.',
|
||||
},
|
||||
{
|
||||
q: 'Should I get my own legal advice?',
|
||||
a: 'What you sign at the end of a mediation is an agreement, so it is worth having someone look at your own position before the day rather than after it. If nobody is advising you, say so at the start.',
|
||||
},
|
||||
{
|
||||
q: 'What happens on the day?',
|
||||
a: 'I usually start with everyone in one room. After that the parties often sit separately and I move between them. Some matters run that way from the beginning, with the parties never in the same room. You book either a half day or a full day, and which one you need is settled before the date is fixed.',
|
||||
},
|
||||
{
|
||||
q: 'Does what I say stay private?',
|
||||
a: 'The terms everyone signs at the start deal with confidentiality. A caucus is when I meet one side on their own, without the other side there. One part of what happens in it is mine rather than the document’s:',
|
||||
/* Rendered through <Undertaking> below, not as body prose — §4's third
|
||||
class gets one treatment across the site so a reader can tell a promise
|
||||
from a description. The graph gets lead and promise as one answer. */
|
||||
undertaking: CONDUCT_UNDERTAKINGS.mediationCaucus,
|
||||
},
|
||||
{
|
||||
q: 'What does it cost, and who pays?',
|
||||
a: `${money(FEES.mediation.halfDay.amount)} for a half day, including ${FEES.mediation.halfDay.prepIncluded} hours of preparation, and ${money(FEES.mediation.fullDay.amount)} for a full day, including ${FEES.mediation.fullDay.prepIncluded} hours. ${FEES.taxNote} ${FEES.terms[0]}`,
|
||||
},
|
||||
{
|
||||
q: 'What if we do not settle?',
|
||||
a: 'Then the mediation ends without an agreement. Nothing you said becomes a ruling, because I do not make one. What gets written down is only what everyone agrees to write down.',
|
||||
},
|
||||
{
|
||||
q: 'How do I get ready?',
|
||||
a: 'Bring the documents that matter, not all of them. Know the number you would accept and the number you would walk away at. Bring someone who can agree to a settlement on the day, or be able to reach them quickly. Expect to be asked what the weakest part of your own case is.',
|
||||
},
|
||||
];
|
||||
|
||||
/* ONE SOURCE, TWO SHAPES. The page renders the lead-in and the undertaking as
|
||||
separate elements; a `FAQPage` answer is plain text, so the node gets them
|
||||
joined. Neither is typed twice. */
|
||||
const graph = forPartiesGraph({
|
||||
faq: FAQ.map(({ q, a, undertaking }) => ({
|
||||
q,
|
||||
a: undertaking ? `${a} ${undertaking}` : a,
|
||||
})),
|
||||
imageUrl: new URL(ldImage.src, Astro.site).href,
|
||||
});
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title="For Parties · What Happens at a Mediation · Pouya Lajevardi"
|
||||
description="What happens at a mediation, in plain language: who the mediator is, what the day looks like, what it costs and who pays, and how to get ready."
|
||||
jsonLd={graph}
|
||||
>
|
||||
{/* ---- 1. Hero -------------------------------------------------------- */}
|
||||
<section class="section hero">
|
||||
<div class="wrap">
|
||||
<Eyebrow dot>For parties</Eyebrow>
|
||||
<h1 class="display hero-h">What happens at a mediation.</h1>
|
||||
<p class="hero-lede">
|
||||
This page is for you if you are going to a mediation and nobody has
|
||||
explained what one is. It is the same day the rest of this site
|
||||
describes, written without the shorthand.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ---- 2. The role, before anything else ------------------------------ */}
|
||||
{
|
||||
/* NEUTRAL_ROLE_LINE gets its own section rather than a slot in the FAQ.
|
||||
docs/03 requires this page to say it explicitly, and the sentence a party
|
||||
most needs is not one to make them scroll for. */
|
||||
}
|
||||
<section class="section section-alt reveal">
|
||||
<div class="wrap">
|
||||
<div class="section-head">
|
||||
<SectionHeading eyebrow="First" level={2}>
|
||||
<span slot="heading">Who I am in the room.</span>
|
||||
</SectionHeading>
|
||||
</div>
|
||||
<div class="prose">
|
||||
<p class="statement">{NEUTRAL_ROLE_LINE}</p>
|
||||
<p>
|
||||
I also do not decide who is right. There is no ruling at the end of a
|
||||
mediation. There is either an agreement everyone signs, or there is
|
||||
not one.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ---- 3. The questions ----------------------------------------------- */}
|
||||
<section class="section reveal">
|
||||
<div class="wrap">
|
||||
<div class="section-head">
|
||||
<SectionHeading
|
||||
eyebrow="Questions"
|
||||
level={2}
|
||||
lede="The ones parties ask most often, answered plainly."
|
||||
>
|
||||
<span slot="heading">What you probably want to know.</span>
|
||||
</SectionHeading>
|
||||
</div>
|
||||
<div class="faq">
|
||||
{
|
||||
FAQ.map((item) => (
|
||||
<div class="faq-item">
|
||||
<h3 class="faq-q">{item.q}</h3>
|
||||
<p class="faq-a">{item.a}</p>
|
||||
{item.undertaking && (
|
||||
<Undertaking>{item.undertaking}</Undertaking>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div class="cta">
|
||||
<Button href="/fees/" variant="gold">The full rate card →</Button>
|
||||
<Button href="/process/" variant="ghost">The five steps →</Button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ContactBand />
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
.hero {
|
||||
padding-block-start: var(--space-9);
|
||||
}
|
||||
.hero-h {
|
||||
margin-block: var(--space-4) var(--space-5);
|
||||
font-size: var(--text-6xl);
|
||||
}
|
||||
.hero-lede {
|
||||
max-inline-size: 58ch;
|
||||
font-size: var(--text-lg);
|
||||
line-height: var(--leading-body);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* The compliance sentence, set larger than the paragraph under it. A party
|
||||
who reads one line on this page should read this one. */
|
||||
.statement {
|
||||
font-size: var(--text-lg);
|
||||
line-height: var(--leading-body);
|
||||
}
|
||||
|
||||
.faq {
|
||||
display: grid;
|
||||
gap: var(--space-7);
|
||||
max-inline-size: var(--width-prose);
|
||||
}
|
||||
.faq-q {
|
||||
margin-block-end: var(--space-2);
|
||||
font-family: var(--font-serif);
|
||||
font-size: var(--text-xl);
|
||||
line-height: var(--leading-tight);
|
||||
}
|
||||
.faq-a {
|
||||
line-height: var(--leading-body);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* A row of standalone CTAs, not prose: WCAG 2.5.8's inline-link exception
|
||||
does not cover them, so `.btn` carries the 44px target. */
|
||||
.cta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-3) var(--space-4);
|
||||
margin-block-start: var(--space-8);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user