Redress Claims Advocacy

Generative Assets · industry demonstration 447

How this page was built

Redress Claims Advocacy is a fictional Subiaco practice that reads an insurer’s settlement offer against a builder’s scope of works. Its audience is a homeowner, strata council or small-business owner holding an offer that does not cover the work. The page has one job: show the size of the gap, name the routes that cost nothing, and take only the claims where paying somebody is actually worth it.

Everything on the site is procedural — no photographs, no icon library, no JavaScript framework, no build step. Two self-contained files.

The proof element

The settlement gap check

Two currency inputs, both off the reader’s own paperwork: what the insurer offered, and what their builder says the work costs. The difference is the gap, and the gap is the only thing this business sells against. The card answers three questions in one screen — how big is the gap, will you take it, and what would it cost me — and draws all three to scale.

The arithmetic

Our fee is 15% of the gap we recover, with a $900 minimum, and nothing if nothing is recovered. Below a $3,000 gap we decline the work outright. Every figure is held in integer cents and divided once at display, so no rounding drift can appear between the ledger and the drawing.

OfferScopeGapVerdictOur feeYoursFee as a share
$42,000$71,500$29,500Taken$4,425$25,07515.0%
$9,500$14,200$4,700Taken, floor applies$900$3,80019.1%
$18,000$20,400$2,400Declined
$0$3,000$3,000Taken (first gap we take)$900$2,10030.0%
$0$6,000$6,000Taken (floor lifts here)$900$5,10015.0%
$50,000$40,000−$10,000Nothing to recover

Every row above is reproduced by an independently reimplemented oracle in the build harness, not read off the page’s own function. The harness drives the two inputs, reads window.__claimsadvocate, and compares the model field by field.

The second read

Under the split bar sits a small curve: our fee as a share of the gap, from $3,000 to $30,000. Because the fee is max(15% of gap, $900), the share starts at 30% and falls until the two meet. They meet at exactly $6,000 — $900 ÷ 0.15 — and the page marks that point with a dashed line and names it. That figure is derived in code from the fee constants, never typed, so the drawing cannot drift from the model. It is also the least flattering fact on the page: it tells a reader with a small claim that we are expensive.

Where the page argues against its own sale

The decline branch is the page

Below a $3,000 gap the result card stops being a quote. It is built at the same size and with the same design budget as the sell branch, in the page’s dark band, and it contains no dollar figure at all — the build harness asserts zero occurrences of a dollar sign inside the verdict card in that state, because the temptation to slide a small fee in underneath is exactly what the branch exists to resist.

The card does not argue in our voice. It quotes the authority the reader would check — the Australian Financial Complaints Authority — verbatim, with the source named under each quotation:

“AFCA’s complaint resolution scheme is free of charge for Complainants” · AFCA, afca.org.au

“A Financial Firm is not permitted to recover its costs from a Complainant in connection with our consideration of a complaint.” · AFCA, afca.org.au

“There is no need to obtain legal or other advice when lodging a complaint unless you wish to.” · AFCA, How to make a complaint

“Completing your complaint online usually takes 30–50 minutes.” and “the first step is usually to raise it with them directly” · AFCA, Make a complaint

It then ends in something the reader can do today: AFCA’s public line, 1800 931 678, as a live tel: link, and a free fifteen-minute scope read from the business with no file opened and no engagement letter. A refusal that ends the conversation is a lost lead dressed up as honesty; this one leaves two things on screen to act on.

What was verified, and what was left out

Colour

Palette

A claims file is paper and a red ledger line, not a friendly insurance blue. The oxblood is the shortfall — it only ever draws the part of the scope the insurer has not paid for, and our fee. The steel blue is the insurer’s side of the table and, in the split bar, the reader’s own money. Ratios below are pasted from the wave contrast log, not computed by hand.

