Concept
Downpour Gutters & Guards is a fictional Gosnells gutter-replacement operator built for homeowners staring down the June rains — and buyers told "the gutters are shot" on a building report. The page has one job: a replacement-estimate enquiry with the metres already on the meter. The drama lives in the weather; the page stays calm and ruled beneath it, speaking real roof-plumbing vocabulary — quad profile, Colorbond, Monument to Surfmist.
Palette — argued from the storm and the rusted quad
Dark-site discipline: every piece of body copy was probed against the slate ground (≥4.5:1 everywhere; the two inks measure 13.4:1 and 6.9:1), and the two accents are spent exclusively on marks, lines and large bold CTAs.
Type
Bitter 600/700 for display — a slab that holds weight on a dark ground the way a cast gutter bracket holds a quad. The typographic moment is the meter's own readout, "30 METRES OF QUAD", set as the panel headline with the count in rain blue. Source Sans 3 carries body and UI: legible at 16.5px on a phone in the rain, which is where this page would actually be read.
The signature — the Roofline Meter
An SVG house elevation under live procedural rain. The scene is rebuilt as one SVG template per state — wall, hip roof, quad gutter with a magnifiable bead line, 0–8 downpipes, a dimension line that reads the current metres — while a canvas overlay in the same 1000×560 coordinate space runs the weather: ~130 rain streaks with drift, rivulets running the roof plane, dashed water flow along the quad toward each downpipe's watershed, the fall down every pipe, and a splash ring at each shoe. With zero downpipes the quad visibly overflows — the honest picture. With the guard on, leaf specks tumble in, hit the mesh and shed off the front (the second-read detail). A copper-pulsed annotation marks the rust-through joint "you hear in June".
The ledger prices the scene live from the pinned anchors — $68/lm single storey, $86 double (stated on-card as an $18/lm access premium, not a different gutter), $120 a downpipe, $28/lm mesh — with a $1,700 total-level minimum whose note appears only when it binds (the boundary sits exactly at 25 lm / 0 downpipes / single / no guard). Metres and storeys pre-fill the enquiry form, so the demo interaction walks straight into the lead.
Engineering notes: every control handler bumps an animation token before the state swap, so in-flight entrance animations and settle timers invalidate cleanly under rapid-fire input; the canvas loop reads the live geometry object each frame (no stale closures over old downpipe arrays); the SVG gets entrance choreography on first draw only (26 ms stagger, 1.1 s cap) and snappy redraws after (8 ms, 380 ms cap); DPR is capped at 2, the loop pauses when the tab hides, and reduced motion renders one settled frame with the rain re-rolled above the roof silhouette. A window.__gutters probe exposes scenario, computed figures and a settled flag for state-gated QA.
Pinned pricing anchors
| Item | Rate | Notes |
|---|---|---|
| Colorbond quad replacement, single storey | $68 / lm | supplied & installed, old run disposed |
| Colorbond quad replacement, double storey | $86 / lm | the $18 is an access premium, stated on-card |
| Downpipes, Colorbond to 3 m | $120 each | swapped with the run |
| Aluminium mesh gutter guard | $28 / lm | installed with the new gutters |
| Minimum job | $1,700 billed | total-level clamp; note shown only when binding |
| Gutter cleaning | from $190 | single storey, flat to 30 lm — deliberately not in the meter |
| Leak & overflow repairs | from $190 | half-day minimum stated |
| Fascia replacement | no number | designed price-less state — quoted on inspection |
Every displayed figure was measured from the running page and cross-checked against an independently reimplemented oracle of these anchors: rest state 30 lm / 4 downpipes / single / guard off = $2,520; guard on = $3,360; double storey = $3,060; 15 lm + 2 downpipes rates to $1,260 and bills at $1,700 with the note; exactly 25 lm / 0 / single / off lands on $1,700 with no note. The estimator's cheapest reachable output equals the services grid's "from $1,700" floor, and all totals display to the whole dollar.
Conversion decisions
- Meter beside the hero copy, not below it — at 1200px the signature shares the first 750px with the value proposition, so the thumbnail and the first impression are the same thing: rain, roofline, a priced ledger.
- Two CTAs, one verb each. "Price my roofline" walks down the page's own argument; the call button is for the household with water already coming in. On mobile a solid sticky bar keeps both under the thumb — no backdrop-filter anywhere on conversion chrome.
- Form fields mirror how the trade actually quotes: name, phone, suburb, rough metres, storeys. The meter pre-fills metres and storeys, and a handoff button writes the whole scenario into the message — a warmer lead than a blank textarea. Confirmation is a designed local panel (hidden until a valid submit) that says plainly no details were sent.
- Honesty as positioning: the clamp note explains why short runs bill at $1,700; the double-storey line names the access premium; fascia stays price-less by design; the repair FAQ tells people when not to replace.
Local SEO we'd implement for the real business
This demo page ships only WebPage/CreativeWork structured data, because fictional business schema in a real index is dishonest markup. For a real gutter operator we'd ship a RoofingContractor profile — schema.org's exact construction-family subtype for roof plumbing — wired to their real NAP, licence, hours and review feed:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "RoofingContractor",
"name": "Downpour Gutters & Guards",
"description": "Colorbond gutter replacement, guards and downpipes across the Perth metro.",
"telephone": "+61-8-XXXX-XXXX",
"url": "https://www.example.com.au",
"address": {
"@type": "PostalAddress",
"addressLocality": "Gosnells",
"addressRegion": "WA",
"postalCode": "6110",
"addressCountry": "AU"
},
"areaServed": ["Gosnells","Thornlie","Maddington","Canning Vale","Perth"],
"openingHours": ["Mo-Fr 07:00-16:00","Sa 08:00-12:00"],
"priceRange": "$$",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.9",
"reviewCount": "137"
}
}
</script>
Panel note: the top-level @type is RoofingContractor — an actual LocalBusiness-family organization subtype, not a specialty enumeration. The aggregateRating block only ships when it's fed by the client's genuine review source (Google Business Profile via API, or a reviews platform), never typed in by hand.
Iteration log
Pass 1 — Craft
The screenshot review caught a real ship-blocker every DOM assert sailed past: the meter's control row used a viewport-width media query for its four-column layout, but the panel itself is only ~560px wide inside the hero grid — the guard switch was pushed clean out of the clipped panel and the "Double" chip was cut. Replaced with a wrapping flex row that composes at any panel width. Also softened the lit dusk window from 0.5 to 0.16 alpha (it read as a tan cardboard rectangle, louder than the signature), and re-verified the dark-ground contrast pairs: body 13.4:1, muted ink 6.9:1, copper and rain blue confined to marks, lines and large bold CTAs.
Pass 2 — Depth
The native-resolution scene review showed downpipes crossing window glass at several counts — pipes now nudge to the nearest clear wall either side of each pane. Confirmed the guard's leaf-shedding second read and the zero-downpipe overflow branch on screen, and added the total-figure tick (a 450 ms scale-and-colour breath when the billed figure changes — skipped under reduced motion and on first draw). Drove every stepper, chip and toggle against the independent oracle: $2,520 / $3,360 / $3,060, the $1,260→$1,700 clamp with note, the exact 25 lm boundary with none, stepper floors and caps, and two rapid-fire bursts (a dozen dispatched clicks in one evaluate, no settle) with zero console errors and oracle-matching final state.
Pass 3 — Hardening
Fixed the reduced-motion static frame: drops that spawned below the roof silhouette were being respawned off-canvas, thinning the rain to nothing over the house — they now re-roll above the silhouette before the single draw. Removed the map's echo coastline stroke (the one ornament too many). Verified at 375px: masthead row clear of collisions, h1 + quote CTA above the fold, sticky call bar inside the bottom 140px, zero horizontal overflow on both pages; the guide's pricing table ships in its scroll wrapper. Focus rings on every control, DPR capped at 2, rain paused on hidden tabs, form validation v-flag-safe (required + minlength, no brittle pattern attributes), and the confirmation panel probed for its visibility transition — hidden on load, hidden on empty submit, shown only after a valid one.
What would change for the real client
- Their evidence: real before/after job photos replacing the procedural elevation's supporting role, and a live review feed (Google Business Profile) instead of demo copy — which also unlocks the review schema above.
- Their workflow: the quote form posts into their job-management system — ServiceM8, Tradify or AroFlo are the ones WA roof plumbers actually run — with the meter's scenario attached as structured fields, not prose. Missed-call text-back in winter.
- Their numbers: rates and the minimum tuned to their book, suburb pages for the corridors they want to own, and call tracking so the June spike is measured, not remembered.