A 900 mm arc, drawn to scale, in millimetres.
Barrier Line Pool Safety is a fictional Canning Vale pool-barrier business. Its customer is someone holding a local-government defect notice she does not understand, and the page has one job: turn “will my pool fence pass?” into a booked inspection by drawing the answer — including the answer no. Every figure on it comes from AS 1926.1-2012 and the Building Regulations 2012 (WA), and the page never pretends to issue the certificate.
The signature: the arc, compared as squares
AS 1926.1-2012 defines the non-climbable zone on the outside of a pool barrier as a 900 mm arc struck from the top of the barrier. Anything a small child could stand on inside that arc is a foothold, and the barrier has to be tall enough that the object’s near top corner falls outside it.
That is a distance test, and a distance test is where floats get in. So the page never computes a distance. For an object of height o at setback s against a barrier of height b, it compares squares in square millimetres:
inside the arc ⟺ s² + (b − o)² < 810000 // 900² mm², all integers
required barrier = max( 1200, ceil( (o + ⌈√(810000 − s²)⌉) / 50 ) × 50 )
└ statutory minimum └ integer square root, rounded UP to the next 50 mm
The square root is an integer square root — a search, not Math.sqrt — and it is rounded up, so the answer is always the smallest 50 mm increment that genuinely clears the arc. Building to that height always clears: substituting b = required gives s² + (required − o)² ≥ s² + (810000 − s²) = 810000, which is the test, exactly at equality or above. The site’s own oracle enumerates that invariant over the whole grid and finds zero exceptions.
Every height and setback on the page prints in whole millimetres and never in metres. The whole argument is a 900 mm radius. A decimal metre would render a 1,450 mm barrier as “1.5 m”, which is the same number as 1,500 mm and 1,460 mm, and the difference between those is a fail.
The required-height table, as shipped
A 600 mm retaining wall, by how far it sits off the fence. This is the table the drawing draws.
| Setback (mm) | 0 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900+ |
|---|---|---|---|---|---|---|---|---|---|---|
| Required barrier (mm) | 1,500 | 1,500 | 1,500 | 1,450 | 1,450 | 1,350 | 1,300 | 1,200 | 1,200 | clear |
The highlighted cell is the page’s rest state. At 700 mm and beyond the requirement drops under the statutory 1,200 mm, so the minimum stands and nothing is forced; at 900 mm the object is outside the arc at any barrier height, because 900² = 810000 on its own.
The refusal
The refusal is scoped to the business, not to the standard: the string reads “there is no barrier we can build on this line”. Whether an inspector would accept some other arrangement is the inspector’s call, and this page does not make it.
The force, and its partial unwind
The barrier the page prices is climb ? max(entered, required) : entered — a pure function of the three controls, with no hidden memory, so every intermediate value a stepper visits is a real, correct state (W49: a stepper chain is not a chip chain). The harness walks the whole route and asserts each step:
| Step | Object | Setback | Built barrier | What happened |
|---|---|---|---|---|
| 1 | — | — | 1,200 mm | Nothing beside the fence. The statutory minimum stands. |
| 2 | 600 mm | 300 mm | 1,450 mm | Forced. Badge line 2 appears. |
| intermediates | 600 mm | 400 → 700 mm | 1,450 · 1,350 · 1,300 · 1,200 | Every step the stepper visits, asserted. |
| 3 | 600 mm | 800 mm | 1,200 mm | Restores. Badge line 2 asserted absent. |
| 4 | 1,000 mm | 300 mm | refusal | 1,850 mm required. No dollar figure anywhere. |
| 5 | 1,000 mm | 500 mm | 1,750 mm | Partial unwind: legal again, and it does not fall back to 1,200. |
| intermediates | 1,000 mm | 600 → 800 mm | 1,700 · 1,600 · 1,450 | The same constraint re-evaluating, step by step. |
| 6 | 1,000 mm | 900 mm | 1,200 mm | Outside the arc entirely. Restores. |
Palette, argued from a Perth backyard
Pool water, frameless glass, sand limestone and buffalo grass. Held off the cream-and-terracotta default by a cool water paper, off near-black by being light, and off the broadsheet default by letting the elevation, not a hairline rule, carry the structure. Every ratio below was computed with WCAG arithmetic from the shipped hex, not estimated, and measured against the grounds the page actually paints it on.
Type
Familjen Grotesk 600/700 for display — a friendly-but-precise Scandinavian grotesque that keeps a safety page from reading as either bureaucratic or cute. Public Sans 400/500/600 as the workhorse, 17px on mobile and 18px above 900px. JetBrains Mono for every millimetre and every dollar, because a tabular figure is what a tape measure deserves.
The typographic moment is the section mark: 900 set at display scale with mm at exactly a quarter of it, and the non-climbable arc struck from the centre of the second numeral’s own bowl. The centre is not eyeballed — the page reads getStartPositionOfChar(2) and getEndPositionOfChar(2) off the SVG text after document.fonts.ready, so the arc lands on the glyph whatever the font metrics turn out to be, and quietly does not draw at all if those metrics are unavailable.
How the drawing is built
One inline SVG, no libraries, no raster anything. The scene is a section through the barrier — the only view in which a setback is a real distance — and it is held entirely in millimetres, so the SVG user unit is a millimetre. One scale governs both axes, which is the whole point: a gradient drawing that stretches an axis would lie about the only thing being sold, and the 900 mm arc would render as an ellipse.
- A fixed frame, argued. 0–2,400 mm above ground and 0–2,450 mm out from the barrier, at every viewport width. The smallest drawn object, a 100 mm pot, is 4.2% of the vertical axis and gets a dimension outside the frame so it stays legible. A faint 500 mm height grid fills the sky and keeps the scale readable without a ruler.
- Constant rendered type. Stroke widths and font sizes are authored in pixels and multiplied by the current millimetres-per-pixel, so a 10.5px label is 10.5px at 375 and at 1440 — the fixed-viewBox trap that shipped 4.7px labels elsewhere in the collection cannot happen here.
- The annotation band below ground is laid out in pixels, not millimetres. Only the drawing above the ground line is at true scale; the labels underneath it sit on a 22px rhythm so they never crowd each other on a phone.
- Badge-vs-scene clearance is measured, not assumed. The sky band’s height is (measured badge height + 22px) × mm-per-pixel, recomputed on every draw, so the price badge can never cover the drawn subject. The harness asserts the two bounding boxes have an intersection area of zero at 375, 1000 and 1200.
- One rAF loop. Entrance choreography runs on a cold-load firstDraw flag and a resize can never re-enter it, because a clipped screenshot changes device metrics and would otherwise photograph an empty shed. Delta is clamped at zero as well as capped, the loop idles while document.hidden, and prefers-reduced-motion renders the settled frame immediately.
- A never-invisible floor. A sweep dot rides the arc and the foothold mark breathes between 0.72 and 1 — the signature is alive at any capture instant without any phase arithmetic against the seven-second thumbnail settle, and it comes to rest fully visible.
- Redraws are synchronous. Every control rebuilds the scene in the handler before anything is deferred, so the rapid-fire drive — nine control clicks in one evaluate with no settle between — cannot leave an animation closed over a stale scene.
window.__poolfencing exposes the full control vector, every computed figure, both badge strings, whether the badge is docked, and a settled flag. The harness gates on that state and never on elapsed seconds.
Conversion decisions
- The drawing is the argument, so it shares the fold with the hero. Above 1000px the elevation sits beside the headline, and the price badge’s bounding box is inside the first 750px at 1200 wide — the thumbnail is the commercial pitch, and a ledger below the fold does not make the capture.
- The primary CTA carries the price. “Book an inspection — $220” beats “Get a quote” because the fee is the objection, and it is small. The header owns a tel: link at every width; below 641px a sticky bar owns both a tel: link and an in-page anchor to the form, with 48px targets.
- The estimator’s cheapest output equals the services grid’s floor. Both are $220. A page whose calculator can undercut its own “from” price is arguing with itself.
- Controls either move the price or say why they cannot. In inspection mode the length stepper and the gate chips are disabled with the reason on the page — the fee is flat whatever we find — while the barrier type stays live because it still changes the drawing. When the arc forces the build height, the barrier stepper keeps working and the page states plainly that moving it changes the drawing, not the price, until it passes the required height.
- Six form fields, two of them selects. Name, phone, suburb, pool or spa, what you need, and one open field asking the question that actually matters: what is standing beside the fence. The confirmation is a designed local panel — hidden on load, hidden after an empty submit, shown only after a valid one — and nothing is ever sent anywhere.
- The refusal is the best moment on the page. A demonstration that only ever says yes is a brochure. This one draws the ceiling it will not build past and tells the owner the fence has to move.
Honesty
- The business is fictional and both pages say so in the colophon. Phone (08) 9000 0408 is a reserved pattern, the address is suburb-level, and BC00000 / ABN 00 000 000 408 are visibly placeholders.
- No claim about drowning appears anywhere on the site. The regulation’s purpose is a barrier to unsupervised access to the water, and the page says that and nothing more.
- The page never issues or implies a compliance certificate. The line “this is the same arc your local government’s inspector swings, but theirs is the one on the certificate” sits directly beneath the drawing, the trust strip carries “we do not certify”, and the services grid’s lodgement card says their inspector signs it, not us.
- Live structured data is WebPage, WebSite and CreativeWork only. No LocalBusiness, Review or AggregateRating with invented data reaches a real index; the sample below is a code panel, not markup.
Three iteration passes
Each pass drove the real interface — every chip, every stepper, the empty and the filled submit, the full six-step force chain and the refusal — and asserted on output. The harness ends at 101 assertions, run against a model reimplemented from scratch in the harness itself, and the standalone oracle enumerates all 1,103,232 control cells at 57/57.
A build-tool bug that made the whole signature disappear
- The scene never drew, and every static assert still passed. The script is inlined by a small build step, and String.replace treats $' in the replacement as “everything after the match”. The application code is full of $('#id'), so the inlined script was shredded and the page threw Invalid or unexpected token — while the badge, which is static markup, still read $4,069 exactly as intended. Fixed by truncating and appending instead of replacing, and a zero-console-error assert now stands in front of it.
- The header call button was 40px tall against the 44px tap-target floor at 375. Raised.
- The masthead sub-line ellipsised at 375 — POOL SAFETY · CANN…. Split into “Pool Safety” with the suburb shown only above 640px.
- The badge’s pinned short form had drifted: the state probe reported 1,450 mm · 14 m · $4,069 while the DOM printed the long form with a middot. Both now come from one function.
- Three label collisions in the drawing at 1200: the object name sat on the foothold mark, the object’s dimension label ran into the reference aircon’s caption, and the barrier dimension label crossed the barrier top. All three re-anchored.
Before and after in one frame
- The second-read detail. The solid barrier is drawn at the height you entered, with its arc catching the wall’s top corner in fail red — and the height it has to reach is ghosted above it in water ink with its own arc, clearing the same wall. The diagnosis and the fix are the same picture.
- A 500 mm height grid now fills the sky the fixed frame creates, so the true scale is readable without counting, and it gives the 1,450 mm ghost something to be measured against.
- The comparison the code actually makes is printed on the scene: 450,000 mm² — inside the 810,000 the arc allows. It updates with the controls and it is the same arithmetic as the branch.
- A third surface for the forced value. Beside the badge and the ledger, the controls carry a locked strip — we’d build to 1,450 mm · set by the 900 mm arc, not by us — so the force is legible where the decision is being made.
- An honest note for repair mode. A repair puts a barrier back to standard; it does not raise it. Where the arc forces a taller barrier, repair mode now says so in the mode note and in the plain-text mirror, without touching the price.
- Two greyed reference objects — a typical garden bed and a typical aircon unit — drawn at true scale so an owner can find their own yard, each suppressed when the live object would collide with it.
- A constant scale mark, 1,000 mm, labelled “one scale, both axes”, because that claim should be checkable on the page rather than asserted in a guide.
375 first, then the pixels
- The masthead at 375 was checked before anything else: wordmark right edge against call-button left edge, asserted numerically and looked at in a native-resolution screenshot.
- The annotation band under the ground line was re-laid in pixels. The 375 capture showed the object’s name and the setback dimension 10 pixels apart — a spacing authored in millimetres, which shrinks with the viewport. Only the drawing above the ground line is at true scale; the labels beneath it now sit on a fixed pixel rhythm at every width.
- Density gates by scene width, not viewport: reference objects and grid labels above 430px, long label forms above 560px, the 100 mm ground-gap dimension above 700px and only when the object is far enough not to crowd it. That ground-gap dimension is the ornament this pass removed from the narrow and crowded states.
- The badge docks beneath the artwork at ≤640px of viewport width — not scene width, which a two-column grid can make phone-sized on a desktop — and the badge/subject rectangle-intersection assert runs at 375, 1000 and 1200.
- Reduced motion asserted to render a settled, fully opaque frame and to report settled immediately; the come-to-rest-visible assert drives the controls, waits with nothing poking the page, and then requires every animated group opaque.
- Both form patterns proved by driving checkValidity on deliberately invalid values, because a v-flag regex that fails to compile leaves a field silently validating nothing.
- The service-area map argued with its own list. The first dashed boundary left Mandurah, Secret Harbour and Rockingham outside it while the column beside it promised a Tuesday and Thursday run to all three. Redrawn to contain every named suburb.
- Both pages scanned for a word character followed by = and a typographic double quote — the defect class that silently voided 21 class attributes elsewhere in the collection. Zero hits.
Where this build disagreed with its brief
Six things the brief did not pin, resolved here and written down rather than resolved quietly:
- The reference objects had no setbacks. Shipped a 300 mm garden bed 900 mm wide at 1,000 mm and a 600 mm aircon unit 500 mm wide at 1,750 mm — both at 900 mm or more, so neither is ever inside the arc at any barrier height and neither can read as a defect.
- Inspection mode had no badge line. Shipped Inspection and report — $220, short form Inspection · $220.
- The object-height labels were a list, not a mapping. Shipped 0 nothing there · 100–200 a pot · 300 a garden bed · 400–500 an aircon unit · 600–1,200 a retaining wall, chosen so the pinned rest state reads “a 600 mm retaining wall”.
- How the force surfaces. The brief’s chain says the barrier is forced to 1,450 mm, while its rest-scene description draws the solid barrier at 1,200 mm with 1,450 ghosted above. Both shipped: the stepper stays free at the entered height, the forced value gets its own locked readout, and the page states that until the entered line passes the requirement, moving it changes the drawing and not the price. That keeps the control honest rather than silently inert.
- Repair mode and the arc. The model prices a repair on a line the arc fails, because the repair is still worth doing; but a repair does not raise a barrier, so the page says so. No price changed.
- The lodgement line is labelled “certificate paperwork and lodgement”, not “certificate”, and every surface that mentions it says the local government’s inspector signs the compliance.
Local SEO we would implement for the real business
None of this ships on the demonstration, because publishing invented review data into a real index is dishonest markup. For a real Barrier Line, with real reviews and a real licence, this is what would go on the page — HomeAndConstructionBusiness is the right organisation subtype for a barrier builder that also inspects.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "HomeAndConstructionBusiness",
"name": "Barrier Line Pool Safety",
"description": "Pool barrier inspections, repairs and new barriers to AS 1926.1-2012 across Perth's south-east and the coast.",
"url": "https://barrierline.com.au/",
"telephone": "+61 8 XXXX XXXX",
"image": "https://barrierline.com.au/img/glass-barrier-thornlie.jpg",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "Unit N, XX Example Road",
"addressLocality": "Canning Vale",
"addressRegion": "WA",
"postalCode": "6155",
"addressCountry": "AU"
},
"geo": { "@type": "GeoCoordinates", "latitude": -32.06, "longitude": 115.92 },
"areaServed": [
{ "@type": "City", "name": "Canning Vale" },
{ "@type": "City", "name": "Thornlie" },
{ "@type": "City", "name": "Rockingham" },
{ "@type": "City", "name": "Baldivis" },
{ "@type": "City", "name": "Mandurah" }
],
"openingHoursSpecification": [{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
"opens": "06:30", "closes": "16:30"
}],
"hasOfferCatalog": {
"@type": "OfferCatalog",
"name": "Pool barrier services",
"itemListElement": [
{ "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Pool barrier inspection and report" },
"priceSpecification": { "@type": "PriceSpecification", "price": "220", "priceCurrency": "AUD" } },
{ "@type": "Offer", "itemOffered": { "@type": "Service", "name": "New frameless glass pool barrier" },
"priceSpecification": { "@type": "UnitPriceSpecification", "price": "690", "priceCurrency": "AUD",
"unitCode": "MTR", "unitText": "per metre" } }
]
},
"aggregateRating": {
"@type": "AggregateRating", "ratingValue": "4.9", "reviewCount": "134"
},
"review": [{
"@type": "Review",
"author": { "@type": "Person", "name": "REAL VERIFIED CUSTOMER" },
"reviewRating": { "@type": "Rating", "ratingValue": "5", "bestRating": "5" },
"datePublished": "2026-07-14",
"reviewBody": "Three defects on the notice and I understood none of them..."
}]
}
</script>
Alongside it: a verified Google Business Profile with the four-year inspection cycle written into the description, service-area pages for the coast run that are genuinely different pages rather than suburb swaps, and the reviews pulled from the profile at build time so the aggregateRating is always a number someone can go and check.
What would change for the real client
Their systems
ServiceM8 is the natural fit for the inspection run: the booking form drops straight onto a job card with the suburb, the pool type and the note about what is standing beside the fence, the inspector works the defect checklist on the phone, and the report leaves site as a PDF before the ute does. Tradify for the repair and new-barrier quoting, so the estimator’s line items become a real quote rather than a re-keyed one.
Their content
Their photographs of finished glass and aluminium barriers, their real reviews feed, their real registration and ABN, their actual local-government lodgement details per council — and their own numbers behind the estimator, which is the only part of this page that has to be re-derived rather than re-skinned. The arc does not change: it is 900 mm for everyone.
The one thing that would not change is the refusal. A real barrier business turns down work on lines that cannot be made to comply, and a page that can say so before the deposit is worth more than one that cannot.