Ground#F6F4F0 page
Surface#FFFFFF cards
Ink#16181C 16.18:1 on ground
Muted#4E525A 7.14:1 on ground
Oxblood#6E2436 9.71:1 on ground
Steel blue#2A5680 6.97:1 on ground
Band#1B1E24 carries #F3F0EA at 14.68:1
On dark / on primary#F3F0EA 9.38:1 on oxblood
Map water#D7E0E9 minted — ink 13.31:1

Colours minted during the build, with their measured ratios, because the wave log declares only ground/surface/band: #D7E0E9 map water (ink 13.31:1, muted 5.87:1), #F0EEE9 inset paper for the result ledger (ink 15.33:1, muted 6.76:1, oxblood 9.20:1, steel 6.61:1), and two hairlines that never carry text — #DBD5CC and #C9C2B6 on light grounds, #343941 on the band. Every token on the page sits only on a ground the log declares PASS for it: #F3F0EA appears only on the band and on oxblood fills, #FFFFFF only on steel-blue fills, and ink and muted only on the light grounds.

Type

Fraunces and Source Sans 3

Fraunces at 600 and 700, optical size driven hard — opsz 144 on the gap figure, opsz 96 on the headline, opsz 20–36 on section heads. It is a soft serif with enough authority to carry a legal-adjacent page without looking like a law firm’s letterhead, and its high-optical-size cut gives the gap figure the flared, ledger-ruled quality the whole page is about. The one moment of typographic bravery is that figure: the gap set at up to 64px in Fraunces 700 with tabular lining numerals, so the digits do not shuffle as the reader types.

Source Sans 3 at 400 and 600 does everything else. Body copy is 16.5px, never below 14px anywhere on the page, and every number — ledger, bars, curve, form — is set with font-variant-numeric: tabular-nums lining-nums.

Technique

How the drawing works

Three stacked SVG bars share one scale: the insurer’s offer, the builder’s scope with the shortfall drawn in oxblood and bracketed, and the gap itself re-scaled to full width and split between the reader and us. The second and third bars are painted as a full-width base rect with the smaller segment drawn over it, so there is no seam to mis-join and no transition that can leave a white sliver mid-animation.

Every bar element is created once, synchronously, when the script runs, and updates only move attributes — nothing is inserted into the SVG after first paint, which is the failure mode that leaves a scene geometrically correct and visually blank in headless Chrome. There is no requestAnimationFrame loop anywhere on the page: the only motion is a CSS entrance stagger on cold load and a 420ms width transition on the bars, both switched off under prefers-reduced-motion in CSS and by a matchMedia check in JS. The page therefore reaches a finished, still frame well inside the seven-second screenshot window by construction rather than by tuning.

The service-area map is a single inline SVG: a coastline path, the Swan River as a stroked path in the map-water tint, fourteen suburb dots and a marked office square. Suburb labels are body ink at 13.5px, which measures 17.77:1 on the white land and 13.31:1 where a label crosses water.

Process

Three iteration passes

Each pass drove the enquiry form empty and filled, and drove the proof element through the take branch, the fee-floor branch and the decline branch, asserting the output each time rather than reading the page.

Pass 1 — Craft

Five real defects, four of them visible only in a rendered screenshot.

  • The masthead CTA would not hide at 375. .mast-cta{display:none} was declared before .btn{display:inline-flex} at the same specificity, so source order won and the button stayed live — which forced the wordmark to wrap to three lines and made the header 230px tall. Fixed by scoping the hide rule to .mast-in .mast-cta and pinning the wordmark to one line at a smaller optical size below 560px.
  • A seam in the scope bar. Two abutting rects with a 3px corner radius left a visible white notch at the offer/shortfall join. Repainted as base-plus-overlay.
  • The bracket label collided with its own bracket. “the gap” sat on the dashed rule; the drawing’s viewBox grew from 186 to 198 units and the three rows were re-spaced.
  • Anchor scrolling hid section headings under the sticky masthead. Added scroll-margin-top:78px to every section.
  • Map label collisions and dead space. Morley and Bassendean were 7 units apart on the same baseline; both were re-plotted, and the viewBox was cut from 640 to 545 units to remove an empty third of the frame. Two chip labels were shortened so the preset row fits on one line at 1200 — which is what put the whole drawing inside the thumbnail.

