# prototype.md — the repeatable prototyping process

**Goal:** distill this project's prototyping work into an **atomic, repeatable
process** — ending in a reusable prompt — so that future website projects can be
prototyped the same efficient way. leaguelaw is the first project this process is
developed on; the process itself is meant to outlive it.

**For Claude:** this file is co-owned by Adi and Claude. When we prototype here,
help refine the steps and the prompt below based on what actually worked. Keep
the process **project-agnostic** — project-specific facts belong in `brief.md`
and `adi-note.md`, or in the clearly-marked **instance appendix** at the bottom
of this file (working material for this project's run of the process; it does
not travel to future projects). The end state is: paste the prompt below into a
fresh session on any new website project and get an efficient prototype loop.

---

## Process ruling — 2026-08-20 (Rian, after review)

The review verdict on the first full run, binding until Rian says otherwise:

1. **The missing piece is a direction gate BEFORE any page work.** The process
   must first get the client to confirm a *direction* — "sedan, sports car, SUV,
   or truck," never "comment on the rims and tail-lights." The client reacts and
   confirms without feeling they are committing to a specific design. The
   client-effort rule applies in full: no extra steps, no homework.
2. **Client-facing artifacts anchor on the client's written input, never on a
   replica of the current site.** For this project that anchor is
   `.logs/planning/design-direction.md`. A replica-based artifact reads to the
   client as "we are rebuilding your same site," which is the opposite signal.
3. **Fidelity ruling:** for client-facing direction work, low-fidelity and
   deliberately unfinished-looking wins. Early artifacts *losing* the current
   site's details is the point — those details belong to the design being moved
   away from. The replica keeps real value as an **internal measurement
   artifact** (proportions, section inventory, brand audit) and as the
   photographer's shot-brief substrate; it is not shown to clients and new
   design is not diffed against it. High fidelity returns at the mockup step.
4. **A candidate step-1 mechanism already exists:** the client asked to be sent
   **examples online to rank**. That is a direction-confirmation step invented
   by the client — build the process outward from it.
5. **Automation is the long-term target.** Rian expects parts of this phase to
   be automatable (Scout was a first attempt). Distill every step explicitly
   enough that a future automated pass could run it — direction inputs must be
   written documents, not tribal knowledge.

Step 4's replica-first note below is superseded for client-facing sequencing by
this ruling; the step itself survives with the internal role described above.

## The atomic process (draft — refine as we go)

Each step is atomic: one input, one output, verifiable before moving on.

1. **Intake** — collect the raw inputs: client brief/emails, current site,
   brand constraints, stated likes/dislikes, scope of what was sold.
   **First action, before anything else: read every document in the
   project's planning folder (`.logs/planning/`) and any client-direction
   write-up** — the client's stated position may already be distilled there.
   (Lesson 2026-08-21: `design-direction.md` had existed since 2026-08-10 with
   the four hard criteria and the "examples to rank first" gate; the first
   run built a hero slider without ever reading it.)
2. **Direction** — turn intake into a short design-direction statement
   (what to keep, what to avoid, what "modern" means for this client).
   Scout reactions/rollup feed in here when a Scout project exists.
   **Output includes a brand guide for developers:** typography (families,
   weights, source), the color palette with hex values and roles, signature
   brand shapes/motifs, and the do-not-change list. Distinguish client-stated
   brand facts from the designer's interpretive lens — both are useful, only
   one is a requirement.
3. **Skeleton** — page inventory + section inventory: which page types exist,
   which recurring sections they're built from (the future pattern list).
4. **Replica** — recreate the CURRENT site's key page(s) 1:1 in HTML: real
   assets, measured proportions (from full-page screenshots), real copy.
   This is the initial mockup and the baseline every improvement is diffed
   against — no detail gets lost in translation, and nothing rawer than
   "the site as it already is" is ever shown to anyone.
   *(Supersedes the low-fi wireframe step — tested and rejected on this
   project; see `adi-note.md` 2026-08-20 and the learnings log. Rian's
   underlying intent — settle layout before fidelity debates — survives as
   the explicit-diff discipline below.)*
5. **Improve (high-fidelity mockup)** — evolve the replica part by part
   (header → hero → …) through **option funnels**: broad option set → pick a
   route → variation rounds changing ONE variable each → canonical component,
   integrated back into the mockup page. Real brand applied throughout;
   placeholder imagery always labelled (and doubling as the photographer's
   shot brief where photography is pending).
6. **Review** — put it in front of the decision-maker; capture reactions
   against the direction statement, not as open-ended opinions.
7. **Lock** — write the approved direction + pattern list into the build plan;
   prototyping ends, production build begins.

**File-location rule (multi-user):** every prototype artifact has exactly two
homes — a **served, "finished" copy** in the site's public prototype folder
(the single URL every collaborator and, eventually, the client sees), and
**working/backup versions** in the workspace's `prototyping/` folder (the
version history). Session temp files belong in the session scratchpad — never
in the served folder. Anyone resuming the work starts from the served hub +
this file + `adi-note.md`; those notes are binding for every user and session,
not suggestions. Exact paths for this project are in the instance appendix.

**Client-effort rule (applies to every step):** don't overwhelm the client. We
do the work for them — they react and approve; they never do design work or
homework. How much to show, how many options, and what to decide without
asking is the **designer's judgment call** (Adi on this project), not a
committee question. Each client touchpoint should be one small, easy ask.

## Reusable kit assets

- **Direction Previewer template** (2026-08-24):
  `prototyping/templates/direction-previewer-template.html` (live demo with
  placeholder config: `wp-content/prototype/previewer.html`). Project-agnostic
  client-facing "pick your direction" walkthrough — one self-contained HTML,
  driven entirely by a CONFIG object (title, the client's own rules, 1–4
  options with pencil-wireframe screens or images, final questions, optional
  checklist appendix, internal/client-ready flag). Engine renders steps + nav;
  wireframe vocabulary (.bar .tile .hex .teamrow .sticky …) included.
  **Option-count guidance baked into the file header:** default 3 (smallest
  spectrum — non-picks carry information, real choice = real involvement);
  1 only as a confirmation gate; never pad with options you wouldn't build.

- **Direction Mixer template** (2026-08-24):
  `prototyping/templates/direction-mixer-template.html` (demo:
  `wp-content/prototype/mixer.html`). Multiple-choice variant: the client
  picks per CATEGORY (mood / header / hero / services / footer — config-
  driven, 3 options each), the final step assembles the picks into one
  combined rough page, and the whole selection is encoded in the URL hash
  (`#p=2-1-3-1-2`) — the shareable link IS the client's answer; zero backend.
  **Reclassified same day (Adi): NOT the client-facing instrument** — too
  many micro-decisions; clients are not designers. The Mixer's two legitimate
  uses: (1) internal exploration/review — the designer composes combos and
  shares a combo URL with the senior; (2) selective follow-up — when the
  client contests ONE section of a chosen direction, configure it with that
  single category only. The client-facing direction ask remains the
  Previewer (pick one of ~3 composed wholes).

## The reusable prompt (draft)

> To be written once the process above survives contact with this project.
> Target shape: a single prompt with placeholders like `{client}`,
> `{direction-statement}`, `{constraints}`, `{section-inventory}` that runs
> steps 3–5 (skeleton → replica → improve) in a fresh Claude session.

## To do

- [ ] **Build the brand guide for developers** (this project's instance of the
      step-2 output). Raw material is in `adi-note.md` 2026-08-19: Raleway
      headings / Open Sans body, `#423C37` · `#EF6D3E` · `#46ADC8`, off-white
      backgrounds (~`#F9F9F9`, never plain `#FFF`), and the hexagon polygon as
      the signature brand shape.

## Learnings log

Newest first. Every prototyping session that teaches us something about the
*process* (not the project) gets a line here — this is the raw material for the
final prompt.

- 2026-08-26 — Brand-shape rule (Adi, building home_v1's teams section):
  **a signature shape is ornament and accent, never a photo mask.** Hex-clipped
  portraits were built and rejected the same hour ("too much effort to be
  something") — clipping a face into the brand shape makes the shape shout over
  the person, which is decoration doing structure's job badly. Same family as
  the earlier hive-layout demotion: the shape lives in rules, markers,
  watermarks and buttons; photos stay honest rectangles. Generalizes to any
  client with a signature mark.
- 2026-08-24 — Instrument rule (Adi, after building and rejecting the
  per-section Mixer as a client ask): **clients react well to WHOLES and
  badly to assembling PARTS — synthesis is the designer's job.** Never hand
  a client per-component choices; compose ~3 coherent wholes and let them
  react. Per-section tools are for the designer (internal exploration) or
  for a single contested section as a follow-up.
- 2026-08-21 — Client-ask calibration (Rian, via Adi's evening meeting):
  **fewer options (5 is too many, ~3), short wording, under ~5 minutes of the
  client's time, and an explicit feeling of involvement** — the client must
  feel the decision is theirs at this stage; jumping ahead to finished-looking
  work makes them disengage ("fly away"). Refines the client-effort rule: not
  just "no burden" but "small, easy, early, and theirs."
- 2026-08-21 — Interaction lesson, **corrected same day after Adi pushed back**
  (the first version said hover belongs only on links — too wide, and not a rule
  this project inherited; the standards library only governs hover *legibility*).
  The accurate line: **a decorative element may respond to hover; it must not
  signal that it is a control.** Lift-and-shadow, a sliding arrow, a growing
  underline, the heading changing colour, `cursor: pointer` — that is the
  vocabulary of clickable things, and spending it on an element that goes
  nowhere teaches visitors the site's signals cannot be trusted. So an option
  round for hover splits by *vocabulary*, not by permission: control-vocabulary
  effects require the element to actually be a link; atmosphere effects move
  their trigger out to the whole section, where they reward reading instead of
  hunting. State the touch answer in the same breath: on a phone there is no
  hover, so the resting state must carry the meaning alone.
- 2026-08-21 — Process lesson: **when a rule appears in a design note, record
  where it came from.** This one was written as if inherited and was actually a
  same-session judgment call; the designer caught it in one question. Cheap fix,
  expensive if it had propagated into the reusable prompt as received wisdom.
- 2026-08-21 — Option-round lesson: **a round that ends with "keep what we
  have" is a successful round, not a wasted one** — record the pick and the
  reasoning; the value is that the current choice is now deliberate rather than
  inherited.
- 2026-08-20 — RULING (Rian, review): the fidelity doctrine below is
  **superseded for client-facing work** — replica-first stays as an internal
  measurement step only; client-facing direction artifacts are low-fi,
  unfinished-looking, and anchored on the client's written input (see Process
  ruling above). Lesson for the prompt: the direction phase optimizes for
  *divergence from* the current site, so "losing the old details" in early
  artifacts is success, not risk — fidelity-to-the-old-site is only a goal for
  the internal replica.
- 2026-08-20 — Process lesson (from the review itself): **when an agreed
  approach stops working, the pivot is the check-in** — a two-line async flag
  (what failed, what to try) before hours go into a replacement. Also: every
  client-facing artifact gets checked against the client's written direction
  doc before anyone sees it; that check would have caught the full-bleed hero
  slider contradicting the client's "no large expansive imagery."
- 2026-08-20 — FIDELITY DOCTRINE SETTLED (Adi, after testing pencil → mid-fi
  → replica on one page): **low-fidelity wireframes carry high risk of losing
  load-bearing details and can mislead or overwhelm the client with raw ideas
  not ready to present. The process is replica-first: HTML-recreate the old
  site 1:1, then improve at high fidelity from there, part by part.** This
  supersedes the earlier wireframe-fidelity entries below (kept as history of
  how we got here).
- 2026-08-20 — Design rule from Adi (header polish): **the logo gets an
  exclusion zone — never put decorative objects behind the mark.** Ornament
  lives outside the content grid (outer gutters), near the logo but never
  under it; anchor it at fixed offsets from the grid edge so the distance
  holds at every viewport.
- 2026-08-20 — Design rule from Adi (round 4): **same-size elements demand
  equal spacing; mixed sizes make irregular spacing read as intent.** Uneven
  gaps between identical shapes register as a mistake; vary either the gap
  system or the sizes, never neither.
- 2026-08-20 — Second calibration verdict from Adi: even mid-fi **loses
  load-bearing details** — e.g. the live hero gives the photo ~68% and the
  form ~26% (371px), a deliberate ratio the mid-fi's 50/50 grid misrepresented.
  New approach to test: **replica-first** — rebuild the current page 1:1 in
  HTML (real assets, measured proportions from the full-page screenshot),
  then derive the new design by *diffing against the replica*, so proportion
  decisions are explicit instead of accidentally re-invented.
- 2026-08-20 — Calibration verdict from Adi: pure pencil-sketch is TOO low-fi
  to judge — the working fidelity is **mid-fi**: real typography and real copy
  (so composition/rhythm read true) but strictly grayscale and image-free (so
  the conversation stays on layout). Dark sections render dark (tonal truth).
  Pencil-red handwriting stays for designer notes; dashed outline stays for
  proposed sections.
- 2026-08-19 — Wireframes must *look* unfinished (pencil-style) or clients
  review them as finished and the conversation derails into colors and polish
  before layout is agreed. Fidelity of the artifact sets the fidelity of the
  feedback. (From Rian.)
- 2026-08-19 — The process must scale its client-facing surface down, not up:
  systematic and atomic internally, but each client touchpoint stays one small
  ask. The designer absorbs the complexity and makes the judgment calls.

---

# Instance appendix — League Law (does not travel to future projects)

## Current homepage inventory — www.leaguelaw.com (captured 2026-08-20)

Sources: live HTML crawl + `screenshoots/5-leaguelaw-current-desktop.png`
(1440×7496) + `screenshoots/6-leaguelaw-current-mobile.png` (780×19022).
This is the step-1 **Intake** record: what the current homepage contains, in
order, so the skeleton/wireframe steps work from facts.

### Section-by-section (desktop order)

1. **Header** — logo `uploads/logo.png` ("LaW / LEAGUE and WILLIAMS", orange
   LaW mark with underline), "Call Now" + **250-888-0002**, nav: *What We Do*
   (mega-menu, see below) · *Your Team* (12 lawyers) · *Blogs* · *Careers*.
2. **Hero** — B/W portrait of Darren (orange tie, `DARRENorangebowtie.jpg`)
   left; right panel is a **contact form**: "WE'VE GOT YOUR BACK / Contact us
   today!" — Name, Email, Phone, Message + CAPTCHA, "🔒 Your information is
   kept safe.", teal SEND MESSAGE button, orange field-icon tabs. Award badges
   overlap the portrait (`three-best-awards-1.png`,
   `5yearBOCAwardNB-e1668720099853.png`). ⚠ The page's `<h1>` contains **no
   text** — the visible headline "WE'VE GOT YOUR BACK" is an h5/h3.
3. **Google reviews bar** (orange) — "4.9 ★★★★★ 173 Google Reviews / Read
   reviews on Google".
4. **Location bar** (dark brown `#423C37`-family) — map-pin icon, "Get our
   lawyers on your team", "Headquartered in Victoria, BC with offices in
   Vancouver, Duncan, Campbell River and Kelowna… Read more".
   ⚠ Nanaimo is missing (brief says six locations).
5. **Practice areas** — hexagon icon + H2 "LEAGUE AND WILLIAMS", "With over
   160 years of experience in helping clients in the following areas of law".
   Five items, each a **PNG line-icon inside a hexagon outline** + H2 label +
   one-liner, alternating orange/teal:
   - **INJURIES** (orange, `icon-injuries.png`) — "Did you get in an accident?
     We will help you recover your fullest potential."
   - **ESTATES** (teal, `icon-estates.png`) — "Need a will? Left out of a
     will? Did a family member pass away without one? Estate litigation,
     planning & administration."
   - **BUSINESS** (teal, `icon-business.png`) — "Are you planning to start a
     new business in British Columbia? Are you buying, selling, or
     restructuring an existing business?"
   - **MARINE** (orange, `icon-marine.png`) — "Had a boating accident? Boat
     been seized? Have anchoring or mooring concerns?"
   - **REAL ESTATE** (teal, `icon-real-estate.png`) — "Buying or selling Real
     Estate in BC? Get peace of mind with our real estate law team."
   ⚠ These icons are **raster PNGs**, not the SVG polygon — rebuild wants
   proper SVG.
6. **Team** — orange hexagon briefcase icon, H2 "YOUR TEAM AT LEAGUE AND
   WILLIAMS", two paragraphs ("Trusted advice, just results – …" / "Our firm
   is committed to delivering quality legal advice…"). 13 cards, B/W
   portraits, name + role: Darren Williams (Principal); Associates: Rob
   Graham, Andrew Broadley, Donald E. Linge, Matthew Melnyk, Robert Margolis,
   Lisa Guidi, Vera Syrma, Joji Kawaguchi, Macinly Fram, Reid Warren, Georgia
   Lockhart; card 13 = **"IS IT YOU?"** (LaW hexagon image `law-sm.jpg`) →
   "Go to Careers Page".
7. **Testimonials** (orange band over a photo background) — quote icon, H2
   "What our clients say about us:", carousel of 3: Pamela Ellis (boat
   insurance payout), R Park (injury claim, names staff Taryn Smith & Wendy
   Ferrara), Susan Dubois (estate). 5-star row, prev/next arrows.
8. **Featured articles** — teal hexagon RSS icon, H2 "READ OUR FEATURED
   ARTICLES", 3 cards (thumbnail + title + excerpt): *Estate Dispute Case:
   Changing an Unfair Will* (`green-farm-crops`), *Buying a Home with
   Co-Ownership* (`cytonn-photography…` handshake), *Benefits of Having a
   Will…* (`woman-writing-for-man`).
9. **LaW Facts** (dark section) — "LaW Facts / DID YOU KNOW?" carousel, 6
   facts: 2017 SCC unanimous win (Cowper-Smith v. Morgan); Victoria's best
   law firm 7 years (2018–2023 & 2025); Westside Village home 2014, expanded
   2018; 160+ combined years; free consultations (personal injury + estate
   litigation); largest marine law practice on Vancouver Island. Slide photos:
   `DarrenatSCC-1.jpg`, `BestinCityAwards2017to2022.jpg`, `FrontDoor-1.jpg`,
   `harbour-on-the-sunset.jpg`, `IMG_4959-1.jpg`, `seaplaneVictoria-1.jpg`.
10. **Vlog** — teal hexagon YouTube icon, H2 "WATCH OUR VLOG" + intro
    paragraph, 3 video cards with play overlay: *Liability Insurance Included
    in Renter's and Homeowner's Policies*, *Video Blog: Speeding Cyclists and
    BC Law* (`KAYZ693XlXg` thumb), *Don't be Sorry for Saying Sorry – the BC
    Apology Act* (`BC-Apology-Act` thumb).
11. **Contact strip** (orange) — ☎ 250-888-0002 · ✉ info@leaguelaw.com.
12. **Get in touch** — teal hexagon comments icon, H2 "GET IN TOUCH", "Please
    contact us for more information. Our email is monitored seven days a
    week…", row of 4 small orange hexagon icons, then the same "WE'VE GOT
    YOUR BACK" form again.
13. **Footer** — "Victoria (Main Office) | Phone (250) 888-0002 | Fax (778)
    433-0171 | Email: info@LeagueLaw.com / **Address: 174 Wilson St #210,
    Victoria, BC V9A 7N6**" + Home | Services | Contact | Back To Top.
    ⚠ That is the **old address**, visible in the footer — not only in schema.

### What We Do mega-menu (the practice-area URL space)

- **Injury Claims:** Car, Motorcycle, Cyclist, Passenger, Pedestrian, Hit and
  Run, Slip and Fall, Premises Liability, School Accident, Product Liability,
  Dog Attack, Boating Accidents, Assault & Battery.
- **Estates:** Estate Planning · Estate Administration · Estate Disputes (Who
  can dispute a Will in BC?, Unfair Wills, Invalid Wills, Undue Influence).
- **Business Law** · **Real Estate** (Buying / Selling a Home in BC) ·
  **Marine Law**.

### Icon & SVG system (how the hexagon is actually implemented)

- `polygon.svg` (the teal hexagon, 61×70) is used as a **CSS
  `background-image` on `span.icon` containers**, with a **Font Awesome glyph
  centered inside**: `fa-university` (Estates section header), `fa-suitcase`
  (team), `fa-rss` (articles), `fa-youtube-play` (vlog), `fa-comments` (get in
  touch).
- The 5 practice-area icons are standalone **PNGs** drawn in the same
  hexagon-outline style (orange or teal stroke).
- Other font icons in use: `fa-star` ×20 (reviews/testimonials), `fa-play`,
  `fa-quote-left`, `fa-google`, `fa-map-marker`, `fa-phone`, `fa-envelope`,
  social (`fa-facebook/twitter/linkedin/youtube`), theme arrows
  (`ticon-angle-*`), `ticon-lock`, `ticon-phone`. Only 4 inline `<svg>`
  elements on the whole page.

### Mobile notes (from the 780×19022 capture)

- Stack order: header (logo + phone + hamburger) → Darren portrait → **full
  contact form** → reviews bar → location bar → practice areas (3+2 grid of
  hexagons) → team (2-col) → everything else single-column.
- ⚠ On mobile the form pushes the practice areas ~2 screens down — the
  opposite of Darren's stated priority ("match their issue and click,
  without scrolling"). Contact info *is* at top (phone in header), which he'll
  want kept.
- Page is extremely long on mobile (~24 screens).

### Wireframes produced

- **v1 — as-is calibration** (2026-08-20): pencil-style wireframe of the
  *current* homepage, desktop + mobile side by side, red-pencil designer
  annotations for the flags. Purpose: test/tune the step-4 wireframe style
  itself before wireframing the new layout. Served at
  `wp-content/prototype/home.html`.
  - **v1.1** adds a **proposed FAQ section** (dashed border = proposed, not
    on the current site): 5 draft questions, accordion, to be wrapped in
    FAQPage schema via the Yoast/Kadence FAQ block — never hand-written
    JSON-LD (project rule), and it doesn't depend on the unconfirmed AI
    add-on. Answer copy must be client-approved (no-copywriting rule) —
    seed it from the 427 existing articles where possible.
  - **v2 — mid-fi** (2026-08-20, replaces v1 as the served `home.html`):
    real Raleway/Open Sans + real copy, grayscale, labeled image
    placeholders, dark tonal bands, browser-frame chrome. This is the
    working wireframe fidelity going forward (see learnings log). Pencil v1
    kept at `prototyping/wireframe-asis-v1.html`; v2 source at
    `prototyping/wireframe-home-v2-midfi.html`.
  - **v3 — live replica** (2026-08-20, current `home.html`): 1:1 HTML
    recreation of the live homepage — measured proportions from the 1440px
    capture (hero form 371px/26%, 32/68 split band, two-column team, 60/40
    testimonial, left-aligned 501px bottom form), real brand colors/fonts
    (Raleway + Open Sans, FA4 icons like live), real images served from this
    build's own `wp-content/uploads/` (no hotlinking production). Static,
    desktop-faithful (min-width 1380, scrolls on smaller). Source:
    `prototyping/home-replica-v3.html`.

**Delivery convention & file locations (BINDING for all users/sessions):**

- **Finished / public prototypes** live ONLY in
  `/srv/apps/leaguelaw/wp-content/prototype/`, served at
  <https://leaguelaw.demoing.info/wp-content/prototype/> (behind the site's
  id-auth gate; not claude.ai artifacts — Adi works from the terminal).
  `index.html` there is the hub listing every prototype page; each page is
  named for the page it mocks (`home.html`, `hero.html`, …) — add a card to
  the hub whenever a new page is added. Files need group perms (664, group
  `leaguelaw-dev`) so Apache serves them and other users can edit.
- **Working copies / version history** live in
  `/srv/apps/leaguelaw/prototyping/` at the workspace root (e.g.
  `home-replica-v3.html`, `header-options-v1.html`) — one file per version,
  never overwritten, so any collaborator can trace or roll back.
- **Claude temp/scratch files** go to the session scratchpad (or similar
  temp locations) — never into `wp-content/prototype/`.
- **Multi-user continuity:** two or more people work on this server. Before
  touching prototype work, read `adi-note.md` (Adi's design decisions) and
  this file — they are to be respected and followed, and updated when a new
  decision lands, so the next person (or session) continues seamlessly.

### New-design explorations (part by part, diffed against the replica)

- **Header — 10 options** (2026-08-20): `wp-content/prototype/header.html`
  (source `prototyping/header-options-v1.html`). All keep contact info loud
  at top per Darren's email. A/B/C/E put the five practice areas directly in
  the main nav (Darren's findability ask); D is the compromise (keeps "What
  We Do ▾" + adds a hexagon service-chip bar); B and J name all six locations
  (fixing the missing-Nanaimo defect). **F–J are the hive set** (Adi's
  bee/honeycomb lens): F comb cluster behind logo · G hexagon-tile nav ·
  H hanging comb fringe · I hexagon CALL NOW badge · J honeycomb lattice bg
  with centered crest logo. **Adi picked F** (2026-08-20).
- **Header F — 5 variations, round 2** (2026-08-20):
  `wp-content/prototype/header-f.html` (source
  `prototyping/header-f-options-v1.html`). Layout held constant, only the
  hive expression varies: F1 baseline on a true comb lattice · F2 line-art
  outline rings (matches the practice-icon style) · F3 corner + faint echo
  behind the phone · F4 full-height hive slab off the left edge · F5
  roofline comb fading left→right. **Adi picked F3** (2026-08-20).
- **Header F3 — 5 inks, round 3** (2026-08-20):
  `wp-content/prototype/header-f3.html` (source
  `prototyping/header-f3-options-v1.html`). Same lattice positions in every
  variant; only the ink changes: F3a full brand color (baseline) · F3b warm
  grayscale hive so the logo owns the color (Adi's request) · F3c one-ink
  tonal brown · F3d full color at watermark opacity · F3e micro/jewelry
  scale. **Adi picked F3d**, flagging that the same-size corner cells had
  uneven gaps (~2px diagonal vs ~4px horizontal) — same-size cells demand
  equal spacing; mixed sizes make irregularity read as intent.
- **Header F3d — 5 geometries, round 4** (2026-08-20):
  `wp-content/prototype/header-f3d.html` (source
  `prototyping/header-f3d-options-v1.html`). Ink locked at watermark; only
  geometry varies: ·1 uniform 4px gap (straight fix) · ·2 welded 1px seams ·
  ·3 airy 10px gap · ·4 left goes mixed-size like the echo · ·5 both sides
  formally regular. **Adi picked F3d·4 — CANONICAL HEADER** (2026-08-20):
  watermark-opacity hive, mixed-size organic scatter on both sides, services
  in the main nav, CALL NOW stack right. Integrated into `home.html` (v4 —
  replica body + new header; source `prototyping/home-v4-newheader.html`).
  Header funnel complete after 4 rounds: 10 options → F → F3 → F3d → F3d·4.
  **v5 adds hover mega menus** (2026-08-20, `prototyping/home-v5-megamenu.html`):
  one panel per nav item, full-wrap width, styled to the header language
  (white panel, orange top edge, Raleway column heads, watermark hive in the
  panel corner, per-area rail with icon + homepage one-liner + CALL NOW).
  Mega menus polished with Adi 2026-08-20: 1280px-wide panels anchored to the
  wrap (not the nav), per-area CTA buttons, quiet 13px gray rail prose, light
  gray column eyebrows, hairline link separators with a reserved-gutter
  orange comb-cell hover (no layout shift), image|links|rail layout for the
  sparse menus (Business/Marine/Real Estate) and a 4-column Your Team panel
  (names ×2, SCC team photo, "Your Team" rail with small careers link).
- **CTA buttons — 10 options** (2026-08-20): `wp-content/prototype/button.html`
  (source `prototyping/button-options-v1.html`). Fixing the weak
  orange→darker-orange hover. B1 current · B2 →brown · B3 solid→outline ·
  B4 outline→fill · B5 lift+glow · B6 arrow reveal · B7 white secondary with
  comb cell · B8 sliding fill · B9 brown→orange · B10 comb-edge shape.
  **B11–B20 = the hive set:** cell-on-shoulder · lattice fill · cells sweep
  in · hexagon end-cap arrow · hive-grows corner · honey dip (⚠ proposes new
  accent #F2A83B — brand-guide decision) · flight-path underline · turning
  cell secondary · swarm-assembles · full-hexagon CALL NOW (short labels
  only). Each shown resting + frozen hover state. **Adi picked B19 "the
  swarm assembles" — CANONICAL CTA** (2026-08-20, lattice corrected to
  uniform 2px gaps): brown resting, three scattered orange cells snap into
  a perfect comb on hover. Rolled into all six mega menu rails in
  `home.html`; it is the primary-button standard for the brand guide.
  Link structure comes from the live site's What-We-Do nav; the Injuries
  column grouping (Road/On Premises/Other) and the Business/Marine bullet
  lists are NEW editorial groupings, not live URLs — verify against the real
  page list before build. CSS-only hover; header wrap constrained to 1280px.
  Process note: option rounds work as **funnels** — broad set (10) →
  pick a route → variation set on that route (5) → refine again on one
  variable per round (round 3 varied only the *ink*, holding the lattice
  constant) → canonical component.

- **Hero — 6 options, round 1** (2026-08-20): `wp-content/prototype/hero.html`
  (source `prototyping/hero-options-v1.html`). Brief distilled from Darren's
  Aug 10 email: contact in-your-face · zones clickable without scrolling ·
  no scenery drama (people OK — live already leads with portraits; live hero
  confirmed to be a 7-slide lawyer-portrait slideshow) · league/teams feel ·
  fix empty H1. O = original modernized (working slider + 371px form + B19)
  · A compact hero, zones on first screen · B zones ARE the hero (5 cards,
  "THAT'S MY ISSUE →") · C November team-photo hero (labelled placeholder
  doubling as the photographer's shot brief) · D proven 371px form + zone
  grid where the photo was · E slim strip, form demoted to bottom + side
  tab. Headline copy = design drafts, NOT client copy.
  **Round 1b — Adi's steer:** phone already lives in the header (don't repeat
  it in the hero); highlight IMAGERY (new office / team slider); no H1 or
  copy in the hero yet; full bleed; form accommodated. Added **F** full-bleed
  November slider (3 labelled shot-list slides) with floating 371px form ·
  **G** full-bleed office still with frosted full-height form panel left ·
  **H** slider bleeding to the left screen edge (real current lawyer slides),
  form on paper right · **I** full-bleed team photo with form compressed to
  an overlapping bottom bar. A–E kept on the page as proof of work.
  **J** (Adi's direction): full-bleed slider owns the whole first screen,
  nothing overlaid; the form sits below the fold but peeks — negative offset
  so its orange bar + "WE'VE GOT YOUR BACK" heading rise into view as a
  scroll cue (dashed fold line marked on the mock). **Adi picked the J route.**
- **Hero J — 5 variations, round 2** (2026-08-20):
  `wp-content/prototype/hero-j.html` (source
  `prototyping/hero-j-options-v1.html`). Slider held constant; ONE variable —
  the form peek: J1 baseline ~70px (bar + heading + field sliver) · J2
  shallow (bar + heading only, max image) · J3 deep (heading + full NAME
  field, strongest cue) · J4 centered "continue-tab" peek · J5 comb-crested
  peek (three hive cells on the card's top edge). **Adi picked J2 — CANONICAL
  HERO** (2026-08-20): full-bleed 3-slide November slider (labelled
  placeholders doubling as the photographer's shot list), no copy/overlays,
  hexagon dots, form below the fold peeking ~48px (orange bar + heading
  only), full form card right-docked with the B19 send button. Integrated
  into `home.html` (v6 — source `prototyping/home-v6-hero-j2.html`). Hero
  funnel: 11 options → J route → J2 in two rounds.
  **v7 — scroll-pinned hero** (Adi's scroll behavior, 2026-08-20, source
  `prototyping/home-v7-hero-scrollpin.html`): hero fills 100vh with the form
  peeking 84px at the fold; on scroll the IMAGE PINS (CSS sticky, no JS) and
  only the form travels up the right side until it docks 40px from the top
  (its limit); then image + docked form scroll away together and the Google
  reviews band arrives directly — no white gap section. Mechanism: scroll
  section of 200vh−216px, sticky 100vh image, absolutely-positioned form.
  **v8 — sticky header** (2026-08-20, source
  `prototyping/home-v8-stickyheader.html`): the canonical header now sticks
  to the viewport top (hairline bottom border added); hero math recalibrated
  — image pins at top:92 filling the rest of the screen, form docks 24px
  below the header, scroll section 200vh−292px, dots back at bottom:22. The
  peek form is also click-to-dock (small JS, geometry-derived, ignores
  clicks on fields; safe-text sits above a full-width B19 Send).
  **v9 — minimizable form** (2026-08-20, source
  `prototyping/home-v9-minimizable-form.html`): a "–" control on the card
  minimizes it into a fixed orange tab on the right screen edge (horizontal
  "WE'VE GOT YOUR BACK" text, visible from anywhere on the page); clicking
  the tab restores the form and snaps back to the hero at the 25%-vh
  position. Scrolling past the hero AUTO-minimizes the form into the tab;
  scrolling back restores it (a manual minimize sticks until the tab is
  clicked). Reviews band also aligned to the 1280 wrap (bleeding gradient,
  seam glued to the grid at 50%−230px).
  Open item: award badges from the old hero still need a home (reviews bar?).


- **Footer — 5 options, round 1 (zeina branch)** (2026-08-20):
  `wp-content/prototype/footer.html` (source
  `prototyping/footer-options-v1.html`; baseline integrated in
  `home-v2.html`). All on warm near-black #2A2622 with text-rebuilt logo,
  practice+firm nav (Blogs/Careers rehomed), six locations (Nanaimo fixed),
  new-address placeholder (exact address TBC after November move — confirm
  with client), hexagon socials, review proof, gutter hive watermark, © bar.
  F1 four columns (baseline) · F2 orange CTA band on top (B19 + phone) ·
  F3 centered crest, single nav line with comb separators · F4 honeycomb
  fringe on the page/footer seam · F5 the 371px form docked in the footer
  (pairs with form-demoting hero routes like J). **Adi's composition
  (2026-08-20): F1 four columns + F2's CTA band on top + hive H12** — all
  integrated in `home-v2.html`; the old Get In Touch section was removed
  (its content is now covered by the footer, resolving the duplicate-form
  flag).

- **Footer hive — 5 placements, round 2 (zeina branch)** (2026-08-20):
  `wp-content/prototype/footer-hive.html` (source
  `prototyping/footer-hive-options-v1.html`). F1 footer locked; only hive
  position/size varies: H1 outer gutters (baseline) · H2 big corner bloom
  bottom-right · H3 small cells half-sunk in the page/footer top seam,
  fading L→R · H4 scattered tiny-cell field in open air · H5 diagonal
  (cluster bottom-left, echo top-right). Round 2b added **H6** monument (one
  giant 380px cell at 5%) · **H7** vertical comb column on the right edge ·
  **H8** divider comb riding the © bar's line · **H9** cells cradling the
  brand column (outside the logo's exclusion zone) · **H10** bee trail along
  the bottom bar, growing toward "Back to top" · **H11** header-mirror (exact F3d·4 arrangement on the footer's top corners, brown→faint cream on dark) · **H12** the same flipped to the bottom corners. **Adi picked H12 (raised
  variant: no cell clips the footer's bottom edge)** — canonical footer hive,
  integrated into `home-v2.html` (source
  `prototyping/home-v2-footer-v2-h12.html`). Note: gutter hive visibility
  depends on viewport width (slivers at 1380px, full at 1600px+).

- **CTA — 10 options, band vs section (zeina branch)** (2026-08-21):
  `wp-content/prototype/cta.html` (source `prototyping/cta-options-v1.html`).
  The closing call-to-action between the last content section and the footer,
  explored in two families so the *type* of element is a decision, not an
  assumption. **Bands** (attached to the footer, no real page height): C1 the
  current F2 orange strip · C2 two-tone split, orange books / brown calls, the
  split falling on the 1280 grid · C3 dark band in the footer's own near-black
  with an orange comb rail on the top edge (quietest, makes the footer start
  earlier) · C4 thin one-line eyebrow (~56px, off-white) · C5 C1 with a
  supporting line and a honeycomb cluster bleeding off the right end.
  **Sections** (their own block above the footer): C6 centered hive, the site's
  existing centered language · C7 half orange panel / half photograph · C8
  three honeycomb action cells (call · book · email) as immediate clickable
  zones · C9 quick three-field form card, the hero form card reduced · C10
  full-bleed photo with dark overlay. Every stage renders the page seam above
  and the top of the footer below, because the transition is the thing being
  judged, not the CTA in isolation. Flags carried in the page: C7/C10 depend on
  the November photo shoot (placeholders labelled with shot briefs), and C10
  sits against the client's "no large hero imagery" line in
  `design-direction.md` — check before it goes anywhere near the client. C9
  duplicates the hero form, so it only earns its place if the hero form is
  scrolled past.

  **Adi kept C1** (2026-08-21) — the band already in `home-v2.html`; no change
  integrated. The round's value is the recorded reasoning, not a swap.

- **Section badge (`.hexfill`) — 10 options (zeina branch)** (2026-08-21):
  `wp-content/prototype/hexfill.html` (source
  `prototyping/hexfill-options-v1.html`). The badge above a section heading,
  used four times on the homepage (two practice-area sections, articles, vlog).
  Constraint set by Adi: **keep the hexagon**, change only how it is drawn. X1
  baseline solid teal cell (carry-over from the live site) · X2 the same cell as
  a 4px ring · X3 paired cells (icon cell + orange partner + faint third — the
  header watermark device repeating down the page) · X4 comb rosette, six cells
  on the true lattice around a solid centre · X5 inline lockup, 46px cell beside
  the heading with an eyebrow (saves ~90px × 4 sections) · X6 cell sitting on a
  full-width hairline (gives each section a start edge) · X7 one cell split
  diagonally teal→orange · X8 ghost watermark, no icon, heading over a faint
  cell · X9 brown cell with the icon knocked out to page colour + orange eyebrow
  · X10 comb bar, a short strip of cells with only the centre solid. Stages
  render on the new off-white `#F9F9F9`, not the replica's `#fff`; cards are
  abbreviated because the badge is what is being judged. Open question the round
  surfaced and does not answer: **the icons themselves are generic FontAwesome**
  (`fa-rss`, `fa-youtube-play`) — a badge treatment can be picked independently,
  but the icon set still needs redoing as brand SVG (already flag 4 below).
  **Round 2 — hover (2026-08-21)**, same page, sources
  `prototyping/hexfill-options-v2-hover.html` then
  `prototyping/hexfill-options-v3-hover-corrected.html`. The round split by
  affordance — **decoration may respond to hover, but must not borrow the
  vocabulary of a control** (lift+shadow, sliding arrow, growing underline,
  heading colour change, `cursor:pointer`). Since `.hexfill` links nowhere, the
  live candidates are the section-triggered ones (X11, X14, X15, X16, X17); the
  control-vocabulary ones (X12, X13, X18) are kept only as comparison and are
  valid only if the section header is ever made a link to its archive.
  **Adi picked X16** (2026-08-21) — canonical section badge, integrated into
  `home-v2.html` at all four uses (two practice-area sections, articles, vlog;
  source `prototyping/home-v2-v6-hexfill-x16.html`). At rest it is a neutral
  `#E6E1DA` cell with a brown icon — the teal steps back out of a major role it
  was never meant to hold — and `section:hover` fills it orange from the bottom
  while the icon turns white. Trigger is the `<section>`, never the badge. *Badge + heading
  become a real link to the section archive:* X11 scattered cells snap onto the
  lattice (the B19 "swarm assembles" language, so badge-hover and button-hover
  match) · X12 the outline ring floods with teal · X13 the cell flips to an
  orange arrow · X16 the cell fills bottom-to-top like a cell of honey (the only
  effect in the set this firm alone could own) · X17 the small partner cell
  orbits to the far corner · X18 lift + shadow + arrow + underline opening from
  the centre (most conventional, most legible). *Section-level, claiming no
  affordance:* X14 six neighbours fade in one after another when the cursor
  enters the section · X15 the two-tone diagonal sweeps across the cell. All
  transition-only, all disabled under `prefers-reduced-motion` (same rule as the
  header and B19). Build note learned here: **`box-shadow` is clipped away by
  `clip-path`** — a lift/shadow on a hexagon needs `filter: drop-shadow()` on a
  wrapper element instead. **Open flag against `design-direction.md`:** that
  document says distinctiveness must come from information design, *not*
  decoration, and lists animation among the levers already ruled out — a hover
  round on a decorative badge sits against that sentence. Fine to explore
  internally; must not be presented to the client as the answer to "a little
  different than most websites."

- **`.cards-sec` layout — 9 options (zeina branch)** (2026-08-21):
  `wp-content/prototype/cards.html` (source `prototyping/cards-options-v1.html`).
  The section runs twice on the homepage (featured articles, vlog). The round
  opens by naming what is actually wrong with it, because the faults are
  information faults, not styling ones: **centred multi-line excerpts** (the eye
  has to hunt for each line's start); **no metadata whatsoever** — no date, no
  practice area, so a visitor cannot tell a 2014 post from last month's or
  whether it concerns their problem; **no clickability signal and no archive
  door** (427 posts exist, the homepage offers no route to them); **three items,
  flat hierarchy, ~700px of page**; and **images that carry no information**
  (stock crops heading an estate-dispute piece) while taking the most space in
  each card. Options: L1 baseline · L2 same grid, left-aligned + practice-area
  tag + date/read-time + Read-more + View-all (smallest change that fixes all
  five) · L3 lead article + compact list (hierarchy, four items in three cards'
  space) · L4 text-first list, images dropped, five articles in less height ·
  L5 two columns, six items, 96px hexagon-cropped thumbs · L6 grouped by
  practice area, doubling as a second route into the triage layer · L7
  horizontal rail with a cut-off card · L8 editorial left column (heading,
  intro, View-all) + wide item rows · L9 the vlog variant — brand hexagon as the
  play button, running time on each thumbnail, topic tag. **L4 is the option
  that best satisfies `design-direction.md`** ("distinctiveness from information
  design, not decoration") and is also the biggest visual departure — that
  tension is the decision. Side effect worth recording: **a View-all control
  settles the badge round's open question** — the section header never needs to
  become a link, so the badge stays decoration as picked. Dates, read times and
  tags in the page are invented placeholder data (titles and images are real).
  **Round 2 — featured articles, with the vlog settled** (2026-08-21):
  source `prototyping/cards-options-v2-articles.html`. Because the vlog half is
  now L9, this half stopped being a free choice — **the two halves of one class
  must read as one website** — so every option keeps L9's vocabulary
  (left-aligned mixed-case titles, same card rhythm, hexagon, archive door) and
  every one runs body copy at **15px**, applying the type-size lesson from the
  facts round rather than repeating it. A1 direct sibling of L9 · A2 lead
  article + two · A3 two large cards · A4 rows with thumbnails · A5 text-first
  list (shortest, but breaks visual step with the image-led vlog half) · A6
  zebra rows full-bleed · A7 editorial rail (same structure as facts option K18,
  so the page repeats a pattern instead of inventing one) · A8 **merge** —
  articles two-thirds, vlog one-third in a single "From Our Desk" block, which
  removes a whole section from a long homepage and ends the duplication; the
  trade is that the vlog loses its own heading. Real titles, excerpts and images
  are verbatim from `#block_5d5b0fb6a2bccfb28ee24fc99bf1facf`; extra positions
  are drawn as labelled empty slots rather than invented articles.
  **Two live defects found while reading the block, both outliving any layout
  choice:** (1) the second excerpt reads "What is a Co-Ownership
  Agreement?Two or more people…" — WordPress's auto-excerpt swallowed the post's
  first heading and ran it into the sentence with no space; the fix is
  hand-written excerpts, not layout; (2) **the images are upscaled** — the live
  section serves the 300×200 thumbnail into a ~384px slot, so every card is
  soft, while 768×512 and 1024×683 versions already exist in the media library.
  **Metadata verified against the database (2026-08-21)** after Adi asked
  whether the category tag was real: it now is. The tag is the post's **Yoast
  primary category** (`_yoast_wpseo_primary_category`), set on **396 of 427
  posts** — it has to be the primary term rather than "the category" because
  **373 posts carry more than one** (the estate article sits in four at once).
  Dates and word-count reading times are read from the posts too; **31 posts
  have no primary term and need a fallback.**
  **Taxonomy needs a decision before launch:** 29 categories with heavy overlap
  — Estate Law (117), Estate Planning (107), Wills and Estates (107), Estate
  Disputes (79), Unfair Wills (13) all describe one practice area, and Personal
  Injury Law (64) sits beside Personal Injury (61) as a straight duplicate.
  Either merge the duplicates or map categories onto the five practice areas and
  show the practice area on the card; the mapping is less destructive and
  matches how the rest of the site is organised.
  **The finding that changes the section's brief:** the three "featured"
  articles were published **2020-03-03, 2021-10-01 and 2022-07-07**, but the
  blog is active — newest post **2026-07-02**. They are hand-picked and were
  never rotated, so *adding dates to the section as it stands would make an
  active blog look abandoned*. Three honest answers, all content decisions
  rather than layout ones: pull the latest posts automatically (dates become an
  asset), keep the hand-picked three and show no dates, or re-pick the featured
  three each quarter. Options now render the real dates so the problem is
  visible rather than hidden. Source
  `prototyping/cards-options-v3-real-meta.html`.
  **Process lesson: when an option round invents metadata to show a layout, say
  so at handover and verify it before the round is used to decide anything** —
  the placeholder dates here (2026) had quietly implied a firm publishing
  monthly, which would have sold a layout on a fiction.
  **Adi picked L2** (2026-08-21) — integrated into `home-v2.html` scoped to
  `.cards-sec.articles` (source `prototyping/home-v2-v9-articles-l2.html`): the
  same 3-up grid the client already knows, with the five things it lacked —
  copy left-aligned, practice-area tag, publish date, explicit read-more, and a
  "View All Articles" door. Real data throughout (primary categories, real
  dates and word-count reading times, 768px images instead of the upscaled
  300×200), and the WordPress wiring notes live in the section's CSS comment.
  **Two open items deliberately left visible rather than silently resolved:**
  (1) the vlog half runs L9 *without* its tagline while the articles half now
  shows one — a one-line change either way, but it is Adi's call which way the
  pair should match; (2) the dates now on the page are real, which exposes that
  the three hand-picked articles are from 2020–2022 while the blog's newest post
  is 2026-07-02.
  **Adi picked L9 for the vlog, minus the topic tagline** (2026-08-21):
  integrated into `home-v2.html` (source `prototyping/home-v2-v7-vlog-l9.html`).
  Hexagon play control replacing the generic circle, running time on each
  thumbnail, left-aligned mixed-case titles, cards are real links, "Watch All
  Videos" as the archive door. Deliberately **scoped to `.cards-sec.vlog`** so
  the featured-articles half keeps its current layout until it is decided
  separately — noting that the two halves are now visually out of step, which is
  a state to resolve, not to leave. Note on hover: the vlog cards ARE links, so
  the play control may use control vocabulary (fill + scale) — the rule from the
  badge round is not violated, it is being applied. **Open data item:** the
  running times (3:42 / 2:58 / 4:15) are invented — real durations must come
  from the videos before this is shown to anyone.

- **`.facts` layout — 8 options (zeina branch)** (2026-08-21):
  `wp-content/prototype/facts.html` (source `prototyping/facts-options-v1.html`).
  The "LaW Facts / Did You Know?" block. Faults named first, because they are
  structural: **948px — most of a screen — for one sentence** (tallest section on
  the page, least information per pixel); **the firm's strongest proof is hidden
  in a slider** (a unanimous SCC decision as one of N rotating panels); **"Did
  you know?" files it under trivia**; **nothing is clickable** (no route to the
  case, the results, or the lawyers); **it names one lawyer**, working directly
  against the client's own "we are *teams*, not lawyers supporting clients";
  and **credibility is scattered** — 160 years, six offices, 4.9★/173 reviews
  and the SCC win live in four unrelated places or nowhere. Since
  `design-direction.md` assigns this zone to "credibility — reviews, 160 years,
  results", the stronger options stop treating it as a fact slider and start
  treating it as the proof layer. Options, with heights against the current
  948px: K1 baseline · K2 proof band, four hexagon stat cells, ~300px · K3 lead
  fact + proof rail, ~520px · K4 case notes as Situation → What we did → Outcome,
  ~560px · K5 team-first, the same SCC win retold as the team that won it,
  ~560px · K6 the approved split shape halved and de-slidered, ~470px · K7 quiet
  display-type statement over a stat rule, ~430px · K8 reviews-led with the
  4.9★ and client quotes leading, ~480px. **Content-integrity flag carried in
  the page itself:** the SCC fact is real and already published, but the K4 case
  notes, K8 review quotes and K5 team names are placeholder copy written to show
  layout — invented case outcomes and invented reviews are a legal/ethical
  problem for a law firm, not merely a content gap, and every one must be
  replaced with real client-cleared material (and the review numbers confirmed
  against the live Google profile) before anyone outside the build sees it.
  **Round 2 — no slider, image kept (2026-08-21)**, same page, source
  `prototyping/facts-options-v2-image-noslider.html`. Constraint: every fact
  visible at once *and* the photograph stays in the block — round 1's densest
  answers (K2, K7) had bought their efficiency by dropping the image. K9 wide
  photo band with four proof cards overlapping its bottom edge, ~560px · K10
  facts beside a **photo comb** — three photographs cropped into hexagons on the
  real lattice, the brand shape finally structural rather than ornamental,
  ~520px · K11 four stats over a darkened full-bleed photograph, ~430px ·
  K12 alternating photo/text strips, one fact per strip, scales by adding a
  strip, ~500px · K13 half photo + numbered facts with a hexagon photo inset
  straddling the seam so the halves interlock, ~500px · K14 **comb mosaic** —
  six lattice cells, three photographs and three facts interlocking, ~600px.
  **K11 carries its own objection:** it uses large expansive imagery, which
  `design-direction.md` rules out; it is listed with the objection attached
  rather than quietly offered. All photography is labelled placeholder at final
  crop sizes per the project rule.
  **Round 3 — the real six facts (2026-08-21)**, source
  `prototyping/facts-options-v3-six-facts.html`. Adi pointed out the live slider
  holds **six** facts; they were pulled from the live homepage and wired into
  every option, replacing the invented statistics: the SCC win, the Victoria
  News readers' award, Westside Village since 2014 (expanded 2018), 160+ years
  combined, free injury/estate consultations, and the largest marine practice on
  Vancouver Island. Grids re-cut to fit six (K2 3×2, K7 five stats under the
  statement, K9 3+3 with the first row overlapping, K11 3×2, K12 three strips,
  K13 six numbered rows, K14 a nine-cell mosaic of six facts + three photos).
  **Design finding worth keeping for other projects:** most of the six are
  *statements*, not statistics — only two carry a real number — so pure
  stat-grid layouts (K2, K7, K11) have to invent tokens like "Largest"/"Free" to
  fill the number slot, which is a sign the layout is fighting the content. The
  list and story layouts (K10, K12, K13) hold the same six without distortion.
  **Two content problems surfaced while collecting them, both needing the client
  rather than a designer:** (1) the live copy says "7 years in a row – 2018 …
  2023 & 2025", which is seven wins but *not* consecutive — 2024 is missing, so
  "in a row" is wrong as printed; (2) "in its Westside Village home since 2014"
  expires with the November office move, same flag as the footer address.
  **Round 4 — verbatim, and the pairing discovery (2026-08-21)**, page
  regenerated, source `prototyping/facts-options-v4-verbatim.html`. Adi asked
  for the copy to follow the live block 100%, un-shortened, and named the block
  id; reading `#block_5a2b7010162c99e695ff8537e241434d` on the live homepage
  showed the section is **two synchronised sliders, not one** — six fact texts
  *and* six photographs rotating together, one image chosen per fact
  (SCC→DarrenatSCC, award→BestinCityAwards, Westside Village→FrontDoor,
  160 years→harbour-on-the-sunset, free consultations→IMG_4959, marine
  →seaplaneVictoria). All six files are already in this build's uploads, so the
  options now use the real images, each kept with the fact it belongs to.
  **Process lesson: reading the actual source block changed the design brief** —
  four earlier rounds had treated the block as "facts plus a photo", and the
  no-slider question is really "how do you show six text-image *pairs* at once".
  Options regenerated at 12, every one carrying all six facts word for word:
  K1 baseline · K2 dark band, six statements, no photo · K3 lead fact + five ·
  K6 approved panel shape, rotation removed · K7 two-column typographic list ·
  K8 award-led (third-party recognition first) · K9 photo band + six cards ·
  K10 six facts beside a three-photo hexagon comb · K11 six over a full-bleed
  photo (carries its own direction-doc objection) · K12 **the pairing unrolled**
  — each fact with its own photograph, six at once · K13 photo half + six
  numbered facts · K14 all six photographs as a hexagon comb, fact under each.
  Third copy problem found: **"the reader's of Victoria News"** — apostrophe
  error in the live text, reproduced verbatim rather than silently corrected, so
  the client sees it and decides. Dropped from the page in this regeneration:
  the old K4 (invented case notes) and K5 (team-first) — neither was built on
  the six facts; both survive in `prototyping/facts-options-v3-six-facts.html`
  if that strategic direction is wanted later.
  **Round 5 — six more layouts (2026-08-21)**, source
  `prototyping/facts-options-v5-more-layouts.html`, page now at 18 options, same
  rule throughout (verbatim copy, each photo kept with its own fact): K15
  alternating spine down a central hairline with hexagon markers, reads as a
  sequence — useful because three facts carry dates · K16 zebra rows full-bleed,
  image and text swapping sides, most legible at any width and scales by adding
  a row, but the tallest thing here · K17 proof wall, photographs and colour
  tiles interlocking in one dark grid with two-cell spans · K18 editorial rail +
  two-column facts, deliberately the **same structure as the articles-section
  option L8** so the page gains a repeated pattern instead of a new one · K19
  dark band of facts + all six photographs as a desaturated full-width filmstrip
  beneath, so text and image stop competing · K20 contact sheet, numbered 01–06,
  image side swapping each row, reading as documentation rather than marketing.
  Trade-off the round makes explicit: **every layout that shows six text-image
  pairs at readable size costs 500–1200px**; the compact answers (K2, K19)
  either drop the photographs or decouple them from the text.
  **Round 6 — K12 modernised (2026-08-21)**, source
  `prototyping/facts-options-v6-k12-modern.html`, page at 23 options. Same
  content contract as K12 (one photograph per fact, copy verbatim); only the
  visual register changes. **K12·M1** editorial index — card containers removed,
  hairline per item, small orange numeral, wide air, caption held to a narrow
  measure · **M2** tight mosaic, zero gutters, photo and caption tiles forming
  one continuous surface with two tiles in brand colour · **M3** scrim, caption
  over its own photograph, image easing on *section* hover · **M4** duotone,
  photographs held in brand brown and desaturated, full colour on section hover
  · **M5** asymmetric spans (2 wide, 3 narrow, 1 wide) so the SCC fact takes the
  largest frame. **M4 answers a real content problem, not a stylistic one:** the
  six live photographs were shot at different times, qualities and colour
  temperatures (a courtroom snap, an award graphic, a front door, a sunset, an
  office interior, a seaplane) — a duotone makes them read as one deliberate set
  rather than a folder of odds and ends. Note the hover in M3/M4 is section-level
  because the cells are not links, per the rule from the badge round; both
  transitions are disabled under `prefers-reduced-motion`.
  **Round 7 — synced autoplay (2026-08-21)**, source
  `prototyping/facts-options-v7-synced-slider.html`, page at 25 options.
  Adi's brief: K13 without the hexagon inset, the photograph back to a slider
  running the six images **in the order of the six facts**, and the row for the
  fact currently on screen taking a different background. Built as **K13·S1**
  (light list, numerals) and **K13·S2** (brown panel, hexagon marker filling
  orange). The point of the pattern: *the slider returns, but it no longer
  hides anything* — all six facts stay on screen and readable, and the rotation
  only says which one the picture belongs to. Mechanics worth reusing: **one
  30s CSS timeline, six 5s slots**, with slides, row highlight, numeral colour
  and a six-segment progress meter all driven from the same keyframes and
  offset per slot by `animation-delay`; no JavaScript. Two build notes: the
  rows must sit in their own wrapper because `:nth-child` counts *all*
  siblings (the heading and eyebrow would shift every delay by two), and
  `animation-delay: inherit` lets a pseudo-element (the meter fill) pick up its
  parent's slot. Under `prefers-reduced-motion` the whole thing stops on fact 1
  with the full list legible — **motion is never load-bearing.**
  **Adi picked K13·S2** (2026-08-21), with the hexagon marker removed — the
  orange left edge plus the darkened row are enough, because only one row is
  ever lit. Source `prototyping/facts-options-v8-s2-refined.html`.
  **Type-size finding, raised by Adi's question and worth carrying to every
  future option round:** the site's body scale is 15–15.5px (cards 15px, the
  facts panel 15.5px/1.85), but most options on the page had been drawn at
  13–13.5px so six verbatim facts would fit on one screen. **That means the
  compact heights quoted in earlier rounds were partly bought with undersized
  text — a saving the finished site cannot keep.** S2 was corrected to
  15.5px/1.8 and its height restated honestly (~780px, still ~170px shorter
  than the 948px it replaces); a disclosure box now sits at the top of the
  options page so no other option's height is read as trustworthy until it gets
  the same correction. **Rule for the reusable prompt: never let an option round
  shrink type below the body scale to win a height comparison — quote the height
  at real reading size, or the comparison is fiction.**
  **Resolution (2026-08-21):** shown at the full 15.5px (~780px), Adi chose to
  **return S2 to 13.5px/1.7 (~660px)** — the designer's call, made with the
  trade-off on the table. Recorded in the CSS comment and in the page's
  disclosure box rather than left implicit, so the height is never mistaken for
  a free saving, and with the condition for revisiting it written down: if the
  six facts are ever shortened, the type goes back up at no cost in height.
  Source `prototyping/facts-options-v10-s2-final.html`.
  **Integrated into `home-v2.html`** (2026-08-21, source
  `prototyping/home-v2-v8-facts-k13s2.html`), replacing the 948px slider block:
  section height drops to ~660px while going from one visible fact to six, the
  six photographs run in the facts' own order, and the row whose photograph is
  showing takes an orange left edge. Keyframes and the per-slot delays live with
  the section's own CSS, with the constraints written into the comment block —
  motion never load-bearing, no Ken Burns, copy verbatim, rows must stay inside
  `.rows` for `:nth-child` to count correctly, and the condition for raising the
  type back to body scale.

  **Round 8 — quiet cards, from a reference image (2026-08-23)**, source
  `prototyping/facts-options-v11-quiet-cards.html`, page at 29 options. Adi
  supplied a screenshot of a layout he liked — soft grey panels, a large plain
  icon, a short serif heading, a short paragraph, three across — and asked for
  the same thing **with the facts' photographs included**. Built as **K21**
  (photograph across the head of the card), **K22** (photograph desaturated to
  15% *inside* the panel, no separate image band), **K23** (split card,
  photograph beside the words, two per row) and **K24** (no grey at all — the
  photograph *is* the card, brown scrim carrying the words at the foot).
  Four things had to be declared rather than quietly absorbed, and this is the
  pattern for every future round that starts from a reference image:
  - **The reference's serif is not in the brand system.** Headings stay Raleway.
    Adopting a serif is a brand-guide decision, not a section decision — noted on
    the page instead of smuggled in as part of a layout choice.
  - **The reference's grey is cool (blue-grey); the brand's is warm.** Panels use
    `#F1EFEB`, mixed toward the brand off-white and rule colour, so they sit with
    the page rather than fighting it.
  - **The headings are new copy.** The live facts have no titles — they are six
    loose sentences. Every heading is a phrase lifted out of the fact beneath it
    (three exact substrings, two compressed), so no new claim is made, but a
    heading is still a new editorial element and is flagged on the page as
    needing Darren's sign-off. *Rule: a layout that requires a field the content
    does not have must name the field it is inventing, in the artifact, at the
    moment it is drawn.*
  - **The icons are the same FontAwesome placeholders** as the rest of the
    prototype, restated in the round intro so a card layout built around a large
    icon is not mistaken for a finished one.
  These are also the **first options on the page drawn at the site's real 15px
  body scale**, and the honest consequence is recorded per option: K21 comes out
  **taller** than the 948px block it replaces. Kept and labelled rather than
  shrunk, because the type-size rule from round 7 says the comparison is fiction
  otherwise. Two defects the round exposes and the label names: the facts differ
  3:1 in length (209 characters against 76), so an even three-up grid leaves
  visible empty grey under the short cards — K23's wider measure is the layout
  answer, levelling the copy is Darren's; and K24's scrim eats the lower half of
  each frame, so any photograph with its subject low in frame needs re-cropping
  before it could ship.

  **Round 8b — five more, each changing something structural (2026-08-23)**,
  source `prototyping/facts-options-v12-quiet-cards-more.html`, page at 34
  options. The rule the second set was drawn to: *a second batch in the same
  visual language has to move a joint, not restyle a surface* — otherwise it is
  five ways of looking at the same card and the funnel stops narrowing.
  So each one asks a different question. **K25** moves the photograph to the
  foot and pushes all six onto a common baseline, which turns the ragged-bottom
  defect K21 exposed into aligned pictures with the slack absorbed above them —
  the choice is now purely reading order, picture-then-claim or claim-then-
  picture. **K26** deletes the panel: same rhythm on white with one hairline
  between cells, put there as a deliberate A/B because the reference layout is
  largely *defined* by its grey box. **K27** stops treating the six facts as
  equals — the Supreme Court fact leads at double width on brown, the other five
  run as compact rows beside it — which is the only layout in eight rounds that
  answers the page's own standing criticism that the firm's strongest proof is
  one rotation among six. **K28** lets the photograph *replace* the icon, cut to
  the brand hexagon at the exact size the reference gives its glyph, which also
  removes the placeholder-icon caveat from the option entirely. **K29** moves
  the icon down onto the seam between photograph and panel so the card reads as
  built rather than as two stacked rectangles.
  **Build note worth keeping — spanning grid cells can cost height, not save
  it.** K27 was first drawn as a 3×3 grid with a 2×2 feature. That tiles
  perfectly with five cards left over, which is why it looks right on paper, but
  it forces *three* card-rows to hold *five* cards and came out near 1300px —
  worse than the 948px block it replaces. Rebuilt as a tall feature column
  beside a flex stack of five compact rows, it lands at ~790px and is the
  shortest option in the round. **Check the row count a span implies before
  quoting a height; a grid that tiles neatly is not the same as a grid that
  packs efficiently.**
  Heights for the round were restated after that, not before: K27 ~790px,
  K28 ~900px, K26 ~960px, K21/K25 ~1010px, K29 ~1040px. K27 is the only one that
  beats 948px without dropping below the 15px body scale — every other option in
  the family is taller than what it replaces, and that is recorded on each label
  rather than averaged away.

  **K29 revised — 3:2 photograph (2026-08-23)**, source
  `prototyping/facts-options-v13-k29-3x2.html`. Adi: the picture looked
  *gepeng*. He was right, and the cause is a habit worth naming: **every card in
  this round set its image with a fixed pixel height inside a fluid column, so
  the ratio was whatever the column width happened to make it** — 410px over
  134px is nearly 3:1, a letterbox nobody chose. Fixed to
  `aspect-ratio: 3/2` on the frame, which holds the ratio at any column width
  and at any breakpoint. *Rule: in a fluid grid, state an image's **ratio**, not
  its height; a pixel height is a ratio you did not decide.*
  The second half of his note — make the content a little smaller — was taken
  out of **spacing, heading size and leading, not out of the paragraph**, which
  stays at 15px. That is the round-7 rule holding under pressure: rebalancing a
  card against a bigger picture is a legitimate reason to tighten a layout and
  never a reason to drop below the body scale. Cost stated on the label rather
  than absorbed: a 3:2 frame is ~274px per card against 134px, so K29 grows to
  ~1160px and becomes the tallest option in the round, with K23's two-per-row
  geometry named as the lever if that height turns out to matter.

  **Round 8c — hexagon to the right, and &ldquo;more modern&rdquo; asked as four
  positions (2026-08-23)**, source `prototyping/facts-options-v14-k29-modern.html`,
  page at 38 options. Adi moved the seam hexagon from the left of the card to the
  **right** — which is also the better reading argument: on the right the eye
  finishes the line and meets it, instead of colliding with it before the heading
  starts. Applied to K29 and to all four variants.
  The second half of the brief, *make it look more modern*, is the kind of note
  that is easy to answer badly, because &ldquo;modern&rdquo; is not one thing and
  a single guess hides the choice inside it. **Split into four positions that
  disagree with each other:** **M1** softens the card (white, 16px radius, soft
  shadow, grey moved out to the section); **M2** deletes the card entirely
  (picture, air, words, nothing else); **M3** keeps the card and turns the
  section dark; **M4** interlocks the two halves by lifting the panel up over the
  foot of the photograph. Everything else is held constant across all four — same
  3:2 frame, same 15px paragraph, same headings — so what is being compared is
  only the idea.
  **The declaration M1 forces, and the reason it is not a section decision:**
  rounded corners are a deviation from the brand system. Every component locked
  so far — header, `.rbtn`, section badge, hive, cards — is square-cornered and
  built around a pointy-top hexagon. Choosing M1 softens the *whole system*, not
  one section, so it belongs in the brand guide. Recorded on the option label
  rather than left for someone to discover after it ships. *Rule: when an option
  can only be adopted by changing a system-wide rule, say so on the option, not
  in the handover.*
  **Height, stated once for the whole set instead of per option:** all four land
  ~1050–1160px. A 3:2 photograph plus six verbatim facts at real reading size
  sets that floor and **no styling choice moves it** — the levers are geometry
  (two per row, or K27's lead-plus-five), never decoration. Worth carrying: when
  a batch of variants shares a constraint, quote the constraint once at the top
  of the batch, or each label quietly re-argues a number nobody can change.
  **Standing flag, still open and now louder:** this whole quiet-cards line runs
  against `design-direction.md`'s position that distinctiveness should come from
  information design, not decoration. M2 is the only option in the set that
  satisfies it — noted on its label as such, since the direction document is a
  constraint Adi wrote and is entitled to override, but not to override by
  accident.

  **Small fix worth naming (2026-08-23),** source
  `prototyping/facts-options-v15-m2-inset.html`: in M2 the hexagon had been set
  to `right:0`, aligning it to the text edge, and Adi flagged it as too tight.
  The cause is a habit rather than a typo — in a card *with* a panel, `right:26px`
  is read off the panel's own padding, so when the panel was removed the value
  collapsed to zero as if that were the neutral equivalent. It is not: with
  nothing to sit inside, an element flush to the text edge reads as falling off
  the card rather than resting on it. Inset to 26px to match M1/M3/M4. *Rule: in
  a container-less layout, zero is not the neutral value — an element that had
  been living off a container's padding has to be given its own.*

  **Adi picked K29·M3** (2026-08-23) — quiet cards, dark section, 3:2
  photographs, hexagon on the right of the seam. **Integrated into
  `home-v2.html`**, source `prototyping/home-v2-v11-facts-k29m3.html`,
  replacing K13·S2. Options page source `prototyping/facts-options-v17-m3-picked.html`.
  **This is the first pick in the project that reverses an earlier pick**, and it
  is worth being precise about what actually changed, because the obvious framing
  is wrong. The slider is gone — but K13·S2 was *already* showing all six facts;
  its rotation only said which photograph belonged to which sentence. So nothing
  is being un-hidden. What is gained is that all six **photographs** are now
  permanently visible, each attached to its own fact, and the section stops
  moving. *Rule: when a replacement retires a mechanism, describe what that
  mechanism was doing at the end, not what it was doing when it was first
  criticised — K13·S2 had already fixed the hiding, and calling this swap
  "removing a slider that hid five of six facts" would have been a lie by
  inheritance.*
  **The debt from round 7 is repaid:** type is back at 15px/1.75, the site's real
  body scale. K13·S2 ran 13.5px specifically to hold ~660px.
  **The cost is height, and it is large:** ~1160px against K13·S2's ~660px and
  the live block's 948px, making the facts section the tallest thing on the page.
  Written into the section's own CSS comment along with the only levers that can
  reduce it — geometry (two per row, or lead-plus-five), never decoration and
  never type size — so a future session reaching for the type slider finds the
  answer already refused.
  Also carried into that comment rather than left in this document, because a
  code session reads the code: no `prefers-reduced-motion` branch is needed (no
  motion remains, and the `llfade`/`llrow`/`llbar` keyframes were removed with the
  slider); the six headings are new copy awaiting Darren; the icons are still
  placeholders; the copy errors are still verbatim; and the section head keeps the
  client's "LaW Facts / DID YOU KNOW?" wording instead of the `.hexfill` + `h2.sec`
  convention the vlog, articles and testimonials sections use — **an open
  inconsistency left visible on purpose**, since switching it retires vocabulary
  the client uses and that is not a designer's call.
  Noticed on integration and flagged rather than fixed: `home-v2.html` now carries
  **four dark values** (`--brown`, `--band-dark`, `#2A2622`, `--footer`).
  Consolidating them is a brand-guide job, not a section edit.

  **Quote-mark defect, testimonials (2026-08-23),** sources
  `prototyping/quotes-options-v6-quotemark.html` and
  `prototyping/home-v2-v12-quotemark.html`. Adi: the mark on the T2 cards does
  not read as a quote mark. It didn't — and the useful part is that **three
  separate causes were stacked in one 40px declaration**, only one of which was
  the glyph: `#E6E1DA` on white is ~**1.26:1** contrast, so whatever shape was
  there never resolved; **40px** is too big to be punctuation and too small to be
  an ornament, landing in the gap where it reads as neither; and **Raleway is a
  geometric sans** whose quote marks are angular wedges rather than the curly
  comma the eye recognises as a quotation. *Rule: when something "looks wrong"
  and cannot be named, check contrast, size and typeface separately before
  changing any of them — a single fix aimed at the wrong one of the three makes
  the result better and still wrong.*
  Fixed by setting the glyph in Georgia at 68px with real contrast, and
  **declared**: Georgia is not in the brand system. Setting one punctuation glyph
  in a serif is an ordinary typographic move and is not the same as adopting a
  serif for headings — but it is a second typeface on the page, so it is named in
  the CSS comment and on the options page rather than smuggled in with a defect
  fix. *A defect fix is the easiest place in a project to introduce an
  undeclared system change, because everyone is looking at the defect.*
  Three alternatives drawn side by side as option **QM** in `quotes.html` so the
  deviation can be overruled cheaply: the FontAwesome quote glyph (in-system, but
  repeats the section badge's own mark), or no mark at all (the badge, the orange
  top rule and the stars already say "review"). Recorded on the label: if the
  second typeface is unwelcome the answer is removing the mark, **not** returning
  to the version that did not read.

  **Adi picked c** (2026-08-23), the FontAwesome quote glyph in orange, and it is
  now in `home-v2.html` — sources `prototyping/home-v2-v13-quotemark-c.html` and
  `prototyping/quotes-options-v7-qm-c.html`. Georgia is out; **no second typeface
  is added to the page**, and the declared deviation is withdrawn rather than
  merely disclosed. Worth keeping as a pattern: *offering the in-system
  alternative alongside the deviation is what let the deviation be refused in one
  word.* Had only the serif version been built, the declaration would have sat in
  the file indefinitely as a thing "everyone knows about" — which is how
  undeclared system drift actually happens, one accepted disclosure at a time.
  The trade the pick accepts, written into the section's CSS comment so nobody
  re-discovers it later as a bug: `fa-quote-left` now appears **twice** in the
  testimonials section — once in the hexagon badge, once per card. If that
  repetition ever grates, the answer is dropping the card mark entirely, not
  returning to a mark that does not read.


### `.team` — the team block

  **Round 1 — eight layouts (2026-08-23)**, `wp-content/prototype/team.html`,
  source `prototyping/team-options-v1.html`. **P1** baseline replica · **P2** six
  across with the careers tile pulled out · **P3** hexagon portraits · **P4** the
  principal leads · **P5** cards carrying the stored practice line · **P6** rail
  kept, six across · **P7** dark band · **P8** names only, no portraits.
  **The data was read before a single layout was drawn**, and it changed the
  brief more than any styling opinion could have. From the database
  (`lawyers` post type, 13 published records) and a read-only read of the live
  site:
  - **No job-title field exists.** One custom field on the whole post type
    (`email`, on 12 of 13) and no taxonomy. "Principal" and "Associate" are
    printed by the theme, not stored — which is why eleven different people carry
    one identical label, and why the intro's promise of "lawyers *and staff*" is
    not kept by the grid. *A label that eleven records share is not data; it is a
    default wearing data's clothes.*
  - **A practice line exists for only 7 of the 12** (`post_excerpt`). P5 is built
    to show the five gaps rather than pad them, because that option cannot ship
    until the five lines are written — a content job, and hiding the gap would
    have hidden the dependency.
  - **All twelve portraits are black-and-white** (measured: mean chroma
    0.1–3.5/255). That is an asset, and it is what makes the dark band (P7)
    worth drawing at all.
  - **Five portraits are low-resolution** (four at 260×345, Darren at 287×378;
    the rest 761×1024+). This is a hard ceiling on the whole section: above about
    130px those five soften visibly. P4 renders one at 300px deliberately so the
    ceiling is visible rather than described.
  - **Backgrounds do not match** (corner luminance 44–124), so any edge-to-edge
    portrait treatment will show studio grounds ranging from near-black to light
    grey.
  - **The careers tile is not a portrait** — `law-sm.jpg` is 820×280, a colour
    landscape photograph, forced into a portrait frame beside twelve monochrome
    headshots. Six of the eight options take it out of the grid.
  - `menu_order` has **two ties** (5,5 and 9,9) and gaps, so two pairs are
    currently ordered by record ID rather than intent.
  **The structural finding that drove most of the round:** thirteen tiles in a
  four-column grid leaves an orphan row, and the thirteenth tile is the one that
  is not a person. Removing the advert from the grid leaves **twelve**, which
  tiles perfectly six-across in two rows. *Rule: before choosing a grid, ask
  whether every item in the set is the same kind of thing — an odd count is often
  an odd item, not an odd number.*
  P8 (names only, no portraits) is in the set to hold the others to account
  rather than to win: it is the only option immune to the portrait problem and
  the only one that satisfies `design-direction.md`. It sets the question the
  portrait layouts have to answer — do these twelve pictures earn 370px of page?

  **Round 2 — dark portrait cards, from a reference image (2026-08-23)**, source
  `prototyping/team-options-v2-dark-cards.html`. Adi supplied a screenshot —
  dark section, tall monochrome portraits, a small round LinkedIn badge on each
  photograph, heavy uppercase name with the role beneath — and asked for the badge
  to become **email** and the shape to become the **brand hexagon**. Built as
  **R1** (six across, two rows), **R2** (four across, at the reference's own card
  scale), **R3** (name and role laid over the photograph), **R4** (the same
  construction on the light ground).
  The email is real: all twelve have an `@leaguelaw.com` address in the `email`
  meta field, so the badge links to stored data rather than to a plausible-looking
  placeholder. (The careers record stores the literal string `NULL` in that field —
  a placeholder that was saved as a value.)
  **Three things this reference forced into the open, none of them stylistic, and
  this is the reusable part:**
  - **It amplifies the missing role data rather than causing it.** The reference's
    three people carry three different roles; ours carries "Associate" **eleven
    times** in exactly the position the reference gives its most useful word. *A
    layout that gives a field prominence is a test of whether that field holds
    anything — copying the layout without checking the field is how a design ships
    a repeated placeholder in 60pt.*
  - **It publishes twelve email addresses on the homepage** as plain `mailto:`
    links, where the live site currently publishes none — harvestable by bots.
    Flagged with the alternative (badge points at the profile page's contact
    section: same shape, same position, no exposed address) so the decision is
    made before it ships, not after. *A visual reference can carry a
    non-visual consequence; adapting the picture is not the whole job.*
  - **It requires large portraits, and five of ours are 260×345.** R2 is included
    at the reference's own scale specifically so the cost is seen rather than
    described: ~304px per card means those five are *upscaled past native*, soft
    on every screen rather than only on retina, and the block runs ~1690px. The
    reference works because it shows three people; we have twelve. *When a
    reference's proportions assume a smaller set, say what the set size does to
    them instead of quietly shrinking everything.*
  Build note kept in the CSS: the reference card looks like one link but holds
  two, and nested `<a>` is invalid HTML — so each card is a DIV with two sibling
  links (portrait and name to the profile, hexagon to the mail), with the hover
  fill on the card, which is legitimate here because both children really are
  links.

  **Adi likes R2, badge moved to the seam (2026-08-23),** source
  `prototyping/team-options-v3-seam-badge.html`: the email hexagon comes off the
  photograph and sits on the **joint** between the portrait and the name box —
  the same construction the LaW Facts cards use in `home-v2.html`, so the two
  card types on the page are now built the same way rather than merely looking
  related. Applied to R1, R2 and R4; **R3 keeps the badge on the photograph
  because it has no name box and therefore no seam** — the same instruction
  cannot be carried out where the joint does not exist, and saying so is better
  than approximating it.
  Build detail worth reusing: the badge and the name box are **siblings** (the
  name box is itself a link, so the badge cannot live inside it), which means the
  seam placement needs a shared positioned parent whose top edge *is* the seam —
  a `.bw` wrapper around the two. Without it there is nothing to measure
  `top:-26px` from, because the portrait's height comes from `aspect-ratio` and
  is not a number the CSS knows.
  The name box takes extra top padding rather than the hexagon taking a smaller
  size: the text clears the badge instead of squeezing past it. That costs ~14px
  per card, ~40px over three rows, and the quoted heights were updated rather

  **Badge hidden until hover (2026-08-23),** source
  `prototyping/team-options-v4-mail-on-hover.html`. Adi: the hexagon should not
  sit on the card before it is hovered. Done — and the interesting part is what
  that one instruction breaks if it is implemented literally and left there.
  **A hover-only link does not exist on a phone.** There is no hover on a touch
  screen, so the email would be silently unreachable for most visitors — a
  functional loss, not a styling one, and invisible to anyone reviewing on a
  desktop. Pinned permanently visible under `(hover:none)`/`(pointer:coarse)`,
  which is the whole fix. **A hover-only link is also unreachable by keyboard**,
  so `:focus-within` sits on the same rule as `:hover` and tabbing into either
  link in the card brings the badge up.
  *Rule: "show it on hover" is a statement about one input device. Before
  shipping it, say what happens on the other two — touch and keyboard — because
  the answer is usually "the feature is gone" and nobody sees that in review.*
  The name box keeps its enlarged top padding at rest so the space the badge will
  occupy is already reserved and nothing moves when it appears. The slightly
  wider gap above the resting name is that reservation, and it is written into
  the CSS comment so a later session does not "tidy it away" and reintroduce a
  layout shift.

  **Correction — badge grey, not hidden (2026-08-23),** source
  `prototyping/team-options-v5-mail-grey-no-overlay.html`. Adi's "don't overlay"
  meant *don't sit on the photograph*, not *don't be visible*; I had read it as
  hide-until-hover and built that. Corrected: the hexagon is **grey at rest**,
  visible at all times, at the top-right of the name box flush with the seam, and
  orange on hover. *Rule: "don't overlay" is a statement about position, not
  about visibility — when an instruction has a spatial reading and a temporal one,
  the spatial one is almost always what was meant, and building the wrong one
  costs a round.*
  The rebuild is better than the version it replaces for a reason worth keeping:
  `.bw` became a **two-column grid** (name box, then hexagon) instead of a
  positioned parent with an absolutely-placed badge. An overlap is now impossible
  *by construction* rather than avoided by arithmetic, and nothing is absolutely
  positioned, so nothing drifts when the card width changes. The enlarged top
  padding and the whole hover/touch/keyboard apparatus from the previous step
  went with it — the badge is always present, so `(hover:none)` and
  `:focus-within` visibility fixes are no longer needed at all. *A layout answer
  removed three behavioural workarounds; when a change deletes special cases
  rather than adding them, it is usually the right change.*
  Quoted heights returned to ~1690px (R2) and ~880px (R1/R4), since the padding
  that bought the seam overlap is gone.
  **R3 is the declared exception:** it has no name box, so it has no seam, and its
  badge necessarily sits on the photograph — grey there too, but it cannot satisfy
  "no overlay" without becoming a different layout. Named on the option rather
  than quietly left inconsistent.
  One measured consequence on the label: at six across (R1, R4) the hexagon takes
  40px out of a 197px card, so the longest names wrap to two lines. At R2's scale
  they do not — which is one more argument for the option Adi already likes.

  **Position restored to the seam, colour kept grey (2026-08-23),** source
  `prototyping/team-options-v6-seam-grey.html`. Adi: the position was not what
  was being objected to — keep it straddling the joint, exactly as
  `.facts .c .ic` does in `home-v2.html`. Final state: **hexagon on the seam,
  grey at rest, orange on hover.**
  **What I got wrong, twice, and the lesson underneath it.** "Jangan overlay"
  was read first as *don't be visible until hover*, then as *don't touch the
  photograph* — and it meant neither. It meant *don't be loud at rest*; the
  clarification that followed ("gunakan gray color sebelum hover") was the whole
  instruction, and the word "overlay" was describing the orange fill, not a
  coordinate. *Rule: when a one-line note could be about position, visibility or
  emphasis, the next sentence the person writes usually disambiguates it — read
  the pair together before rebuilding. Two rounds were spent moving something
  that never needed to move.*
  Stated on the option label rather than left to be re-discovered: this position
  **does** cover the bottom ~25px of each photograph. That is what the facts card
  does and it is the intended look — writing it down is what stops it being
  re-filed as a bug by whoever looks next. Heights return to ~1730px (R2) and
  ~910px (R1/R4), since the content box again carries the top padding that lets
  the name clear the hexagon.

  **Copy matched to the live site (2026-08-23),** source
  `prototyping/team-options-v7-live-copy.html`. The R options had been drawn with
  the heading only; they now carry the live block's heading *and* both paragraphs,
  verbatim — the two-line "Your Team at / League and Williams", "focussed" with the
  British double-s, the en dash after "just results". The same pass fixed a
  flattened heading in six earlier options (the live break had been dropped) and a
  missing second paragraph in five.
  Two source oddities carried over rather than silently corrected, and named on the
  page: the live markup writes the break as `</br>`, which is not a valid tag, and
  the first paragraph ends with a stray trailing space. *Reproducing copy verbatim
  means reproducing its defects too — but only if they are labelled, otherwise the
  next person fixes them and nobody knows whether that was allowed.*
  **The placement cost, stated because it is real and easy to miss:** on the live
  site this copy sits in a **side rail** beside the portraits. Every option except
  P1 and P6 puts it *above* a centred grid, which reads better and adds roughly
  110–130px of height — text that used to occupy otherwise-empty column space now
  occupies a band of its own. P1 and P6 keep the rail for exactly that reason.
  *When copy moves from a rail to a header, it stops being free; a layout change
  that "only" relocates text still buys height.*

  **Careers band raised to an invitation (2026-08-23),** source
  `prototyping/team-options-v8-careers-highlight.html`. It had been a quiet
  off-white strip with an orange rule — a footnote under the portraits, and on the
  dark options a barely-visible 5%-white panel. Now an orange band with a large
  hexagon, the recruiting line set as a real heading, and the site's own B19 arrow
  button. The per-section overrides that quietened it on the dark grounds were
  deleted rather than re-tuned: *when an element's job is to stand out, giving it
  a different treatment per background is how it ends up invisible in half of
  them.* One band, one rule, everywhere.
  **The decision that comes with it, flagged rather than absorbed:**
  `home-v2.html` already carries an orange CTA band lower down the page. Two
  orange bands is a choice about emphasis, not a styling detail — a section-level
  invitation now competes with the page-level one. The alternative is written into
  the CSS comment as a one-line swap (`var(--orange)` → `var(--brown)`), which
  makes it a strong quiet invitation instead of a second shout. *Raising one
  element's emphasis is never local: it is always relative to whatever else on the
  page was already loudest.*

  **Careers band to grey (2026-08-23),** source
  `prototyping/team-options-v9-careers-grey.html`. Adi took the orange back out —
  which also settles the two-orange-bands question the previous step raised: this
  stays a *section*-level invitation and does not compete with the page-level CTA.
  Worth recording because the band did not lose its prominence with the colour:
  it is still the only panel in the section, still larger than anything around it,
  the recruiting line is still set as a heading, the orange moved into the hexagon,
  and the call to action is still the site's real B19 arrow button. *Emphasis is
  carried by size, isolation, typographic rank and a real control — colour is the
  cheapest of the five and the first one that should be spendable.*
  Kept from the previous step: **one grey on every background**, no per-section
  override. On the light options it reads as a soft panel, on the dark ones as a
  lit one.

  **Band to #B7AFA6, and the contrast that came with it (2026-08-23),** source
  `prototyping/team-options-v10-careers-b7afa6.html`. Adi named a darker warm
  grey. Applied — and the paragraph colour had to move with it: `#6B6B6B` on
  `#B7AFA6` measures **2.46:1**, which fails WCAG AA for body text (4.5:1);
  `#423C37` on the same ground is **5.02:1** and passes. Changed, with the numbers
  in the CSS comment. *A background change is never only a background change:
  every colour that sits on it was chosen against the old one. Darkening a ground
  silently invalidates the text on it, and the failure looks completely fine in a
  screenshot — which is why it has to be measured rather than eyeballed.*
  **Measured but deliberately not changed:** the orange hexagon is only **1.40:1**
  against this ground, so the accent nearly dissolves into the band. Left as-is
  because it is a graphic, not text, and because it is Adi's accent to spend —
  but the number and the one-line swap (brown, 5.02:1) are written on the rule so
  the choice is informed rather than accidental. *Fix what is broken; report what
  is merely weakened.*

  **Toned down to #D3CDC4 (2026-08-23),** source
  `prototyping/team-options-v11-careers-d3cdc4.html`. Re-measured rather than
  assumed, which is the point of the entry: brown body text goes from 5.02:1 to
  **6.88:1** (comfortable), `--muted` would still be **3.37:1** and still fail, so
  the brown stays; the orange hexagon improves from 1.40:1 to **1.92:1** because
  lightening the ground moved it away from the orange rather than toward it.
  *Every re-tone of a panel is a re-test of everything sitting on it — and the
  direction of the change does not tell you which way each contrast moved. Here
  one number got better for a reason opposite to the one that fixed the text.*

  **Ground restored to the original (2026-08-23),** source
  `prototyping/team-options-v12-careers-original-bg.html`: `--paper` on the light
  sections, the translucent 5%-white panel on the dark ones. Everything else the
  highlight round added is kept — larger padding, the recruiting line as a heading,
  the hexagon, the real B19 button — so on the dark options the band's prominence
  now comes from **size, typographic rank and a control**, not from its panel,
  which is again nearly invisible there. That is the trade the original ground
  brings back, and it is a choice rather than a regression.
  **The per-section overrides had to come back with it, and the reason is the
  useful part.** I had deleted them on the principle that an element whose job is
  to stand out should not be re-treated per background. That principle holds only
  while the element keeps *one* ground. Once the ground itself changes per section,
  everything sitting on it has to change too: brown text on the dark panel is
  unreadable, and the brown button measures about **1.0:1** against it — literally
  invisible. On dark the text goes light and the button takes the site's existing
  on-dark form (orange with white arrows). *An element with one ground can have one
  rule; an element whose ground varies cannot, and insisting otherwise ships an
  invisible button.*
  Text returned to `--muted`, valid again at 5.06:1 on `--paper` — it was only
  forced to brown while the ground was dark enough to fail it. The original 3px
  orange left rule was **not** restored, because only the background was asked for;
  noted in the CSS as a one-line addition if it is wanted.

  **Careers band reverted entirely (2026-08-23).** Adi asked for the pre-highlight
  appearance back, so `team.html` was restored from
  `prototyping/team-options-v7-live-copy.html` — the snapshot taken immediately
  before the highlight round. The quiet off-white strip with the orange left rule,
  the small hexagon, the plain text link, and the per-section dark panels are all
  back exactly as they were; nothing else in the file moved, which a diff against
  v7 confirmed before the copy (every difference was inside `.cband`).
  **The reason the revert was one command rather than an unpicking exercise:** the
  backup chain in `prototyping/` is written *before* each change, not after, and
  each file is named for what the next step did to it. Five successive edits to one
  element (highlight → grey → #B7AFA6 → #D3CDC4 → original ground) collapsed to a
  single `cp`, with a diff as the proof that the collapse was safe. *A revert is
  only cheap if the snapshot was taken at the right moment; taking one per
  instruction, not per session, is what makes "put it back" a five-second answer.*
  It also caught something: the incremental edits had left a **broken CSS comment**
  in the live file — an orphaned fragment after a closing `*/`, so several lines of
  prose were being parsed as CSS. Nobody had reported it because it happened to be
  harmless. *Repeated in-place surgery on the same block accumulates damage that
  the visible result does not show; a periodic revert-to-snapshot is a cheap way to
  find it.*

  **Left rule removed from the careers band (2026-08-23),** source
  `prototyping/team-options-v13-cband-no-rule.html`. Done — with one measured
  consequence reported rather than left to be found in a review: **the rule was
  the only thing making the band visible on the light grounds.** `--paper` on
  white is 1.05:1, so on P2/P3/P4/P5/P8 the band now reads as unmarked page, and
  on **R4 — whose section ground *is* `--paper` — it disappears completely.** The
  dark options are unaffected; their 5%-white panel still separates.
  Not fixed unasked, because the removal was deliberate and the answer is a design
  choice: if the band should stay findable on light grounds, the lever is its
  *ground* (#F1EFEB or #EFECE7), not putting a rule back. Written on the CSS rule
  so the trade travels with the code. *Removing a border is never only removing a
  border — check what else was carrying the element's edge, because on some
  backgrounds it was carrying all of it.*

  **Adi picked R1** (2026-08-23) — dark portrait cards, six across, 3:4
  portraits, grey email hexagon on the seam. **Integrated into `home-v2.html`**,
  source `prototyping/home-v2-v14-team-r1.html`; options page marked at
  `prototyping/team-options-v14-r1-picked.html`.
  The block that went is the rail plus a four-across grid of 128px portraits. Two
  structural faults went with it: the thirteenth tile (the careers advert — a
  colour landscape photograph in a portrait frame) is now a band under the grid,
  and twelve tiles divide cleanly six-across where thirteen left an orphan row.
  **Correction made at integration, and worth recording as a process failure, not
  a rounding error.** The heights quoted on the R options were **understated**:
  they were derived before the live intro copy was added to those heads, and never
  re-derived afterwards. Re-computed from the construction: R1 ~1420px (quoted
  910), R2 ~2270px (quoted 1730), R3 ~1260px (quoted 740), R4 ~1420px. A warning
  box now sits at the top of the options page with the old and new figures side by
  side. *Rule: a quoted height is a claim about the current build, not a label that
  travels with the option name. Anything added to an option after its number was
  written — copy especially — invalidates the number, and the moment to re-derive
  it is when the content lands, not when someone picks it.* R2 in particular is
  more than twice the block it replaces, which was not visible while it was the
  option Adi liked.
  Everything the section now owes is written into its own CSS comment rather than
  left here: the five low-resolution portraits and the instruction **not** to widen
  the cards to fix anything else (four across upscales them past native); the
  eleven identical "Associate" labels and the absent job-title field; the twelve
  `mailto:` addresses now published on the homepage where the live site publishes
  none, with the one-line alternative; the hexagon covering the bottom ~25px of
  each photograph by design; the two-sibling-links construction that must not be
  "simplified" into one anchor; and the height, with the only lever that reduces it
  named — move the intro copy back into a side rail, not shrink type or portraits.
  than left standing.
  **Ken Burns removed (2026-08-21)** after Adi noticed a slow zoom nobody had
  asked for: each slide had been scaling 1 → 1.06 across its slot. Removed from
  both S1 and S2, keyframes kept with a one-line comment showing how to restore
  it. Two reasons it should stay out: the section already carries one movement
  (slide change + row highlight) and a second competes with it; and
  `design-direction.md` lists animation among the levers the client ruled out.
  **Process lesson for the prompt: any effect added beyond what was asked for
  must be named at handover.** It was in the build and not in the note, so the
  designer had to discover it by watching the page — the cost of that is trust,
  not just a revision.

- **`.quotes` testimonial layout — 8 options (zeina branch)** (2026-08-21):
  `wp-content/prototype/quotes.html` (source `prototyping/quotes-options-v1.html`).
  Copy is the clients' own words, read from the `testimonials` post type in this
  build's database — nothing written by the designer. **The database holds 10
  published testimonials and the homepage shows one, inside a slider** — the
  same fault the old facts block had: the material exists and the layout hides
  it. Lengths run **165–634 characters**, so equal-height cards either crop the
  long ones or leave holes under the short ones; the options either embrace the
  unevenness (T4 masonry), pair one long with several short (T3), or use only the
  short ones (T2). The quotes also **name the lawyer who acted** (Darren
  Williams, Robert Graham, Andrew Broadley) — an asset the current layout throws
  away, and the reason T6 exists: a review becomes a route to that person and
  their team, which is the client's own "teams, not lawyers" idea. Options: T1
  baseline · T2 three cards · T3 lead story + rail · T4 masonry wall showing
  eight at once · T5 the approved photo split with two quotes always visible ·
  T6 attributed to the lawyer · T7 quiet editorial single quote · T8 the
  K13·S2 pattern reused (listed with the caution that repeating it may read as
  the page doing the same trick twice).
  **Four data problems found in the testimonials, none of them layout:** (1) one
  record ("Susan Dubois") contains raw Google review HTML pasted into
  post_content and needs cleaning; (2) names are inconsistent as data — `MC C`
  signed "Marguerite Chin" in the body, `LESLEY BELLAS` in caps, "Pamela Ellis"
  signed "Pamela and Graham Ellis"; (3) several testimonials carry the client's
  signature *inside* the quote text, so any layout that also prints the name
  shows it twice — the signature belongs in a field; (4) **no star ratings are
  stored** — the five stars on the live site are decoration, so if reviews are
  meant to carry ratings they need a real source (a Google feed or a rating
  field), otherwise the stars are a claim nothing backs.
  **Eyebrow replaced by the hexagon badge (2026-08-21)** at Adi's direction, so
  this section opens the same way as the articles and vlog halves: the canonical
  X16 cell, `fa-quote-left`, filling orange on *section* hover. Two variants were
  needed and are worth reusing: on the near-black stage the neutral `#E6E1DA`
  cell is too loud, so it drops to `rgba(255,255,255,.08)` with a cream icon; on
  a coloured panel (T5's orange, T8's brown) a neutral cell reads as a hole, so
  it inverts to a translucent-white cell at 62px, left-aligned rather than
  centred. Source `prototyping/quotes-options-v2-hexbadge.html`.
  **Sourcing check (2026-08-21), prompted by Adi asking where the context line
  came from — it came from me, not the data.** A testimonial record holds
  exactly two fields: `post_title` (client name) and `post_content` (the quote).
  **Zero taxonomy terms are attached to any testimonial**, and the only meta is
  a Yoast content score plus an *empty* `_yoast_wpseo_primary_testimonials_category`
  — the fossil of a taxonomy the dead Total theme registered and nobody filled.
  So three things in the options have no source: the matter type (`.qctx`,
  written by reading each quote), the lawyer attribution T6 is built on (read
  out of the quote text), and the star ratings (decoration on the live site).
  Each implies build work rather than disqualifying a layout: a **Matter type**
  field valued from the five practice areas, a **Lawyer** relationship field
  pointing at the `lawyers` CPT, and a real rating source or no stars. Recorded
  in the options page itself so no option is shown to the client as if its
  metadata already exists. Source
  `prototyping/quotes-options-v3-source-disclosed.html`.
  **Rule reinforced (third time this project): metadata invented to demonstrate
  a layout must be labelled in the artifact at the moment it is invented, not
  when someone asks.** Placeholder dates, invented category tags and now
  invented matter types were each caught by the designer rather than declared.
  **Adi's ruling (2026-08-21): quote and client name only** — the two fields a
  testimonial record actually holds. Page rebuilt on that basis (source
  `prototyping/quotes-options-v4-name-quote-only.html`): matter type, lawyer
  attribution and star ratings all removed, so **every remaining option is
  buildable against today's data with no new fields**. The hexagon initials stay
  because they derive from the name rather than adding a field. **T6 was
  removed** — attributing each review to the lawyer it names required a Lawyer
  relationship field that does not exist, and with quote and name only it has
  nothing to stand on; it is preserved in
  `prototyping/quotes-options-v3-source-disclosed.html` should that field ever be
  added. Remaining: T1, T2, T3, T4, T5, T7, T8. The wp-admin cleanup items
  (pasted Google HTML in one record, inconsistent name casing, signatures inside
  the quote body) survive the ruling and still need doing.
  **Amended same day: stars stay on** (source
  `prototyping/quotes-options-v5-stars.html`). Adi's call, made with the gap
  known — no rating is stored, so every review renders the same five stars.
  That is truthful only while every published testimonial is genuinely a 5-star
  review; **the moment a 4-star one is added the section needs a Rating field
  rather than a fixed row of stars**, and the condition is written into the CSS
  comment and the options page so it is not lost. Build note: on the orange
  panel (T5) the stars must invert to white — orange on orange disappears.
  **Adi picked T2** (2026-08-21) — integrated into `home-v2.html` (source
  `prototyping/home-v2-v10-quotes-t2.html`), replacing the 500px photo-and-panel
  slider: three reviews visible instead of one of ten, the canonical X16 badge
  opening the section like the articles and vlog halves, hexagon initials
  derived from the name, stars, and a "Read All Reviews" door. **The three shown
  are deliberately the short testimonials** so the cards sit level — with
  lengths running 165–634 characters, a three-up grid of the long ones would
  crop or leave holes. All the section's constraints and outstanding wp-admin
  cleanup items are written into the CSS comment block, including the condition
  that ends the uniform five stars.

## Practice areas (`.areas`) — option round 1 (2026-08-24, zeina branch)

Nine layouts in `wp-content/prototype/areas.html` (backup
`prototyping/areas-options-v1.html`). Data verified against the database and a
read-only read of the live homepage **before** any layout was drawn.

**What the verification turned up, in order of consequence:**

1. **The replica dropped the links.** On the live site both the icon and the
   heading of each practice link to `/our-services/<slug>/`. `home-v2.html`
   renders five practices with no anchor at all — the section is a poster where
   the original is navigation. Every option on the page restores the links;
   **this is a fix worth shipping whichever layout wins**, independent of the
   round.
2. **Five items in a three-column grid leaves an orphan row.** Marine and Real
   Estate sit under columns one and two with a hole at the right. Same shape of
   defect as the team section's thirteen tiles in four columns, and the same two
   honest cures: make the column count divide the item count (A2, A3, A7, A9),
   or stop using a grid (A5, A8). A4 and A6 change the hierarchy instead.
3. **The five practices are not peers.** Sub-pages behind each: Injuries 13 ·
   Estates 3 · Real Estate 2 · Business 0 · Marine 0. The current layout gives
   all five identical weight. A4 (feature-and-four) and A9 (sub-pages listed)
   make the imbalance visible rather than smoothing it over — both are content
   decisions that need Darren, not styling choices.
4. **Homepage order ≠ menu order.** Homepage: Injuries, Estates, Business,
   Marine, Real Estate. Site menu: Injuries, Estates, Business, Real Estate,
   Marine. One is wrong; nobody has decided which.
5. **The area paragraphs are duplicated verbatim in the header mega-menu rails**
   inside `home-v2.html`. Rewriting this copy means rewriting it twice in one
   file.
6. **There is no `practice_area` post type** — the homepage block is hand-built
   against five ordinary child pages of *What We Do* (post 14659). Nothing
   generates it, so nothing keeps it in sync when a practice is added.

**The icons are the hard constraint — measured, not assumed.** All five are
8-bit palette PNGs at 93×107 (business 91×104), 1.5–3.1 KB, very sparse line
art. Two consequences that bound every option:

- **96px is already an upscale.** The baseline renders a 93px raster at 96px, so
  there is no resolution left to spend. No option on the page draws an icon
  larger than 96px. A layout that wants a big icon needs the set redrawn as SVG
  first — which is flag 4 below, now with a number attached to it.
- **The colour is baked into the file.** Injuries #E16239 and Marine #EF6D3E are
  orange; Estates, Business and Real Estate are #46ADC8 teal — flat, one-colour,
  and *not* recolourable by CSS. They cannot go white on a dark panel and cannot
  invert on hover. A6 and A7 work only because orange and teal both survive
  their grounds; that was checked before drawing, not hoped.

**The nine:** A1 baseline replica (with the links restored, orphan row intact,
~905px) · A2 five across, one row (~615px) · A3 five across ruled as one strip
(~635px) · A4 feature-and-four, Injuries leads (~800px) · A5 five full-width
ruled rows (~880px) · A6 honeycomb, three over two (~760px, **drops all five
paragraphs** — a hexagon has no room for one) · A7 dark band on `#2A2622`
(~640px) · A8 rail-and-rows, heading beside the list (~600px, shortest) · A9
five across with each practice's sub-pages listed (~720px, the two empty cards
shown honestly rather than padded).

**Reusable rule confirmed again:** an `<a>` may hold flow content in HTML5, so a
whole-row link wraps its heading and paragraph in a **DIV**, never a `<span>` —
the same trap that produced invalid markup in the team round.

**Content questions raised for Darren, not answered by me:** what the
orange/teal alternation means (it is not litigation-vs-transactional and not
alphabetical — if it means nothing it is decoration pretending to be a
category); whether Business and Marine belong on the homepage with zero
sub-pages each; whether "over 160 years of experience" is still current; and
whether *Air Traveler Injury Claims* — a published top-level page in no practice
group — is a sixth practice or a stray.

## Practice areas (`.areas`) — option round 2 (2026-08-24, zeina branch)

Adi asked for options that look genuinely different, not more variations on the
same card. Round 1 solved geometry inside one visual family — line icon, name,
paragraph. Round 2 changes the family. Eight added, B1–B8, appended to the same
page (backup `prototyping/areas-options-v2-different-look.html`).

**The find that made the round possible: the photographs already exist.** Six
images sit in the media library attached to *What We Do* (post 14659), plus two
more under Injuries and Estates. **None is set as a featured image on any
practice page** — so the practice-to-photo pairing is inferred from filenames and
is a *proposal*, not something recovered from the site. That is badged on the
page rather than presented as data.

Measured, and it bounds four of the eight:

- **No larger originals exist.** The upload folder holds only downscaled
  derivatives (300/150/96/48/24px). **500–600px is the hard ceiling**: Estates
  600×387, Business/Marine/Real Estate ~500×333, Injuries 411×258. A five-across
  grid (244px columns) is comfortable; B2's half-width rows ask 640px and upscale
  every image.
- **Injuries is the odd one out.** `injuries-thumb.jpg` is near-monochrome and
  dark (mean luminance 60, chroma 1.4) beside four colour stock photographs, and
  it is the smallest file. Any photo-led option needs it replaced.
- **`adults-analysis-brainstorming-1661004.jpg` is 4000×2191 and 1.78 MB,
  unresized** — a page-weight defect wherever it gets used.

**The eight:** B1 photo cards, five across (~715px) · B2 editorial rows, photo
and copy alternating sides (~2000px, the most generous and by far the tallest) ·
B3 numbered index, typography only (~865px) · B4 photo mosaic with names on a
scrim, Injuries on a double tile (~800px) · B5 tabs, one practice open at a time
(~700px) · B6 honeycomb photographs with the paragraphs returned as a legend row
(~900px) · B7 sticky rail and photo strips (~880px) · B8 deepened colour panels,
no imagery at all (~680px).

**Contrast arithmetic decided B8's colours, not taste.** White body copy on the
brand orange `#EF6D3E` measures **3.03:1** and on the brand teal `#46ADC8`
measures **2.60:1** — both fail AA, and teal fails even the 3:1 large-text floor.
The panels therefore use deepened variants: `#B44322` (5.61:1) and `#2F7186`
(5.50:1). **The icons are omitted from B8** because their baked-in brand colour
would disappear on those grounds — which is the icon constraint from round 1
reappearing as a colour problem rather than a resolution one.

**Costs stated rather than hidden:**

- **B4** reveals the four small tiles' paragraphs on hover, so on a touch screen
  four of five descriptions are unreachable. Needs a tap-to-open or
  always-visible variant before it could ship.
- **B5** hides four practices behind tabs — a homepage section that must be
  operated before it says anything is weaker for a first-time visitor.
- **B6** crops each photograph at four corners; any off-centre subject gets cut.
- **B2** is ~2000px, roughly doubling the section on its own.

**Immunity map, worth keeping:** B3 and B8 use neither icon nor photograph, so
neither the 93px icon ceiling nor the unassigned-photo question touches them.
B1, B2, B4, B6 and B7 all depend on the photo mapping being confirmed. Every
round-1 option depends on the icons being redrawn as SVG before they can grow.

**Reusable rule, hit for the third time:** `<h3>` and `<p>` are block elements
and must never sit inside a `<span>`. An `<a>` may hold flow content in HTML5, so
a whole-card link wraps its heading and paragraph in a **DIV**. Caught by the
tag-balance check before the page was published, in B1, B4 and B6.

## Practice areas (`.areas`) — option round 3 (2026-08-24, zeina branch)

**Adi picked B4's look and rejected its behaviour:** four of the five paragraphs
only appeared on hover. That was the cost written under the option, and the
objection is correct — on a phone there is no hover at all, so those four
descriptions were simply unreachable. Four variants that keep the mosaic and show
every paragraph at rest: **B4·N1–N4** (backup
`prototyping/areas-options-v3-b4-no-hover.html`).

**The height increase is arithmetic, and it needs saying plainly.** B4 measured
~800px *because four paragraphs were not on the page*. A small tile is 306px
wide; inside 22px padding the copy runs ~36 characters a line, so Estates (136
characters) and Business (133) need **four lines** = 99px, and with the rule, the
name and the spacing the text block is ~144px. On a 212px tile that leaves 68px
of visible photograph — not a mosaic any more. **Showing the copy costs 175–275px
and no styling choice avoids it.**

**There is exactly one lever that would buy it back, and it is not mine to pull:
the copy.** Injuries and Marine are 76 characters; Estates and Business are
133–136. Trimmed to Marine's length every variant loses a line (~50px) and the
tiles stop being ruled by their two longest paragraphs. That is new copy and
Darren's call, so all four variants carry the live wording untouched.

**The four:** N1 same mosaic with tiles grown 212 → 296px, copy still on the
image (~975px, smallest change) · N2 copy off the image onto a solid `#332E29`
panel under each photo — the LaW Facts card construction, the most in-system
(~1075px, tallest) · N3 mosaic untouched at 212px with the five paragraphs lifted
into a legend row beneath (~985px) · N4 re-cut: Injuries becomes a full-width
band with a real door, the other four in one even row below (~1010px).

**Legibility was measured, not eyeballed.** N1 and N3 still set copy over a
photograph, so the scrim was deepened to 0.94 at the bottom: `#E2DCD4` on that
ground measures **13.9:1** against the flat colour and about **9:1** over a
mid-brightness photo. N2 and N4 sidestep the question by putting copy on a solid
panel.

**Trade-offs stated per option:** N2 spends some of B4's boldness — the mosaic
reads more as a card grid than a photo wall. N3's weak point is pairing: the
reader must map legend column three to the tile it describes, and the colour rule
under each name is the only thread tying them together.

**Two build defects caught before publishing.** A CSS specificity collision —
`.n4 .ar.lead h3` (0,3,1) was silently beating `.n4x .lead h3` (0,2,1), so N4's
lead heading would have rendered at the shared 27px instead of its intended 30px.
And N4's lead heading was not a link, which contradicts the round-1 fix that put
the practice links back; it now wraps in an anchor like every other practice name
on the page. Nested-anchor check run across all 21 options: zero.

## Practice areas (`.areas`) — option round 4 (2026-08-24, zeina branch)

Adi took **B4·N1** and asked for two changes: cut the descriptions to something
short, and bring the old-site icons back. Three options, **B4·N1·i1/i2/i3**,
identical except for where the icon sits — the one part of the request with no
obvious answer (backup `prototyping/areas-options-v4-n1-short-icons.html`).

**The short copy is NEW COPY and is badged as such.** Everything else across the
24 options is the live wording verbatim; these five lines are not. They compress
the live sentences, keeping every practice claim and dropping the rhetorical
questions, but they are mine and need Adi's or Darren's approval:

| practice | live (ch) | proposed (ch) |
|---|---|---|
| Injuries | 76 | Hurt in an accident? We help you recover in full. (48) |
| Estates | 121 | Wills, estate planning, administration and disputes. (51) |
| Business | 124 | Starting, buying, selling or restructuring a BC business. (56) |
| Marine | 76 | Boating accidents, seizures, anchoring and mooring. (50) |
| Real Estate | 84 | Buying or selling in BC, with peace of mind. (43) |

The live spread is 76–124 characters, which is *why* the tiles were ruled by
Estates and Business. The proposed spread is 43–56, so all five wrap to two lines
and the tiles stop fighting each other. **If these lines are adopted, decide
whether the header mega-menu rails follow** — they carry the long copy verbatim
in the same file.

**The short copy pays for the icons almost exactly.** At two lines the text block
drops ~144px → ~94px, letting tiles come back 296px → 240px. **i1 ~860px and i2
~830px, with every paragraph visible AND the icons added** — within touching
distance of the original B4's 800px, which got its figure by hiding four
descriptions. i3 spends the saving on icon size instead (~970px).

**The three lockups:** i1 icon in a dark hexagon stamp top-left over the photo ·
i2 icon inline beside the name, replacing the colour rule, inside the deepest
scrim · i3 icon large (64px small tiles, 88px lead) stacked above the name,
closest to how the icons read on the current homepage.

**Two measurements decided details that would otherwise have been taste:**

- **i1's plate is dark, not light.** On white the teal icons measure **2.60:1** —
  below the 3:1 non-text floor. On the dark plate over a photo the teal icons
  measure ~4.2:1 and the orange ~3.6:1.
- **The icons will read lighter here than on today's homepage.** Median stroke is
  **3px at 93px wide**; at i1/i2's 46px that renders ~1.5px and at i3's 64px
  ~2.1px, against ~3px in the current 96px rendering. Fine on retina, softening
  on 1×. None of the three upscales — this is the raster set showing its limit
  from the *other* direction, and the **third distinct symptom of the same root
  cause**. Same fix, already on the list: redraw the five as SVG.

## Practice areas (`.areas`) — option round 5 (2026-08-24, zeina branch)

Adi's three changes on the round-4 tiles, applied to all three lockups so the
placement question stays open: **i1·v2 / i2·v2 / i3·v2** (backup
`prototyping/areas-options-v5-orange-band.html`).

**1. The Injuries lead tile carries no icon.** Only the four small tiles do. Side
effect worth naming: the lead now differs in size *and* treatment, so it stops
reading as "a bigger one of the same thing" and starts reading as the tile the
section is built around. A gain — but a change in meaning, not only decoration.

**2. The overlay is the copy panel and nothing else.** The full-tile gradient is
gone; a solid `rgba(18,15,13,.90)` band wraps the text and stops there.
**Consequence that must not be left silent:** that gradient was what dimmed the
photograph for the sake of text sitting on it. With the copy on its own panel
that job no longer exists, so the image filter was lightened
`grayscale(.35) brightness(.70)` → `grayscale(.2) brightness(.9)`. Left alone the
photographs would have stayed muddy for a reason that had been removed. **If they
now read too bright, the filter is the lever, not the overlay.** Measured on the
new band over a mid-brightness photo: body `#E2DCD4` **9.7:1**, name in white
**13.2:1**, orange icon **4.3:1**. The band edge is deliberately hard; a 20px
fade is one line of CSS.

**3. All five icons are orange — which meant new files.** The originals are flat
palette PNGs with colour baked in (three teal, two orange), so CSS could not
recolour them. A recoloured set was generated into
`wp-content/prototype/img/icon-<name>-orange.png`. **Nothing in the media library
was touched.** The recolour was done properly rather than with a CSS filter:
anti-aliasing in these files is carried in the **alpha** channel, so alpha is
preserved untouched and only RGB is flattened to `#EF6D3E` — verified afterwards,
all five contain exactly one colour value. This also removes a latent defect: the
palette had baked a **white fringe** into the edge pixels, which would have shown
as a halo against these dark tiles. `icon-injuries-orange.png` exists but is
unreferenced, since the lead tile dropped its icon; kept so the set stays complete.

**What going all-orange costs, stated so it is a decision and not a side effect:**
the orange/teal split was the only visual grouping the practice areas had. It
never meant anything consistent — that is the open question from round 1 — and
all-orange settles it by removing it. If a grouping is ever wanted back it should
come from something real (litigation versus transactional), not from the colours
these files happened to ship with.

**One number changed because of change 2.** i1's icon plate went from `.74` to
`.88` opacity: once the full-tile scrim came off, the photo behind the plate got
brighter and the orange fell to **2.9:1**, under the 3:1 floor for graphics. At
`.88` it measures **4.1:1**.

**Heights:** i1·v2 ~860px · i2·v2 ~830px · i3·v2 ~950px. In i3 the panel is taller,
so the confined overlay buys the least there — it still covers most of each photo.

## Practice areas (`.areas`) — option round 6, the correction (2026-08-24, zeina branch)

**Round 5 removed the wrong thing.** Adi's "hilangkan icon on image" meant the
icon *inside the photograph* — a white outlined hexagon with a wheelchair
pictogram burned into `injuries-thumb.jpg` — not the orange icon added on top of
it. Round 6 restores the orange icon on every tile including Injuries, restores
the gradient overlay, and takes the graphic out of the picture instead:
**i1·v3 / i2·v3 / i3·v3** (backup `prototyping/areas-options-v6-corrected.html`).

**The wheelchair hexagon is burned into the JPEG**, at roughly x 153–240,
y 59–164 of a 411×258 image, sitting over the car's front fender. No setting
removes it. Cropping around it fails — it sits near centre, so the widest clean
strip is ~165px of a 411px photo, far too narrow for a tile needing a 1.28 ratio
— and the media library holds no other injury photograph. So it was
reconstructed: the strokes were masked (thin outlines, not a filled shape, which
is the only reason this is recoverable), then filled by directional interpolation
from surrounding paintwork over three detect-and-fill passes, mask restricted to
the hexagon geometry so genuine car highlights were not eaten.

**It is a reconstruction, not a recovery — the pixels underneath were never in
the file.** It holds up on the small tiles. On the lead tile it renders at 631px
from a 411px source — a 1.5× upscale on top of the repair — and the fender reads
softer than the rest of the car if you look for it. Cleaned file at
`prototype/img/injuries-thumb-clean.jpg`; **the media-library original is
untouched** (md5 verified unchanged).

**The standing recommendation is unchanged and now stronger:** this photograph is
the weakest asset in the section — smallest (411×258 against 500–600px),
near-monochrome where the other four are colour, and now known to have carried a
burned-in graphic. On the tile the whole section is built around it should be
re-shot or replaced. Everything in round 6 is making the best of the file that
exists.

**Reusable rule learned here:** the gradient overlay and the image filter are
**one mechanism, not two settings**. Round 5 confined the overlay and therefore
lightened the filter; round 6 restores the gradient and the filter goes back with
it to `grayscale(.35) brightness(.70)`. i1's plate returns to `.74` for the same
reason — over a gradient-dimmed photo the orange measures 3.6:1, above the 3:1
non-text floor. Changing one without the other leaves a tile dimmed for a reason
that no longer exists, or copy on a ground that no longer protects it.

**Unchanged from round 5:** all five icons orange, from the recoloured set with
alpha preserved and RGB flattened to `#EF6D3E`; nothing in the media library
modified. The cost of all-orange still stands — the orange/teal split was the
practice areas' only visual grouping, and removing it settles that question
rather than answering it.

## Practice areas (`.areas`) — option round 7 (2026-08-24, zeina branch)

**Adi picked i1·v3** and asked for one change: the four service tiles read too
small next to the Injuries lead. Four re-cuts, **M1–M4** (backup
`prototyping/areas-options-v7-mosaic-recut.html`). The tile itself is untouched —
same gradient, same orange stamp in its dark hexagon plate, same short copy, same
photographs. Only the grid geometry differs.

**Why the four are 306px, stated as arithmetic rather than taste.** A 1280px wrap
in four columns with 18px gutters gives columns of 306px; the only widths that
exist in that grid are 306, 631, 955 and 1280. **While the lead occupies two of
the four columns beside them, 306px is the only width the other four can have.**
Not tunable — it is what the grid permits. Hence exactly three ways out, one per
option family:

- **grow vertically instead** — M1, rows 240 → 300px (~977px section)
- **change the column count** — M2, three columns, narrowest tile 415px, Real
  Estate takes a wide 848px bottom tile (~1190px)
- **move the lead out from beside them** — M3, Injuries as a full-width band with
  the four at 631×272 (~1220px); M4, two-over-three with no dominant lead
  (~975px)

**Wider tiles run into the photographs, which have not got bigger** — the round-2
ceiling reappearing a third time. Native widths: Injuries **411px**, Estates
600px, the other three 500px.

| option | service tile | upscale on the four | Injuries tile |
|---|---|---|---|
| M1 | 306px | **none** | 631px — 1.5× |
| M2 | 415px (Real Estate 848px) | none, except Real Estate **1.7×** | 848px — 2.1× |
| M3 | 631px | 1.05–1.26× | 1280px — **3.1×** |
| M4 | 415–631px | up to 1.26× | 631px — 1.5× |

**M1 is the only option that asks nothing new of the image files.** M3 delivers
the biggest four and the worst Injuries tile in the same move — a 411px
photograph, already carrying the paint-out repair, stretched to 1280px. It is the
strongest layout of the four and the one most dependent on that photograph being
re-shot.

**M4's cost is not a pixel cost:** it gives up the hierarchy. Thirteen sub-pages
against zero, zero, two and three is a real difference, and a layout with no
dominant lead stops showing it.

**Detail worth keeping:** the stamp scales with the tile — plate 76→90→104px,
icon 46→55→64px. **64px stays the ceiling**; the icon files are 93px wide and
nothing upscales them.

## Practice areas (`.areas`) — round 8: M4 picked, live copy restored (2026-08-24, zeina branch)

**Adi picked M4** and asked for the descriptions to go back to the site's own
wording. Result is **M4·L** (backup `prototyping/areas-options-v8-m4-live-copy.html`) —
two 631×344 tiles over three 415×300 tiles, orange stamp in a dark hexagon plate
on every one, gradient overlay, repaired Injuries photograph, and the five live
paragraphs verbatim.

**The re-cut he picked for one reason paid for the other.** The short copy existed
because at the old 306px tile Estates (121 characters) and Business (124) each
needed **four lines**, which pushed tiles to 296px and the section past 970px. At
M4's 415px and 631px the same sentences wrap to **three lines** and **two**. The
live wording costs about **45px** here, against the 175–275px it cost in the
four-column grid. Section total **~1020px**.

Row heights were derived from the longest paragraph in each row, not guessed: row 1
at 17px/1.8 capped to 54ch tops out at three lines (Estates); row 2 at 15.5px/1.7
across ~44 characters tops out at three (Business). Rows 344px and 300px leave
~120px and ~118px of visible photograph.

**What this settles:**

- **The mega-menu duplication question is closed.** The header rails carry these
  exact sentences; with live copy back on the tiles the two agree with nothing to
  reconcile.
- **The proposed short lines are out of play** — preserved in rounds 4–7 on the
  options page, and they never went near the site.

**What it does not settle:** the Injuries photograph — 411px native, rendered at
631px, carrying the paint-out repair. Every other constraint on this section has
now been designed around; that one can only be fixed by re-shooting.

**Not yet integrated into `home-v2.html`** — the section there still carries the
original three-column replica. Integration awaits Adi's word, as with every other
section.

## Practice areas (`.areas`) — round 9: grey grounds (2026-08-24, zeina branch)

Four grey grounds for M4·L: **G1–G4** (backup
`prototyping/areas-options-v9-grey-grounds.html`). The tiles are identical in all
four and identical to M4·L.

**A grey ground changes less than it looks like it should, and that is the thing
to know before choosing.** The copy sits *on photographs*, so each tile carries
its own dark gradient whatever colour the section is — **the section ground cannot
take that job over.** What it actually controls is the 18px gutters and the
heading. All four are the same height and the tiles look the same in each: the
choice is what the tiles sit *on*, not how they look.

**Measured, and the page's ordinary body colour fails on two of them:**

| ground | heading `#423C37` | body `#6B6B6B` | sub used `#5A544E` |
|---|---|---|---|
| G1 `#F1EFEB` | 9.46:1 | 4.64:1 passes | 6.50:1 |
| G2 `#E4E1DC` | 8.33:1 | **4.09:1 fails AA** | 5.73:1 |
| G3 `#D8D4CE` | 7.36:1 | **3.61:1 fails AA** | 5.06:1 |
| G4 `#4A443E` | white 9.60:1 | — | `#CFC8C0` 5.79:1 |

**Not specific to this section — worth writing into the brand guide.** Any section
that moves from white to a grey deeper than about `#EAE7E2` has the same problem
with the same fix (`#5A544E` for body-scale text). Solving it four more times
per-section is the wrong shape.

**New problem a light ground creates:** the X16 badge is a pale plate (`#E6E1DA`)
designed to sit on white. On G2 and G3 it is close enough to the ground to vanish,
so it lifts to `#EFECE6` there. On the dark ground the badge never had this issue
— a light plate on a light ground is a new one, and it will recur on every grey
section.

**G4 is the only option that reduces home-v2's dark-value problem instead of
adding to it** — `#4A443E` could replace one of the five darks already in that
file rather than becoming a sixth.

## Practice areas — M4·L on G1 integrated into home-v2 (2026-08-24, zeina branch)

Adi first said "M4·L saja", then corrected to **G1** — the light warm grey
`#F1EFEB` ground — with the section badge matched to the testimonials section,
which sits on its own grey. Integrated into `home-v2.html`, replacing the
three-column replica (source `prototyping/home-v2-v16-areas-m4l-g1.html`;
the state before is `home-v2-v15-before-areas-m4l.html`).

**The correction avoided a real defect I was about to have to flag.** Plain M4·L
is `#2A2622`, and the section immediately below it is the team at `#1C1916`. Those
two grounds measure **1.17:1** against each other — the boundary would have been
effectively invisible, and the page would have read as one continuous dark slab
from the hero down through the team. G1 puts a light break exactly where the page
needed one. Ground order now runs hero (dark) → band → **areas `#F1EFEB`** → team
`#1C1916` → quotes `#F9F9F9` → articles → facts `#2A2622` → vlog → CTA → footer.

**The badge is the page default, with no override at all** — the same `#E6E1DA`
plate and brown glyph the testimonials section uses, which is what "samakan
seperti section testimonial" means in practice: not a new treatment, the absence
of one. It measures 1.13:1 against `#F1EFEB` versus 1.24:1 against the
testimonials' `#F9F9F9` — a shade weaker, same treatment. The badge is a quiet
plate by design; the honey-fill on section hover is what gives it life.

**`.sub` also keeps the page default.** `#6B6B6B` on `#F1EFEB` measures 4.64:1 and
passes AA, so round 9's `#5A544E` override was not carried in. **The margin is
small and it is written into the CSS comment: if this ground is ever deepened the
sub colour must move** — at `#E4E1DC` it is already 4.09:1 and fails.

**Three defects fixed by the integration itself**, independent of the layout: the
practice areas are links again (the replica had no anchor at all, turning
navigation into a poster); the orphan row is gone (six-column grid, two tiles
spanning three over three spanning two); and the four services are no longer
306px, which in a four-column grid with a lead beside them was the *only* width
available to them.

Every debt is written into the section's CSS comment in `home-v2.html`: the
repaired-not-clean Injuries photograph and the instruction to re-shoot it; the
photo-to-practice pairing being inferred rather than stored; the recoloured icon
copies and why CSS could not do it; what all-orange deleted; the 64px icon
ceiling; the row heights being derived from the copy rather than chosen; the copy
duplication in the header mega-menu rails; and that the gradient and the image
filter are one mechanism.

Verified: tag balance across the whole file, zero nested anchors, zero block
elements inside spans, all ten image paths resolve, no `class="grid"`/`class="area "`
remnants, and the page returns HTTP 302 (the id-auth gate, which is correct).

## Hero — home v1's J2 scroll-pinned hero lifted into home-v2 (2026-08-24, zeina branch)

Adi asked for home-v2's `.hero` to match home v1. It now carries v1's hero
**verbatim** — CSS, markup, tab button and script lifted from `home.html` rather
than re-typed, so both pages hold the same component instead of two versions of
it. Source `prototyping/home-v2-v18-hero-j2.html`; the state before is
`home-v2-v17-before-hero-j2.html`.

**What it replaced:** the as-is replica — a 655px dark radial-gradient band with
Darren's portrait bleeding off the left, two award badges, and the contact form
parked inside it.

**Three dependencies came with the hero, and none is optional. This was a bigger
change than "update the hero" sounds:**

1. **The header is now sticky.** The scroll-pin maths is written against a 92px
   header that stays put: the image pins at `top:92px` filling
   `calc(100vh - 92px)`, the form docks 24px under the header, the section is
   `calc(200vh - 292px)` tall. With a static header every one of those numbers is
   wrong. `.nheader` changed `position:relative` → `position:sticky; top:0` with a
   hairline bottom border, matching v1 exactly. Both headers measure 92px (22px
   padding twice plus a 48px logo), so the numbers transferred unchanged. **This
   touches the locked F3d·4 header** — done because the hero cannot work without
   it, and it makes home-v2 match v1 rather than diverge.
2. **The page now runs JavaScript.** home-v2 had no `<script>` at all. It now has
   v1's: click-to-snap on the peeking form, the minimize control, and
   auto-minimise into a fixed orange tab once you scroll past the hero.
3. **The form is a different component.** No longer parked inside the hero box —
   it lives in `.peekwrap`, an absolutely positioned overlay in the tall scroll
   section, and it travels. It uses the B19 `.swarmbtn` instead of the flat teal
   `.send` button.

**Two content changes rode along, both v1's:**

- **The page has an `<h1>` again.** v1 sets the form heading as
  `<h1 class="h5">WE'VE GOT YOUR BACK</h1>`; home-v2 had **no h1 at all**, which is
  flag 1 on the rebuild list. This closes it — though a form heading is a weak h1
  for a law firm's homepage and the real fix is still a proper page heading.
- **The required-fields notice is gone.** The replica carried `"*" indicates
  required fields` above the heading; v1's form does not, so the `.req` rule went
  with it. **If the live form marks required fields, that notice has to come
  back.**

**Still placeholder:** all three slides are dashed boxes describing photographs
that have to be taken (new office exterior · whole team in reception · teams at
work). The hero cannot be called finished until those three shots exist.

Verified after the lift: tag balance across the file, every class the new CSS and
JS reference exists in the markup and vice versa (14 checked), `@keyframes oslide`
present once, all four `querySelector` targets resolve, exactly one h1, one script
block, and the page returns HTTP 302.

**Inherited from v1 as-is:** the `.send-row` rule is dead in both files — v1's own
markup uses `.safe-above` + `.swarmbtn.wide`. Left in place rather than
"corrected", because matching v1 was the instruction; worth removing from both at
once when the hero is next touched.

## Reviews + locations band (`.band`) — option round 1 (2026-08-24, zeina branch)

Eight treatments in `wp-content/prototype/band.html` (backup
`prototyping/band-options-v1.html`). Verified against the database and a
read-only read of the live homepage before drawing.

**Four defects found in the band as it stands — all four are true today:**

1. **Nanaimo is missing.** The sentence names Victoria, Vancouver, Duncan,
   Campbell River and Kelowna — five. The site has **six** published location
   pages under *Contact Our Lawyers*. A real office is left off the homepage.
   This confirms rebuild flag 3 against the database rather than against the
   brief.
2. **The six offices are prose and none is a link.** Every one has its own page;
   the band names them and sends you nowhere.
3. **The Google link is a dead 2019 search URL.** The live "Read reviews on
   Google" points at a copy-pasted SERP carrying 2019 session parameters
   (`ei=D3LGXP6wOpX99QPiuaawBg`). The durable part buried in it is the place id
   `0x2f8ff2a91eea7904`, so every option links to
   `google.com/maps?cid=3427224649634314500` — derived from that id, and stable.
4. **The Google mark is an invented letterform.** The replica sets a bold "G" in
   Open Sans at 44px; the live site uses the actual `fa-google` icon.

**The rating is a hardcoded string and nothing keeps it true.** 4.9 and 173
Google Reviews are typed into a WordPress block — no API, no cache, no refresh.
It was correct on the day someone typed it and has drifted since. Every option
repeats it because it is what the site says, but **a review count that cannot
update is a number that will eventually be wrong in public.** Either pull it from
the Places API or drop the count and keep the rating and the link.

**One colour to collapse.** home-v2 paints the dark half with `--band-dark
#453F39`; the live site uses `#423c37`, which is the brand's own `--brown`. The
two measure **1.05:1** against each other — indistinguishable. `--band-dark` is a
near-duplicate that exists for no reason, and one of the five dark values already
flagged in home-v2. Every option uses `--brown`.

**The eight:** B1 baseline with only the four defects fixed (128px) · B2 office
directory, the six become links (128px) · B3 three parts, reviews + offices +
the phone (128px) · B4 one dark band, the orange block goes (118px) · B5 taller,
rating at 52px and offices three-across in two rows (168px) · B6 hexagon rating
badge (148px) · B7 compact, everything on one line (88px) · B8 two full-width
strips, reviews over offices (144px).

**B1 is not really a layout option** — if none of the others wins, those four
fixes should still ship.

**Costs stated per option:** B2 drops "we serve clients from around the world with
legal issues in BC", a claim the list alone does not make. B3's "free
consultations" is the firm's own line but applies only to personal injury and
estate litigation — written that way, and it must not be shortened. B4 removes
one of the few places the brand orange appears at full width, which is a brand
decision. B5 costs 40px directly under a hero that already fills the screen. B7
has the least slack — a seventh office would break it to two lines.

## Reviews + locations band (`.band`) — option round 2 (2026-08-24, zeina branch)

Round 1's eight were all the same shape — a horizontal band, orange one side,
brown the other. Seven more that change the *form*: **C1–C7** (backup
`prototyping/band-options-v2-different-forms.html`). The verified facts and all
four defect fixes from round 1 carry into every one.

**The seven:** C1 floating card pulled 46px up over the hero, inside the grid
rather than full-bleed (~150px) · C2 light ground, the whole value structure
inverted (128px) · C3 honeycomb — six offices as six hexagon cells, alternating
(~174px) · C4 credibility row, five numerals instead of a sentence (~140px) · C5
photograph and panel (200px) · C6 route line, six stops on one thread with
Victoria marked head office (~150px) · C7 full-bleed orange (128px).

**Two of them ask for something that does not exist yet:**

- **C5 needs a photograph and there isn't one.** No office, harbour or courthouse
  image exists in the media library at a usable size — the two candidates that
  appear in the database (`seaplanevictoria`, `supreme-court-building-…`) have no
  files on disk. Drawn as a dashed placeholder, the same convention the hero
  slides use. It is a request for a photograph as much as a layout.
- **C1 constrains the hero.** A card pulled over the hero covers whatever sits in
  the bottom of the slide, and the three hero photographs have not been taken. The
  option is a note to the photographer as much as a layout.

**Costs stated per option, and two are worth carrying forward:**

- **C4 mixes checked facts with the site's own claims.** Six offices and twelve
  lawyers are counted from the database; 4.9 and 173 are typed into a WordPress
  block; "over 160 years" is the practice-areas sub-heading. Five identical
  numerals in one row make them all look equally verified. They are not. C4 is
  also the only option with no Google mark — a row of numerals has no room for
  the icon, so the rating is attributed by the words alone.
- **C6's route line is a diagram, not a map.** The six are evenly spaced left to
  right and that spacing means nothing geographically — Victoria to Kelowna is a
  ferry and a day's drive. If it reads as a map it is lying.
- **C3:** a hexagon is a poor container for a long word. "Campbell River" wraps to
  two lines inside a 104px cell while the others sit on one.
- **C7:** white body text on `#EF6D3E` measures **3.03:1** and fails AA. Everything
  small in that band is therefore 13.5px **semi-bold** or larger, which qualifies
  as large text at 3:1 — it passes, but only just, and any lighter weight or
  smaller size in that band breaks it.
- **C2 removes the band as a colour event entirely** — on the live site this strip
  is one of two places the brand orange appears full-width. C7 is the opposite
  move on the same axis.

## Reviews + locations band — round 3: the head office, five ways (2026-08-24, zeina branch)

C6 is the only option that says one of the six offices is the head office. Five
treatments of that one detail: **C6·h1–h5** (backup
`prototyping/band-options-v3-head-office.html`). Everything else on the band is
identical in all five.

**A correction rode along, and it applies beyond this band.** The round-2 draft
printed "HEAD OFFICE" with a CSS `::after { content: "HEAD OFFICE" }`. **Generated
content is not reliably exposed to assistive technology, cannot be selected or
copied, and is invisible to translation tools** — the wrong mechanism for a fact
about where the firm is based. It is real markup in all five new options, and C6
itself was fixed too rather than left on the page as a known-defective option.
**The rule: decoration can live in CSS; facts cannot.**

**The five, by what kind of difference they make:** h1 makes the marker bigger — a
difference of degree (~152px) · h2 makes it a different kind of object, a filled
hexagon holding the institution glyph (~168px) · h3 moves the label off the name
and onto the diagram as a pinned tag with a pointer (~168px) · h4 takes Victoria
out of the row entirely so the hierarchy is positional and nothing can contradict
it (~156px) · h5 removes the claim and keeps only the emphasis (~140px).

**The site's own word is "Headquartered"** — the live sentence opens
"Headquartered in Victoria, BC…". These print **HEAD OFFICE** because it fits a
10px tracked label where "HEADQUARTERS" does not, but the two are not quite the
same claim and the wording is Adi's to settle.

**Costs stated:**

- **h2** borrows the `fa-university` glyph that already opens the practice-areas
  section on the same page. Either a system reading as a system, or the same icon
  twice — worth checking against the whole page.
- **h4**'s block carries "Serving clients across British Columbia and beyond",
  which is a compression of the live sentence, **not** the live sentence. If h4
  wins, either that line gets approved or the block carries the office address —
  which needs the new address, still unknown.
- **h5** is honest about what it gives up: nothing in it states that Victoria *is*
  the head office. Given "Headquartered in Victoria" is the live sentence's first
  word, that fact may not be optional.

## Reviews + locations band — round 4: head office without a route line (2026-08-24, zeina branch)

**Adi ruled out C6's form**, and with it h1–h5, which were all variations of it.
Six bands that mark the head office some other way: **D1–D6** (backup
`prototyping/band-options-v4-no-route-line.html`). Same verified facts, same four
defect fixes, same real-markup label.

**Each draws the distinction by a different mechanism — that is the whole point of
the round:** D1 by size and isolation, Victoria bigger and standing alone
(~150px) · D2 by content, the head office is the one with an address and a phone
(~176px) · D3 by fill, six identical chips with one solid (132px) · D4 by label
alone, a two-row key-value list and nothing else (118px) · D5 by scale, VICTORIA
at 46px (~154px) · D6 by colour, the site's own orange half reassigned from the
rating to the head office (132px).

**D2 is the most useful of the six and it cannot ship yet.** It shows the head
office address, and the exact address after the November move is still unknown, so
it carries the same placeholder the footer already does — "across from the
courthouse", TBC note included. Everything else on the page is buildable today;
that one is waiting on a fact.

**D4 is the only option that adds no new shape.** The page already carries
hexagons in the header hive, the section badges, the practice tiles and the footer
comb. If the objection to C6 was that the band was turning into another diagram,
D4 is the far end of that axis — two labelled rows of type, 10px shorter than
today's band.

**Costs stated:** D5 revives the 300-weight uppercase Raleway that the old
practice-area headings used and that the new mosaic just dropped — either
continuity with the brand or the return of a style the page moved away from. D6
demotes the rating, which is the only piece of third-party proof on the strip;
whether the head office or the 4.9 deserves the loud half is a marketing
judgement, not a layout one.

**Small fix while here:** C6·h3's pinned label used `class="tag"`, which is also
the options page's own option-chip class. Scoped differently so it rendered fine,
but two meanings for one class name is a trap — renamed to `.hqtag`.

## Reviews + locations band — round 5: the site's own copy, kept (2026-08-24, zeina branch)

Every option from D backwards replaced the live sentence with labels — HEAD
OFFICE, ALSO IN, FIVE MORE OFFICES. Six that keep the live heading and the live
sentence and solve the same problems around them: **E1–E6** (backup
`prototyping/band-options-v5-live-copy.html`).

**One change to the copy, and it is the unavoidable one.** The live sentence names
five offices; the site has six published location pages. **Nanaimo is inserted.**
Every other word — the heading "Get our lawyers on your team", the closing "Read
more" — is the live wording untouched.

**Keeping the copy removes the head-office question rather than answering it.** The
sentence opens "**Headquartered** in Victoria, BC". That is the site's own word,
and it does the job D1–D6 were doing with a caption and a coloured marker.

**Where the city names are links, the underline stays on.** Colour alone is not a
sufficient link cue, and inside running prose there is nothing else to tell a
reader that six of these words are clickable — so they carry a persistent 1px
underline that turns orange on hover.

**The six:** E1 the live band with the six place names linked inside the prose
(128px) · E2 one dark band, orange block gone, sentence gets full width (118px) ·
E3 the sentence given room at 17px with a 24px heading (~162px) · E4 the purist —
prose completely unlinked, offices as their own row beneath (~152px) · E5 live
copy on a light ground (128px) · E6 live copy as a card over the hero (~150px).

**The trade this round is really about:** six links inside one 160-character
sentence is a lot of underlining in a small space. **E4 is the option that avoids
the question entirely** — and it pays by naming the six places twice, once in the
sentence and once as chips. There is no third answer; either the links go in the
prose or the places get said twice.

**Costs stated:** E3 is 34px taller directly under a hero that already fills the
screen. E5 sets body copy at `#5A544E` rather than the page's `#6B6B6B` — the
usual colour passes on white, but this band is likely to sit against grey
elsewhere and `#5A544E` holds up on both. E6 carries C1's constraint: the card
covers the bottom of the hero slide, and those three photographs do not exist yet.

## Reviews + locations band — round 6: D3 without the button (2026-08-24, zeina branch)

**Adi picked D3** (filled chip — one solid, five outlined) and asked for it without
the All Locations button. Five variants, **D3·a–e** (backup
`prototyping/band-options-v6-d3-no-button.html`). The chips themselves do not
change in any of them.

**Removing the button leaves the right end of the band empty, and that is the only
decision left.** The button was doing two jobs: it linked the *Contact Our
Lawyers* page, and it occupied the right third so the row did not look like it
stopped early. Each option answers that differently — **a** lets the space stay
empty (the literal request) · **b** grows the chips into it · **c** moves the
rating there, offices leading · **d** keeps the destination but not the control,
"All locations" as underlined text at the end of the row · **e** puts the phone
number there. All 132px.

**One thing goes with the button in a, b, c and e:** nothing in those versions
links the *Contact Our Lawyers* parent page — only the six individual office
pages. Small, and probably the footer's job in production (home-v2's footer
"Contact" is still a `#` placeholder like every other footer link in this
prototype), but worth knowing it happened rather than discovering it later. **D3·d
is the version that keeps the destination without the button.**

**Costs stated:** b's equal-width chips make "Duncan" occupy as much space as
"Campbell River", so short names float in a lot of padding — the price of a tidy
right edge. c demotes the Google rating from first thing in the band to last; on
the live site it sits in the orange block precisely because it is meant to be seen
first. d adds a seventh thing to a row of six, and it is the only one that is not
a place. e puts the phone number in the band, the header and the footer — three
places on one page, which is either useful repetition for a firm people call, or
the same number three times.

## Reviews + locations band — round 7: forms not tried yet (2026-08-24, zeina branch)

Six more, **F1–F6** (backup `prototyping/band-options-v7-new-forms.html`). All keep
the filled-chip idea Adi picked — six offices, Victoria solid with its label, the
other five outlined — and none uses the All Locations button.

**Each does something none of the thirty-seven above does:**

- **F1** the offices become the band itself — six full-height cells divided by
  hairlines, not chips on a field; the rating retreats to a thin line above
  (~138px). Every office gets the same 213px.
- **F2** the band stops bleeding to the edges and sits inside the 1280px grid with
  the page ground visible on all four sides (~172px overall).
- **F3** the only symmetrical composition on the page — rating centred, short
  orange rule, offices centred beneath, which is how every section heading on the
  page is already set (~146px).
- **F4** a background made of the score itself: 4.9 at 132px and 5.5% white behind
  the content, `aria-hidden`, with the readable rating still stated once at normal
  size (140px).
- **F5** the header's hive motif reused as texture — four hexagons in the right
  gutter, one faintly orange (132px).
- **F6** the rating demoted to a footnote, offices take the whole band (96px —
  shortest on the page by 22px).

**Two of these argue with decisions already made on the live site, and should be
chosen knowingly rather than picked for looks:**

- **F6** shrinks the Google rating to caption size when the live band gives it a
  full orange block. That is a change of position on whether the rating is a
  selling point, not a change of layout.
- **F5** repeats the header hive, which currently works partly because the page
  uses it once. The chips also needed a semi-opaque backing to stay legible over
  the cells — a sign the texture is close to being too much.

**Other costs stated:** F1 makes the whole band interactive, leaving it no quiet
area. F2 introduces `#F1EFEB` above and below the ribbon — the same ground the
practice areas now use — so it reads as that section starting early. F3 leaves
ragged edges on both sides and has no obvious place for a seventh office; the row
would recentre and every chip would move. F4's watermark must stay at ~5.5%; any
brighter and it competes with the chips in front of it.

## Reviews + locations band — round 8: modern and simple (2026-08-24, zeina branch)

Five options, **M1–M5** (backup `prototyping/band-options-v8-modern-simple.html`).
The rule for the round: **every option removes something.** No chip borders, no
uppercase tracked micro-labels, no button, no two-colour split, at most two type
sizes, one accent used once.

**A contrast defect was found in the option Adi picked, and it is not small.**
White at 13.5px semi-bold on brand orange measures **3.03:1**. AA needs 4.5:1 for
body text, and 13.5px semi-bold does **not** count as large text — that starts at
18.66px bold or 24px regular. **So D3's filled chip fails, and so does every
option on the page that used it.** Brand orange as small *text* is no better:
3.03:1 on white, 3.58:1 on brown.

Three ways out, and this round takes the third:

1. Darken the fill — white on `#B44322` is **5.58:1**. Costs the brand orange.
2. Enlarge the chip text to 18.66px bold, which qualifies as large text at 3:1.
   Costs the compact row.
3. **Stop asking orange to carry words.** It becomes a dot, a rule or a star, and
   the head office is marked by **weight**. Costs nothing, and it is the simpler
   design.

**Orange never carries a word in this round.** The one place it still appears at
3.03:1 is the five stars — as a non-text graphic the floor is 3:1 rather than
4.5:1, so they pass, and the rating is stated numerically right beside them so
nothing depends on the stars being read.

**The five:** M1 one line, no boxes, no ground, orange dot over Victoria (92px) ·
M2 two lines, cities at 17px, "head office" in lowercase beside Victoria (120px) ·
M3 centred, type only, six uppercase names divided by hairlines (128px) · M4 a
single 2px orange rule under Victoria, whitespace as the split (104px) · M5 the
same design on `#2A2622` (104px).

**What "simple" meant here, in numbers:** the band today has two grounds, a boxed
rating, an icon, a heading, a sentence, a link, and in later options six bordered
chips and a button — around fourteen visible elements. These have **seven to
nine**. Nothing was styled down; things were taken out.

**Costs stated:** M1 and M5 leave the head-office fact to a 6px dot plus weight,
so a reader has to infer it. M3 states it not at all. M4's orange rule is the
band's entire accent, which means the underline pattern is spoken for — any hover
underline elsewhere in the strip would read as a second head office. M5 adds a
fourth dark block between the hero and a now-light practice-areas section, giving
dark-dark-light-dark; M1 is the same design without that problem.

**Caught in my own round:** M2 initially turned a 17px city name brand orange on
hover — 3.03:1, breaking the rule the round had just stated. Moved to `--brown`
(10.86:1).

## Reviews + locations band — round 9: D3·d refined (2026-08-24, zeina branch)

**Adi picked D3·d** and asked for two changes: the head office **written**, never a
dot, and the row to read clearly as **locations**. Five variants, **D3·d·v1–v5**
(backup `prototyping/band-options-v9-d3d-locations.html`). The "All locations"
text link stays; the button does not come back.

**A fix Adi did not ask for is in all five, because the chosen chip fails AA.**
White at 13.5px semi-bold on brand orange `#EF6D3E` measures **3.03:1**; AA needs
4.5:1 at that size, and 13.5px semi-bold does not qualify as large text (that
starts at 18.66px bold). The filled chip has been failing since D3.

**The fill is now `#BF5732`, at 4.54:1** — the brand orange at **80% brightness**,
found by walking the brand colour down one step at a time and stopping at the
first value that passes, so the smallest possible amount of the brand is given up.
Beside `#EF6D3E` it reads as the same colour, slightly deeper. **This method is
worth reusing** anywhere else the brand orange has to carry white text.

**v5 is the one option that keeps `#EF6D3E` exactly** and pays a different price:
the city name goes to 19px bold, which qualifies as large text at the 3:1 floor,
and the HEAD OFFICE words move out from inside the chip to underneath it (orange
on brown, 3.58:1 against a 3:1 requirement). Both routes are legitimate; they cost
different things.

**How each makes the row read as locations:** v1 by the label (OUR LOCATIONS with
a marker) · v2 by giving every chip its own marker so a chip is legible as a place
on its own · v3 by spelling the head office out as words at full size · v4 by
saying it in the label and again on the chip · v5 by scale.

**Costs stated:** v2 puts seven markers in one band — if that is one too many, the
label's marker is the one to drop, not the chips'. v3 makes the first chip ~200px
against 90–130px for the rest, so the row is visibly front-heavy. v4 states the
same fact twice in 60px of vertical space — emphasis or redundancy depending on
how much the head office actually matters. v5 grows the band 14px and moves the
head-office words off the marked object, a slightly weaker join than v1–v4.

## Reviews + locations band — round 10: v3, locations as labels (2026-08-24, zeina branch)

**Adi picked D3·d·v3** with three changes: "All locations" becomes **Read more**
pointing at the contact page (the live site's own wording and destination), the
locations lose their hover, and the locations are no longer links. Four variants,
**v3·a–d** (backup `prototyping/band-options-v10-labels-readmore.html`). Only Read
more and the Google link are interactive now.

**Making the chips inert creates one problem, and it should be decided rather than
inherited.** Six bordered, padded, evenly-spaced objects in a row is **button
vocabulary** — people will click them and nothing will happen. That is a false
affordance, and it is the one thing the request creates. So:

- **a** is the literal request, shape untouched, so the risk can be judged directly.
- **b** removes the outline entirely — six names as plain text with 26px between them.
- **c** swaps the outline for a soft 8% fill: a fill says "these belong together",
  an outline says "press me".
- **d** runs the names together as one line divided by middots — no shape left to
  mistake for a button.

**What is lost, stated plainly:** the six location pages exist and until now every
option linked them. They are no longer reachable from this band — but **Read more
goes to `/contact-our-lawyers/`**, where all six live, so the route is one click
longer rather than gone. This is exactly what the live site does, so it is a
return to the old behaviour, not a new gap.

**One measurement to carry if b wins:** its "Head Office" is orange on brown at
**3.58:1**, under AA for body text, and 15px semi-bold is not large text. If b is
chosen, that phrase should be white and the orange kept for the stars.

**Two details carried across:** the head-office fill stays `#BF5732` (brand orange
at 80% brightness, white on it 4.54:1) because pure brand orange fails AA at this
size. And the em dash in "Victoria — Head Office" is now real markup rather than
CSS generated content, since it sits inside a phrase a screen reader should read
whole. The middot separators in **d** stay in CSS, correctly — punctuation between
names is not information.

## Reviews + locations band — v3·a integrated into home-v2 (2026-08-24, zeina branch)

**Adi picked D3·d·v3·a.** Integrated into `home-v2.html`, replacing the two-colour
split of an orange rating block beside a dark sentence (source
`prototyping/home-v2-v20-band-v3a.html`; state before,
`home-v2-v19-before-band-v3a.html`).

**Four defects fixed by the integration itself:**

1. **Nanaimo is on the homepage.** The live sentence named five offices; the site
   has six published location pages. A real office had been left off.
2. **The Google link works and will keep working.** The live one is a copy-pasted
   2019 results page carrying session parameters; this uses
   `google.com/maps?cid=3427224649634314500`, derived from the place id buried
   inside it.
3. **The Google mark is the real icon**, not a bold "G" in Open Sans at 44px.
4. **`--band-dark` is gone.** `#453F39` against `--brown #423C37` measured
   **1.05:1** — indistinguishable. The band now uses `--brown`, which left the
   variable unreferenced, so the declaration was deleted.

**Two instructions written into the CSS comment so nobody helpfully undoes them:**

- **The six locations are deliberately not links and deliberately have no hover.**
  The route to the office pages is Read more → `/contact-our-lawyers/`, where all
  six live — one click longer, and exactly what the live site does.
- **The cost was accepted knowingly:** six bordered, padded, evenly spaced objects
  in a row is button vocabulary, so people will click them and nothing will
  happen. v3·b (no outline), v3·c (soft fill) and v3·d (running text) are drawn in
  `band.html` and keep the behaviour without the button shape. If dead clicks ever
  become a complaint, the answer is already there.

**The head-office fill is `#BF5732`, and that is not a style choice.** White at
13.5px semi-bold on `#EF6D3E` is 3.03:1 — under AA, and not large text.
`#BF5732` is the brand orange at 80% brightness, the lightest value that passes
(4.54:1). Reverting it to `#EF6D3E` re-breaks the band.

**Still carried, and still true:** 4.9 and 173 are hardcoded exactly as they are
in the live WordPress block — no API, no refresh. A review count that cannot
update will eventually be wrong in public.

**Housekeeping found while there:** two more custom properties are declared but
referenced nowhere — `--hero-bg #464646`, orphaned when the J2 hero replaced the
radial-gradient one, and `--footer #222222`, which the footer never used (it
paints `#2A2622` directly). Both harmless; both recorded in the dark-values note
rather than silently deleted.

## FAQ — new section added to home-v2 (2026-08-24, zeina branch)

Adi asked for a new FAQ section with five entries, after "Watch Our Vlog". Added
to `home-v2.html` between the vlog and the footer (source
`prototyping/home-v2-v22-faq.html`; state before,
`home-v2-v21-before-faq.html`).

**The site has no general FAQ content, and the thing that looks like it isn't.**
There is no FAQ page, no FAQ post type, nothing in the navigation. The database
does hold five question-titled top-level pages (17549, 17571, 17580, 17592,
17604) — "Who can you sue?", "What types of compensation are available?" and so
on — which read as a ready-made FAQ at a glance. **Every one of them opens
"Injured Air Travelers — …" and is specific to air-travel injury claims.** Putting
them on the homepage would present one narrow practice as the whole firm. They are
not used.

**So all five Q&A are NEW COPY needing Darren's approval — but none of it is
invented fact.** Each answer restates something the site or the database already
says, and the source of every fact is named in the section's CSS comment:

1. **Free consultation** — the firm's own live line, "In the areas of personal
   injury and estate litigation, League and Williams provides free
   consultations". **The scope limit is kept deliberately and must not be
   shortened to "free consultations".**
2. **Offices** — six published location pages, plus the live "Headquartered in
   Victoria, BC…".
3. **Practice areas** — the five published children of What We Do.
4. **Experience** — "over 160 years" is the live practice-areas sub-heading;
   twelve lawyers counted from the database.
5. **Getting started** — the published phone number and the hero form on this page.

**Nothing here is legal advice, and that is deliberate.** The questions a real
law-firm FAQ needs — how fees work and whether the firm takes cases on
contingency, how long someone has to start a claim, whether a case is worth
pursuing — are absent because a designer must not write them. **Those are the
slots Darren should want to fill.**

**No FAQPage JSON-LD, on purpose.** FAQ schema is what earns the expandable
Google results and is worth adding — but adding it now would publish unapproved
answers to a search engine. Add it when the copy is signed off.

**Build notes:** native `<details>`/`<summary>`, so no JavaScript is added (the
page's only script stays the hero's) and keyboard and screen-reader behaviour are
correct by default — **do not replace this with a div-and-click accordion.** The
first entry is open at load so the section has a resting height; they are not a
radio group, deliberately, so comparing two answers does not close one. Ground is
`#F1EFEB`, so the page reads white (vlog) → warm grey (FAQ) → dark (footer).

**Two contrast fixes caught inside my own new section, both the same rule I had
just written for the band — brand orange must not carry words:**

- The open-state marker was white on `#EF6D3E` (3.03:1) → `#BF5732`.
- Three hover colours were `#EF6D3E` on 17px/15.5px/14.5px text — 3.03:1 on white
  and **2.64:1** on `#F1EFEB`, none of it large text → `#A94A29`, which is 5.68:1
  on white and 4.94:1 on the section ground, so one value passes on **both**
  grounds the section uses. Brand orange now appears in this section only as the
  open-state left rule, which is non-text.

## FAQ — hexagon marker replaced with an ordinary chevron (2026-08-24, zeina branch)

Adi did not like the hexagon `.mk` marker and asked for a conventional dropdown
icon on the right. Done in `home-v2.html` (source
`prototyping/home-v2-v24-faq-chevron.html`; state before,
`home-v2-v23-before-faq-chevron.html`).

`fa-angle-down` at the right-hand end of each summary row, rotating 180° on open,
`#8A837B` at rest and `#BF5732` open. The answer's indent moved with it — it was
70px on the left to clear the old hexagon, and is now 26px left / 62px right so
the answer aligns under the question instead of under a marker that is no longer
there.

**The chevron is `aria-hidden`.** `<details>` already announces whether the panel
is open, so the icon is a visual echo only; a second announcement would be noise.
That also means it only has to clear the **3:1 non-text floor** rather than 4.5:1
— `#8A837B` on white is 3.74:1, `#BF5732` is 4.54:1. Both pass.

The `prefers-reduced-motion` guard already in the section covers the new rotation,
so the chevron does not spin for anyone who has asked for less movement.

## FAQ — the open-state left rule removed (2026-08-24, zeina branch)

Adi asked for no `border-left`. The 3px orange rule on open panels is gone from
`home-v2.html` (source `prototyping/home-v2-v26-faq-noborder.html`; state before,
`home-v2-v25-before-faq-noborder.html`). The transparent 3px border that reserved
its space went with it, so the panels now sit flush.

**Two consequences worth recording:**

- **The open state is now carried by the panel's height and the rotated chevron,
  nothing else.** Those are the conventional signals for an accordion and they are
  enough — and `<details>` still announces the state natively, so nothing was lost
  for assistive tech.
- **The brand orange `#EF6D3E` has left this section entirely.** The left rule was
  its last appearance here. What remains is the deepened `#BF5732` on the open
  chevron and `#A94A29` on hover — both values that exist because the brand orange
  fails AA on these grounds at these sizes.

## FAQ — ground matched to the testimonials section (2026-08-24, zeina branch)

Adi asked for the FAQ background to match the testimonials section. `.faq` moved
from `#F1EFEB` to `#F9F9F9` (source `prototyping/home-v2-v28-faq-paper.html`;
state before, `home-v2-v27-before-faq-paper.html`).

**The change had a consequence, and it needed handling rather than shipping.**
White panels separate from `#F1EFEB` at **1.15:1** but from `#F9F9F9` at only
**1.05:1** — they effectively vanish. Each panel therefore gained a 1px `--line`
hairline.

**That hairline is not the border Adi removed.** The 3px orange left rule was an
open-state indicator; this is a card outline. It is also exactly the job the
testimonials section already does on the same ground — its cards are identical
white panels on `#F9F9F9`, defined by an orange top rule. **If the hairline is
unwanted, the alternative is to drop the white panels entirely and separate the
questions with dividers — not to delete the border and leave invisible cards.**
Written into the section's CSS comment so nobody does the latter.

**The move improved two contrast figures:** the sub-heading and the closing line
at `#6B6B6B` go from 4.64:1 to **5.06:1**, and the hover `#A94A29` from 4.94:1 to
**5.39:1**. Both were passing before; both have more margin now.

**Page rhythm now:** vlog white → FAQ `#F9F9F9` → footer `#2A2622`. The FAQ ground
is a lighter step than it was, so the separation from the white vlog above is
subtler than the earlier warm grey gave.

## Low-fidelity conversion of home v2 (2026-08-24, zeina branch)

Adi asked for a new folder to hold a low-fidelity conversion of the hi-fi
prototype. Created **`/srv/apps/leaguelaw/wp-content/lofi/`** (2775,
`leaguelaw-dev`), served the same way `prototype/` is, holding
`home-v2-lofi.html` and its own `index.html`. Backup
`prototyping/lofi-home-v2-v1.html`; a card was added to the prototype hub.

**Rebuilt three times on 2026-08-24 at Adi's instruction, and the third is the
one that works.** First the project's existing hand-drawn pencil language — not
wanted. Then a Figma-style sheet with annotation pins, prose and a mobile frame —
still not it. Then a redrawn desktop-only sheet with the real copy but
approximated boxes. Adi's last instruction was **1:1 with the prototype on
element size, shape, font and layout**, which rules out redrawing anything.

**So the current file is not a drawing of home-v2. It is home-v2, desaturated.**
Generated by `scratchpad/gen_lofi_11.py`:

- Every colour — hex, `rgb()`, `rgba()`, and the hexes inside CSS SVG data-URIs —
  is replaced by **the grey of the same relative luminance**, so the value
  structure (which block is darker than which) survives exactly rather than being
  guessed at.
- Every `<img>` keeps its element, its box and its `object-fit` and points at a
  placeholder SVG, so the photographs are absent **without a single pixel of
  layout moving**.
- Fonts, sizes, weights, letter-spacing, paddings, gaps, grid columns and
  clip-paths are untouched, because it is the prototype's own stylesheet.
- The hero script is intact, so the pinned slider and the travelling form behave
  as they do in the prototype.

**Then made static (2026-08-24), because a low-fidelity sheet should not respond
to input.** Removed: every `:hover`, `:focus` and `:active` rule; every
`transition`, `animation` and `@keyframes` block; every `cursor` declaration; the
hero script; and every `href`. The FAQ panels are forced open because `<details>`
is a control, and the hero slider no longer cycles — slide 1 is pinned visible.
`pointer-events:none` is applied to links, buttons, fields and summaries **but not
to the page**, so the text stays selectable and copyable.

**`position:sticky` is deliberately kept.** It is layout, not a pointer response,
and flattening it would change the hero's height and break the 1:1. If the sheet
should be inert on scroll as well, that is a separate decision.

**Verified mechanically, not by eye:** 522 layout declarations — width, height,
padding, margin, gap, grid columns, font-size, weight, letter-spacing,
line-height, aspect-ratio, flex, clip-path, position, display — are **identical**
between the two files. Zero non-grey values, zero hover/focus/transition/
animation/cursor rules, zero `href`s, zero scripts, zero empty or unbalanced
blocks.

**A bug in my own generator, worth recording because it was silent.** The
rule-walker read the comment sitting in front of a selector *as part of* the
selector. A comment before an `@media` block hid the `@` from the at-rule test, so
the block was parsed as an ordinary rule ending at its first inner `}` — which
deleted the rule that followed it. That is how `.facts { background; padding }`
vanished from an early build. Caught by the layout-declaration diff, not by
looking at the page; fixed by stripping comments out of the selector before
testing it.

**It is output — do not hand-edit it.** Re-run the generator after any change to
`home-v2.html`, or the two will drift.

#### Hero unpinned in the lo-fi (Adi, 2026-08-24)

In the prototype the hero image pins and the **WE'VE GOT YOUR BACK** form travels
up over it as you scroll. That is a scroll response, and a low-fidelity sheet does
not have those — so the pin is flattened in the lo-fi. The image is an ordinary
block; the form sits in flow directly beneath it, pulled up by `margin-top:-84px`,
which is the exact overlap the prototype loads with. The section is no longer
`200vh - 292px` tall, it is as tall as its contents, so no empty run of scroll
follows it.

**Four declarations — and only four — now differ from the prototype**, all of them
this: `.nhero-scroll{height}`, `.nhero-sticky{position,top}`,
`.peekwrap{position,top,margin-top}`. The diff proves the rest: of 781 layout
declarations, 758 are byte-identical and the 23 absent ones all sit inside
`:hover` selectors that were deliberately stripped.

**The header is still `position:sticky`.** It was left alone because Adi named the
form; flattening it is one word away. Note for whoever does it: use
`position:relative`, never `static` — `.nheader` is the containing block for
`.combclip` and `.mega`, and `static` would resolve those against the page and
throw the header's comb decoration across the whole document.

#### Form lifted over the hero in lofi v2 (Adi, 2026-08-24)

The wireframe had the form card tucked inside the hero, poking 8px past its
bottom edge — the *docked* end state of the prototype's hero, not its opening
composition. Adi asked for the opening one: the card lying **on** the hero and
running down across the review-and-location band.

Numbers, so the next person does not have to re-derive them. The card is
`bottom:-84px` on the 250px hero — 84px is the prototype's own overlap figure,
which is why it is the one used here. Card height is 311.5px (14+14 padding,
1+1 border, h4 18.1, sub 22.6, four fields 177, safety note 26.9, button 37), so
its top lands 22px below the hero's top edge: it covers all of the hero but the
first sliver, which is what "on the hero" has to look like to read as deliberate
rather than as a misplacement.

Three things had to move with it, and each one is the drawing telling the truth
about a decision the design owes an answer to:

* **MESSAGE became a 66px box.** It is a `<textarea>` in the prototype and was
  drawn as a one-line field here. Without that height the card is 273px and
  cannot reach the band at all — the overlap Adi asked for was arithmetically
  impossible until the field was drawn correctly.
* **The card widened to 268px** (was 220), ≈28% of the frame, which is the share
  the 371px form takes of the prototype's 1280px container.
* **The band keeps its original spacing** (`margin-top:26px`). I had dropped its
  content 60px to clear the card; Adi reverted that — the overlap is the point,
  and content sitting under the form is allowed. It costs nothing here: the card
  occupies x 720–988 of a 1018px block, and the "OUR SIX LOCATIONS" label sits in
  the left half of the right column, so the 4.5px of band the card actually
  covers is empty. **That is luck, not design.** The moment the band's content
  reaches further right — a seventh location, a longer label, a button on that
  edge — the form will start eating it, and the built page will have to decide
  between clearing a lane for the form and letting it cover something.

The slide caption narrowed to 360px for the same reason: the wider card would
otherwise have crossed it.

**And it still did not cross anything.** `.ph` is `overflow:hidden` — it has to
be, that is what keeps the diagonal cross-lines inside the placeholder box — and
the card was a child of it, so every pixel of the overhang was being clipped at
the hero's own edge. The arithmetic above was right and the drawing was wrong,
which is the failure mode a measurement cannot catch: nothing about the numbers
tells you a parent is cutting the result off.

**A card that has to straddle two sections cannot live inside either of them.**
The card is now a sibling of `.ph`, absolutely positioned against the hero block
itself (`right:30px; top:48px; z-index:3`), flush with the content column the way
the prototype's form is flush with its 1280px container. It lies over the hero
from 22px below its top edge and hangs 56px past the block's bottom border into
the band — a real crossing, not a clipped one.

#### Vlog play button became the hexagon in lofi v2 (Adi, 2026-08-24)

The wireframe drew the play control as a line of text — `▶ 3:42` floating in the
middle of the thumbnail. The prototype has two separate things there: a **hexagon
play button** centred on the thumb, and the **duration as its own chip** in the
bottom-right corner. The wireframe had collapsed them into one, which quietly
loses the brand shape — the hexagon is the firm's mark and it appears on the
thumbnail for that reason, not as decoration.

Sized by ratio, not by eye: the prototype's hexagon is 64×74 on a 206px thumb, so
its height is 36% of the thumb. This sheet's thumb is 96px, so the hexagon is
30×35 — 36.5%. The duration chip moved to the corner where the prototype puts it.

#### Hexagons on the dark blocks were invisible (Adi, 2026-08-24)

Adi flagged the hexagon on the LaW Facts cards as blending into everything around
it. It was `--fill3 #DADADA`, the sheet's default hexagon fill, which is a light
grey — fine on a white block, meaningless on a dark one. Measured against the
three greys it can land on: **1.04:1** against the card it overlaps, **1.22:1**
against the placeholder above it, **1.08:1** against the block itself. It was not
subtle; it was absent.

Now `#666666`, which clears the **3:1 non-text floor against all three** — card
4.27:1, placeholder 3.36:1, block 3.80:1. `#6E6E6E` was the tidier choice because
it is already in the palette, but it lands at 2.99:1 on the placeholder, and a
value chosen for tidiness that misses the floor by 0.01 is just a worse value.

**Applied to every hexagon on a dark block, not only the six Adi named** — one
rule, `.blk.d .hex`, reaching 22 hexagons across the band, the facts cards and the
team. The same defect was on all of them, including the LaW Facts section's own
heading hexagon one line above the cards; fixing six and leaving the rest would
have left the section inconsistent with itself.

#### CTA band split left/right in lofi v2 (Adi, 2026-08-24)

The wireframe had run the whole band into one sentence — heading, phone number
and button as a single line of text. The prototype's band is
`justify-content:space-between`: the headline on the left, and on the right a
group holding the phone and the **Book Consultation** button. Redrawn that way.

That is not only alignment. Drawn as running text, the phone number and the
button stop being *things you can act on* and become part of a sentence — a
wireframe is supposed to show where the actionable objects are, and this one was
hiding two of them.

#### Two sheets, deliberately

`lofi/home-v2-lofi.html` — the 1:1 conversion (above).
`lofi/home-v2-lofi-v2.html` — the earlier sheet, **drawn rather than converted**:
the page reduced to blocks, boxes and rules at one scale, real copy, no
proportions carried over. Kept at Adi's request as the wireframe-grade read; the
1:1 sheet cannot do that job, because being faithful is the opposite of it.

Archived: `prototyping/lofi-home-v2-v1.html` (pencil),
`lofi-home-v2-v2-figma.html` (annotated, with mobile),
`lofi-home-v2-v3-desktop-copy.html` (redrawn, real copy — now published as
lofi v2),
`lofi-home-v2-v4-11.html` (1:1, still interactive),
`lofi-home-v2-v5-static.html` (1:1, static, hero still pinned),
`lofi-home-v2-v6-before-hero-unpin.html`,
`lofi-home-v2-v7-hero-unpinned.html` (current).

Generator is now `scratchpad/gen_lofi_12.py`.

**The three findings the pencil version surfaced are no longer written on the
sheet** — it is a conversion now, not a critique — but they still stand: the hero
is three photographs that do not exist; the practice mosaic loses its whole idea
in one column; the header's six mega panels have no decided mobile behaviour.

## Round: the first screen — hero, or straight to the services? (`hero-service.html`)

**Asked 2026-08-24.** The client has said they do not want a hero and would rather
show the practice areas immediately, pointing at a competitor whose homepage opens
on a checkerboard of service tiles. Adi asked for options that take that request
seriously **and** options that still read as an opening — an `h1` and short,
to-the-point copy — while showing the services.

### The thing that is not negotiable

**"No hero" is a decision about layout. It is not a decision about the page
heading.** The competitor page in the example appears to have no `h1` at all, and
that is the same defect already logged against this rebuild as flag #1 — the
current League and Williams homepage has an empty `h1`. Copying the competitor
wholesale would copy their defect. Every option in this round carries a real
heading, including the three with no hero: in S1 it is one quiet line above the
grid, in S2 it is a tile *of* the grid.

(In the specimens the element is drawn as a `<p class="pgh1">` so the sheet does
not carry seven `h1`s. In the built page it is the `h1`.)

### The six

| | | |
|---|---|---|
| **S1** | Checkerboard — the client's example, in brand | no hero |
| **S2** | Checkerboard with the opening inside the grid | no hero, has heading |
| **S3** | Five full-height gateways, heading underneath | no hero |
| **H1** | Split — opening left, service mosaic right | hero |
| **H2** | Heading band, then a full-width service row | hero |
| **H3** | Short hero (320px) + icon row | hero |

**Recommendation: S2.** It answers both halves of the brief with one structure
instead of stacking a hero on top of a grid — the services still start at the top
of the screen, and the page still says what it is.

**S2's cost is countable and should decide the pick:** ten cells, the opening
takes two, so only three of the five services keep a photograph — **business and
real estate appear as text only.** That is a real decision, not a drawing artefact.

**A detail worth keeping whichever wins.** In S1 the checkerboard is arranged so
that **every photograph touches its own service's text cell** — injuries, estates,
real estate and marine pair sideways, business pairs vertically in column 5, and
the true T-P-T-P-T / P-T-P-T-P alternation survives. The competitor's grid does
not do this consistently; a photograph next to the wrong service is a small lie
the eye still reads.

### Round 2 — different shapes (same sheet)

Round 1 answered the brief with two ideas, a checkerboard and a hero. Round 2
changes the structure itself.

| | | |
|---|---|---|
| **B1** | Alternating full-width bands, one service at a time | no hero |
| **B2** | One tall lead beside a 2×2 | no hero |
| **B3** | Typographic index — **no photographs at all** | no hero |
| **B4** | Honeycomb — five hexagons interlocked | no hero |
| **B5** | Heading band, cards crossing its bottom edge | hero |
| **B6** | Photo wall with the heading floating on it | hero |

**Pick of round 2: B5.** The crossing is what does the work — the cards belong to
the heading instead of following it, so the eye reads one unit rather than two
stacked blocks, and photograph, name and sub-line all survive at 232px per card.

**Two options here say something the other ten do not.**

* **B3 is the only option on the sheet not standing on photographs that do not
  exist.** It could be built this week, it is the fastest first screen of the
  twelve, and it degrades to mobile without a decision. That is worth putting in
  front of the client explicitly, because every other option is a promise about a
  photo shoot nobody has booked.
* **B2 stops treating the five practice areas as equals.** Injuries is the firm's
  largest practice and the only one with sixteen sub-pages in the database; the
  other eleven options give all five the same weight, which is a claim about the
  business nobody has actually made. B2 takes a position — and therefore needs the
  firm to confirm the ranking before it is honest.

**What B4 costs, stated because it is easy to miss:** there is no room inside a
hexagon for a sub-line, so **B4 shows five names and nothing else** — the detail
the client's own example page leads with is gone. The hexagon also crops hard,
so its photographs need a subject dead centre.

Comb geometry is exact, not eyeballed: a pointy-top hexagon's vertical pitch is
0.75 × its height, so the second row overlaps the first by 302 − 226.5 =
**75.5px**. The two lower hexagons land precisely on the midpoints of the three
above them.

### Round 3 — the services and nothing else (Adi, 2026-08-25, same sheet)

Adi: *"tambahkan opsi dimana hero langsung menunjukan service tanpa h1 dan copy
content lain selain services."* Six more options (**C1–C6**) where the first
screen carries **no page heading, no sentence of copy and no button** — the only
words above the fold are the five practice names and, where the layout has room,
each one's own sub-line. The site header (logo, nav, phone) stays: that is site
chrome, not hero copy. Verified mechanically — the six C stages contain no
`pgh1`, `hcopy`, `wbtn`, `rbtn` or title strip, and a text dump of each stage
returns nothing but the service names and sub-lines.

| | | |
|---|---|---|
| **C1** | Five full-height gateways (607px), nothing above or below | no h1 |
| **C2** | The competitor page taken exactly — checkerboard from the header down | no h1 |
| **C3** | Asymmetric mosaic — wide lead + four tiles, 600px edge to edge | no h1 |
| **C4** | The comb alone on the screen | no h1 · **names only** |
| **C5** | The names *are* the layout — 44px type, no photographs | no h1 · no images |
| **C6** | Five photographs, each name in a card crossing its own picture | no h1 |

**Pick of round 3: C5.** Every other option here answers "no hero, no copy" by
making the photographs carry the page — which hands the entire first screen to
five images that do not exist yet at the size they are being asked to fill. C5
owns the constraint instead of hiding it: if the page is going to say only five
things, set those five things large enough to be the design. It is also the only
round-3 option buildable this week and the only one that reaches mobile without a
decision.

#### The distinction that keeps this round honest

**"No `h1` in the hero" and "no `h1` on the page" are two different things, and
only the first was asked for.** The heading can move down to the first section
under the services and the page still has exactly one descriptive `h1`. Nothing
is lost for accessibility (a screen reader reaches a heading by structure, not by
position) and nothing is lost for search (an `h1` is worth what it says, not how
high it sits). What *is* lost is the sighted visitor who does not already know the
firm: on the first screen of all six, the page never says who these people are,
where they practise, or what it costs to call them. That is a business decision,
not a technical one, so it belongs to the client stated plainly.

**What must not happen:** a page with no `h1` anywhere. That is what the
competitor example appears to do and what the current homepage already does —
flag #1 on this rebuild. Round 3 must not quietly re-create it.

#### First-screen arithmetic (header is 93px; target viewport 700px)

* C1 — 607 + 93 = **700**, exact.
* C2 — 2 × 256 + 93 = **605**.
* C3 — 2 × 300 + 93 = **693**.
* C4 — 302 + 226.5 (0.75 pitch) + 74 padding + 93 = **695.5**.
* C5 — 5 rows × ~109 + 50 padding + 93 = **~689**.
* C6 — 430 photo − 60 overlap + ~132 card + 44 + 93 = **~639**.

All six fit one screen. That is the point of the round: with the copy gone there
is nothing to push below the fold, so the layout must earn the whole frame.

**C4's cost doubles in this round.** With the heading removed *and* no room for a
sub-line inside a hexagon, **C4's first screen contains five words in total** —
Injuries, Estates, Business, Marine, Real Estate. Choose it with that said out
loud, not by accident.

### Round 4 — same rule, a different layout language (Adi, 2026-08-25, same sheet)

Adi: *"tambahkan opsi lagi dengan layout yang berbeda."* Six more (**D1–D6**) that
keep round 3's rule exactly — no heading, no sentence, no button on the first
screen — and change the shape vocabulary instead of the grid.

| | | |
|---|---|---|
| **D1** | Staircase — five 236×340 tiles, each dropped 36px below the last | reading order, not a grid |
| **D2** | Five full-bleed 120px strips, the name set across the picture | names only |
| **D3** | Arches — five doorways, names on white beneath | courthouse, not honeycomb |
| **D4** | Fanned cards — four spines 108px wide, the front card open | one service leads |
| **D5** | One photograph as the ground, five white plates on it | **one image, not five** |
| **D6** | Five tabs, one 520px panel open beneath | four services hidden |

**Pick of round 4: D5, on grounds of what actually exists.** Everything else in
rounds 3 and 4 asks five photographs to carry a whole screen at a size the
current 411–600px files cannot hold. D5 asks for **one** good photograph —
Victoria, the building, the harbour — and gives the five names white plates that
hold regardless. One photo-shoot decision instead of five. What it gives up is
real: no practice area gets a picture of its own, so the visual argument becomes
about the firm and the city rather than about the work.

**D2 is the other option that answers the asset problem rather than dodging it.**
A 120px strip only needs a good horizontal band out of an image, not a whole
composition, so a 500px file is genuinely enough at that height — unlike C1,
which asks the same file to fill a 607px column.

#### Three of these six cannot treat the five practice areas as equals

D1's stair gives the top-left tile the reading position, D4's fan has a front
card, and D6's tabs open on one and hide four. Injuries is drawn in the lead
position in all three because it is the largest practice and the only one with
sixteen sub-pages in the database — **but nobody has confirmed that ranking**, so
until somebody does, these three are proposals about the business as much as
about the layout. Same standing item as B2.

#### D6's cost is the plainest on the sheet

Four of the five services sit behind a click, which is close to the opposite of
what the client asked for. It also needs JavaScript, so it has to degrade to all
five panels stacked when that fails — and that fallback is a second layout to
design, not a detail.

#### Two defects caught by arithmetic rather than by eye

* **D2's name sits at the exact centre of the strip, which is where a
  left-and-right gradient is thinnest.** Worst case is a bright sky: after
  `brightness(.58)` its relative luminance is 0.296, and white needs the composite
  ≤ 0.183 to clear 4.5:1, so the middle stop has to be **≥ 0.39 alpha**. The first
  draft had 0.34 → 2.66:1, a fail. Now 0.48 → **5.1:1**.
* **D4's vertical spine runs from 22px to 352px of a 470px card**, well above the
  point where a bottom-weighted scrim has thinned out — 0.295 there, giving 4.0:1
  on a bright frame. The curve was raised to .90/.62/.44, which puts the top of
  the spine at **5.7:1**; the front card's text is at the bottom and only gains.

Both were invisible in the drawing and only showed up in the numbers. Same lesson
as the `#6E6E6E` miss: a scrim value chosen because it looks right is not a scrim
value.

#### One thing removed on second look

D6 first printed the practice name twice — once in the active tab, once in the
panel. On a screen whose entire budget is five words, saying one of them twice is
not a detail. The panel now carries the rule and the sub-line only; the tab names
it.

#### First-screen arithmetic (header 93px, target viewport 700px)

* D1 — 340 + 4×36 stair + 80 padding + 93 = **657**.
* D2 — 5 × 120 + 93 = **693**.
* D3 — 420 arch + ~96 caption + 84 padding + 93 = **693**.
* D4 — 470 card + 116 padding + 93 = **679**.
* D5 — 600 ground + 93 = **693**.
* D6 — 64 tabs + 520 panel + 93 = **677**.

### Round 5 — Adi's reference layout, rebuilt for five (2026-08-25, same sheet)

Adi supplied a reference image: three columns, three different treatments — a
photograph above a card, a card above a photograph, and one taller column where
the words sit **on** the picture — warm card ground, rounded corners, generous
white around everything. Round 3's rule still holds (no heading, no sentence, no
button).

**The whole problem is that the reference holds three services and this page has
five,** and there are only three honest ways out: squeeze the columns, keep the
column width and take a second row, or divide by four and give the fifth a
different shape.

| | | |
|---|---|---|
| **E1** | The reference extended literally to five columns; tall ones at 2 and 4 | 241px columns |
| **E2** | Reference proportions kept — 3 wide columns, then 2 on their side | **two screens** |
| **E3** | Centre-led — one tall column in the middle, two split columns each side | one service leads |
| **E4** | Four in the rhythm, the fifth laid across the bottom | 306px columns |

**Pick of round 5: E2.** The reference works *because* its cards are wide enough
to read. E1 keeps the arrangement and loses that; E2 keeps the thing that made it
good and solves "five" by changing direction instead of shrinking. Its cost is
stated rather than hidden: 34 + 520 + 18 + 186 + 40 = 798, plus the 93px header =
**891px** — the only option in rounds 3–5 that does not fit one screen. That is a
real trade to put to the client as one: *readable cards, or all five above the
fold.*

#### Two things in the reference are new to this project, and both are decisions

* **The card ground is a warm blush, not the project's cool paper.** `#F4EFE9`
  checked by hand: brown name **9.50:1**, muted sub-line **4.66:1** — clears the
  4.5 floor with nothing to spare, so that sub-line never gets smaller than
  11.5px. Rust hover 4.97:1. Against a white section ground the card reads at
  1.14:1, a tint rather than a boundary — which is exactly what the reference does.
* **Corners are rounded at 14px**, the opposite instinct to the rest of this
  rebuild: the firm's mark is a hexagon and every other option on the sheet has
  square corners. Rounded is defensible, but it has to be chosen for the whole
  page, not for one section.

#### The tall column is prominence, so the arrangement ranks the practices

In the reference the tall column is the one that carries. E1 puts the tall slots
at positions 2 and 4, which in ordinary practice order hands prominence to
**Estates and Marine — the two smallest practices**. That is an accident of the
pattern rather than a decision, and it is the kind a client notices. E3 makes the
choice deliberate and puts injuries in the middle, which makes it the same
proposal as B2/D1/D4/D6 and needs the same sign-off. If the firm will not rank
the five, E1 or E2 is the safer pick.

#### Height arithmetic corrected after the first draft

The first pass shipped notes whose numbers did not match the CSS: E2 was called
"roughly 870px" (it is 891) and **E4 was called "about 600px" when its own CSS
made it ~790**. Fixed in the CSS rather than in the prose — E4's tall column came
down to 372, its photographs to 176 and its bottom card to 140, so the section is
22 + 372 + 14 + 140 + 26 = 574, plus the header = **667px**, and the claim is now
true. E1's tall column came down 556 → 520 (687px total) and E3's lead 590 → 520;
what makes E3's middle column lead is that its four neighbours are 432px split
columns, so it stands 44px proud at each end.

**Lesson, same family as the D2/D4 scrim misses:** a number written in an option
note is a claim about the CSS, and it has to be derived from the CSS rather than
estimated beside it.


## Inner service page — first build in home_v1's language (2026-08-27, zeina branch)

**Status:** built, then PARKED — Adi asked on the same day for the served
`inner-service.html` to be the live-site replica instead (see the next section).
This build is complete and re-servable at any time by re-running its generator.
**Source of record:** `prototyping/inner-service-v1-home_v1-style.html` ·
generator `prototyping/gen_inner_v1.py`
**Models:** <https://www.leaguelaw.com/our-services/bc-injury-claims/car-accident-claims/>
(content + information architecture) and `wp-content/prototype/home_v1.html`
(the design language). `index.html` and `home_v1.html` were not touched.

### What was asked

Adi: an inner **service** page, built to `home_v1`'s style. (The ask before it in
the same session — a 1:1 replica of the live inner page — was superseded at the
time, and then reinstated: see "Inner service page — the live replica, served"
below. The measurement work is written up under "The live inner page, measured"
and is the reference for what the old page actually does.)

### The rule the build follows: the chrome is LIFTED, not retyped

`gen_inner_v1.py` reads `home_v1.html` at build time and slices out the whole
`<style>` block, the header with its mega menus, the contact band, the
articles/FAQ block, the footer, the consultation modal + tab + fold ruler, and
the script block. Only the page-specific sections are new, and only the new CSS
is appended.

**Why it matters:** two hand-copied headers drift within a week — someone edits
one and forgets the other, and the "same design" claim quietly stops being true.
Lifting makes drift impossible: change `home_v1.html`, re-run the generator, and
the inner page is current. It also means this page carries home_v1's decisions
automatically — hexagon-light, the swarm button, the `.abox` cards, the
logo-underline hover, the fold ruler.

The one place the lift is edited is the nav: `Injuries` gets `class="mi cur"`
(orange + a 2px inset underline). The generator asserts the substitution landed,
so a change to home_v1's nav markup fails the build instead of silently
producing a page with nothing marked.

### What is on the page, and where each piece came from

| Section | Lineage |
|---|---|
| header + mega menus | lifted from home_v1, `Injuries` marked current |
| **opener** | NEW — replaces the live page's orange-tinted photo banner |
| **body** (768/512) | NEW frame · copy verbatim from the live page |
| contact band | lifted verbatim |
| **other injury claims** | NEW section · `.abox` cards from home_v1's Injuries panel |
| **your injury team** | NEW section · the five lawyers home_v1's Injuries panel already names |
| articles + FAQ | lifted verbatim |
| footer · modal · tab · fold ruler · scripts | lifted verbatim |

**The opener carries no photograph.** The live page opens on a truck photo
tinted 30% black with the title over it. Darren's ban is on the *intro image*,
and home_v1 honours it on the home page; an inner page that re-introduced a
banner photo would break the same rule one level down. So the opener is type
plus the practice icon: breadcrumb → kicker → `h1` → the live page's own `h2` as
a deck → the live lede — and on the right, across a hairline, the phone number
at 40px, the free-consultation line, Book Consultation, and the head office.
Contact is on the first screen without a form, which is what the compliance
brief asks for.

**The body is 768 / 512 — the five-cell lattice** the contact band (512+768) and
the articles/FAQ block (512+768) already use, so the inner page measures on the
same grid as the home page rather than inventing its own.

**The sidebar's two jobs are kept, and split.** The live sidebar does two things:
it offers a form and it lists the thirteen injury claims. Here the rail carries a
consultation card (phone, the "kept safe" line, Book Consultation) and, under it,
the thirteen claims as a two-column list with the current one marked — reading
DOWN each column, not across the pair, because a reader scans a column. The rail
is sticky; its hairline sits on a stretched wrapper so the rule runs the full
column instead of stopping where the card ends.

**The Part 7 bullet list became four outlined cards.** Same four sentences, not a
word added or removed — the figure is simply pulled out to carry the weight
(`Up to $150,000` / `in medical and rehabilitation expenses`). Cards use the
outlined vocabulary the locations grid and the sub-service boxes already use, and
`align-items:start` so a one-line card is one line tall instead of matching the
longest one.

### Decisions taken, and why

- **The current page is not in the "other injury claims" grid.** Thirteen cards in
  a four-column grid leaves one orphan on a row of its own; twelve is exactly
  three rows. Dropping the page you are already on is both tidier and more
  honest — a card is a link, and this one would link to itself. Orientation is
  not lost: the breadcrumb and the rail list both mark it.
- **The injury bench is five, not twelve.** Darren Williams, Joji Kawaguchi,
  Matthew Melnyk, Reid Warren, Georgia Lockhart — exactly the five home_v1's
  Injuries panel already names, in its order, so the two pages cannot disagree.
  Carried with the same caveat home_v1 carries: **who actually staffs a matter is
  the firm's call**, and the note under the row says so rather than implying the
  page knows.
- **Articles and FAQ are home_v1's, verbatim.** On the real build the articles
  become "related articles, filtered to injuries" and the FAQ becomes
  car-accident questions with FAQ schema. Both are copy, and copy is the firm's —
  writing injury-specific Q&A here would have been the prototype putting words in
  the client's mouth. The FAQ keeps its existing draft flag.
- **The photograph in the article is flagged.** The live page's own image is a
  4:3 monochrome shot; home_v1's photography policy is colour, 16:9. The frame is
  16:9 and carries the `PLACEHOLDER · NOVEMBER SHOOT` tag, per the
  never-an-unlabelled-placeholder rule.
- **The modal is contextual for free.** home_v1's modal already had a
  `car-accidents` slug in its context map, so every Book Consultation on this
  page (opener, rail, each sibling card's ✉) opens with the car-accident image and
  caption, and `#cta-car-accidents` deep-links to it.

### Open, and deliberately not decided here

- **Reading measure.** The prose column is 704px at 16.5px — about 88 characters.
  The live page is 832px (~104), so this is better, but still above the 45–75 band.
  Narrowing it means either breaking the five-cell lattice or leaving slack on the
  right. Worth a decision with Adi rather than a silent choice.
- **Which sibling claims deserve consultation slugs.** Four of the thirteen
  (Hit and Run, School Accident, Product Liability, Assault & Battery) have no
  image in home_v1's context map, so their ✉ opens the default team photo. Either
  they get their own image, or the default is accepted as correct for them.
- **The 4.9 / 173 figures and the office address** ride along from home_v1 and carry
  its open questions unchanged (hardcoded; address TBC after the November move).

### The live inner page, measured (2026-08-27) — reference, not a deliverable

Before the brief changed, the live page was measured with headless Chrome at a
1440px viewport (`getBoundingClientRect` + `getComputedStyle`, plus a pixel scan
of a full-page capture). Those numbers are what the old page actually does, and
they are worth keeping because every future inner-page decision is a departure
from them:

- Container **1280**; content **65% (832)**, gutter **5% (64)**, sidebar **30% (384)**.
- Top bar **52px** `#f3f3f3`; header band **43px** same grey; the logo (400×69) is
  pulled up with `margin-top:-50px` so it straddles both.
- Page header **252px** — `padding:100px 0`, the truck photograph `cover`, a flat
  **`rgba(0,0,0,.3)`** overlay, title Raleway 600 36px white, breadcrumbs absolute right.
- Article body **17px / 28px, `#3f3f3f`**; the `h2` is Raleway **700 26px `#000`**;
  the practice hexagon is a 50×65 SVG background, not a font icon.
- Sidebar nav rows are **38.16px** each (13 = 496px); the current row is solid
  `#46ADC8` with white text; sub-rows carry a `\f138` FontAwesome bullet at `#777`.
- Both forms give each field a **1px orange border** with a **1px `#e1e1e1`** input
  inside it (field 45px, input 43px, pitch 61px) and a 40px orange icon block at left.
- Contact strip **128px**, full-bleed, split 50/50 — **`#EF6136`** left (a redder
  orange than the brand `#EF6D3E`) and **`#423C37`** right.
- Footer bottom **125px** `#222`, text `#999`, links `#bbb`. Whole page **3260px**.

Two findings from that pass are worth carrying forward as rules:

1. **Google Fonts v1 vs css2 changes every line break.** The live site loads the v1
   CSS API, which serves the pre-2021 static Open Sans. `css2` serves the variable
   Open Sans, which is about 5% wider — the same 17px test string measures
   **584.02px** on v1 and **613.59px** on css2, and every paragraph in the article
   re-wraps. Any replica of the live site must use the v1 URL. (`home-replica-v3.html`
   uses css2 and therefore does not wrap like the live site.)
2. **Never retype body copy — extract it.** The live copy carries non-breaking
   spaces (`via email at info@leaguelaw.com.`, `critical.  The lawyers`).
   Retyping loses them, and a lost NBSP moves a line break. Copy is extracted from
   the crawl, never transcribed by eye.

**Lesson, same family as the D2/D4 scrim misses and the round-5 height arithmetic:**
a measurement taken from a *local copy* of a live page is not a measurement of the
live page. The saved copy rendered its footer contact strip inside the 1280
container while the live page renders it full-bleed, and its sidebar form sat 13px
higher — one stylesheet did not survive the save. The full-page capture of the real
URL is the ground truth; the local copy is only a convenience for reading computed
styles, and every number it gives has to be confirmed against the capture.

## Inner service page — the live replica, served (2026-08-27, zeina branch)

**Served:** <https://leaguelaw.demoing.info/wp-content/prototype/inner-service.html>
**Source of record:** `prototyping/inner-service-v2-live-replica.html` ·
generator `prototyping/gen_inner_replica.py`
**Replicates:** <https://www.leaguelaw.com/our-services/bc-injury-claims/car-accident-claims/>

Adi: *"update inner service menjadi replika old site."* The home_v1-style build
(previous section) is unchanged and parked in `prototyping/`; only which file is
served changed. `index.html` and `home_v1.html` untouched, as instructed.

This is the replica-first artefact the process asks for at step 4: the current
page recreated 1:1 in hand-written HTML, so the new design can be derived by
**diffing against it** instead of by memory.

### How faithful, in numbers

Every value came from the live page — headless Chrome at a 1440px viewport for
computed styles, plus a pixel scan of a full-page capture of the real URL for the
geometry. Structural band edges, live vs replica:

| edge | live | replica |
|---|---|---|
| header band ends | 96 | 95 |
| page header ends | 347 | 347 |
| contact strip starts | 1922 | 1921 |
| contact strip ends | 2050 | 2049 |
| footer bottom starts | 3135 | 3135 |
| page ends | 3260 | 3261 |

**Max drift: 1px, and the paragraph line breaks match line for line.** Element
geometry lands the same way — `.gfield` 45px with its 1px orange border, sidebar
nav rows 38.164px (13 = 496), the sidebar form card 752px, the footer form card
608px, the map 751×500 at x=609.

### The three things that made it exact

1. **Google Fonts v1, not css2.** The live site loads the v1 CSS API (pre-2021
   static Open Sans). `css2` serves the variable Open Sans, ~5% wider — the same
   17px test string measures **584.02px** on v1 and **613.59px** on css2, and every
   paragraph re-wraps. The replica uses the v1 URL and carries a comment saying so.
   (`home-replica-v3.html` uses css2 and therefore does NOT wrap like the live site
   — worth fixing there too if that replica is ever used for measurement.)
2. **The copy is extracted, never retyped.** The live copy carries non-breaking
   spaces — `via email at\u00a0info@leaguelaw.com.`, `critical.\u00a0 The lawyers`
   — and a lost NBSP moves a line break. The generator holds the article markup
   lifted from the crawl, with only URLs rewritten to this build's own
   `/wp-content/uploads/`.
3. **The ground truth is a capture of the real URL, not of a saved copy.** A saved
   copy of the page rendered its contact strip inside the 1280 container while the
   live page renders it full-bleed, and its sidebar form sat 13px higher — one
   stylesheet did not survive the save. The saved copy is only a convenience for
   reading computed styles; every number it gives is confirmed against the capture.

### Two live-site defects reproduced, not corrected

A replica that quietly fixes things stops being a measuring instrument.

- **The footer form's SEND MESSAGE button sits on top of the "Your information is
  kept safe." line** — the button is lifted 50px and covers the left 150px of that
  text. On the live site it reads `...afe.` The replica reproduces it exactly, with
  a comment.
- The page header's photograph is tinted with a flat `rgba(0,0,0,.3)`, which is
  what makes the truck read as dusk. Kept as-is.

### Known departures, all deliberate

- Images are served from **this build's own** `/wp-content/uploads/` — production
  is never hotlinked. All 16 referenced files were confirmed present.
- FontAwesome 4.7 stands in for the theme's `ticons` font (same glyph codepoints);
  the practice hexagon is a `clip-path` rather than the theme's `polygon.svg`.
- The forms are static and the "Back to Top" button (which only appears on scroll)
  is omitted.
- The Google My Maps iframe is the site's own public embed, kept for fidelity — the
  one external request the page makes beyond fonts and FontAwesome.



## Inner service hero — option round 1 (2026-08-27, zeina branch)

**Served:** <https://leaguelaw.demoing.info/wp-content/prototype/hero-inner.html>
**Source of record:** `prototyping/hero-inner-options-v1.html` · generator
`prototyping/gen_heroinner.py`
**Reference:** a competitor practice-area hero Adi supplied — three panels: a
colour block with the title, a photograph, and a contact block (phone, two
fields, two buttons). `index.html` untouched, per Adi's standing instruction
while inner-service work is in progress.

Adi's ask: hero options for the inner service page carrying what the reference
carries, **plus a breadcrumb**, **plus** the practice hexagon with its geometry
fixed — "icon pas ditengah dan hexagon tidak gepeng."

### The contract every option signs

Six options, one variable. Each carries exactly five parts, and the sheet
**checks it mechanically** rather than claiming it: breadcrumb · the `.hex`
practice hexagon · one `h1` · one photograph · a contact block of eyebrow,
phone, availability line, two fields, two buttons. All six pass.

### The hexagon: fixed as a ratio, not as a second number

A regular pointy-top hexagon has height 2R and width √3·R, so its box is
**always** `width / height = √3 / 2 = 0.8660254`.

| drawn | ratio | diagonal side vs vertical side |
|---|---|---|
| **50 × 65** — the live site | 0.769 | **−8.3%** |
| 95 × 110 — live, "Get in touch" | 0.864 | −0.2% |
| 11 × 13 — home_v1 kicker dot | 0.846 | −1.7% |
| 74 × 85 — home_v1 hive | 0.871 | +0.4% |
| **width + `aspect-ratio`** — these options | **0.8660** | **0.0%** |

The squash Adi saw is the live site's 50 × 65: at that ratio the four diagonal
sides come out 8.3% shorter than the two vertical ones. The fix is not a better
pair of numbers — it is **declaring the ratio and setting only a width**, so the
second number cannot drift again. Measured in the browser: all six hexagons come
out at 0.8661 (0.01% error) and the glyph centres to within **0.01px on both
axes**, with the live site's `margin-left:3px` nudge removed — on a pointy-top
hexagon the geometric centre already is the optical centre.

**This is worth carrying to the other files.** home_v1's `.hexpt` sizes are hand-
paired (11×13, 74×85, 16×18…) and each is 0.4–1.7% off. Nobody will see 1.7%,
but the mechanism that produced 8.3% is the same mechanism.

### Which brand colours can hold text — measured, and it decided every panel

| white on | ratio | usable for |
|---|---|---|
| brown `#423C37` | **10.86:1** | any size — the only brand colour safe everywhere |
| deep orange `#B44A33` | **5.29:1** | any size — but not a brand colour yet |
| brand orange `#EF6D3E` | **3.03:1** | large text only (≥24px, or ≥18.7px bold). Fails for body copy |
| teal `#46ADC8` | **2.60:1** | nothing — fails even the large-text floor |

This is why the reference's own arrangement works and why these options copy it:
**bright block for the title, dark block for the details.** A1 puts only the 38px
title and a 20px bold sub-line on brand orange (3.03 clears the 3:1 large-text
floor) and all the small contact copy on brown. A2 buys the ability to set the
deck at reading size inside the colour block by deepening the orange to
`#B44A33` — which is a **new brand colour**, so it is Adi's decision, not a detail.

**A finding that is not about this sheet:** home_v1's contact band already sets
its availability line and office note in `#FBE3D8` on brand orange — **2.47:1**.
That is in the picked homepage design and wants fixing there too.

### The six

| | what it is | hero height | left of a 607px first screen |
|---|---|---|---|
| **A1** | the reference mapped one-for-one; breadcrumb on a white strip above the band; the diagonal cut kept | 341px | 266px |
| **A2** | same three panels, breadcrumb as a slim brown bar flush under the header, deepened-orange title block | 324px | 283px |
| **A3** | one wide photograph, title card and contact card floating on it, picture visible between them | 360px | 247px |
| **A4** | no third panel — brown half carries breadcrumb/hexagon/title/deck/phone, photograph is the other half with a white contact card inset | 380px | 227px |
| **A5** | type on paper the way home_v1 opens, contact card across a hairline, photograph below as a full-bleed strip | **510px** | **97px** |
| **A6** | title centred on a full-bleed photograph, one contact ribbon straddling its bottom edge by 58px | 395px | 212px |

Notes worth keeping:

- **A3's cards are solid, not translucent.** A translucent card over a photograph
  is where contrast quietly stops being calculable — the number depends on what
  is behind it, which changes with every image.
- **A4 is the only option whose contact block sits on white**, so its small copy
  is at full contrast with no colour arithmetic at all. It is also the only one
  that gives the photograph half the band — worth seeing before the November
  shoot decides how good the pictures will be.
- **A5 is the calm one and the expensive one.** It is the only option that does
  not put a title over a picture, and the only one that carries the page's own
  lede sentence — and it costs almost the entire rest of the first screen.
- **A5's strip is a hard crop:** 1440 × 220 is 6.5:1 out of a 3:2 photograph.
  Nothing in the library survives it well. If A5 is picked, the November shoot
  needs a wide master for that slot — a brief for the photographer, not a CSS
  problem.
- **A6's ribbon is one row**, so it can hold two fields and two buttons *or* an
  availability line, not both.

### Open, and deliberately not decided here

- **Does Darren's ban on the intro image reach inner pages?** It is documented
  for the homepage first screen only. Five of the six put a photograph in the
  hero; **A5 is the option that does not need the question answered.**
- **The availability line.** All six use home_v1's approved "Free consultations
  for injury & estate litigation". A car-accident page would rather say it about
  car accidents — that is the firm's sentence to write, not the prototype's.
- The photograph is the same in every frame on purpose (the option is what
  varies, not the picture): League's own `passengerclaim.png`, the closest thing
  in the library to the reference's approach of showing the *person* rather than
  the wreckage. Monochrome, a placeholder until the November colour shoot, and
  labelled in every frame.

### The replica is not changed

`inner-service.html` stays the faithful 1:1 replica, squashed hexagon and all.
A replica that quietly fixes the thing it is supposed to be measuring stops being
a measuring instrument. The corrected hexagon lives in the new design, which is
where the correction belongs.

## Inner service hero — round 2: A1, revised (2026-08-30, zeina branch)

**Served:** <https://leaguelaw.demoing.info/wp-content/prototype/hero-inner.html>
**Round 1's six options, still served for comparison:**
<https://leaguelaw.demoing.info/wp-content/prototype/hero-inner-r1.html>
**Source of record:** `prototyping/hero-inner-v3-a1-panels.html` · generator
`prototyping/gen_heroinner_r2.py`
(v2 = `hero-inner-v2-a1-revised.html`, before the panel widths were re-cut)

Adi picked **A1** and asked for six changes, in two passes. `index.html`, `home_v1.html` and
`inner-service.html` all untouched, per the standing instruction.

The two rounds cannot share a page — both live in the `.a1` namespace and round
1's rules *are* what changed — so round 1 is served as its own file rather than
greyed underneath. The round 2 generator **lifts the shared CSS out of round 1's
generator at build time** (base, page-head, header stand-in, hexagon, breadcrumb,
title) and asserts the hexagon rule survived the lift, so the two rounds cannot
drift on anything that was not deliberately changed.

### The changes

| # | asked | done |
|---|---|---|
| 1 | `.tp` — the slanted `::after` is not needed, a straight line is enough | **Wedge removed.** It was a 38px clipped triangle that needed `z-index` to paint at all (the photograph follows it in the DOM), and it cut into the frame at head height. The orange panel now meets the photograph on a straight vertical edge. |
| 2 | `.in` — too full, no space above or below | It was **12px over**: the type measured 236px inside a 300px band that already spent 76px on padding, so the padding was eaten from both ends. Fixed **at the cause** — the band is `min-height`, not `height`, so type can never squeeze the padding out again — plus padding 38 → **48px** and the rules at 16px. Measured slack is now **24.17px**. |
| 3 | `.ph` — the photograph is too small, take the room from `.cp` | **330 × 300 → 420 × 380**: +27% wide, +27% tall, **+61% area**. The width came out of `.cp` and then out of `.tp` as well (change 5); the height out of the band. |
| 4 | `.cp` — carry the same content as `.call` in home_v1 | Lifted part for part: lead line · phone at display size · availability · two fields · the swarm button · the office note — centred, in that order. |
| 5 | `.tp` is too wide | **460 → 380**, a **336px** type column. The widest line the title actually sets is `CAR ACCIDENT` at **313.27px**, so 336 leaves 22.7px and the wrap is unchanged. The 80px went to the photograph (20) and to change 6 (60). |
| 6 | `.cp` needs a padding-left | **60px**, and it is load-bearing rather than decoration: the contact block's own left edge — and so the left input field — was sitting **flush against the photograph**. Only the centred text looked as though it had air. Measured gap now **60.00px** at every width. |

### The bug the measurement found

Round 1's `.tp` was `width:520px` with `padding-left:calc((100% − 1280px)/2)`.
The padding grows with the viewport but the width does not, so **the type column
shrank as the screen got wider** — 416px at 1380, **153px at 1920**, where the
title wrapped to four lines and pushed the band from 380 to 399px. This was in
round 1 and nobody would have caught it by eye at 1440.

Fixed by putting the gutter into the *width* as well as the padding, which turns
the panels into a model that closes on the container exactly:

```
   380  (type)  +  420  (photograph)  +  480  (contact)  =  1280
```

each still bleeding to its own edge of the screen on top of that. (The contact
panel's 480 is 60px of gap plus a 420px column.) Verified at 1380 / 1440 / 1600 /
1920: the type column holds at **336.00px**, the band at **380.00px**, the gap
between photograph and contact block at **60.00px**, and both the type's left
edge and the contact block's right edge land exactly on the container at every
width.

### Copying home_v1's `.call` onto brown — two forced changes, and one free fix

| part | home_v1 | here | why |
|---|---|---|---|
| the button | brown on orange, white label — 10.86:1 | **white, brown label** — 10.86:1, orange swarm kept | The panel is brown, so home_v1's brown button would be brown on brown. Filling it with brand orange instead puts a white **13px bold** label on **3.03:1** — under the 4.5:1 floor for text that size. Inverting keeps the exact ratio the button has on the homepage. |
| swarm particles | 9 × 10.5 — ratio 0.857 | **9 × 10.392** — ratio 0.8660 | Same arithmetic as the big hexagon: 9 / 0.8660254 = 10.392. home_v1's pair is 1.0% off — small, but it is the same mechanism that produced the 8.3% squash Adi asked to fix. |
| availability + office note | `#FBE3D8` on orange — **2.47:1** | `#FBE3D8` on brown — **8.84:1** | Nothing changed but the ground under it. **This does not fix the homepage** — home_v1's contact band still sets those two lines at 2.47:1 and still wants fixing there. |

The phone stays at home_v1's **54px**. It measures **381.63px** of the 420px
column — 18.2px of air each side. That measurement is the floor under the whole
panel model: the call column cannot go below about 390 without the number itself
having to shrink, which is what fixes `.cp`'s content box at 480 (60 + 420) and
therefore what `.tp` and `.ph` had left to share.

### What it costs on the first screen

Measured below the 93px header; a 700px viewport has 607px to give away.

| | breadcrumb strip | band | hero total | left for the page |
|---|---|---|---|---|
| round 1 | 41px | 300px | 341px | 266px |
| **round 2** | 41px | **380px** | **421px** | **186px** |

The bigger photograph and home_v1's contact block are paid for out of the same
80px, and re-cutting the panel widths (changes 5–6) did not move this at all —
it is entirely a horizontal change. If 186px is too little, the phone comes down
from 54px and the band with it — one number.

### Still open (carried, not decided)

- **Does Darren's ban on the intro image reach inner pages?** Documented for the
  homepage first screen only. A1 puts a photograph in the hero.
- **The availability line** is still home_v1's approved "Free consultations for
  injury & estate litigation" — a car-accident page would rather say it about car
  accidents, and that is the firm's sentence to write.
- **The office note** came across with the rest of `.call`, and it carries the
  same open question it carries on the homepage: *which number* does a six-office
  firm show.
- The photograph is still `passengerclaim.png` — monochrome, labelled a
  placeholder in the frame, until the November colour shoot.

## Inner service page — A1 folded in as the hero (2026-08-30, zeina branch)

**Served:** <https://leaguelaw.demoing.info/wp-content/prototype/inner-service.html>
**Source of record:** `prototyping/inner-service-v5-replica-hero-a1.html` · generator
`prototyping/gen_inner_replica_hero.py`
**The pure replica, still served untouched:**
<https://leaguelaw.demoing.info/wp-content/prototype/inner-service-replica.html>

Adi: *"gunakan A1 sebagai hero di inner service"* — then, correcting me:
*"saya hanya meminta kamu mengganti hero nya saja, section dibawahnya tidak
perlu kamu ganti, tetap gunakan replika terlebih dahulu."*

### The wrong turn, recorded because the reasoning was wrong, not just the output

My first build put A1 on the **home_v1-style** inner page and replaced the whole
page. The argument was that A1 is drawn in home_v1's vocabulary and would look
like a chimera on the replica. That argument was about **consistency**, and
consistency was not the job. **The replica is the measuring instrument**, and
this rebuild proceeds by replacing one part at a time and diffing against what
is still there. Swapping the whole body throws away the comparison for every
part that has not been designed yet.

That build is parked, not deleted: `prototyping/inner-service-v4-hero-a1.html`,
generator `prototyping/gen_inner_v2.py`. It is where this page goes once the
other parts are picked too.

### What actually shipped

The replica, with **one section replaced**. Proven mechanically, not claimed:
everything from `<!-- 4 · content + sidebar -->` to the end of the document is
**byte-identical** to `prototyping/inner-service-v2-live-replica.html`. Above the
hero, exactly six lines differ — the `<title>`, the font `<link>`, and the four
comment lines explaining it.

| | |
|---|---|
| out | `.phead` — the 252px background photograph under a flat `rgba(0,0,0,.3)` wash, h1 left, breadcrumb right — and its now-dead `.crumbs` rules |
| in | A1: breadcrumb strip, orange title panel, photograph, brown contact panel |
| unchanged | the article, the sidebar nav, both forms, the contact strip, GET IN TOUCH, the map, the footer |

The hero measures **identically** to the option sheet: hero 421.00, breadcrumb
strip 41.00, band 380.00, type column 336.00, photograph 420 × 380, gap 60.00,
contact block 255.09, hexagon ratio 0.8661, glyph centred to 0.00 / −0.01px.

### Two hero class names had to move out of the replica's way

`.a1` is re-scoped to `.shero`, but scoping only stops the hero leaking **out**.
The replica leaks **in**: `.crumbs{position:absolute;right:0;top:10px;color:#fff}`
and `.lead{padding:10px 0 40px}` would both have reached inside the hero.

- `.crumbs` — **cut**, along with the rest of the `.phead` block. Those rules
  died the moment the banner did.
- `.lead` — **renamed** to `.shlead` in the hero only. The article's own `.lead`
  keeps its padding (verified: `10px 0px 40px`).
- `.wrap` — **renamed the other way**, to the replica's `.container`. The sheet
  and the replica call the same 1280px centring box by different names; renaming
  into the replica's means the hero sits on the replica's grid *by construction*
  rather than by a second declaration that could disagree with it.

The build **works this out rather than trusting the list**: it intersects the two
stylesheets and fails, naming the selector, if any replica rule's classes are all
hero classes. `RENAME` and `SHARED` are the answers; the check is the question.

### The hero was 11px taller here than on the sheet — fixed at the source

The replica sets `body{line-height:23.1px}` (the live site's own). That inherited
into the hero's breadcrumb and its three small contact lines, growing the hero
from 421 to 432px. **A picked hero must not change height because of the page it
lands on.**

Fixed in the option sheet's generators, not patched on this page, so all three
consumers get it: `line-height` is now *declared* on `.crumbs` (12px),
`.call .lead` (19px), `.call .avail` (18px) and `.call .officenote` (17px) —
exactly the values `normal` was already rendering on the sheet, so the sheet
itself did not move a pixel. `hero-inner.html` and `hero-inner-r1.html` rebuilt.

The form fields and the button were never affected: form controls do not inherit
`line-height`, which is why they measured 42.00 and 39.00 on both pages all along.

### One addition to the font request, and why it is safe

The v1 CSS API URL gained **Raleway 800** — the hero's phone number needs it. The
**Open Sans half is byte-identical** and asserted at build, because that is what
makes the replica wrap like the live page. No text below the hero uses Raleway
800, so nothing re-measures.

### Left alone on purpose

- **The article still opens with the live page's own contact line** — teal
  hexagon, the h2, and "Contact us today for a consultation · (250) 888-0002" —
  which now says the phone number twice within 200px of the hero. That is the
  replica's content and Adi's instruction was to leave it; it is a **decision for
  the next part**, not a bug in this one.
- **The article hexagon is still the live 50 × 65** (ratio 0.7692, the squash).
  The corrected hexagon exists only inside the hero. Fixing it in the article
  would mean editing the part that is still the measuring instrument.
- `index.html` and `home_v1.html` untouched.

## Inner service — the consultation tab, and sidebar options (2026-08-30, zeina branch)

**Sidebar options:** <https://leaguelaw.demoing.info/wp-content/prototype/sidebar-inner.html>
**The tab is live on the page:** <https://leaguelaw.demoing.info/wp-content/prototype/inner-service.html>
**Source of record:** `prototyping/sidebar-inner-options-v1.html` · generator
`prototyping/gen_sidebar.py` · page `prototyping/inner-service-v6-ctatab.html`

Adi asked two things in one sentence, and the second answers the first: *"buatkan
opsi tampilan untuk sidebar … menurutmu apakah tetap perlu ada form? karena di
bagian hero sudah ada form dan … sudah ada ctatab."*

### The tab, lifted whole

`.ctatab` came across from home_v1 **with the modal it opens** — a tab that opens
nothing is a decoration, and the whole sidebar argument depends on it actually
working. CSS, markup and the driving script are all lifted at build time and
re-scoped to `.sconsult`. Verified in the browser: clicking the tab sets
`body.consult-open`, shows a 780 × 573 card with four fields, and stamps `#cta`.

The rescoper needed two things it had not needed for the hero:

1. **`@media` blocks.** The modal carries a `prefers-reduced-motion` block. The
   at-rule has to stay at the top level while its *contents* get scoped.
2. **Body-state selectors.** `body.consult-open .cmodal` must keep `body` first;
   blindly prefixing gives `.sconsult body…`, which matches nothing and would
   have left the modal permanently invisible with no error anywhere.

Three replica rules reached inside the modal — `.topbar`, `.safe`, `.safe .fa` —
and were renamed in the modal's subtree only. Verified: the modal's bar is 10px
orange, the page's own top bar is still 52px grey, the sidebar form's `.safe` is
still 11px.

**The replica below the hero is still byte-identical** (9,635 characters,
asserted at build). The tab and modal are appended after the footer.

### Does the sidebar still need a form? No — and it is a count, not an opinion

Every way the page currently asks to be contacted:

| where | what it asks for |
|---|---|
| hero contact panel | phone at display size + **2 fields** + Call Me Back |
| article, opening line | "Contact us today for a consultation" + the number |
| article, closing line | "may be contacted by phone … or via email" |
| **sidebar form** | **4 fields** + Send Message |
| contact strip, full width | phone + email |
| Get in touch | "Please contact us for more information" |
| footer form | **4 fields** + Send Message |
| footer bottom | phone, fax, email, address |
| **consultation tab** (new) | always on screen → modal with **4 fields** |

Nine places. **14 input fields. The phone number 11 times.** Four submit buttons.

- **The sidebar form is not one of several — it is a literal duplicate of the
  footer form.** Same four fields, same "*" legend, same "Your information is kept
  safe", same SEND MESSAGE. The page ships one component twice.
- **The tab does its job better.** A sidebar form is on screen for part of the
  scroll; the tab is on screen for all of it and opens the same four fields.
- **Three forms is three definitions of "enough"** — two fields in the hero, four
  in the sidebar and footer. That is a decision pushed onto the reader.
- **The sidebar has a job nothing else can do:** it is the only route to the other
  twelve injury claims. The form pushes that list up and competes with it.

### The five

Shown in real geometry — `832 + 64 + 384 = 1280` — with the real article copy at
real size beside each one, because a 384px column only means something next to
the 832 it has to hold its own against. The tab is drawn on every frame.

| | what it is | sidebar height | of the 1,534px column | fields |
|---|---|---|---|---|
| **S1** | navigation, then one card: phone + Book Consultation (opens the tab's modal) | 855px | 679px left empty | **0** |
| **S2** | navigation, then *who takes the case* — the five injury lawyers as faces | 980px | 554px left empty | **0** |
| **S3** | navigation, then one field: a phone number and nothing else | 758px | 776px left empty | **1** |
| **S4** | navigation, then the form exactly as it is, redrawn | 1107px | 427px left empty | **4** |
| **S5** | navigation only, **sticky** | 611px | follows the reader instead | **0** |

- **Recommendation: S1.** A card keeps a *visible* call to action in the column —
  the tab is on the screen edge and easy to read past — without asking for four
  fields the page already asks for twice.
- **If a form has to stay: S3.** One field is a *different offer*, not the same
  offer a third time, and it matches the hero's own Call Me Back promise.
- **S2 is the only option that puts something in the sidebar that exists nowhere
  else on the page.** "Who would I be dealing with" is a real question on a claims
  page and nothing on this page answers it.
- **S4 is kept so the cost is visible rather than argued.**
- **S5 is the only option that uses the column's real length.** In every other
  option the bottom two-thirds of the sidebar is empty space that scrolls past.

### Not decided here

- **Whether the footer form stays either.** If the sidebar form goes because the
  tab does its job, the same argument reaches the footer form. Worth deciding
  once, for both.
- **The article still opens with its own contact line** — teal hexagon, then
  "Contact us today for a consultation · (250) 888-0002" — about 200px under a
  hero that has just given the same number at 54px. That is the article's part,
  and it is still the replica.

## Sidebar navigation — options (2026-08-30, zeina branch)

**Served:** <https://leaguelaw.demoing.info/wp-content/prototype/sidebar-nav.html>
**Source of record:** `prototyping/sidebar-nav-options-v1.html` · generator
`prototyping/gen_sidebarnav.py`

Adi, deciding the previous sheet and asking the next question in one sentence:
*"bisakah sidebar hanya bagian navigation seperti Injury claims nya saja.. namun
dibuat sticky scroll. kemudian buat beberapa opsi tampilan untuk sidebar
navigation nya tersebut."*

**Settled, and not re-opened by this sheet:** the sidebar is the thirteen sibling
injury claims and nothing else, and it sticks. No option has a form.

### Sticky turns a styling question into a measuring one

A sticky block taller than the viewport has a bottom the reader can never reach —
it stops scrolling with the page and the last claims sit permanently below the
screen edge. So the number that decides these options is how tall they are.

**The budget is the viewport minus `top`, not the viewport minus the header** —
once the block has stuck, the header has already scrolled away. At `top:24px`
that is **676px** on a 700px viewport and **744px** on a 768px one.

| | what it is | height | spare at 700px |
|---|---|---|---|
| **N2** | compact — hairlines dropped, type a step down, padding halved | **425px** | 251px |
| **N4** | solid brown panel, type reversed out | **508px** | 168px |
| **N3** | grouped into three named sets | **546px** | 130px |
| **N1** | hairline rows — the baseline, S5 plus a parent link | **562px** | 114px |
| **N5** | the live site's own shape, corrected | **580px** | 96px |

All five fit, so the headroom is what to read, not the pass mark. **That margin is
what a sticky header would eat first** — if the header is ever made sticky, `top`
becomes its height plus 24 and every option loses exactly that much.

If a future option does not fit, the fix is one rule —
`max-height:calc(100vh - 48px); overflow-y:auto` on the sticky block, so the list
scrolls inside itself instead of hiding its own tail. It costs a scrollbar inside
a sidebar, which is why it is a fallback and not the default.

### A way back up — all five have one, none of the earlier options did

N1–N4 carry an explicit **"All injury claims"** link at the top; N5 carries the
parent as its own row, the way the live site does. Without one of the two there is
no route from an inner claim back to the category it belongs to: the breadcrumb
has one, but the breadcrumb scrolls away and a sticky sidebar does not.

### Orange marks, brown reads — a rule this sheet had to learn on itself

The first build of these options set the current claim in brand orange, the group
headings in teal and the parent link in `#8D867E`. Measured afterwards:

| | ratio | verdict |
|---|---|---|
| current row — orange on white, 13px bold | **3.03:1** | fails 4.5:1 |
| N5 current row — orange on `#FBF6F1` | **2.82:1** | worse |
| N3 group heading — teal on white, 10.5px | **2.60:1** | the worst number on the sheet |
| parent link — `#8D867E` on white, 11.5px | **3.59:1** | fails |

Three failures of exactly the kind this project keeps flagging in other people's
work. Fixed by making the rule explicit rather than patching the three:

> **Orange is a mark, not a voice.** Brand orange on white is 3.03:1 — enough for a
> non-text indicator (3:1), not enough for type (4.5:1). So the current claim is
> carried by its **orange hexagon plus weight**, and the words are brown
> (**10.86:1**). Teal is off the type entirely. The parent link is `#6B6B6B`
> (**5.33:1**).

This is the same rule the hero already follows — orange block for the 38px title,
brown block for everything at reading size. It is now a rule rather than a
coincidence.

The parent link's own hexagon is **grey**, not orange, for the same reason: on this
sheet orange means "you are here", and the parent row is the one row that is
explicitly not here.

### N4's numbers, since it is the only option on a dark ground

`#D8D4CF` rows on brown **7.37:1** · current row white on brown **10.86:1** ·
"All injury claims" `#B7AFA6` on brown **5.02:1**. All three clear 4.5:1.

### N5 could not reproduce one thing from the live site

The live sidebar fills the current row with a **solid teal bar and white text** —
**2.60:1**, below even the 3:1 large-text floor. There is no version of that bar
that passes. The current row is marked instead by an orange left rule and a pale
ground with the words in brown (10.12:1).

### Open — the firm's, not the prototype's

- **N3's grouping is a proposal.** "Vehicle & travel / property & premises / other"
  is derived from the thirteen claim names alone. Whether that is how the firm
  thinks about its own injury work — and whether Boat Accidents belongs with
  vehicles — is theirs to confirm. N3 is the only option that makes the list *mean*
  something rather than just fit, so the grouping is worth the conversation.
- **Whether the order is meaningful.** All five keep the live site's order. If it is
  accidental rather than by volume or importance, a sticky sidebar is the place
  that shows it up.

### Round 2 — five more, in a more contemporary idiom

Adi: *"tambahkan beberapa opsi lagi tampilan modern."* Same sheet, second round,
so all ten compare on one page. "Modern" is not a mood here — each of the five
does something **structural** the first five do not, and all five obey the rules
round 1 established: sticky, no form, orange marks / brown reads, hexagons on
ratio, a way back up.

| | what it is | height | spare at 700px |
|---|---|---|---|
| **N9** | disclosure by group — only the current group open | **385px** | 291px |
| **N6** | connecting rail — a hairline down the left, a node per claim | **464px** | 212px |
| **N8** | ordinal index — 01…13 in tabular figures | **503px** | 173px |
| **N10** | filter field above the list, count updates live | **514px** | 162px |
| **N7** | soft rows — rounded hit-areas, no rules, no bullets | **529px** | 147px |

Against round 1: N2 425 · N4 508 · N3 546 · N1 562 · N5 580. **All ten fit 676px.**

- **N6's rail is a connector, not a progress bar.** Nothing above the current node
  is coloured in, because these thirteen are **siblings, not steps**. Colouring
  the run would tell a reader they are part-way through a sequence that does not
  exist — an easy and completely silent lie.
- **N7 is the quietest at rest and the most responsive in use** — the whole row is
  the target, not the words. Tint `#FBEFE8` carries brown at **9.63:1**, the hover
  tint at **8.48:1**. The rows are pulled 12px into the gutter so the fill aligns
  with the column edge instead of floating inside it.
- **N8's numerals say how many there are** and how far down any one sits, which
  nothing else on a thirteen-item list does. The current row **swaps its numeral
  for the hexagon** — the mark says *here*, the numeral says *which of thirteen* —
  so "current" is still never carried by orange type. Numerals are `#6B6B6B`,
  **5.33:1**: they are text, so they get a text ratio.
- **N9 is the shortest thing that still reaches all thirteen, and the only option
  whose height does not grow when the firm adds a fourteenth claim.** The cost is a
  click between the reader and eleven of the thirteen links, on a sidebar whose
  whole job is lateral movement. It inherits N3's open question about the grouping.
  Opening one group does not close the others.
- **N10 solves a problem the page does not have yet.** Thirteen items are
  scannable; a filter earns its place at thirty. It is on the sheet because it is
  the answer if the list keeps growing, and because the cost is worth seeing: it
  puts an input back into a sidebar we just cleared of inputs, and a reader who
  sees a field in a sidebar has to work out that this one does not send anything.
  Its placeholder is `#6B6B6B` (**5.33:1**) — placeholder text is text.

The filter matches **anywhere** in the name, not just the start: typing `cyc`
returns Cyclist Accident Claims *and* Motorcycle Accident Claims, which is right —
someone looking for "cyclist" and someone typing "accident" are both correct.

### Round 3 — N5 without the hexagon

Adi: *"N5 juga saya suka namun buat tanpa hexagon."*

**N5 uses the hexagon in exactly one place** — the bullet on each claim row. It is
**not** what marks the current claim: that is the orange left rule, the pale
ground and the brown bold type, none of which involve a hexagon. So taking it out
costs nothing structural. It just leaves a slot, and something has to decide what
lives there — which is the actual question, and why this is three frames and not
one.

| | the mark | height | spare at 700px |
|---|---|---|---|
| **N5·a** | nothing — the slot is left empty | 580px | 96px |
| **N5·b** | a chevron `›`, grey → orange, nudging right on hover | 580px | 96px |
| **N5·c** | a 10px rule that grows to 14px and turns orange | 580px | 96px |

**Removing the bullet does not change the height.** All three are 580px, exactly
N5's — the bullet sat inside the row's own line box, so it was never paying for
any of it.

- **N5·a is the honest reading:** take it out and put nothing back. *Nothing is
  lost* — the hairlines already separate the rows, so the bullet was a third thing
  doing a job two things were already doing. It is also the only one of the three
  with no decoration to explain.
- **N5·b is the closest thing to "the live shape" that is not a hexagon.** The
  live sidebar already puts a chevron on its parent row, so the mark is the site's
  own, moved down a level. It is the only one of the three that says *this goes
  somewhere* rather than just *this is an item* — worth something on a list whose
  entire job is lateral movement.
- **N5·c is the mark with no vocabulary of its own** — neither a brand shape nor a
  direction. Useful if the hexagon is going *because the page already has enough
  shapes in it*, since a rule adds none. Its growth on hover is doing work the
  colour change alone would not.

All three keep N5's "Navigation" title and its parent row, and all three inherit
N5's one correction to the live site: the current row is never a solid teal bar
(2.60:1) — it is an orange left rule (3.03:1, a non-text indicator needing only
3:1) on a pale ground with the words in brown (10.12:1).

### The parent row was an affordance that lied — and is now a control

Adi: *"apakah bagian 'Injury Claims' di N5·a dropdownnya berfungsi?"*

**No.** It carried a chevron and did nothing — a `<div>`, not a control, and no
script ever looked at it. It came across from the live site's shape, where the
chevron presumably means something; here it meant nothing.

A mark that promises an action has to perform one. There were exactly two honest
resolutions — take the chevron off and let the row be a label, or make it work —
and the second is the one the chevron was already claiming:

- The row is a **`<button>`** that collapses the thirteen claims.
- **`aria-expanded`** tracks the state; the chevron turns over.
- Verified by clicking it: list `block → none → block`, sidebar **582 → 88 →
  582px**, `aria-expanded` `true → false → true`, and the other three N5 variants
  stay open — they are independent, not ganged.

**Collapsed, all four drop to 88px** — the title and the parent row alone. That is
the cheapest the sidebar can be while still offering a way back into the thirteen.

### "Injury Claims" — uppercase and greyer

Adi's second ask, applied to N5 as well as N5·a/b/c so the four stay comparable:

- **Uppercase comes from `text-transform`, not from retyping the words.** The
  markup still reads `Injury Claims`; asserted at build (`>Injury Claims` appears
  four times, `INJURY CLAIMS<` never). Capitals baked into copy are a copy change,
  and copy is the firm's.
- **`#6B6B6B` — 5.33:1**, so it still clears 4.5:1 at 12px bold. Greyer without
  going under the floor. The chevron itself is `#8D867E`; it is a mark next to a
  word that already says what it is, so it is decoration and takes no ratio.
- **`letter-spacing:.12em`**, because caps set at body tracking close up and stop
  being scannable. The row also went 13px → 12px: a label should be smaller than
  the things it labels.

The row heights moved 580 → **582px** with the new padding, and the table on the
sheet was re-measured rather than left to drift.

### The sheet said sticky and was not — two silent killers (found 2026-08-30)

Adi picked **N1** and asked the right question: *"namun apakah itu sticky
scroll?"* The honest answer at that moment was **no** — the declaration was
there, the behaviour was not, and nothing anywhere reported it.

Measured while scrolling, before the fix:

```
before it sticks : sidebar top in viewport = 240.4   article top =  289.4
just after       : sidebar top in viewport = -59.6   article top =  -10.6
300px further    : sidebar top in viewport = -359.6  article top = -310.6
```

The sidebar moved 1:1 with the article. Two causes, both invisible in a
screenshot and neither producing an error:

1. **`.stage { overflow:hidden }`**, inherited from the option-sheet chrome that
   every one of these sheets lifts. **Any ancestor with a non-visible overflow
   becomes the sticky element's scrolling box.** That box never scrolls, so the
   element never sticks.
2. **`align-items:flex-start` on the row.** It shrank the rail to its own
   content, so the sticky block exactly filled its containing block and had **no
   room to travel**. Stuck from the first pixel looks exactly like not sticky.

After the fix (`.stage{overflow:visible}` and letting the row stretch):

```
just after       : sidebar top in viewport = 24.0    article top =  -10.6
300px further    : sidebar top in viewport = 24.0    article top = -310.6
600px further    : sidebar top in viewport = 24.0    article top = -610.6
near frame end   : sidebar top in viewport = -307.6  article top = -1020.6
```

Pinned at exactly `top:24px` through 600px of article travel, then released when
the rail runs out — which is correct sticky behaviour, not a failure.

**The real page can do it.** Checked on `inner-service.html`: no ancestor of
`.sidebar` sets `overflow`, and none sets `transform`, `filter`, `perspective` or
`contain` (each of those also silently disables sticky). `.cwrap{display:flex}`
stretches by default, so the sidebar column is already as tall as the article and
the block will have somewhere to travel.

**The lesson is a checklist, not a war story.** Before declaring `position:sticky`
anywhere, check every ancestor for: a non-visible `overflow`; `transform`,
`filter`, `perspective` or `contain`; and a containing block no taller than the
sticky element itself. Then *measure it while scrolling* — a screenshot cannot
tell a sticky element from a stationary one.

### N5·a is in — `inner-service.html`, 2026-08-30

Adi: *"oke pakai N5·a, pasang ke inner-service."*

**Served:** <https://leaguelaw.demoing.info/wp-content/prototype/inner-service.html>
**Source of record:** `prototyping/inner-service-v7-sidebar-n5a.html`

Two things came out of the sidebar and one went in:

| | |
|---|---|
| out | the navigation widget (`.wtitle`, `.snav`, the teal current-item bar) and the **four-field form** |
| in | N5·a — thirteen claims, a working parent row, sticky, no marks, no form |

**Lifted, not written.** The markup comes out of the option sheet's own builder
(`n5x("n5a")` is executed) and the CSS out of its stylesheet, both at build time,
so the page and the sheet cannot drift. The build asserts the picked variant
arrived and the unpicked ones did not: `.n5b`/`.n5c` absent, `.n5a` present, and
**no `clip-path` anywhere** — N5·a is the no-hexagon variant, and a hexagon
sneaking back in with it would be silent.

**No re-scoping was needed, and that was checked rather than assumed.** N5·a's
class names collide with exactly one thing the replica had — `.wtitle` — and that
rule was dead the moment the widget went, so it was cut rather than renamed.

**What was cut, and what was deliberately kept.** The `.snav*` block and the
`.sform*` rules are gone. `.fcard`, `.gf`, `.legend`, `.safe` and `.sendbtn`
**stay**, because the footer form still uses every one of them — cutting the whole
form block would have taken the footer's form down with it, silently, since
nothing on the page would have errored.

**Measured on the real page, not on the sheet:**

| | |
|---|---|
| sidebar column | 384px wide, **1534px** tall — stretched to the article, so the block has 950px of travel |
| the sticky block | **582px**, `position:sticky`, `top:24px` |
| does it stick | **yes** — block top pinned at **24.0** at two scroll positions 400px apart |
| collapse | 582 → **88px** → 582, `aria-expanded` `true → false → true` |
| fields in the sidebar | **0** |
| hexagons in the sidebar | **0** (walked every element's `::before` and `::after`) |

**And everything else is still where it was:** the footer form still has its four
fields, the article's `.lead` still has `10px 0px 40px`, the article hexagon is
still the live 50 × 65 (the replica's, deliberately uncorrected), the hero band is
still 380, the consultation tab is still there, and the article markup between the
hero and the sidebar is **byte-identical** to the replica.

### `.lead` removed (2026-08-30)

Adi: *"hilangkan bagian ini class='lead' di inner service."* Done — markup and its
now-dead CSS. **Source of record:** `prototyping/inner-service-v8-no-lead.html`.

The block carried **four** things, not one, so it is worth writing down what left
with it:

| | |
|---|---|
| the third printing of the phone number | **this is why it went.** "Contact us today for a consultation · (250) 888-0002" sat ~200px under a hero that had just set the same number at 54px |
| the live site's squashed teal hexagon | 50 × 65, ratio 0.7692 — **the worst one on the page, and now gone**. What is left in the replica is the "Get in touch" hexagon at 95 × 110 (0.8636, −0.2% off), which nobody will ever see as wrong |
| the page's **h2** | "League & Williams are Experienced Car Accident Injury Claims Lawyers" |
| the page's **lede** | "Our team of lawyers are experienced in car accident injury claims & work to ensure that injured victims recover their fullest potential. Free consultations." |

**The last two are a real loss and they are flagged, not hidden.** The page now has
its `h1` in the hero and **no `h2` of its own** — the article opens straight on
"Being involved in a car accident can be scary…". For a service page whose h2
carried the practice-area phrase, that is a structural change, not just a visual
one. Restoring them is one line: the same `.slead` block already written for the
home_v1-style build (`gen_inner_v2.py`) puts the h2 and lede on white above the
prose, which is where they belong — they cannot go in the hero, because that
panel is brand orange and white on brand orange is 3.03:1.

Measured after: phone printings **11 → 9**, article column **1534 → 1272px** (the
sidebar block is 582, so it still has 690px of travel and stays sticky). Sidebar,
hero, consultation tab, footer form and the shared form chrome all unchanged.

### home_v1's footer replaces five replica sections, and the photograph gets its size back (2026-08-30)

Adi: *"bagian class='cstrip' sampai footer ganti menjadi seperti footer
home_v1.html, lalu cari tempat yang sesuai untuk menampilkan img
class='wp-block-image' yang saat ini menurut saya terlalu kecil."*
**Source of record:** `prototyping/inner-service-v9-home_v1-footer.html`.

#### The footer

Out: the contact strip, Get in touch, the socials row, the footer form + map,
and the footer bottom bar. In: home_v1's `.nfoot` — orange CTA band, four
columns, the decorative hexagons, the bar. **Lifted whole at build time**, and
the markup is home_v1's *verbatim* (asserted against `home_v1.html` itself; the
only difference is the rename below).

- **`.wrap` → `.container`** in both the lifted CSS and the lifted markup. The
  homepage and the replica call the same 1280px box by different names; renaming
  into the replica's means the footer sits on the page's own grid by
  construction rather than by a second declaration. Measured: footer container
  1280, page container 1280.
- **`.hexpt` and `.swarmbtn` were bare utilities in home_v1** and are scoped to
  `.nfoot` here, since the footer is the only thing on this page that wants them.
  The build asserts every lifted rule starts with `.nfoot`. Proof it holds: the
  footer's button is home_v1's brown-on-orange while the hero's is still white.
- **Cutting those five sections killed the last user of the shared form chrome.**
  `.fcard`, `.gf`, `.legend`, `.safe` and `.sendbtn` were kept alive earlier
  *only* because the footer form still used them; the sidebar form went first,
  the footer form goes now, so the block goes too. The build asserts none of
  them survives.

The page now has **no `<form>` of its own at all** — every contact route is the
hero's two fields, the CTA band's Book Consultation, or the consultation tab's
modal. That is the end state the sidebar sheet argued for, arrived at one
section at a time.

#### The photograph

`wp-block-image` was floated right at **256 × 192** out of a **1024 × 768**
original — 6% of the column, small enough that the damage in it could not be
read.

- **Now 832 × 468** — the full column at 16:9. **3.25× wider, 7.9× the area.**
- **Its place in the reading order is unchanged.** It still sits between the Tort
  claim and Part 7, which is the hinge of the article — the point where the copy
  stops explaining one kind of claim and starts on the other. It was already
  there; it was just floated into a corner of it.
- **The crop is by height**, so the people at the top and the road at the bottom
  go and the car keeps the frame (`object-position:50% 45%`).
- The caption is set at a **64ch measure**, not the full 832 — a caption running
  the width of the column is a caption nobody finishes.

The article column grew 1272 → 1760px, which the sticky sidebar does not mind:
its block is 582, so it has 1178px of travel now instead of 690.

### The lifted footer was not yet home_v1's footer — two things were missing (2026-08-30)

Adi: *"gunakan footer seperti di … home_v1.html."* It was already lifted, so the
right response was to find out **what was actually different** rather than to say
so. Measured on both real pages at the same viewport, the same ten boxes:

| | home_v1 | inner-service | |
|---|---|---|---|
| `.nfoot` | 479 | **523** | +44 |
| `.cols` | 346 | **384** | +38 |
| `.fcontact` | 250 | **288** | +38 |
| `.fmenu` | 17 | **23** | +6 |
| `.fbar` | 50 | **56** | +6 |

**Cause 1 — the base line-height, again.** home_v1's `body` declares no
line-height, so its footer inherits `normal`; this page's body declares the live
site's **23.1px**. Every footer line grew. `.fmenu` going 17 → 23 is one line
doing exactly that.

Fixed with **one rule** rather than by declaring line-height on twenty selectors:
`.nfoot{line-height:normal}` restores the ground the footer was designed on. The
four rules inside it that set their own line-height still win.

**Cause 2 — not every footer rule lives in the footer block.**
`.nfoot .fc { display:none }` sits ~320 lines earlier in home_v1's stylesheet,
under a cross-cutting decision: *"HEXAGON-LIGHT (Adi 2026-08-27): home_v1 drops
the big hexagon styling — header watermark hive, mega-menu corner hives, **footer
hive**, hex social buttons."* Lifting the block alone brought the hive back and
made this footer differ from the homepage's by **72,767 pixels**.

The fix is not "also copy that line" — it is a **sweep**: the build now reads
home_v1's whole stylesheet, collects every `.nfoot` rule as a
`(selector, declarations)` **pair**, and brings across any that the block did not
contain. Pairs, not selector substrings: `.nfoot .fc` appears in the block too,
with different declarations, so a substring test would have found nothing wrong.

**Parity now, asserted at build:** every one of home_v1's 46 `.nfoot` rules is on
this page (modulo the deliberate `.wrap` → `.container` rename), the markup is
home_v1's verbatim, and all ten measured boxes match exactly — 479 / 83 / 346 /
50 / 68 / 17 / 250 / 46 / 36 / 48. This page adds ten rules on top and each has a
reason: the line-height reset, and home_v1's bare `.hexpt` and `.swarmbtn`
utilities scoped to `.nfoot` because the footer is the only thing here that wants
them.

**One thing this page fixes that home_v1 has not:** the footer's "Back to top ↑"
points at `#top`, and **home_v1 has no `#top` anchor** — the link is dead there.
This page now carries `<span id="top">`. Worth fixing on the homepage too.

**A note on the pixel diff, since it was the wrong instrument here.** Comparing
screenshots of the two pages kept surfacing differences that were not the
footer's: home_v1's own fixed *fold-ruler* button (a labelled measurement
instrument) sitting over its footer in a tall capture, and the two pages'
different body colours showing beyond the footer's last row. Isolating the footer
into an empty document made it worse, because home_v1's own scripts run on the
same `load` event. The box measurements — same viewport, same script, both real
pages, no surgery — were the sound comparison all along.

### home_v1's header replaces the replica's (2026-08-30)

Adi: *"samakan header seperti di … home_v1.html."* Out: the replica's two bands —
the 52px top bar and the 43px nav band with the logo hanging out of it. In:
`.nheader`, mega menus and all. **Source of record:**
`prototyping/inner-service-v11-home_v1-header.html`.

**Swept, not cut** — the footer taught this lesson and the header needed it
immediately. Two of the header's rules (`.nheader .combclip{display:none}` and
`.mega .mhex{display:none}`) live ~320 lines from the header block under the
HEXAGON-LIGHT decision. So the build reads home_v1's whole stylesheet and keeps
every rule rooted at one of the header's four roots — `.nheader`, `.mega`, `.mi`,
`.hexpt` — in source order, `@media` wrappers included. `.mega`, `.mi` and
`.hexpt` all live inside `.nheader` in the markup, so they are scoped to it.

**One new bug the sweep found in itself.** Chunking CSS on `}` makes everything
since the last brace part of the selector — so a rule that *follows a comment*
reads as `/* … */ .nheader` and fails the root test. That silently dropped the
base `.nheader` rule and every other rule that opened a section. Comments are now
stripped before picking. (The footer's sweep was safe because its helper already
stripped them; the header's did not, and the difference was invisible until the
header rendered unstyled.)

**Parity, asserted at build:** every one of home_v1's 60 header rules is on this
page (modulo `.wrap` → `.container` and the `.nheader` scoping), and the measured
boxes match exactly — header **93px**, sticky, `top:0`, `z-index:20`, logo
278 × 48, services 571 × 39, phone 164 × 44, six nav items, six mega menus,
`combclip` and `mhex` both `display:none`. Same nav labels in the same order.
"Injuries" is marked `.mi.cur`, in orange, linking to the injury-claims index.

### The sticky header cashed a cheque the sidebar sheet wrote

The sidebar options sheet set `top:24px` and said, in as many words: *"The page's
header does not stick today, so 24 is the whole number. If a sticky header is
ever added, this becomes that header's height plus 24, and every option here
loses exactly that much room."*

home_v1's header **is** sticky. So:

- `.nheader` = 22 + 48 + 22 + 1 = **93px**, and 93 + 24 = **`top:117px`**. Derived
  from the header's own padding and logo height, both asserted, so the number
  cannot rot if the header is ever re-padded.
- That leaves the 582px block needing a **699px viewport**. A 1366 × 768 laptop
  gives about **648** after browser chrome — headroom would have been **−51px**,
  and the last two claims would have sat permanently below the screen edge with
  no way to reach them. Not a warning to write down: a defect to fix.
- Fixed with the sheet's own fallback: `max-height:calc(100vh - 141px);
  overflow-y:auto; overscroll-behavior:contain`. The list scrolls **inside
  itself**, and only when it has to.

Verified at four window heights (real viewports in brackets):

| window | viewport | block | scrolls inside | every claim reachable |
|---|---|---|---|---|
| 648 | 561 | 420 | yes | **yes** |
| 768 | 681 | 540 | yes | **yes** |
| 900 | 813 | 582 | no | **yes** |
| 1080 | 993 | 582 | no | **yes** |

In all four the block sticks at exactly **117**, clearing the 93px header.

### The mega menu was 145px too wide — the rename borrowed a box that was not positioned

Adi: *"perbaiki width mega menu nya. samakan seperti di … home_v1.html."*
**Source of record:** `prototyping/inner-service-v12-mega-width.html`.

Measured on both pages:

| | home_v1 | inner-service |
|---|---|---|
| `.mega` | **1280.0** wide, L72.5 → R1352.5 | **1425.0** wide, L0 → R1425 |
| the box it sizes to | `.wrap`, `position: relative` | `.container`, **`position: static`** |

**The cause is the rename itself.** `.wrap` → `.container` borrows the host's
1280px box, and the two boxes are the same *size* — which is exactly what made
the rename look safe when the footer used it. But home_v1's `.wrap` is also
`position: relative`, and the replica's `.container` is not. `.mega` is
`position:absolute; left:0; right:0`, so it sizes to its **nearest positioned
ancestor**: `.wrap` on the homepage, and nothing at all here, which meant the
whole 1425px viewport.

Nothing errored, nothing looked broken in the markup, and every rule had been
lifted correctly. The menu was just 145px too wide.

**The fix is not `position:relative` typed in somewhere.** The build now computes
`_box_delta()` — what home_v1's `.wrap` declares that the replica's `.container`
does not — and emits the difference **scoped to whichever component borrowed the
box**. It also asserts the two boxes still agree on `width` and `margin`, so if
they ever diverge the build says so instead of rendering something subtly wrong.

Today that emits two lines, `.nheader .container{position:relative}` and
`.nfoot .container{position:relative}`, and the page's own `.container` is
untouched.

**After:** all six mega menus measure **1280.0 × their own height at L72.5**,
identical to home_v1's, column widths 254 / 222 / 210 and the rail at 300 on
both. Confirmed by screenshot as well as by number.

**A measurement note.** The first screenshot after the fix still showed the menu
translucent, with the hero visible through it — not a bug in the page but in the
capture: `.mega` has `transition: opacity .16s`, and forcing it open with an
inline style meant the frame was grabbed mid-fade. Setting `transition:none`
before the opacity is what made the comparison honest.

### The caption now runs the width of the image (2026-08-30)

Adi: *"perbaikin width figcaption agar sesuai lebar image."*

It was capped at `max-width:64ch` — about 400px — which is the comfortable
measure for reading, and the reason I set it. But a caption that stops two thirds
of the way across the picture it belongs to reads as a fragment rather than as
that picture's caption. The cap is gone.

Measured: image **832.0 × 468.0** at L72.5 → R904.5, caption **832.0** at
L72.5 → R904.5 — both edges match to within half a pixel. The text falls to
**two clean lines** instead of three ragged ones, so the wider measure costs
nothing here in practice.

### Still the replica, still open

- **The page has no `h2` of its own** since `.lead` was removed — see above. One
  line restores it above the prose if the firm wants it.
- **Whether the footer form stays.** If the sidebar form went because the tab does
  its job, the same argument reaches the footer form. Still one decision, still
  unmade.
- `index.html` and `home_v1.html` untouched.

## Your Team — the live replica (2026-08-30, zeina branch)

**Served:** <https://leaguelaw.demoing.info/wp-content/prototype/team-replica.html>
**Source of record:** `prototyping/team-replica-v1.html` · generator
`prototyping/gen_team_replica.py` · data `team.json`, `team_menu.json`,
`team_intro_body.html`

Adi: *"sekarang saya ingin membuat prototype untuk halaman your teams seperti di
old site https://www.leaguelaw.com/lawyers/."* Same method as the inner service
page, and step 4 of the process: **the replica comes first**, because the
redesign is derived by diffing against a faithful copy.

### The shell is not written twice

The live team page and the live inner service page share a shell — 52px top bar,
43px header band, page header, 832 + 64 + 384 content, contact strip, Get in
touch, socials, footer form + map, footer bottom. All of it is **executed out of
`gen_inner_replica.py`**, which already measured it against the live inner page.
Only three things are written here, because only three things differ:

| | the inner page | the team page |
|---|---|---|
| page header | 252px, `truck-2677373`, breadcrumb pinned top-right | **303px**, `law-1.jpg`, a sub-line, breadcrumb below the h1 |
| entry | the article | the icon/intro block + a thirteen-card grid |
| sidebar | claims list + form | main menu (submenus collapsed) + form |

Everything is data, not typing: the thirteen cards, the four-level menu and the
intro copy are all extracted from the crawl, and the build asserts the copy still
carries its **non-breaking spaces**.

### Measured against the live page, box for box

| | live | replica |
|---|---|---|
| content-wrap | 1280 × 1600 | ✔ |
| primary / entry | 832 × 1600 / 832 × 1560 | ✔ |
| page header | 1425 × 303, inner 1280 × 101 | ✔ |
| h1 / sub-line / breadcrumb | 50.4 / 24.9 / 25.8 | ✔ |
| intro block | 832 × 450, hexagon 50 × 64, h2 762 × 78 at L142.5 | ✔ |
| grid | 832 × 1090 | ✔ |
| a card | 183 × 232.5, image box 183 × 178, name 22.5, role 17 | ✔ |
| card positions | 73 / 289 / 505 / 721, rows at 888 / 1161 / 1433 / 1706 | ✔ |
| the thirteen image widths | 129.1, 128.1, 126.3, … 143.6 … | ✔ identical |
| document | 3377 | 3378 |

### Three things the numbers hid, and the side-by-side found

Measuring only the boxes I thought to name matched every number and still gave a
visibly wrong page. Putting the two screenshots side by side found all three in
one look:

1. **A sub-line.** The 24.9px "gap" between the h1 and the breadcrumb was not a
   gap — it is `.page-subheading`, *"Your choice for legal advice"*.
2. **The card names.** Uppercase, centred, and **black** — the shell paints every
   `.entry` link teal, and the name is the card's link.
3. **The sidebar form.** I had measured the second widget at zero height and
   concluded the page had no form. Wrong widget: the form is the *middle* one,
   751px with 20 fields. **"Your Team" is also the current row**, filled solid
   teal with white text.

**The lesson is about the instrument, not the page.** A measurement only checks
what you name; a picture checks everything at once. Neither replaces the other.

### Four across, and the 0.2px that decides it

`4 × 183.031 + 3 × 33.2656 = 831.9` of the 832 column, and **every fourth card
has `margin-right: 0`** — measured on the live page. Leave that margin on and its
margin box is 216.3 against 183.2 of remaining line, so it wraps: the grid
silently becomes three across and five rows deep, which is exactly what my first
build did. Chrome places a float by its **margin** box, not its border box.

### Defects reproduced on purpose

- The intro hexagon is **50 × 64** here and **50 × 65** on the inner page. Both
  are wrong (a regular hexagon 50 wide is 57.7 tall) and both are reproduced as
  found — rounding the two to one number would be tidying the thing being measured.
- **The current sidebar row is white on teal — 2.60:1**, below even the 3:1
  large-text floor.
- **Thirteen portraits at thirteen different widths** (126.3 to 143.6), because
  the height is fixed and the width follows each source.
- **An empty trailing `<p>`** left behind by whoever last edited the page. It
  renders at zero height and still contributes 20px of margin — the whole of the
  difference between a 1540px entry and the live 1560.
- The phone number appears in the intro **and** in the sidebar form **and** in the
  contact strip **and** the footer, exactly as on the inner page.

### One residual, stated rather than buried

The sidebar form measures **758.4px against the live 751** — 7.4px taller, with
its button 150px wide against the live's auto-width 139.6. It is the shell's
form, which matched exactly on the inner service page, so the two live pages
differ slightly from each other. Left alone: it is 7px inside the one component
the redesign has already decided to delete.

### Copy provenance — every line is traceable, except two

Heading and sentence use only facts already verified for this rebuild: six offices
in BC (database — the live band names five), 160+ years combined, free
consultations for injury and estate litigation (the firm's own LaW Facts).

The Armstrong-style sub-line under each service came from the database where it
exists:

* **Injuries, Estates, Real Estate** — the real child pages.
* **Business and Marine have no sub-pages at all.** Those two lines are new copy
  derived from their existing descriptions and **need the firm's sign-off before
  publication.**

### What every option in this round is standing on that does not exist

* The five practice photographs are 411–600px wide and **are not assigned to a
  practice area anywhere** — the pairing is inferred from filenames. S3 asks a
  500px image to fill a 520px column; it is showing a layout, not a picture.
* The five icons are 93×107 raster PNGs with the brand colour baked in, so H3's
  icon row cannot be recoloured or placed on a dark ground until they are SVG
  (flag #4).

Contrast checked by hand for every colour on the sheet: service name 10.86:1,
sub-line 5.33:1 on white and 5.06:1 on paper, S2's opening 10.86:1 / 8.58:1 /
7.24:1 on brown, hover `#A94A29` 5.68:1. Brand orange carries no word anywhere in
the round — it is a rule, a bar or a hexagon only.

### Rebuild-relevant flags (collected from above)

1. Empty `<h1>` on the homepage (SEO defect to fix in rebuild).
   **Partly closed 2026-08-24** — home-v2 gained an `<h1>` with v1's J2 hero
   (the form heading). A form heading is a weak h1 for a law firm homepage; a
   proper page heading is still the real fix.
2. Old Wilson St address in the visible footer AND schema.
3. Location bar omits Nanaimo (six locations per brief).
   **Confirmed against the database 2026-08-24** — six published location pages
   exist under Contact Our Lawyers; the band names five. Fixed in every option
   in `band.html`.
4. Practice icons are raster PNGs → redo as SVG in the brand hexagon.
   **Measured 2026-08-24:** 93×107 8-bit palette PNGs, brand colour baked in.
   96px display is already an upscale, and they cannot be recoloured, inverted
   on hover, or put white on a dark panel until they are SVG.
5. Mobile buries practice-area zones under the form → layout decision for
   wireframes.
6. Duplicate contact form top + bottom; decide one strategy.

## Your Team — the sidebar removed (2026-08-31, zeina branch)

**Asked:** *"namun saya ingin untuk halaman your team ini tanpa sidebar."*

Served: **<https://leaguelaw.demoing.info/wp-content/prototype/your-team.html>**
(26,493 bytes · HTTP 302, the id-auth gate, which is correct).
Generator `prototyping/gen_team.py`; backup `prototyping/your-team-v1.html`.

**`team-replica.html` is untouched, deliberately.** The live page HAS a sidebar; a
replica that drops it is no longer a copy of anything, and this rebuild is
derived by diffing against the replica. So the replica stays the measuring
instrument and this is the first build taken from it. The diff between the two
files is the complete record of what removing the sidebar changed — that is the
whole reason for keeping them as two files.

**Nothing was transcribed.** `gen_team.py` executes `gen_team_replica.py` (which
in turn executes the shell, `gen_inner_replica.py`) and takes the page header,
the entry, the intro copy, the thirteen cards and the footer as objects. Only
the *consequences* of removing the sidebar are written in this file — 60 lines
against the replica's 243. Nothing can drift, because there is only one copy.

### Removing a sidebar is three decisions, not one

Taking out 384 + 64 px does not just delete a column; it hands 448px to the page
and something has to be decided about each of the three things that were sized
against the old 832.

**1 · The column.** `832 + 64 + 384` collapses to a single 1280. Measured:
`.primary` 1280 (was 832), `.cwrap` `display:block`, sidebar `MISSING`,
`asides=0`, `forms=0`.

**2 · The body copy does NOT widen.** The intro stays at 832 — a 762px measure at
17/28 once the hexagon's 70px indent comes off. Running it to the full 1280
would put ~175 characters on a line, roughly twice a readable measure. Freeing
width is not a reason to spend it on the one element that does not want it. So
the intro block measures *identically* to the replica: `icontext` 832×450,
`h2` 762×78 at L142.5, first paragraph 762×112. Zero drift, on purpose.

**3 · The grid re-flows, and thirteen is an awkward number.**

| across | card | rows |
|---|---|---|
| 4 | 296 | 4/4/4/**1** — one card alone on row four |
| **5** | **230.4** | **5/5/3** |
| 6 | 186.7 (≈ the live 183) | 6/6/**1** — same lone card |

Five. `1280 = 5 × 230.4 + 4 × 32`. The gutter is the home page's 64px lattice
gutter halved, and lands a third of a pixel off the live 33.2656 — a round
number instead of a float that has to come out exact.

**CSS grid, not floats.** The live four-across depends on every fourth card
carrying `margin-right:0` **and** on 0.2px of slack in the line, because Chrome
places a float by its *margin* box; get either wrong and the grid silently drops
to three columns and five rows, which is exactly what the first replica build
did. Grid has no such trap, and the row gap is declared once instead of being
carried in thirteen bottom margins.

Measured: grid 1280×777.5; card 230.4×232.5; card lefts
`72.5 / 334.9 / 597.3 / 859.7 / 1122.1` — steps of 262.4 = 230.4 + 32, and the
fifth card's right edge lands on 1352.5, which is the container's right edge to
the pixel. Rows `888:5 · 1161:5 · 1433:3`. Document 3065 against the replica's
3378: the page is 313px shorter for holding the same content.

Everything above the content is bit-identical to the replica — page header
1425×303 with its 1280×101 inner block, h1 50.4, sub-line 24.9, breadcrumb 25.8
— because none of it was in the sidebar's column.

### What the picture found that the numbers did not

Every box came out where it should, and the grid still reads wrong: **the
portraits do not fill the cards.** The thirteen images render at thirteen widths
(126.3 … 143.6 — a live-page defect the replica reproduces on purpose) and they
are now centred in 230.4px cards, so each one floats in 43–52px of white on both
sides, and the ragged right edges of the row are far more obvious than they were
at 183. Removing the sidebar did not cause this defect; it **amplified** it, and
that is a consequence of this change, so it is recorded here rather than left in
the replica's list.

**Left as found, not silently fixed.** The answer is a uniform portrait box —
one aspect ratio, `object-fit:cover` — but choosing a crop for thirteen
head-and-shoulders photographs is a design decision, not a side effect of
deleting a column. It is the next thing to decide for this page.

Still open on this page, carried from the replica: the 50×64 hexagon (a regular
hexagon 50 wide is 57.7), and the November photo shoot, which is what actually
retires the thirteen-widths problem.

## Your Team — A1 fitted as the hero (2026-08-31, zeina branch)

**Asked:** *"buat style heronya seperti .../inner-service.html."*

Served: **<https://leaguelaw.demoing.info/wp-content/prototype/your-team.html>**
(36,460 bytes · HTTP 302). Backup `prototyping/your-team-v2.html`; `-v1` is the
version with the live photo banner.

### Three files, one hero

It is not copied from `inner-service.html`, and not copied from the option
sheet either. `gen_team.py` **executes** `gen_inner_replica_hero.py` and calls
that file's own lifting functions: the CSS comes back already re-scoped
`.a1 → .shero`, and the markup comes out of the option sheet's `A1()` builder
with this page's content put **into the builder's globals before it runs**,
rather than run-then-edited. `hero-inner.html`, `inner-service.html` and
`your-team.html` therefore cannot drift; a change to A1 lands on all three.

Content into A1's four slots: hexagon icon `fa-users` (the inner page's is
`fa-car`), crumbs `Home » Our Lawyers`, and — the one thing A1 writes inline
rather than reading from a global — the sub-line, swapped with an assertion.

### What the collision test caught

`_assert_no_collision` (the inner page's test, run against this page's
stylesheet) refused the build over **`.crumbs`**. The replica shell styles the
breadcrumb with a bare `.crumbs{position:absolute;right:0;top:10px}` — no
ancestor — and A1's breadcrumb is also `.crumbs`. Left in, it would have pinned
the hero's crumb trail to the top right of the crumb bar. The whole 252px
banner block goes with it (`_drop_banner`), and this page's own `.phead.team`
block goes too (`_drop_phead`), both asserted empty afterwards: a stylesheet
that still describes an element the page no longer has is dead code that reads
as if it still ran.

### The photograph is the page's own

`law-1.jpg` — what the live page already runs across the top — not a new
image. It is **1800×332 (5.42:1) in a 420×380 (1.11:1) panel**, so `cover`
matches the *height* and crops the width to a 367px slice. That inverts the
inner page's situation: there a 3:2 source made vertical `object-position`
inert, here the **horizontal** one is the only control over what the panel
shows, and the 50% default lands on the blur behind the statue.
`object-position:70% 50%` is where the statue stands. One declaration, and it
is the only thing this page adds to A1.

### The h1: measured, not assumed

The live h1 is 68 characters — *"League and Williams BC Injury, Estate, Marine
and Real Estate Lawyers"*. A1's type column is a **constant 336px** at every
viewport, and `.htitle` is 38px. Rendered both ways rather than guessed:

| h1 | h1 box | band | hero | document |
|---|---|---|---|---|
| the live 68-character title | 336×**303.2** (7 lines) | **572.4** | 613.4 | 3376 |
| **"Your Team"** | 336×43.3 (1 line) | 380 | 421 | 3183 |

The live title turns the type panel into a 7-line wall and pushes the whole
page down 192px. So the h1 is **"Your Team"** — the site's own name for the
page, in the nav and in the breadcrumb — and A1's fifth line takes the live
page's own sub-line, *"Your choice for legal advice"*, which the replica
carries as `.psub`.

**This is a copy change and needs sign-off.** The 68-character string is a
keyword-era h1; dropping it loses those words from the heading, though the
intro h2 immediately below ("BC Lawyers: Experienced litigators and solicitors
providing trusted advice") covers the same ground and is better written. If it
has to stay verbatim, the panel needs a smaller type step for this page — say
26px, where it comes back to three lines — and that is a second decision, not
a free one.

### Measured

Hero 1425×421 (crumb bar 41 + band 380) · type panel 452.5 with a **336px type
column at 1366, 1425 and 1920** — round 2's gutter-in-the-width fix holds ·
photo panel 420×380 · contact panel 552.5 with the 420px call block · band
380 at every width. Below the hero **nothing moved**: content-wrap 1280×1287.5,
intro 832×450, grid 1280×777.5, 5/5/3. Document 3183, up 118 from the banner
version — the hero is 118px taller than the 303px banner it replaced.

### Two differences from the inner page that are NOT the hero

Both are shell parity, not hero style, so they are left alone until asked:

1. **The header above it.** `inner-service.html` carries home_v1's `.nheader`;
   this page still carries the replica's. The hero sits under both correctly.
2. **The consultation tab** (`.ctatab`) is on the inner page and not here.

One difference that *is* inside the hero and is worth a decision: **this
photograph is in colour** where the inner page's is monochrome and all thirteen
portraits below are black and white. The bronze reads warm against the orange
and brown and may well be right; left as-found rather than filtered, because
choosing to desaturate is a treatment decision.

## Your Team — intro centred, home_v1's bench, header, footer and CTA tab (2026-08-31, zeina branch)

**Asked:** *"hilangkan class=hex, kemudian buat copy content menjadi rata tengah.
kemudian untuk tampilan anggota team tampilkan seperti class=teams di home_v1.
untuk bagian class=cstrip hingga footer hilangkan dan ganti menjadi seperti
footer home_v1. Header juga diganti menjadi sama dengan header di home_v1. Lalu
tambahkan class=ctatab juga."*

Served: **<https://leaguelaw.demoing.info/wp-content/prototype/your-team.html>**
(63,443 bytes · HTTP 302). Backup `prototyping/your-team-v3.html`.

### The page now shares its shell by construction, not by resemblance

`gen_team.py` stopped building on the replica's twelve-block stylesheet and
adopted **`gen_inner_replica_hero.py`'s own** — the sheet already reduced to the
two blocks this page keeps (content, article) with a named slot for each lifted
component. The four requests are then four calls into files that already build
these parts for `inner-service.html` and `home_v1.html`:

| part | where it comes from |
|---|---|
| header | `HNS["_header"]()` — home_v1's `.nheader`, swept |
| hero | `HNS["_hero_css"]()` + the option sheet's `A1()` builder |
| bench | swept out of `home_v1.html` for `.teams .bench .bx .hexpt` |
| footer | `HNS["_footer"]()` — replaces `.cstrip` → `.fbottom`, five sections |
| CTA tab | `HNS["_consult"]()` — tab, modal and the script that drives it |

Four files, one shell. Change home_v1's header and this page's header changes
with it; there is no second copy to forget.

**Which `class="hex"`.** Two on the page: `<span class="hex">` in the intro and
another in Get in touch — and the hero's is `class="hex m w"`, so the bare one
Adi named is the intro's. The other went with the footer replacement anyway.
The build asserts `class="hex"` appears nowhere in the output.

**The nav's current item.** The header lift hard-marks *Injuries* as current,
because the page it was written for is an injuries page. This one is not, so
the marker is moved to **Your Team** — both swaps asserted, so a change to
home_v1's nav breaks the build instead of quietly underlining the wrong word.
Mega menu measures 1280, so the `_box_delta` fix carries over.

### Centring is a change of axis, not of measure

The hexagon was the reason the intro was indented 70px and set left. With it
gone nothing holds the left edge, and the page now runs a centred hero title
over a centred bench, so the copy between them centres too.

**The measure stays at 762px** — the width the copy was written for, and what
it measured on the live page (832 minus the hexagon's column). Letting a
centred paragraph run the full 1280 would be ~185 characters a line. Centred
text gets *harder* to read as the measure grows, not easier: every line starts
at a different x, so the eye has to find the start of each one, and a long
measure makes that hunt longer. Measured: `.tc` 762×384 centred in the 1280
column, `text-align:center`, zero `.hex` spans.

### The bench retires a defect this rebuild has been carrying

`.lgrid` put **thirteen portraits at thirteen widths** (126.3 … 143.6) in
fixed-height boxes — a live-page defect the replica reproduced on purpose, and
one that removing the sidebar amplified because each portrait then floated in
43–52px of white. `.bx .bph` is a fixed box with `object-fit:cover` and
`object-position:top`. Measured: **all twelve images exactly 210.0 wide**, every
cell 210×310, photo box 210×250, two rows of six.

**Swept, not block-cut** — 19 rules, count asserted — for the reason the footer
taught: a component's rules are not all filed under it (`.hexpt`, the kicker's
marker, sits ~250 lines from the bench block). The sweep also asserts that no
bench rule has moved inside an `@media` block, since one that had would vanish
silently.

**home_v1's 10px blur is deliberately NOT carried over.** Its own comment says
why it exists: *"static-blurred 10px on purpose: low-fi until the November
shoot, so the client discusses layout, not imagery."* That is exactly wrong
here — these portraits are the finished studio photographs and they are this
page's entire content. `scale(1.06)` goes with it; it only existed to hide the
halo the blur left inside the crop. Both removals are asserted. Restoring the
low-fi look is one line if it is ever wanted for a review.

**Twelve in the bench, not thirteen.** home_v1's bench has twelve lawyers; the
live team page has those twelve plus an **"IS IT YOU? / Go to Careers Page"**
tile. That tile is a recruitment CTA, not a lawyer, and thirteen cells in a
six-column grid leaves it alone on a third row. It keeps its own centred line
under the bench, with the live page's own words and its own link. The build
asserts the bench's twelve names are a strict subset of the live thirteen and
that the *only* one missing is the careers tile — so a lawyer quietly dropped
from home_v1 fails the build here.

**One thing lifted with the bench that is worth a decision.** home_v1's `.bfo`
line is a practice area ("Injury, estates & marine litigation"); the live team
page's is a role ("Principal", "Associate"). Taking home_v1's component takes
its copy, so the role words are not shown. The practice line is the more useful
of the two, but *Principal* is information the page currently carries and this
loses it.

### Measured

Header 1425×93 · hero 1425×421 (band 380) · content-wrap 1280×444 with the
intro measure 762×384 centred · teams band 1425×955 full-bleed on `--paper`,
its wrap 1280, head 1280×103, bench 1280×636 in two rows of six ·
careers line at 1879 · footer 1425×478.5 · CTA tab 43×212 pinned right ·
25 images, none broken · document **2432**, down from 3183 — the bench is 454px
shorter than the float grid it replaces and the footer 313px shorter than the
five sections it replaces.

The tab was clicked in headless Chrome rather than assumed: `.ctatab` →
`body.consult-open`, modal 1425×813.

## Your Team — contact line cut, bench only, white band (2026-08-31, zeina branch)

**Asked:** *"hilangkan Contact us today for a consultation (250) 888-0002 di copy
content. kemudian untuk display team bisakah untuk halaman your team ini
langsung diambil dari section class=bench saja? dan untuk bg color tetap
putih."*

Served: **<https://leaguelaw.demoing.info/wp-content/prototype/your-team.html>**
(61,553 bytes · HTTP 302). Backup `prototyping/your-team-v4.html`.

### 1 · the intro's closing contact line

Cut by its own paragraph boundaries and asserted both ways, so a change to the
crawled copy fails the build rather than quietly leaving the line in. The intro
is now a heading and two paragraphs; the non-breaking spaces are re-asserted
after the cut.

Worth recording *why* it was the weakest line on the page and not just one
Adi did not want: it was the **fifth** printing of the phone number, and the
one set in body type. The hero's is 54px with a form beside it, the CTA band's
sits next to a Book Consultation button, and the footer prints it twice. A
paragraph asking for the call in 17px running text competes with four louder
places that ask for the same thing.

### 2 · the bench without its section head

home_v1's `.teams` is a bench **plus** a section head — kicker "Behind every
team", *"The whole bench."*, and the Google credibility line. On the homepage
that head does the introducing. On this page the intro paragraph two inches
above has already done it, and a second heading between the two read as the
page starting over.

So the head goes, and with it every rule that exists only to style it —
including `.hexpt`, which is on the kicker and nowhere else in this component.
**Ten rules named explicitly and asserted**, not matched by pattern: the sweep
still asserts home_v1 yields 19, then that exactly the ten listed are dropped,
leaving 9. A rule that quietly stopped being dropped — or one that vanished
from home_v1 — fails the build instead of changing the page.

Markup cut on the same principle: bounded by `<div class="head">` and
`<div class="bench">`, with the cut region checked for the words it should
contain, and the result checked for `.head`, `.kick`, `.cred` and `<h2` being
gone.

### 3 · the band stays white

home_v1 puts the bench on `--paper` so it separates from the white sections
above and below it. Here there is nothing to separate from: with the head gone
the bench is simply the rest of the page, and a tinted band would draw a box
around it for no reason. `background: var(--paper)` → `#fff`, asserted.

The **padding stays** — 64px above, 56px below. It is now the only thing
holding the bench off the copy, and with `.icontext`'s own 46px tail that puts
**110px** between the last paragraph and the first face. That is a section
break's worth of air, which is what it is doing; if it reads loose, the 64
is the number to change.

### Measured

Intro 762×336 centred (was 384 — the contact line was 48px) · teams band
1425×808 on white, wrap 1280, **bench starts at the top of the wrap** (no head)
· bench 1280×636, twelve cells 210×310, all twelve images exactly 210.0 wide ·
careers line at 1684 · footer 1425×478.5 · CTA tab 43×212 · 25 images, none
broken · document **2237**, down from 2432.

## Your Team — the gap above the bench, 110 → 80 (2026-08-31, zeina branch)

**Asked:** *"kurangi sedikit jarak 110px itu."* Backup `prototyping/your-team-v5.html`.

The number moved, but the reason to record this round is that **no element
declared 110**. It was `.icontext`'s 46px bottom padding plus home_v1's 64px
band padding — two paddings doing the same job, stacking into a number neither
rule says. A gap you cannot find by reading either rule is a gap nobody can
tune: the next person to want it tighter changes one of the two, gets a number
they did not predict, and changes the other as well.

So one element owns it now. `.icontext` goes to `padding:14px 0 0`, and the
band's own padding carries the whole gap at **80px**. The number in the
stylesheet is the number on the page.

Measured: copy ends at 904, first face at 984 — 80.0 exactly. Document 2207,
down 30. Everything else unchanged: bench 1280×636, twelve cells 210×310, all
twelve images 210.0 wide.

## Your Team — the gap again, 80 → 56 (2026-08-31, zeina branch)

**Asked:** *"kurangi lagi."* Backup `prototyping/your-team-v6.html`.

56 is not a number picked by eye: it is the band's **own bottom padding**. The
bench now sits in equal air above and below, so the one figure in the rule
describes both edges and there is no second number to keep in step.

Measured: copy ends at 904, first face at 960 — 56.0 exactly; band 1425×800,
document 2183 (down 24). Bench unchanged: 1280×636, twelve cells 210×310.

Below this the copy and the first row start to read as one block — the two
things are different in kind (a centred paragraph, a hard-edged grid of faces)
and need a visible beat between them. If it should go tighter anyway, that is
worth doing as a deliberate look rather than another trim.

## Service Index — first build (2026-08-31, zeina branch)

**Asked:** *"saya ingin membuat halaman Service Index ... dengan header, hero,
ctatab dan footer yang sesuai seperti halaman halaman sebelumnya. dan tidak
perlu sidebar."*

Served: **<https://leaguelaw.demoing.info/wp-content/prototype/service-index.html>**
(63,611 bytes · HTTP 302). Generator `prototyping/gen_service_index.py`; backup
`prototyping/service-index-v1.html`.

### The shell is not designed here, it is executed

Four calls into the files that already build it — the same four
`your-team.html` makes: `HNS["_header"]()`, `HNS["_hero_css"]()` + the option
sheet's `A1()` builder, `HNS["_footer"]()`, `HNS["_consult"]()`. Three pages,
one shell, no second copy to forget.

**The nav marks nothing current, and that is a finding.** The header lift
hard-marks Injuries; this page is the *parent* of all five areas, and the
rebuild's header has no "What We Do" item at all — it puts the five areas
straight in the bar. So the marker is removed and asserted gone. The
breadcrumb still reads Home » What We Do, pointing at a page the nav does not
link to. Someone has to decide whether the index page survives the rebuild or
whether the mega menus replace it.

**The hero's sub-line does a job here.** The live page header has none. A1 has
the slot, and the five area names is the most useful thing in it: the hero
says what the page contains before the index has scrolled. Two lines at 336px,
and the band stays 380 — the type block is 245.5 inside it.

### The index is built from two sources, and the disagreement between them is the finding

| source | what it decides |
|---|---|
| `team_menu.json` (the live site's menu) | what **exists** — the real tree, the real URLs |
| `home_v1.html`'s mega menus | how it **reads** — the grouping of the injury claims, each area's paragraph and icon |

Every name in home_v1's grouping is resolved against the live tree, and the
build fails on any that does not resolve. That is what stops the page
promising a page the site does not have.

**Six topics home_v1 names have no page.** Business (*Starting a new business
in BC · Buying or selling a business · Restructuring an existing business*) and
Marine (*Boating accidents · Boat seizures · Anchoring & mooring concerns*)
each carry three items in the homepage mega menu, and the live site has **zero
sub-pages** under either. This matches the practice-areas round's own count
(Injuries 13 · Estates 3 · Real Estate 2 · Business 0 · Marine 0), now
confirmed from a second direction. The index shows both areas with **no list
and a line saying so** — padding them with the homepage's topics would be
inventing pages, which is the ruling that round already made ("the two empty
cards shown honestly rather than padded"). The count is asserted at 6: **if a
page appears for one of them, this build fails and the index gains it.**

**A group heading can be a page.** home_v1's mega uses *Estate Disputes* as a
column label; on the live site it is a real page with the four claims beneath
it. On a menu a label is fine — on an index page it would be the one heading
in the section that cannot be reached. So a heading that resolves to a live
page not already listed becomes a link, which is how Estates accounts for
**7** live pages and not 6.

**Three naming schemes, none of which agree.** The rebuild's nav says
*Injuries / Estates / Business / Marine / Real Estate*; the live menu says
*Injury Claims / Estates / Business Law / Real Estate / Marine Law*; the live
services page's own tiles say *INJURIES / Estate Law / Business Law / Marine
Law / Real Estate Law*. The map between them is written out in the generator
rather than hidden behind a slug, so the disagreement stays visible. The page
uses the rebuild's names and the live URLs, in the **live menu's order** —
which puts Real Estate before Marine, where home_v1's nav has them the other
way. That is flag 4 of the practice-areas round, still nobody's decision.

### Why this is not the homepage's practice-areas screen

home_v1's `.triage` exists for exactly this content, and it was the obvious
thing to lift. It is the wrong component here, and the reason is the job, not
the look: **triage routes, an index lists.** The homepage's first screen wins
by getting a visitor into one of five areas in a glance, so hiding each area's
pages behind a panel is right there. An index page is read once, to find a
particular thing, so nothing on this page is behind a tab, a hover or a panel —
all 22 pages are on the screen at rest.

### Layout, and the numbers that are not free

`1280 = 384 (the area) + 64 + 832 (its pages)` — the same lattice the inner
pages use for content and sidebar. Inside the 832, **the column is 256
whatever an area's group count is**: `(832 − 2×32)/3`. Letting the groups
divide the 832 between them would give Injuries three 256px columns and
Estates two 400px ones, and the eye reads that as two different tables rather
than one index. A fixed column also means an area with less to show runs out of
columns rather than stretching to fill.

The hexagon plate is **64 × 73.9** — `64 / 0.8660254`. Every hexagon on this
rebuild is on ratio or it is a bug.

**The icons pass on the dark plate, and that was checked rather than hoped.**
The practice-areas round established that the five icons are 93×107 8-bit PNGs
with the brand colour baked in — they cannot be recoloured, so "put them on a
dark panel" is not a styling choice, it is a contrast question. Measured
against the brown plate `#423C37`: brand orange **3.58:1**, brand teal
**4.18:1** — both clear the 3:1 non-text floor with the colour they already
have. Drawn at 46px, under the 64px ceiling the round set.

**Every colour computed, not chosen.** Service names brown 10.87:1 · group
labels and the no-pages line `#6B6B6B` 5.33:1 · the "All …" door `#2F7186`
5.50:1 · hover `#A94A29` 5.68:1. **home_v1's own label grey `#9A948B` is not
reused**: it measures **3.01:1** on white and 2.86:1 on its `--paper` band, so
it fails AA at every size it is used at — including on the bench this rebuild
just put on the team page, which is a defect inherited from home_v1 and worth
fixing there. Brand orange carries no word on this page; it is the rule under a
hovered row and nothing else.

### The mistake this round made, because it is the same one twice

`.sidx .alist a` also matched the **group heading's** link — the heading sits
inside `.alist` too — so *Estate Disputes* came out at the pages' 14px with
their padding and their rule under it, and the one heading that is a link
stopped looking like a heading. Same shape as the `.crumbs` collision on the
team page: a descendant selector reaching a link it was not written for. Fixed
by scoping to a **direct child** of the group, which is what a page row
actually is. Found by looking at the picture, not by any measurement — the box
numbers were all correct.

### Measured

Header 1425×93 · hero 1425×421 (band 380, type column 336) · intro 762×148
centred · index 1425×1701, wrap 1280, five areas at 321/321/321/296/321 · six
groups, **all 256.0 wide** · 22 page links, every one a real `/our-services/`
URL (asserted) · plate 64×73.9, ratio 0.8661 · footer 1425×478.5 · CTA tab
43×212, click → `body.consult-open`, modal 1425×913 · 18 images, none broken ·
document 2895.

### Open for Adi

1. **The intro copy promises family law.** *"…personal injury, family,
   business, estate and marine law"* — there is no family practice in the nav,
   no family area page, and the team page's own copy says free consultations
   are available *except on family law matters*. The line is the live site's,
   carried verbatim; it needs Darren.
2. **This page and the team page now share a hero photograph** (`law-1.jpg` —
   it is the banner the live site puts on both). Distinguishing them is a
   November-shoot decision.
3. Whether the index page survives at all, given the nav has no item for it.

## Service index — option round 1, drawn on one service (2026-08-31, zeina branch)

**Asked:** *"bisakah kamu buatkan beberapa opsi untuk menampilkan service index.
mungkin service index ini ditampilkan per service, misal untuk page sekarang
kita ambil contoh untuk service index injuries saja terlebih dahulu."*

Six options in **<https://leaguelaw.demoing.info/wp-content/prototype/service-index-options.html>**
(29,330 bytes · HTTP 302). Generator `prototyping/gen_svcidx_options.py`;
backup `prototyping/service-index-options-v1.html`.

The data is **executed** out of `gen_service_index.py` — same live tree, same
home_v1 grouping, same real URLs — so no option can drift from the page it is
proposing to replace. All 90 links on the sheet are asserted to be real
`/our-services/` URLs.

### Injuries is not an example, it is the worst case

Thirteen pages in three groups, against Estates' seven, Real Estate's two, and
Business and Marine's **nothing at all**. An option that reads well on Marine
has been tested against nothing. So every caption says what its option does to
the four thin services, and the sheet's table has a column for it — because
whatever wins has to survive an area with an empty list, and **only S1 does
that without help.**

### The six

| | | height | an area with no pages |
|---|---|---|---|
| **S1** | rail and columns | **335** | **holds its shape** |
| **S5** | dense strip (chips) | 419 | collapses to the head alone |
| **S3** | group panels | 497 | nothing left to draw |
| **S2** | head across, three columns | 620 | head with a hole under it |
| **S4** | numbered index, typography only | 705 | a heading and no list |
| **S6** | full-width ruled rows | 962 | a label column beside nothing |

Measured in headless Chrome at 1440, not estimated.

**S1 is the shortest and it is not close, and the reason is structural rather
than stylistic.** It is the only option that puts the service's head **beside**
the list instead of above it, so the plate, the name, the paragraph and the
door cost nothing vertically. Every other option pays 150–220px before its
first claim. Stack five services on one page and that is the difference between
a page scrolled once and a page scrolled five times — which is exactly the
decision Adi's question is really about.

**S5 is the most compact list and still loses on total height** — thirteen
claims in three bands against S6's thirteen rows — because it pays for a head
above the list. Worth separating those two facts rather than letting "compact"
stand unqualified.

### What the round is really testing

Three of the six (S3, S6, and to a lesser extent S4) make **the grouping**
structural. The grouping is home_v1's mega-menu proposal — *Road Accidents ·
On Premises · Other Claims* — and **the live site's own menu lists the thirteen
flat, with no groups at all**. If the grouping is wrong those three are wrong
in a way S1 and S5 are not. That is the firm's confirmation to give, and it is
badged on the sheet rather than assumed.

### Two constraints bound all six, and only S4 escapes both

The five practice icons are 93×107 8-bit PNGs with the brand colour baked into
the file, so nothing draws one above 46px and the dark plate was **checked**:
orange **3.58:1** and teal **4.18:1** on `#423C37`, both over the 3:1 non-text
floor with the colour they already have. And **there is no photograph for any
of the thirteen claims** — which is why no option on the sheet is photo-led: a
tile-per-claim layout cannot be drawn from what exists. S4 uses neither icon
nor photograph and is immune to both; it is also the least branded thing on the
site, which is its own cost.

**Colour is not one of the variables** — identical in all six so the comparison
is about structure. Page names brown 10.87:1 · labels and copy `#6B6B6B`
5.33:1 · the door `#2F7186` 5.50:1 · hover `#A94A29` 5.68:1. Brand orange
carries no word anywhere on the sheet.

### Sheet note worth keeping

The frame was 1180 wide and the stages are 1280, so the third column of S1 was
being cut off — an option judged on a crop. The sheet is now 1360 (1280 + 2×40)
and every stage is asserted un-clipped (`scrollWidth === clientWidth`), because
a comparison sheet that crops one option is not a comparison.

## Injuries index — the service index becomes one service (2026-08-31, zeina branch)

**Asked:** *"maksud saya service index ini menjadi injuries index terlebih dahulu."*

Served: **<https://leaguelaw.demoing.info/wp-content/prototype/injuries-index.html>**
(57,197 bytes · HTTP 302). Generator `prototyping/gen_injuries_index.py`;
backup `prototyping/injuries-index-v1.html`. `service-index.html` and the
option sheet are left as they are.

### The clarification retires both arguments that won the option round

S1 won the sheet on two counts, and this page removes both:

* *"it survives an area with nothing under it"* — there is only one area here,
  and it has thirteen pages.
* *"its head costs no height, which matters when five stack"* — nothing stacks,
  and **the A1 hero already IS the head.** A second block repeating the plate,
  the name and the paragraph would say all three twice on one screen.

So the body of this page is **a list and nothing else**, and the treatment is
S2's three ruled columns with its service head removed — which is what every
option on the sheet becomes once the hero does the introducing. `LAYOUT` in the
generator switches between `cols` / `panels` / `index` / `chips` / `rows`, so
trying another is one word.

**At 405px every claim sits on one line.** The longest, *Motorcycle Accident
Claims*, measures ~205px. The service-index page's 256px columns wrapped four
of the thirteen; this is the width the wrapping stops at, and it is the whole
practical difference between the two treatments.

### The hero

Photograph: `car-crash-1024x683.jpg` — **the image the live site already pairs
with Injuries**, as the tile background on `/our-services/`. 1024×683 (1.5:1)
in the 420×380 (1.105:1) panel, so `cover` matches the height and crops the
width to 73% of the frame: a **downscale**. That matters here, because most of
the practice photographs cannot do it — the Injuries thumb is 411px native and
would have blown up 1.47× in the same panel.

Title **"Injuries"**, the same decision as the team page's 68-character h1: the
hero takes the site's own short name for the section, the word that is in the
nav and in the breadcrumb, and the live h1 (*"Personal Injury Lawyers in
Victoria"*) is left as a copy question for the firm rather than silently kept
or silently dropped. The sub-line is the parent section, *What We Do* — exactly
what A1's fifth line is for, and the first page since the inner service page to
use it as designed. Breadcrumb Home » What We Do » Injuries, three levels.

**The header's current marker is right for once.** The lift hard-marks
Injuries; the team page had to move it and the service index had to remove it.
This page is an injuries page, so it is left where the lift puts it — and
asserted, rather than left to luck.

### Measured

Header 1425×93 · hero 1425×421 (band 380, h1 43.3 on one line, sub 29) ·
intro 762×109 centred · claims band 1425×398, three columns **405.3 each**,
thirteen links, **all thirteen distinct and all under
`/our-services/bc-injury-claims/`** (asserted) · footer 1425×478.5 · CTA tab
43×212 · 13 images, none broken · document **1554**.

### Not placed, and not lost

The live Injuries page carries **five more body paragraphs** after that intro.
They are crawled and saved verbatim at `prototyping/injuries_body.html` with
their entities intact, but they are **not on the page**: this is an index, and
whether that copy goes above the list, below it, or on a page of its own is a
decision nobody has made. Saved so that placing it is a one-line change and so
that leaving it out today loses nothing.

## Injuries index — a photograph per claim (2026-08-31, zeina branch)

**Asked:** *"bisakah dibuat grid dengan gambar? untuk gambar?"*

Served: **<https://leaguelaw.demoing.info/wp-content/prototype/injuries-index.html>**
(60,412 bytes · HTTP 302). Backup `prototyping/injuries-index-v2.html`; `-v1`
is the text-column version. `LAYOUT` in the generator switches between
`grid` and `cols`.

### The answer to "untuk gambar?" — the pictures exist, and the earlier finding was too narrow

The practice-areas round recorded that **there is no imagery for the thirteen
claims**, and that is why nothing on the option sheet was photo-led. That was
true of the media library as a *practice-area* set: nothing is attached to a
claim page as a featured image. But **each of the thirteen live claim pages
carries an image in its own body or its `og:image`**, and crawling all thirteen
turns up a picture for every single one. So the grid is drawable after all —
from the site's own choices, not from a pairing this prototype invented. The
earlier finding was not wrong, it was asked of the wrong place.

### Eleven of the thirteen are already black and white — measured, not read off the filenames

Three of them *say* they are (`blackandwhitemiata`, `blackandwhiteMotorCycle`,
`DogBiteBW`), which is exactly the kind of evidence worth nothing: a name is
not a measurement. Mean per-pixel chroma on an 80×80 thumbnail, computed at
build time:

**Monochrome (11):** car, motorcycle, passenger, hit-and-run, slip and fall,
premises, school, product liability, dog, boating, assault.
**Colour (2):** cyclist (13.2), pedestrian (12.0).

In a grid of thirteen those two read as mistakes rather than as variety, and
black and white is the site's own tone — every team portrait, the inner service
hero, and eleven of these thirteen. So the tiles are filtered to match: **one
line, changing exactly two of them**, and the build asserts which two, so the
filter cannot quietly start doing more than it should.

### The module is the team page's bench, exactly

`1280 = 5 × 230.4 + 4 × 32`, same cell, same gutter. The site now has **one
card**, used for people on one page and for claims on this one, rather than two
that nearly match. Thirteen is awkward in every column count — 4 leaves a lone
tile on row four, 6 leaves one on row three — and **five leaves a row of three,
which reads as a row rather than an orphan**. Measured: thirteen cells, every
one 230.4 wide, rows 5/5/3, every image 230.4.

`object-fit:cover` in a fixed 230.4×173 box is what makes thirteen pictures of
thirteen shapes — **0.71:1 to 2.00:1** — the same size. Same mechanism that
retired the thirteen-widths defect on the team page.

**The grouping is not drawn.** Road Accidents / On Premises / Other Claims is
home_v1's proposal and the live menu lists the thirteen flat, so a grid that
ignores it loses nothing the site has decided — and the layout does not have to
survive the taxonomy changing.

### Where a crop sits is not a detail

Two sources are portrait and lose most of their height to a 4:3 box, so the
anchor decides whether the tile shows the subject at all. Both were **looked
at**, not guessed: the motorcycle photograph is a rider's-eye view with the
machine in the **lower** half, so the first anchor (top, 22%) produced a tile
of empty road and no motorcycle; the dog's open jaw fills the frame and centres
slightly high. Anchored per photograph — `50% 62%` and `50% 40%` — rather than
by one rule for "tall", and **the build refuses a portrait source that has no
anchor of its own** rather than shipping a tile cropped to whatever the middle
of the frame happens to hold.

### Page weight, stated

The tiles display at 230.4px. The map names **derivatives, not originals**:
Pedestrian's original alone is 5472×3648 and **3.78 MB**. Even so —

| set | total |
|---|---|
| the 768px derivatives used here | **2,427 KB** |
| the 300px derivatives | 379 KB |
| the originals | 6,942 KB |

768 is 3.3× the display size — more than 2× retina needs and far more than the
page should carry; 300 is 1.3×, light but soft on a retina screen. **Neither is
right, because the size that is right (≈461px) does not exist in the media
library.** The real fix is a registered image size at 460px, which is a
WordPress setting, not a layout decision. 768 is used here so the review is not
judged on soft pictures, and the number is written down rather than hidden.

### Measured

Intro 762×109 centred · claims band 1425×791 (56px above the grid, the same
beat the bench sits on) · grid 1280×671 · thirteen cells 230.4×201, photo box
230.4×173 · rows 5/5/3 · `filter: grayscale(1)` confirmed in the computed
style · 26 images, none broken · document **1947**.

### One inherited defect this round names

The team page's bench turns a name **brand orange** on hover — `#EF6D3E`,
**3.03:1**, under the floor for 12px bold. This grid uses `#A94A29` (5.68:1)
instead. **The bench should follow**, and it is the second AA failure inherited
from home_v1 after the `#9A948B` label grey (3.01:1).

## `.claims` — layout options (2026-08-31, zeina branch)

**Asked:** *"buat beberapa opsi tampilan layout untuk class=claims"*

Six in **<https://leaguelaw.demoing.info/wp-content/prototype/claims-options.html>**
(33,190 bytes · HTTP 302). Generator `prototyping/gen_claims_options.py`;
backup `prototyping/claims-options-v1.html`.

Every option carries the real thirteen, their real URLs and the photograph the
**live claim page itself uses** — all executed out of `gen_injuries_index.py`,
78 images and 78 links asserted, so nothing can drift from the page.

### Thirteen is the constraint, and exactly one option solves it

Thirteen is prime, so every plain grid leaves a ragged last row: four across
leaves a lone tile on row four, five leaves a row of three, six leaves a lone
tile on row three. **C3 is the only layout where thirteen fits exactly, and not
by styling** — a 4-column grid is 16 cells over four rows, a 2×2 lead takes
four, and the remaining twelve hold exactly the other twelve claims. Verified
in the browser: rows of 3 / 2 / 4 / 4 counting the lead once, no hole.

| | | height | tile | last row |
|---|---|---|---|---|
| **C1** | grid, caption under | **671** | 230×173 | three of five |
| **C2** | caption on the image | 722 | 230×230 | three of five |
| **C6** | hexagon tiles | 945 | 230×266.03 | three of five |
| **C5** | a row per group | 1018 | 193 / 302 / 411 | each row is full |
| **C3** | mosaic, one leading | 1088 | 296×220, lead 624×472 | **no hole at all** |
| **C4** | rows with thumbnails | 1314 | 96×72 | one column |

**The first draft of that table was wrong in two places, which is why it is
measured.** C2 *looked* like the short one because it has no caption band — it
is 51px taller, because 57px of extra picture on three rows costs more than
three caption bands saved. C3 *looked* like the tall one because its lead tile
is the biggest thing on the sheet — C4 is taller, because thirteen rows is
thirteen rows.

### What each one costs, in one line

* **C1** — the page as it stands, on the team page's bench module. One card for
  people and claims rather than two that nearly match.
* **C2** — the caption band goes back into the picture (173 → 230). **The scrim
  is the contrast, not decoration:** white on `rgba(0,0,0,.86)` measures 8.8:1
  over a mid photograph and **6.0:1 over the brightest of the thirteen**. A
  lighter scrim would fail on the bright tiles only — the worst kind of failure,
  because it looks right on whichever ones you happen to check.
* **C3** — also answers what a flat grid cannot: **the thirteen are not peers**.
  Which one leads is the firm's call, not a layout's.
* **C4** — the most scannable by far, and the only option that could ship at a
  tenth of today's page weight (at 96×72 the 300px derivatives are already
  enough). Cost: it spends the pictures; four of the thirteen are close crops
  that stop reading at that size.
* **C5** — each group fills the full 1280, so **the tile size IS the group
  size**. That is also its cost: **Road Accidents ends up with the smallest
  tiles because it has the most claims**, which is exactly backwards if size is
  saying importance. And it is the option that breaks if the taxonomy changes —
  the grouping is home_v1's proposal, not the firm's.
* **C6** — the brand shape on ratio, `230.4 / 0.8660254 = 266.03`. Cost is in
  the shape: **a hexagon mask cuts four corners off every photograph**, and none
  of these thirteen was framed for it.

### The mistake, and why it matters more than the fix

C2's first render had **thirteen scrims and not one visible name**, and *the
height measured correctly the whole time* — 722px either way. `position:
relative` was on `.ph`, but the name is a **sibling** of the photograph, not a
child, so it positioned against the page and landed nowhere near its tile.
Found by looking at the picture. Third time this round of work that a
measurement passed on a layout that was visibly broken; the rule holds — a
measurement checks what you name, a picture checks everything at once.

### Settled, and identical in all six

**Tone** — eleven of the thirteen are already black and white on the live site,
measured as mean per-pixel chroma rather than read off filenames like
`blackandwhitemiata`; all thirteen are filtered so the cyclist and the
pedestrian do not read as mistakes. **Crops** — the two portrait sources are
anchored where their subject is (`50% 62%` and `50% 40%`), inherited by every
option, so none is judged on a crop the others do not have. **Colour** — names
brown 10.87:1, hover `#A94A29` 5.68:1; brand orange carries no word anywhere.

## `.claims` — the four-column grid, added (2026-08-31, zeina branch)

**Asked:** *"tambahkan opsi untuk layout grid column hanya 4"*

Added to the same sheet, which is now nine frames
(**<https://leaguelaw.demoing.info/wp-content/prototype/claims-options.html>**,
46,301 bytes · HTTP 302; backup `prototyping/claims-options-v2.html`).
`1280 = 4 × 296 + 3 × 32`, tile **296 × 222** at 4:3 — 28% wider than C1's 230,
so the photographs are the biggest of any even grid on the sheet.

### It is drawn three times, because of what four does to thirteen

**Four is the column count thirteen likes least.** 4 + 4 + 4 leaves **one claim
alone on a fourth row beside three empty cells**. Five leaves a row of three,
which reads as a row; one tile beside three holes reads as a mistake, and no
amount of styling changes that. So rather than draw it once and let the caption
apologise, it is drawn as the problem and its two honest cures — the same pair
the practice-areas round arrived at: make the count divide, or stop using a
grid.

| | | height | last row |
|---|---|---|---|
| **C7** | as it falls | 1096 | **one beside three holes** |
| **C7·b** | last row centred | 1096 | one, centred |
| **C7·a** | first claim across the top | 1179 | **no hole at all** |

* **C7·a** cures it **by changing the count, not by stretching a tile**: the
  first claim takes the whole top row at 1280×300, and 1 + 4 + 4 + 4 = 13.
  Same trick as C3, same question behind it — it only works if one claim
  genuinely leads, and *which* one is the firm's call. Cost: the band is 1280px
  of photograph, and only two of the thirteen sources are wide enough not to be
  cropped hard to fill it.
* **C7·b** cures it **by moving it**: flexbox instead of grid, so the short row
  centres itself and the three full rows are untouched — `4 × 296 + 3 × 32` is
  exactly 1280, so there is nothing to centre until the row that is short. One
  property; all thirteen stay the same size, which C7·a's do not. Measured: the
  lone tile's centre lands on **712.5**, the container's centre to the pixel.
  Cost: a centred single tile still announces that the count did not divide —
  it just does it politely.

**C7 and C7·b are the same height to the pixel (1096).** Centring the short row
costs nothing and saves nothing; it is purely about how the gap reads.

### A claim from the last round, corrected

The sheet said *"C3 is the only layout where thirteen fits exactly"*. With
C7·a on it that is no longer true, and the box now says what is actually
general: **two options fit exactly, and both do it the same way — by changing
the count, not the tile.** Neither is a layout solution; both are content
decisions wearing a layout.

## `.claims` — hover, and what the measurement said about it (2026-08-31, zeina branch)

**Asked:** *"bisakah jika di hover, image jadi berwarna?"*

Three hover treatments added to
**<https://leaguelaw.demoing.info/wp-content/prototype/claims-options.html>**
(57,860 bytes; backup `prototyping/claims-options-v3.html`), each drawn twice —
**at rest and hovered** — so the effect is something to look at rather than
something to go and find with a mouse. The row of five is chosen to contain
**both** colour sources.

**Applied to the page:** H·b, the duotone
(**<https://leaguelaw.demoing.info/wp-content/prototype/injuries-index.html>**,
61,943 bytes; backup `injuries-index-v3.html`). `HOVER` in the generator
switches between `duotone` / `colour` / `lift` / `none`.

### The literal answer is no, and the measurement is why

`filter:grayscale(0)` is the whole of "make it colour on hover" — and
**eleven of the thirteen photographs are already black and white in the source
file**, so on eleven tiles it returns nothing. Only the cyclist and the
pedestrian change, which is visible in H·a's hovered row: three tiles
identical, two shifting. **A hover that works on two tiles in thirteen is worse
than no hover** — the reader learns the rule from whichever tile they touch
first, and the other eleven then look broken.

### So the colour comes from the brand instead of from the file

**H·b** puts an orange layer over the photograph with `mix-blend-mode:color`,
which takes its **hue** from the overlay and its **luminance** from the
photograph. It therefore asks nothing of the source: all thirteen behave
identically, and the colour that arrives is *the firm's* rather than whatever
the stock photograph happened to be shot in. Cost: it is a strong effect, and
orange over a dark photograph goes muddy — the dog and the passenger tiles are
the ones to judge it on.

**H·c** is the quiet alternative: `brightness(1.18) contrast(1.06)`, no colour
at all. It works on thirteen for the same reason H·b does, keeps the page in
the monochrome every other page of this rebuild is in, and is **the only one of
the three that survives the November shoot changing every photograph** — H·a
would start working on tiles it does not work on today, which is a hover whose
behaviour depends on which photographs happen to be in the library.

### The same mistake, twice in one session

The duotone's first render painted orange over the **whole section, captions
included**, from a rule aimed at one tile. `.ph` had no `position:relative`, so
the absolutely positioned `:before` with `inset:0` resolved against the initial
containing block. That is exactly the C2 caption bug from the layout round — a
positioned child whose parent was never positioned — and it is now written into
the CSS as a comment at both sites rather than left to be rediscovered a third
time.

Verified per tile rather than by eye: with the hover forced on tiles 1 and 3,
measured chroma is **59.8 / 0.0 / 146.2 / 0.0 / 0.0** across the first row. At
rest the whole grid measures **0.0**.

## `.claims` — hover corrected: grayscale off, C7 only (2026-08-31, zeina branch)

**Asked:** *"yang saya maksud adalah ketika di hover hilangkan filter
grayscalenya dan hanya update pada C7."*

Two corrections, and the second is mine to own.

**1 · The hover is `filter:grayscale(0)`, not a duotone.** C7 now takes the
grayscale off under the cursor, with a 0.3s transition.
`prototyping/claims-options-v4.html`.

**2 · It is on C7 and nowhere else.** I had applied the duotone to
`injuries-index.html`, which was not asked for. Reverted — `HOVER = "none"` —
so the page is back to the orange rule under the tile and nothing more, and the
behaviour lives with the option until the option is picked.
`prototyping/injuries-index-v4.html` (60,997 bytes).

**C7·a and C7·b are deliberately left without it**, so the sheet now shows the
same layout with and without the behaviour, side by side, which is a better
comparison than three copies of the same hover.

### What C7's caption now has to say, because it is C7's behaviour

Eleven of the thirteen sources are already black and white, so on eleven tiles
`grayscale(0)` returns nothing. Verified rather than asserted: with the hover
forced on the car tile (a monochrome source) and the cyclist tile (a colour
source), measured chroma across the first C7 row is **0.0 / 0.0 / 13.5 / 0.0** —
the car does not change at all, and the cyclist's change is real but slight,
because that photograph is low-saturation to begin with.

H·a / H·b / H·c stay on the sheet. They are no longer proposals; they are the
evidence for why C7's hover behaves the way it does, and what the alternatives
would cost if that turns out not to be enough.

**`position:relative` stays on the tile** even though nothing is positioned
inside it today, with the reason written down: any absolutely positioned child
added later — a scrim, a badge, another hover layer — needs it, and without it
one resolved against the initial containing block and painted the whole section
orange.

## `.claims` — option round 2: five different families (2026-08-31, zeina branch)

**Asked:** *"bisakah kamu tambahkan beberapa opsi tampilan layout yang berbeda?"*

Five added to the same sheet, which is now fourteen layouts plus the three
hover treatments (**<https://leaguelaw.demoing.info/wp-content/prototype/claims-options.html>**,
82,155 bytes · HTTP 302; backup `prototyping/claims-options-v5.html`). The
hover round moved to the end — it is not a layout, and it was sitting between
the two rounds that are.

**Round 1 worked the grid. Round 2 changes the family** — a wall, an
interaction, a rhythm, a strip, a shape.

| | | height | what is new about it |
|---|---|---|---|
| **C11** | filmstrip | **223** | one row, scrolled sideways |
| **C9** | index, one preview | 559 | thirteen names, **one** photograph |
| **C8** | the wall, no gutters | 640 | the thirteen as one block |
| **C10** | staggered | 776 | the same grid with a rhythm |
| **C12** | circles | 844 | a shape that is not the brand's |

### C8 answers thirteen a third way

C3 and C7·a solve the ragged row by **changing the count** (a lead tile). C8
solves it by **changing what a row is**: with no gutters, five across is 256 —
the home page's own lattice, `5 × 256 = 1280` — and the last row's three divide
the same 1280 at **426.67** each, so every row reaches both edges and the
ragged row does not occur at all. Measured: 256.00 and 426.66.

Cost is tonal rather than geometric: no air between one accident and the next.

### C9 is the only option that fixes the page weight

Thirteen names and one photograph, the picture changing with the cursor. Pure
CSS — the previews are siblings of the names, so
`:nth-child(n):hover ~ :nth-child(n+13)` reaches the right one and no script is
needed; verified in the browser, exactly **one preview visible at rest**. It is
the only layout here that does not put thirteen images on the page, so twelve
can load lazily and most visitors never ask for them — which is the 2,427 KB
answered.

**Its cost is the one that decides it: there is no hover on a phone.** On touch
it needs a tap-to-show or it degrades to a plain list, which is C4 without the
thumbnails.

### The arithmetic worth keeping from this round

* **C10 costs exactly 105px** — half a tile — over C1 and nothing else, because
  the stagger is a `translate`, not a margin, so the grid still lays out as a
  plain grid. 776 against 671, measured.
* **C11 is 3,187px of strip in a 1,280px window** (13 × 230.4 + 12 × 16), so
  about five of the thirteen are visible. It is the shortest thing on the sheet
  by a factor of three — and on an *index*, **it hides eight**. A visitor who
  never drags never learns the firm handles dog attacks.
* **A circle keeps π/4 = 78.5% of its frame; a regular hexagon keeps exactly
  3/4.** So C12 crops *less* than C6 does, which is worth having before either
  is rejected on cropping. What a circle costs instead is the brand.

### Corrected before publishing

The filmstrip caption said 2,987px. The measurement said **3,187** — 13 × 230.4
is 2,995.2, not 2,795. Arithmetic done in a caption is arithmetic that has not
been checked; the browser checked it.

## `.claims` — C13, the triage checkerboard (2026-08-31, zeina branch)

**Asked:** *"tambahkan opsi lagi dengan tampilan yang mirip hero di home_v1.html"*

Added as **C13** (**<https://leaguelaw.demoing.info/wp-content/prototype/claims-options.html>**,
90,179 bytes · HTTP 302; backup `prototyping/claims-options-v6.html`).

**home_v1 has no hero.** Its first screen is `.triage` — its own comment says
so: *"the first screen. No hero, no h1, no copy."* So the thing to resemble is
the checkerboard, and it is lifted part for part: **gutterless**, five columns,
`grid-auto-rows: 280px`, white type cells alternating with photographs, tone
alternating orange and teal, a 44×3 rule over the heading, and a hexagon marker
that scales in under the cursor. Measured: cells **256.00 × 280**, rows 5/5/3,
**seven photographs and six type cells**.

### One thing is deliberately not copied, and it is a defect

home_v1 sets the triage headings in **brand orange and brand teal at 21px
weight 300**. On white that measures **3.03:1** and **2.60:1** — and 21px at
weight 300 is *not* large text by WCAG, so the floor is 4.5:1, not 3:1. Both
fail; teal fails even the large-text floor it does not qualify for.

Here the heading is **brown (10.87:1)** and **the orange and teal move to the
rule and the marker**, which are non-text and need only 3:1. The alternation —
the thing that makes it look like the triage — survives intact; the failure
does not. **The same fix is owed to the homepage**, and this is now the third
AA failure inherited from home_v1 after the `#9A948B` label grey (3.01:1) and
the bench's orange hover (3.03:1).

### What the checkerboard costs, and the borrowed cure

Seven claims arrive as a photograph and six as a word, and **which six is
decided by position, not importance**. So, borrowing the triage's own `.flip`,
**a type cell reveals its own photograph on hover** and no claim is left
without one. White on `rgba(0,0,0,.82)` measures **7.5:1** over a mid
photograph and **5.0:1** over the brightest of the thirteen — a lighter veil
would pass on the dark tiles and fail on the bright ones, which is the failure
mode that looks fine on whichever tile you check.

Thirteen still does not divide by five, so the block ends two cells short on
the third row. C8 cures exactly that by letting the last row divide the full
width; doing it here would break the 256px module the triage is built on, so it
is left visible rather than fixed with a trick borrowed from another option.

**Height 840** — 3 × 280, and nothing else, because the cell is the whole
layout.

## `.claims` — option round 3: four families that leave the tile behind (2026-08-31, zeina branch)

**Asked:** *"tambahkan opsi layout yang berbeda lagi"*

The sheet is now **nineteen layouts plus the three hover treatments**
(**<https://leaguelaw.demoing.info/wp-content/prototype/claims-options.html>**,
110,928 bytes · HTTP 302; backup `prototyping/claims-options-v7.html`).
Round 1 worked the grid, round 2 changed the family, **round 3 leaves the tile
behind altogether**: a band, a slice, an editorial row, a poster.

| | | height | the picture becomes |
|---|---|---|---|
| **C17** | the poster | **362** | one background for all thirteen |
| **C15** | vertical slices | 420 | a 96.6 × 420 column |
| **C14** | horizontal accordion | 833 | a 1280 × 64 band |
| **C16** | editorial rows | **4224** | a 520 × 280 plate per claim |

* **C14** — thirteen full-width bands, `13 × 64 = 832 with no grid at all`,
  opening to 240 under the cursor. Cost is arithmetic: **a 1280 × 64 band is a
  20:1 crop**, and twelve of the thirteen sources are between 0.71:1 and
  2.00:1, so at rest each is a slit through the middle of its frame. The layout
  only shows a photograph while the cursor is on it.
* **C15** — the same idea turned ninety degrees. **The only option on the sheet
  whose height does not depend on thirteen**: 420 whatever the count becomes,
  which matters for a practice area that keeps growing. `(1280 − 12 × 2) / 13 =
  96.6` per slice, a **1:4.35** crop — the narrowest anything is cropped here.
* **C16** — the family every other option is avoiding. Each claim gets a whole
  row and a 520 × 280 photograph, the largest any single claim gets except C3's
  lead. **Its cost is not a trade-off, it is a number: 4,224px.** It is the
  layout for a page meant to be read through; an index is meant to be scanned.
* **C17** — one photograph behind the section, thirteen names over it. Like C9
  it puts a single image on the page — the 2,427 KB answered — but with **no
  interaction at all, so it behaves the same on a phone**, which is exactly
  where C9 fails. White on `rgba(0,0,0,.78)` measures **6.4:1** over this
  photograph and would be 5.4:1 over the brightest of the thirteen, so the veil
  is safe whichever picture is chosen later. **Which one that is, is a
  decision** — right now the whole of injury law is illustrated by a car
  accident.

### The mistake, for the third time in this family of bugs

C15's names were **clipped**, and the frame's height measured correctly the
whole time. The first version rotated each name about its own bottom-centre, so
half of every long one swung outside the 96.6px slice and `overflow:hidden` ate
it. Replaced with `writing-mode: vertical-rl` + `rotate(180deg)`, which flows
the text *inside* the box so the slice can never be too narrow for it — and
this time the check is mechanical rather than visual: the build's measurement
pass asserts **0 of 13 names fall outside their slice**.

That is now three bugs of one shape on this sheet — C2's caption positioned
against the page, the duotone painted over the whole section, and this — and
all three passed their height measurement. The rule earns its keep: a
measurement checks what you name, a picture checks everything at once, **and a
measurement written to check the thing that actually broke is better than
either**.

## Injuries index — C7 picked and fitted (2026-08-31, zeina branch)

**Asked:** *"gunakan c7 saja terlebih dahulu."*

**<https://leaguelaw.demoing.info/wp-content/prototype/injuries-index.html>**
(60,229 bytes · HTTP 302). Backup `prototyping/injuries-index-v5.html`; `-v3`
is the five-across version, `-v1` the text columns. `LAYOUT` switches between
`c7` / `grid` / `cols`.

Four across, `1280 = 4 × 296 + 3 × 32`, tile **296 × 222** at 4:3 — **28%
wider** than the five-across version it replaces, so these are the biggest
photographs any even grid on the sheet gives them. Measured: thirteen cells,
every one 296.0, rows **4 / 4 / 4 / 1**, grid 1280×1096, claims band 1425×1216,
document 2372 (up 425 from the five-across build — bigger tiles cost a row).

**C7's hover came with it:** `filter:grayscale(0)` with a 0.3s transition, and
the build asserts the two travel together — the grayscale-off hover is C7's,
and it is not drawn for the other treatments. What it does and does not do is
written into the CSS at the site: eleven of the thirteen sources are black and
white in the file, so on eleven tiles it returns nothing and only the cyclist
and the pedestrian change.

**The last row is one tile beside three empty cells, and it is left that way on
purpose.** Thirteen is prime and four is the column count it likes least; the
sheet draws the two honest cures beside C7 — C7·a puts the first claim across
the whole top row so 1 + 4 + 4 + 4 = 13, C7·b centres the short row — and
either is a one-line change here. It falls as it falls because that is the
option that was picked.

Everything above the grid is unchanged: header 1425×93, hero 1425×421, intro
762×109 centred, footer 1425×478.5, CTA tab 43×212, 26 images, none broken.

## Careers — first build (2026-08-31, zeina branch)

**Asked:** *"prototype untuk halaman career … untuk header, hero, footer dan
ctatab mengikuti halaman halaman sebelumnya."*

Served: **<https://leaguelaw.demoing.info/wp-content/prototype/careers.html>**
(65,750 bytes · HTTP 302). Generator `prototyping/gen_careers.py`; backup
`prototyping/careers-v1.html`; content in `prototyping/careers.json`.

**Five pages, one shell.** The four calls are the same ones the team page, the
service index and the injuries index make — `_header()`, `_hero_css()` + the
option sheet's `A1()`, `_footer()`, `_consult()`. Nothing about the shell is
designed here.

Content is a read-only crawl extracted to JSON: three postings with their own
paragraphs, requirement lists and apply addresses, plus the closing block about
future vacancies. Nothing retyped; the non-breaking spaces are asserted.

### The hero writes itself from the page

Icon **`fa-suitcase`** — the live page's own; it sits in the hexagon at the top
of its intro block, so the page keeps its mark rather than being given one.
Title **"Careers"** — the live h1, short, and the site's own word, so unlike
the team page's 68-character h1 and the injuries page's keyword title there is
nothing to decide. Sub-line **"3 positions open"**, **derived from the postings
rather than typed** — on a live site this has to count the openings or it
becomes a lie the first time one is filled. Photograph: two people at a desk,
768×512 into the 420×380 panel (a downscale), tagged like every other hero —
the firm has no photograph of its own people at work, which is what the
November shoot is for.

### The postings: a defect fixed by construction

**The live page has no headings for them.** Its three job titles are
`<p><strong>…</strong></p>` — bold paragraphs — so the whole page has *one*
heading for three jobs and a screen reader's heading list says "Career
Opportunities" and stops. Here each posting is a real `<h3>` inside a
`<details>`, and **the build counts them (3)** so the CSS comment claiming it
cannot drift from the markup.

`<details>`/`<summary>`, not a script: it opens without JavaScript, it is
keyboard-operable and announced as an expandable region for free, and Ctrl-F
finds text inside a closed one in current browsers. Three postings of ~350
words is 2,000+ words of page and a visitor wants **one** of them; the first is
open so the page never reads as three closed doors. Measured: section 1,431
with one open, closed rows 143 and 114, document 2,598.

The hexagon marker is on ratio (13 / 0.8660254 = 15.01) and **turns a quarter
when the posting opens** — a mark that promises an action has to perform one,
which is the same rule the sidebar round arrived at.

### Two things the build caught that would have failed silently

1. **`var(--paper)` and `var(--line)` are not defined on this page.** They are
   home_v1's tokens; the shell's `:root` has `--brown`, `--orange`, `--body`
   but not those two. The vars resolved to nothing, which meant **a transparent
   panel and no rule between any posting — and nothing errored.** Both are
   literals now, and the build asserts every custom property this page's own
   CSS uses is defined.
2. That guard then failed on `var(--paper)` **inside the comment explaining why
   it is not used**. Comments are stripped before the scan — the same trap that
   made the header sweep drop every rule following a comment.

### Left as found, and worth the firm's attention

* **One posting of three states no location.** The litigator posting says
  "downtown Victoria" inside its body and nothing on its title line, where the
  other two carry "Victoria, British Columbia" as a second line. The layout
  does not invent one — an empty meta line is the truth.
* **Two of the three titles repeat the firm's name** ("… – League and Williams
  Lawyers") on a page that is already the firm's careers page.
* The three apply addresses are **jwilliams@**, **ngordon@** and **jwilliams@**,
  and the closing block adds a fourth route to **ngordon@** — four addresses for
  three jobs, printed five times.

## Careers — the count out of the hero, the accordion out of the page (2026-08-31, zeina branch)

**Asked:** *"3 positions open ini sebaiknya cari opsi copy lain, karena client
harus mengupdate jumlah setiap saat … kemudian untuk menampilkan open position
sebaiknya jangan dalam accordion."*

Backup `prototyping/careers-v2.html` (65,658 bytes · HTTP 302); `-v1` is the
accordion version.

### 1 · A number in the hero is a number somebody has to remember

Adi is right and the reason is worth writing down: the day a posting is filled,
the hero is wrong. It was *derived* from the data in this generator, which
hides the problem rather than solving it — on the real site those postings are
hand-edited paragraphs, so the count would be maintained by hand, and the first
person to forget makes the firm look careless **on the one page where
carefulness is the product**.

The line is now **"Join the team"** — the page's own words, from its h2
(*"Career Opportunities at League and Williams – Apply to join our team!"*),
and true whatever the board holds.

Considered and rejected, with the reason: *"Victoria, British Columbia"* — true
and durable, but the postings already say it twice and it tells a visitor
nothing they came for · *"We're hiring"* — rots the same way the moment nothing
is open · *"Careers"* — repeats the h1 directly above it.

**The jump list carries no count either**, for the same reason: it names the
three roles and numbers none of them.

### 2 · Nothing is hidden

The `<details>` accordion is gone. **An open position is what a visitor came
for, and a layout whose first act is to close two of the three makes them work
to find out whether the firm has anything for them.** Ctrl-F and search engines
both prefer it open as well.

What the accordion was solving is real — three postings of ~350 words is 2,000+
words — so **the length is handled by navigation rather than concealment**: a
jump list at the top of the section names the three roles and takes you to one.
Measured: three anchors, **all three resolve**, `scroll-margin-top` so a jump
does not land the heading against the top edge.

The hexagon marker went with the accordion. It was the disclosure's
affordance; with nothing to disclose, a mark promising an action that no longer
exists is the "affordance that lied" the sidebar round already ruled on.

Measured: postings 581 / 948 / 1018, section 3,099, document **4,266** (was
2,598 with two closed). That is the cost of hiding nothing, and it is the right
cost on this page.

Unchanged and still asserted: each posting is a real `<h3>` (the live page's
titles are bold paragraphs), three apply blocks, no count anywhere in the
output.

## Open positions — layout options (2026-08-31, zeina branch)

**Asked:** *"class=roles pada bagian ini saya kurang setuju, karena jika open
position ada banyak akan berantakan. mungkin kamu bisa buat beberapa opsi untuk
tampilan open positionnya."*

Five in **<https://leaguelaw.demoing.info/wp-content/prototype/careers-options.html>**
(28,687 bytes · HTTP 302). Generator `prototyping/gen_careers_options.py`;
backup `prototyping/careers-options-v1.html`. **`careers.html` is unchanged** —
it keeps `.roles` until one of these is picked.

### The objection names the constraint, so the sheet is built around it

`.roles` is one flex row of full job titles. At three it fits on one line and
looks tidy, **which is exactly the trap**. A component that only works at the
count it was drawn for is not a component.

So **every option is drawn twice — with the real three, and with the same three
repeated to nine.** The nine are a **stress test, not invented postings**, and
every stressed frame says so on the frame; the build asserts the badge appears
six times. What is being compared is not how an option looks with three roles.
It is what it does when the firm is hiring.

| | | three | nine | what it costs |
|---|---|---|---|---|
| **P0** | today's flex row | 29 | 89 | **no alignment; wraps into a paragraph** |
| **P2** | ruled rows | 168 | 501 | plain |
| **P1** | cards | 173 | 566 | a big object for a line of text |
| **P5** | grouped | 298 | 587 | needs a taxonomy the firm has not given |
| **P3** | sticky rail | 303 | 628 | 280px of width, always |
| **P4** | no index at all | 395 | 1183 | nothing to jump with |

* **P0** — the baseline, and the nine is the argument: three ragged lines,
  nothing aligned, a paragraph of links rather than a list.
* **P1 cards** — the count stops mattering: nine is three rows, twelve is four,
  and **every card is the same size whatever its title's length**, which is the
  one thing a flex row cannot do.
* **P2 ruled rows** — alignment down the page is exactly what the wrapping row
  cannot give, and it is what makes a long list scannable: the eye runs down one
  column instead of through a paragraph. **Cheapest per role of the five.**
* **P3 sticky rail** — the roles stay on screen while the postings scroll. The
  sidebar round already measured the trap, so the rail is capped at
  `calc(100vh - 48px)` and scrolls inside itself — **which is precisely the case
  a long board produces**.
* **P4 no index** — asks whether the index earns its place. At three it plainly
  does not; the frames are the posting *headers*, so the cost at nine is visible
  as well: 1,183px of headers with nothing to jump with.
* **P5 grouped** — **the only option whose readability improves as the board
  grows.** It also answers something none of the others do: a conveyancing
  assistant and an articling student are not looking for the same page. The
  grouping is a proposal derived from the titles — the firm has not published
  one — the same standing the injury claims are grouped on, and if it is wrong
  this option is wrong in a way P1–P4 are not.

**Colour is not one of the variables** — identical in all five so the comparison
is about growth. Role names brown 10.87:1, meta `#6B6B6B` 5.33:1, doors
`#2F7186` 5.50:1, hover `#A94A29` 5.68:1; brand orange carries no word.

**One posting of three states no location**, so the meta column is empty for it
in every option. That is the live page's inconsistency, not the layout's, and
no option fills it in.

## Careers — P2 picked and fitted (2026-08-31, zeina branch)

**Asked:** *"gunakan P2 saja."*

**<https://leaguelaw.demoing.info/wp-content/prototype/careers.html>**
(67,275 bytes · HTTP 302). Backup `prototyping/careers-v3.html`; `-v2` is the
flex row, `-v1` the accordion.

Ruled rows with the columns aligned down the page: name, place, door.
**Alignment is the whole point** — it is what a wrapping row cannot give, it is
what lets the eye run down one column instead of through a paragraph of links,
and it costs the same per role whether there are three or thirty.

**Verified as alignment, not as looks.** Each column's left edge measured on
every row: name **262.5**, place **876.4**, door **1110.4** — one x per column,
so the three rows line up to the pixel. Rows 58px each; the section is 3,247
and the document 4,413.

**The empty cell stays empty.** The litigator posting states no location, so its
place column is blank. In an aligned list an empty cell is information — it says
this posting does not tell you where the job is — and filling it in would be
invention. That is the same inconsistency the option sheet flagged, now visible
on the page rather than described in a note.

The build asserts what was picked: one `<nav class="roles">`, three name cells
and three doors, every anchor resolving, and still **no count anywhere** in the
output.
