Generative Assets · Industry Demos XXIII · site 328
The section drawing that sells the membrane.
Drysline Waterproofing is a fictional Myaree wet-area and balcony membrane specialist. The page has one job: a booking with the wet area named and priced. This guide documents how it was designed, priced and hardened.
Concept
Waterproofing is invisible once it's done — the whole trade lives under someone else's tiles. So the page puts the hidden thing on display: a technical cross-section at bench height, drawn the way a section appears on a drawing set, with the price badged directly on the membrane layer. The audience is renovators mid-strip, owners with a balcony staining the ceiling below, and builders sequencing a tiler for Thursday. The page should read like a section drawing that happens to sell.
Palette — argued from slate, primer and the membrane tin
The wave's dark site: a workshop-lit drawing board, not a moody landing page. Every contrast figure below is measured from the shipped tokens with WCAG relative-luminance arithmetic (spec figures were hypotheses; Pass 1 measured them).
Working tokens derived during the build: #7FB2E8 as the blue text ink (7.12:1 on slate, 6.42:1 on panels — the base hue is reserved for marks and fills), the pre-minted W33 pair #2F66AC as the badge/button fill under white labels (5.81:1 measured), and #9AA7B4 as a label ink minted in Pass 1 for the control boxes, where screed grey measured 4.23:1 on the lighter #2A3441 ground (the new token measures 5.14:1). Badge sub-copy was lightened from #C9DCF2 (4.15:1) to #E2ECFA (4.87:1).
Type
Archivo 650 for display — the confidence of a drawing title block, used for the wordmark, headings, prices and the sealed-area display line. Instrument Sans as the workhorse: neutral, legible at 16px+ on mobile, and comfortable in dense ledger rows. The typographic moment is the seal line — the selected area written out in words ("TWELVE SQUARE METRES, SEALED") over the cutaway, re-set as the stepper moves.
Signature — the Wet-Area Cutaway
A layered SVG cross-section built entirely in code, no raster anywhere. Each scene (shower recess, full bathroom, balcony) is a builder function returning ordered layers: substrate hatch, wall stubs, screed-to-fall with the outlet, translucent primer, bond-breaker fillets, then two membrane coats drawn as stroked paths, then the ghosted tile finish, callouts, the plan inset (balcony only — it resizes with the area stepper), and the price badge sitting on the membrane layer inside the thumbnail's first 750px.
The membrane coats paint on with a stroke-dash reveal (butt caps, stroke hidden until drawn length > 0 — the W15 round-cap dot lesson). A roller on a requestAnimationFrame loop repaints a fresh highlight pass on an 8.6s cycle: 6.2s painting, 1.4s hold at full length, 1s lift-off where opacity eases 0.9 → 0.55 — a never-invisible floor, so the 7-second thumbnail settle always catches the scene mid-work. The rAF delta is clamped at both ends (dt = min(max(now − last, 0)/1000, .05), the W29 rule). Redraws are dual-speed: the first render gets the full entrance choreography (130ms stagger, 1.3s cap), every later chip/stepper change redraws snappy (36ms stagger, 430ms cap). Every control handler bumps an animation token before the state swap, so an in-flight entrance can never index a stage array that no longer exists (the W25 race). State is exposed at window.__waterproofing — scenario, computed figures, and a settled flag QA gates on.
Second-read details: the drawing title block bottom-left ("DW-328 · BALCONY SECTION · 1:20 · AS 3740") re-titles itself per scene, and a droplet drips into the balcony outlet on a loop — position set on a parent <g transform>, animation on the child circle only, keeping SVG attribute state and CSS animation on separate elements (the W16/W17 split).
Honest pricing
Every figure is pinned from WA-market anchors and the estimator's cheapest output equals the services grid's matching floor. The clamp has one semantic, stated in the meter's own unit: minimum 8 m², billed at the selected balcony rate — membrane alone at $120/m², or the combined $176/m² when strip-out is on.
| Scenario | Arithmetic | Displayed |
|---|---|---|
| Rest — balcony 12.0 m², strip off, flood off | 12 × $120 | $1,440 |
| Balcony 12.0 m² + strip-out | 12 × ($120 + $56) | $2,112 |
| Balcony 12.0 m² + flood test | 12 × $120 + $240 | $1,680 |
| Full bathroom + flood test | $1,150 + $240 | $1,390 |
| Shower recess alone | flat | $680 |
| Boundary — balcony 8.0 m² | 8 × $120, no note | $960 |
| Boundary — balcony 7.5 m² | billed at 8 m², note shows | $960 |
| Boundary — 7.5 m² + strip-out | 8 × $176, note shows | $1,408 |
All eight scenarios were verified twice: driven on the running page through the real controls, and recomputed by an independently reimplemented oracle in the QA harness. The strip-out toggle is disabled with its reason on-page for shower recesses and full bathrooms ("wet-area strip-outs are quoted after inspection — the membrane price holds"), the flood test is flat $240 at every job type and says so on-card, and planter boxes carry a designed price-less line — "quoted after inspection — planters fail in their own creative ways" — because any printed number there would be the dishonesty.
Conversion decisions
- Estimator in the hero. The cutaway is the value proposition — proof the trade is understood — so it shares the first viewport with the h1, the call CTA and the trust chips, and its price badge sits inside the 1200×750 thumbnail.
- Estimator → form handoff. Job type and the composed scenario (area, extras, estimated total) pre-fill the booking form's select and details field; a visitor who has priced a job arrives at the form with it already written down. Editing the details field switches the handoff off.
- Form fields: name, phone, suburb, job type, details — what a scheduler actually needs to confirm a slot; nothing that adds friction. Front-end validation only, with a designed confirmation panel (hidden on load and on invalid submit) that says plainly nothing is sent anywhere on a demo.
- Click-to-call in the masthead at every width; at ≤760px a sticky bottom bar carries Call + Book with ≥48px targets.
- Trust strip leads with AS 3740 and the certificate — the two things a builder checks before booking a membrane sub.
Local SEO we'd implement for the real business
This demo page ships only WebPage and BreadcrumbList JSON-LD naming itself a demonstration — fictional structured data in a real index would be dishonest markup. For a real Drysline we would ship HomeAndConstructionBusiness (waterproofing has no exact schema.org subtype — this is the correct parent) plus a genuine review feed:
{
"@context": "https://schema.org",
"@type": "HomeAndConstructionBusiness",
"name": "Drysline Waterproofing",
"description": "Licensed wet-area and balcony membrane specialists.
Installed to AS 3740, flood-tested on request, certified before tiling.",
"telephone": "+61-8-XXXX-XXXX",
"address": {
"@type": "PostalAddress",
"addressLocality": "Myaree",
"addressRegion": "WA",
"postalCode": "6154",
"addressCountry": "AU"
},
"areaServed": "Perth metropolitan area",
"openingHours": "Mo-Fr 06:30-16:00",
"priceRange": "$$",
"review": {
"@type": "Review",
"reviewRating": { "@type": "Rating", "ratingValue": "5" },
"author": { "@type": "Person", "name": "— real customer —" },
"reviewBody": "— pulled from the live review feed —"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.9",
"reviewCount": "— live count —"
}
}
Plus suburb-level service pages, GBP with real job photography (membranes photographed before tiling are unusually good proof-of-work content), and review capture wired to the certificate email.
What changes for the real client
Their photos replace nothing — the cutaway stays, because it explains the job better than photography can — but their certificate gallery, their reviews feed, and their booking system replace the demo stubs. For a trade this shape we'd wire the form into AroFlo or ServiceM8 (job cards, scheduling, the certificate PDF attached to the job), and invoice through Xero. The estimator's anchors become a config the operator can edit when the membrane price moves.
Iteration log
Pass 1 — Craft
Measured every text token against its real ground: screed grey on the control-box ground #2A3441 came in at 4.23:1 — minted #9AA7B4 label ink for that surface (5.14:1). Badge sub-copy #C9DCF2 on the badge fill measured 4.15:1 — lightened to #E2ECFA (4.87:1). The drawing title block's #5E6C7B annotation sat at 3.22:1 on the well — lifted to screed grey (5.82:1). Bumped the seal line's max size from 1.55rem to 1.72rem so the display moment actually displays, and removed a dead .is-off rule.
Pass 2 — Depth
Gave the seal line a 160ms crossfade when the stepper re-sets it (token-guarded so rapid-fire chip taps can't interleave two pending swaps), and added the outlet drip — a droplet falling into the balcony drain on a 2.7s loop, position on the parent group, animation on the circle only. Verified the roller's lift-off floor by reading the driven opacity: it eases 0.9 → 0.55 and never below, so no capture instant shows a dead scene. Confirmed the dual-speed redraw: first draw settles in ~2.6s of choreography, every subsequent chip/stepper redraw settles under 800ms.
Pass 3 — Hardening
375px: masthead holds one line (wordmark right edge vs phone link left edge compared explicitly), the sticky call bar is present with 48px targets, and neither page scrolls horizontally. Drove the full oracle matrix through the real controls — all eight scenarios matched the independent reimplementation, including the 7.5 m² + strip-out cell billing 8 × $176 with the minimum note showing and the 8.0 m² cell showing no note. Empty submit raises validation with the confirmation panel still hidden; a filled submit via the real submit button reveals it. Rapid-fire drive (chip–stepper–toggle bursts in one evaluate, twice over) produced zero console errors — the handler-side token invalidation holds. Reduced motion renders the cutaway settled at 62% roller progress with all layers visible. Chanel rule: the dead CSS rule went, and the balcony scene's door-threshold micro-label was already marked minor (dropped on compact screens) rather than adding another callout.
Techniques
- Procedural SVG cross-sections — pattern-fill hatching and screed dots, path-based membrane coats with
getTotalLength()dash choreography,getPointAtLength()roller tracking with angle-matched rotation. - Vanilla JS state machine, one
compute()pricing function shared by ledger, badge, note and form handoff — one source of truth for every number on the page. - IntersectionObserver reveals with a no-IO safety net;
prefers-reduced-motioncollapses all animation to a designed settled frame. - No libraries, no build, no raster — Google Fonts is the only external resource.