Drives: take branch $42,000/$71,500 → gap $29,500, fee $4,425, net $25,075, 15.0%. Floor branch $9,500/$14,200 → gap $4,700, fee $900, 19.1%. Decline branch $18,000/$20,400 → gap $2,400, fee 0, zero dollar signs in the verdict. Empty submit → 7 fields flagged, confirmation stays hidden. Filled submit → confirmation panel visible, form hidden.

Pass 2 — Depth

The card answered “what will this cost me” but not “when does your minimum stop hurting me”, which is the question a reader with a small claim actually has. Added the fee-share curve: our fee as a percentage of the gap from $3,000 to $30,000, with the crossing point derived in code as feeMinimum ÷ feeRate and drawn as a dashed marker at $6,000, plus a live dot showing where the reader’s own gap sits on it. It is exposed on the state probe as floorStopsBitingAtGap and asserted at 5,999 (floor bites), 6,000 (exactly 15%) and 6,001 (floor lifts). The curve is hidden in the decline branch, both in the model and in the DOM, so the branch that must carry no price carries no axis labels either.

Also added in this pass: a hero kicker stating the decline rule in the first screen, so the page’s character is legible in the thumbnail rather than only after an interaction; and a live handoff from the proof element to the enquiry form — the decline card’s scope-read button carries the two typed figures across and ticks “ring me, do not open a file”.

Drives: boundary $0/$2,999 declines and $0/$3,000 is taken at a fee of $900, which the card prints as 30.0% of the gap unprompted. Net was swept for monotonicity across every gap from $3,000 to $200,000 in $250 steps — zero reversals, so the quote can never fall as the claim grows.

Pass 3 — Hardening

  • 375px. Document scrollWidth is exactly 375 with no element of any kind past the edge. The h1, the primary CTA and the first trust line each finish above the sticky bar, measured against the bar’s top rather than the viewport.
  • Reduced motion. Media query and matchMedia guard: the entrance class is never applied and bar transitions are off, with every animated element measured at opacity 1 and the state probe still live.
  • Focus. A 3px oxblood :focus-visible ring everywhere, switched to the light ink inside the dark band and the sticky bar so it never disappears against its own ground.
  • The form pattern. The phone field’s pattern is compiled with the v flag in the harness, and the form is driven with junk in the phone box as well as with good data and with nothing at all — a character class that is legal in Node and illegal under v is silently discarded by the browser, and the field then accepts anything.
  • One ornament removed. A sixth services tile restated the decline rule that the proof element already makes at full size and the fee band states again. Deleting it brings the grid back to exactly the five priced lines the business actually sells.

Drives: all three proof branches re-driven at 375, 768 and 1440 with zero console errors at each; the decline card measured over 400px tall at 375 with all three quotations, all three steps and both actions present; the rendered 1200×750 thumbnail opened and read by eye to confirm the gap figure and the full split bar are in frame and legible.

Why this converts

The headline and the answer sit side by side, so a prospect scanning a gallery of thumbnails sees a real number rather than a menu of services — the gap is computed from two figures the visitor already has in front of them, which means the page starts working before anyone fills in anything.

The call button, the phone number and the enquiry anchor are within a thumb’s reach on every screen — header, hero, sticky bar, result card and form aside — because most of this traffic is a phone held in one hand beside an insurer’s letter.

The form asks for seven things and no more, and the two money fields are optional, because the fastest path to a callback should not require the visitor to find their policy schedule first.

The trust line does the work a badge row usually does badly: it names the free first appointment, the nothing-owed-if-nothing-recovered term and the limits of what the business is, in the visitor’s own words, above the fold.

And the page refuses work on screen, using the regulator’s wording rather than its own — which is the single most persuasive thing a business that charges a percentage can do, because a quote that sometimes says no reads as a model instead of a pitch.

Conversion decisions

Why these choices

Why the proof element sits beside the headline

The mobile reading order is the conventional one — masthead, hero, services, proof, why-us, reviews, service area, FAQ, form, footer — and the DOM is ordered so that a screen reader and a 375px phone both get exactly that. At 1024px and up the proof card floats into the hero’s second column, because the 1200×750 preview is what a prospect actually sees first, and a preview showing a headline and a row of tiles sells nothing. The layout is a single display:contents wrapper plus order on the flex children, so one CSS rule switches between the two without duplicating any markup.

Why these form fields

Name, phone, email, property suburb, claim type, claim stage, and a sentence about the argument. The suburb decides whether an on-site attendance is even sensible; the stage decides urgency, because an offer with an acceptance date on it is a different phone call from a claim still waiting on an adjuster. The two money fields are optional and are pre-filled from the proof element when the visitor arrives from it, so the estimate the visitor just ran becomes the first line of the enquiry.

Why the confirmation is local

There is no backend and no faked network round trip. The panel appears in place, repeats what was entered, names a one-business-day callback, and says plainly that this is a demonstration and nothing left the browser.

Why the refusal sits beside the number

A refusal in the FAQ is a disclaimer. A refusal in the result card, where the money is, is a demonstration of how the business quotes — so the decline branch replaces the ledger in the same frame, at the same size, and the fee-share curve that makes the same argument in a picture sits directly above it.

Honesty

What this page does not do

The business is fictional, and the page says so once, plainly, in the colophon on both files. The phone number uses the reserved (08) 9000 0xxx pattern. The address is suburb-level only. The ABN and registration lines are visibly patterned zeros. The reviews are demonstration copy and are never marked up as structured data.

The only structured data emitted live is a single WebPage object that names the page a demonstration. The LocalBusiness schema a real client would ship is below, as a code sample, so the sales evidence exists without polluting a real search index with fictional records.

Local SEO

What we would implement for the real practice

A claims advocacy practice competes on a handful of very specific queries — “insurance claim help Perth”, “insurer offered less than the builder’s quote”, “storm damage claim dispute WA”, “strata water damage claim Perth” — and against a search page where the regulator and the insurers themselves rank above every operator. The work is a Google Business Profile with the correct category and service list, one page per claim type rather than one page listing all of them, a suburb-level service-area page set that is genuinely different page to page, and the structured data below shipped with real, earned reviews only.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "InsuranceAgency",
  "@id": "https://example.com.au/#practice",
  "name": "Redress Claims Advocacy",
  "description": "Insurance claims advocacy for home, strata and small-business property claims.",
  "url": "https://example.com.au/",
  "telephone": "+61 8 XXXX XXXX",
  "priceRange": "$$",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "Suite X, NN Example Street",
    "addressLocality": "Subiaco",
    "addressRegion": "WA",
    "postalCode": "6008",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.949, "longitude": 115.826 },
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
    "opens": "08:00", "closes": "17:30"
  }],
  "areaServed": [
    { "@type": "City", "name": "Perth" },
    { "@type": "AdministrativeArea", "name": "Perth metropolitan area, Western Australia" }
  ],
  "hasOfferCatalog": {
    "@type": "OfferCatalog",
    "name": "Claims advocacy services",
    "itemListElement": [
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Written scope comparison" } },
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Full claim advocacy" } },
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Strata and common-property claims" } }
    ]
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.8", "reviewCount": "63"
  },
  "review": [{
    "@type": "Review",
    "author": { "@type": "Person", "name": "A real, verifiable client" },
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "reviewBody": "A real, earned review — never demonstration copy."
  }]
}
</script>

The rating and review objects above are shown as the shape we would ship. On this demonstration they are deliberately not emitted, because fictional reviews in a real index are dishonest markup whatever the disclaimer says.

For a real client

What would change