Generative Assets · Industry demonstration 415
How the Ironline Heavy Haulage page was made
A lead-generation page for a fictional Kwinana Beach float operator, built so a maintenance supervisor with a crusher to move can price the movement and send a scoped enquiry in about a minute — and so the page never states a regulatory number it cannot stand behind.
The concept
Ironline Heavy Haulage runs drop-decks, low loaders and a widening extendable out of Kwinana Beach — mine site relocations, crushers, tanks, transportables and ag headers, across metro, the Wheatbelt and Goldfields, and the Mid West and Pilbara. The audience is B2B: a project or maintenance supervisor with a machine that has to be somewhere by a date, who wants a number and a phone call, not a brochure.
The page has one job: a scoped enquiry with the load details attached. That is why this form has the most fields of the five sites in the wave and why the estimate sits above it — the estimate exists to make filling that form feel worth it. A supervisor who has already watched the price move with the rig, the distance and the pilots understands why we are asking for mass, dimensions and access, and answers instead of bouncing.
The honesty constraint, stated plainly. This page publishes no numeric oversize or over-mass dimension or mass threshold, no permit fee, no notice period, and no claim about when pilot vehicles or a police escort are legally required. What it does state is the mechanism, which is verifiable: oversize and over-mass movements in Western Australia run on a Main Roads WA permit, and Ironline prepares and lodges that application as part of the job. Pilots on the estimate are a user toggle — “add pilots to see the effect” — and the rate board says so in as many words: “Pilot vehicle requirements are set by the permit for your load and route, not by this page.”
Every figure that is on the page is either the fictional business’s own commercial rate or a road distance. Nothing about a real regulator is quantified.
Palette — steel and oxide
Argued from the trade, not from a mood board: cold rolled steel for the grounds, oxide primer for the marks and the calls to action, and a deck blue that draws the trailers and the route corridors. No cream, no acid accent. Ratios below are measured with WCAG arithmetic and quoted with the hex from the same row of the wave’s contrast sweep.
#EEF1F3The page ground. Cold, slightly blue, the colour of a swept workshop floor rather than paper.#DCE2E7Alternating section ground, so a long page still has rhythm without a second hue.#131A20Body copy. 15.47:1 on steel, 13.44:1 on panel.#414E58Secondary copy and field hints. 7.54:1 on steel, 6.55:1 on panel.#9C3A22CTA fills, eyebrows, the “billed” mark. As ink: 6.09:1 on steel, 5.28:1 on panel. Steel reversed on it: 6.09:1.#1E4A6BTrailers, route corridors, the selected chip. As ink: 8.24:1 on steel, 7.15:1 on panel. Steel reversed on it: 8.24:1.#16222EThe rate board, the result header, the price plate and the footer. Steel reversed on it: 14.21:1.#66757FInput and chip borders, a mark not a text colour. 4.19:1 on steel, 3.64:1 on panel.#A9B5BERules and the road’s dash row. 1.84:1 on steel, 1.60:1 on panel — a line token, never type.Forbidden grounds, declared. Ink and muted are never placed on band, oxide or deck blue — they measure 1.09:1, 2.54:1 and 1.88:1 there. Dark grounds carry steel only. That is why the rate board’s six plates, the result header and the on-drawing price plate all reverse to steel rather than tinting the type, and why the SVG map labels are body ink with a steel halo instead of being drawn in the blue that draws the corridors.
Type
Barlow Condensed 600/700 for headings, the rate figures and every number in the drawing — condensed grotesque is the face of a truck door, a placard and a load plate, and it is the only condensed face in the wave. Barlow 400/500 carries body copy, the ledger keys, the form and the FAQ. One family, two widths: the page reads as one voice, and the width change alone marks what is a figure and what is a sentence.
Tabular numerals are on globally (font-variant-numeric: tabular-nums plus the tnum feature). A rate board where $1,450 and $2,950 do not align on the comma reads amateur to someone who reads rate sheets for a living. Body is 17px at 375 and the headline runs clamp(2.05rem, 7vw, 2.6rem), so the four-line phone headline becomes a three-line desktop one without a separate copy deck.
The one typographic move is the movement total: Barlow Condensed 700 at clamp(2.4rem, 8vw, 3.4rem), reversed out of the band in the result header, and repeated at 23px on a band plate inside the drawing. Nothing else on the page comes near either size.
The proof element — the movement estimate
Three controls, one result card, and a side elevation of the selected float drawn beside them. Rig: drop-deck to 24 t, low loader to 45 t, widening extendable to 60 t. Destination: a metro band to 120 km, or a country distance on a slider with Geraldton (420 km), Kalgoorlie (595 km) and Port Hedland (1,640 km) as presets. Pilots: none, one or two.
The model
- Metro (≤ 120 km) bills a day rate: $1,450 / $2,150 / $2,950 by rig.
- Country (> 120 km) bills the loaded kilometres at $4.80 / $6.60 / $8.90 a kilometre or the day rate, whichever is greater, plus a flat $600 mobilisation.
- Pilots add $2.40 a kilometre each, in both bands.
- Totals round to the nearest $10. Money is held as integer cents inside the model and divided once at display, so no rate multiplication ever lands on a floating-point tail.
| Scenario | Rig | km | Pilots | Total |
|---|---|---|---|---|
| Floor — equals the rate board’s “from” | Drop-deck | 120 | 0 | $1,450 |
| Metro with one pilot | Low loader | 120 | 1 | $2,440 |
| First country cell | Low loader | 121 | 0 | $2,750 |
| Geraldton | Drop-deck | 420 | 0 | $2,620 |
| Rest state — Kalgoorlie, the thumbnail | Low loader | 595 | 1 | $5,960 |
| The same run without pilots | Low loader | 595 | 0 | $4,530 |
| Port Hedland, two pilots | Extendable | 1,640 | 2 | $23,070 |
The pilot line at the rest state is $1,430 — $5,960 less $4,530 — and the ledger prints it as its own row so the toggle’s cost is never buried in the total. The floor, $1,450, is exactly the rate board’s from $1,450 a day, metro: the estimate’s cheapest output and the grid’s cheapest anchor are the same number, so the page cannot argue with itself.
The band-edge inversion, and why the max() is load-bearing
This is the best trust story on the page, and it was caught by the wave’s arithmetic check before a line of the page existed. Write the country formula the obvious way — kilometres times the rate, plus mobilisation — and the price falls as the load crosses the metro band edge:
| Low loader, no pilots | 120 km | 121 km | Reads as |
|---|---|---|---|
| Naive: km × rate + mobilisation | $2,150 | $1,400 | one more kilometre, $750 cheaper |
| Shipped: max(day rate, km × rate) + mobilisation | $2,150 | $2,750 | monotone, and true to how the day is actually consumed |
The naive figure is not merely odd, it is wrong about the world: a 121 km run still burns a driver’s day and a float’s day, so it cannot cost less than the metro day rate. The max() is the honest floor, and the shipped model is monotone in distance for every rig and every pilot count from 121 km to 2,000 km — verified cell by cell against an independently reimplemented oracle rather than against the page’s own function.
Rather than hide the comparison, the ledger shows it. Whichever of the two lines loses is struck through in muted; the one that bills carries a — billed mark in oxide. At 121 km on the low loader the ledger reads Loaded kilometres · 121 × $6.60/km — under the day rate: $798.60, then Low loader day rate, whichever is greater — billed: $2,150. At 595 km the strike-through swaps sides. A supervisor sees the rule work once and stops wondering whether the number is a guess.
The drawing
A procedural side elevation of the selected float, laid out in real CSS pixels (one SVG unit is one device-independent pixel) so a label is never 4px tall on a phone, dimensioned on the deck that decides what fits: Deck 13.6 m, Well 9.0 m, Deck 12.5 m with a dashed Extends to 19.0 m. Pilot vehicles appear in the convoy when the toggle turns them on, which makes the pilot line in the ledger legible without a caption. The dimension rule breaks for its label rather than the label being cased over it — a halo alone lets the rule show through the word gaps and the type reads dotted.
The whole sheet is assembled synchronously and rebuilt on resize with no entrance choreography, and the price plate is a rect inside the artwork, tested at 375, 768, 1000, 1200 and 1440 (and at device pixel ratio 2) so its box never intersects any drawn part of the rig at any rig or pilot count.
The conversion decisions
Why the phone and the form, in that order
Trades pages usually make the call the only real CTA. Heavy haulage is different: allocations cannot price a movement over a thirty-second call, because the answer needs mass, dimensions, access at both ends, a date window and whether the machine drives on or gets lifted. So the masthead and the mobile sticky bar own a real tel: link for the supervisor who wants a human, and the hero’s primary button goes to the form for the one who has the spec sheet in front of him. Both are above the fold at 375 without scrolling, together with the trust line.
Why the form is long on purpose
Eighteen fields, fifteen of them required, is heresy on a landing page — unless the fields are exactly the list the business already works from. The page says out loud, twice, what it needs to quote: as a numbered aside beside the form, and in the first FAQ. The form then asks for precisely those five things and nothing decorative. A long form that mirrors a stated list reads as competence; a short form that then triggers a phone call asking for the same detail reads as a lead-capture trick. The estimate’s Send these details button carries the scenario into the notes field and pre-fills the two suburbs, so the form starts partly answered.
Honest states
Submitting empty raises a message on every required field, focuses the first one, and keeps the confirmation panel hidden. Submitting a valid form shows a designed local confirmation that echoes back the machine, dimensions, route, date and loading method — and says plainly that this is a demonstration page, so it stopped in the browser and nothing was sent. There is no fake network round-trip and no fake delay.
Why this converts
- The primary CTA is in the masthead, in the hero, on the estimate card, on the form and in a sticky bar that follows the phone down the page — so the decision to act is never more than a thumb-length away, and the phone number is a real
tel:link everywhere it appears, not an image of a number. - The form asks for the five things this trade genuinely needs to quote, in the order allocations would ask for them, which turns the longest form of the five sites into the most credible one: a supervisor who recognises the list assumes the people behind it have loaded a machine before.
- The proof element lets a stranger price their own movement without ringing anyone, and the price moves in ways they can check — more distance costs more, a second pilot costs a visible $2.40 a kilometre — so the number reads as a model rather than a marketing figure.
- The trust strip does not claim awards; it claims a yard, a count and a mechanism (“we prepare and lodge the Main Roads WA permit… as part of the job”), which is the specific job a supervisor is quietly worried about having to do themselves.
- Everything the page will not swear to, it declines to say — no permit fees, no thresholds, no legal claims about pilots — and that restraint is visible on the page, which is the cheapest credibility a business can buy.
Local SEO we would implement for the real business
The live page emits only WebPage, CreativeWork, WebSite and BreadcrumbList schema, naming itself a demonstration. Publishing LocalBusiness or Review markup for a business that does not exist would put fictional data into a real index, so we do not. For a real Ironline, the block below is what would ship — shown here as a code sample only, and never emitted live from either page in this collection.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "MovingCompany",
"@id": "https://ironlineheavyhaulage.com.au/#business",
"name": "Ironline Heavy Haulage",
"description": "Drop-deck, low loader and widening extendable movements across WA. Permits prepared and lodged with Main Roads WA.",
"url": "https://ironlineheavyhaulage.com.au/",
"telephone": "+61 8 XXXX XXXX",
"priceRange": "$$$",
"image": "https://ironlineheavyhaulage.com.au/img/yard.jpg",
"address": {
"@type": "PostalAddress",
"streetAddress": "<street>",
"addressLocality": "Kwinana Beach",
"addressRegion": "WA",
"postalCode": "6167",
"addressCountry": "AU"
},
"geo": { "@type": "GeoCoordinates", "latitude": -32.23, "longitude": 115.77 },
"openingHoursSpecification": [{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
"opens": "05:30", "closes": "17:00"
}],
"areaServed": [
{ "@type": "AdministrativeArea", "name": "Perth metropolitan area" },
{ "@type": "AdministrativeArea", "name": "Wheatbelt, Western Australia" },
{ "@type": "AdministrativeArea", "name": "Goldfields-Esperance, Western Australia" },
{ "@type": "AdministrativeArea", "name": "Mid West, Western Australia" },
{ "@type": "AdministrativeArea", "name": "Pilbara, Western Australia" }
],
"hasOfferCatalog": {
"@type": "OfferCatalog",
"name": "Movements",
"itemListElement": [
{ "@type": "Offer", "name": "Drop-deck float, metro day rate",
"priceSpecification": { "@type": "PriceSpecification",
"minPrice": 1450, "priceCurrency": "AUD" } },
{ "@type": "Offer", "name": "Low loader, metro day rate",
"priceSpecification": { "@type": "PriceSpecification",
"minPrice": 2150, "priceCurrency": "AUD" } }
]
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.9", "reviewCount": "41"
},
"review": [{
"@type": "Review",
"author": { "@type": "Person", "name": "<real reviewer>" },
"reviewRating": { "@type": "Rating", "ratingValue": "5" },
"reviewBody": "<verbatim from the review platform, never written by us>"
}]
}
</script>
Beside the markup, the real build would carry: a Google Business Profile with the primary category set to the movement type the business actually wants calls for; the same NAP string byte-for-byte on the page, the profile and every directory; corridor landing pages that earn their keep (“low loader hire Kalgoorlie”, “transportable transport Geraldton”) rather than a suburb-spam doorway set; and reviews pulled live from the profile so the testimonials are never hand-typed marketing copy. AggregateRating only ever reflects a real, auditable review feed.
What would change for the real client
- Telematics. The “tracked floats, real ETAs” claim has to be true, so the page would read from whatever the fleet already runs — Geotab or MTData are the two we see most often in WA heavy vehicle fleets — and turn a movement number into a customer-facing ETA link instead of a phone call to the yard.
- Compliance. Logmaster (or the operator’s existing fatigue and mass management system) for work diaries and the accreditation evidence a mine site asks for at the gate; the page would surface only that the evidence exists, never its numbers.
- The permit workflow. The Main Roads WA permit application is the real bottleneck. The enquiry form is already shaped like the application’s inputs, so for a real client it would post into their job system and pre-populate the application draft rather than emailing allocations a paragraph.
- The estimate. Rates move. It would read a rate table the operator can edit — a spreadsheet or a table in their job system — instead of constants in the page, with the same monotonicity check running in CI so a rate edit can never reintroduce the band-edge inversion.
- Photography. Their own floats. The procedural elevation exists because this is a demonstration with no photography; a real operator has a phone full of loaded decks, and one photograph of their own extendable under a header outperforms any drawing.
The iteration log
Three passes, each driving the real controls in headless Chrome — sweeping rig × destination × pilots against an independently reimplemented oracle, submitting the form empty and filled, tapping the sticky bar — and each one reading the rendered pixels, not only the asserts.
Pass 1 — Craft
- The header CTA was live at 375 and the masthead ran 33px past the viewport (
scrollWidth408 against a 375 box)..mast-cta{display:none}was declared above.btn{display:inline-block}, and at equal specificity source order wins, so the button un-hid itself on every phone. Moved the hide rule below the button block, with a comment saying why it lives there. - The 7-second preview contained no drawing at all. The rig elevation started at y = 1,029 at 1200×750, so the collection’s headline sales asset was a page of copy. Rebuilt the vertical rhythm above it: the hero splits into a headline column and a supporting column at ≥1000px, the rate board’s caption sits on the heading line, and the drawing’s reserved plate band and headroom were cut to exactly what the tallest rig needs (4.5 m clears the extendable’s 4.25 m tank). The elevation now sits 606–746 — entirely inside the frame, price plate and deck dimension included.
- The deck dimension label printed nothing.
dimension()was handedg.deckLabelfrom the geometry table, where the label actually lives on the rig table. Every state assert was green while the one measurement the drawing exists to give was absent. Nowrig.deckLabel. - The rate plates broke “a day, / metro” across two lines with a 24px hole — the unit was inline inside a 22px condensed line box. The unit is a block now, so every plate reads figure-then-unit; and “After hours & weekends” became “After hours” so its heading is one line like its five neighbours.
- The entrance was a rAF-driven class toggle. Headless Chrome services
requestAnimationFrameonly when a frame is requested, so the preview could have captured the drawing at opacity 0. Replaced with a CSS keyframe animation withbothfill, which is settled long before the capture and is killed outright underprefers-reduced-motion.
Pass 2 — Depth
- Made the
max()visible instead of merely correct. The losing line in the ledger is struck through in muted; the winning line carries an oxide — billed mark. Drove 121 km on the low loader (kilometres$798.60, day rate $2,150 billed, $2,750 total) and 595 km (kilometres $3,927 billed, day rate$2,150) and read both renderings. This is now the page’s second read. - Redrew the low loader’s machine. It was three stacked boxes and a floating parallelogram; it is now tracks with a roller line, a slew deck, a house with cab glass, and a boom and bucket folded down for transport. Added a riser web between decks of different heights so a step-deck reads as one trailer rather than two disconnected halves, and moved the drop-deck’s transportable off the upper deck so the step is actually visible.
- The dimension rule now breaks for its label. With a halo alone the rule showed through the word gaps and “Deck 12.5 m” rendered as dotted type — only visible in a 3× capture.
- The service-area map had colliding labels. Northam, Merredin and Southern Cross were all set above a corridor 40px apart, and “Merredin” was completely hidden under “Southern Cross”. Alternated them above and below the corridor and spread the nodes; moved the metro-band caption off the Esperance spur to under the ring; cropped the
viewBoxwest of the coast so the corridors fill the card instead of 90px of empty ocean. - Copy. Off-preset distances read “Kwinana Beach to a 121 km run” rather than the tautological “to 121 km out, 121 km”.
Pass 3 — Hardening
- Six FAQ disclosures had the browser’s default 1px focus ring — the
:focus-visibleselector list covered links, buttons and fields but notsummary. Walked the first 22 tab stops — skip link, wordmark, nav, phone, both hero calls to action, all three chip groups, the distance slider, the estimate’s two buttons and every FAQ disclosure — and confirmed each carries the same 3px oxide ring on a visible box. - Badge-versus-subject clearance, tested rather than eyeballed. The price plate’s box is checked against every drawn part of the rig at 375, 768, 1000, 1200 and 1440, at device pixel ratio 1 and 2, across all three rigs and both pilot extremes — 36 combinations, no intersection. (The first version of that probe grabbed the first
<rect>in the sheet, which is the prime mover’s chassis, and reported six collisions that did not exist; the plate now carries a data attribute and the probe targets it. A new check is wrong before the page is.) - Resize. The sheet is redrawn on a debounced width change and tracks its container exactly at 1200 → 700 → 1440, with the scene still fully opaque afterwards — a resize must never re-enter an entrance, because taking a clipped screenshot changes device metrics and would photograph a fading page.
- Rapid-fire. Nine control clicks dispatched in one evaluate with no settle between them land on the rest total of $5,960 with the drawing intact — no stale closure, no half-built sheet.
- Form. Empty submit: 15 messages against 15 required fields, first bad field focused, confirmation stays hidden. Filled submit: zero errors, panel visible, four summary lines echoing the load. Then a bad email, a three-digit phone and a 900-tonne mass, each rejected with its own message, and the panel correctly re-hides.
- 375.
scrollWidthexactly 375, wordmark and phone both inside the viewport box with clearance between them, no overflow offenders, sticky bar flush to the bottom with 48px targets, and the whole above-the-fold contract (headline, both CTAs, trust line) satisfied at 375×667 as well as 375×812. - The live region was announcing a table.
aria-live="polite"sat on the ledger, which rewrites five rows on every tick of the distance slider — hostile to anyone driving the estimate with a screen reader. The ledger is quiet now and a visually-hiddenrole="status"carries one sentence instead: “Low loader · Kwinana Beach to Kalgoorlie, 595 km · 1 pilot. Billed on the loaded kilometres, which are greater than the day rate. Estimated movement $5,960 ex GST.” — so themax()reaches the third surface too, not just the ledger and the drawing. - The Chanel rule. Removed the
.revealstagger machinery entirely rather than porting it — the page has one entrance, on the drawing, and nothing else moves.
Techniques
- Single file, no libraries, no build step, no raster images. Two fonts from Google Fonts; everything else is inline CSS and one IIFE.
- Both procedural visuals — the rig elevation and the service-area map — are SVG built with
createElementNSand laid out in real CSS pixels, so type stays type at every width. - The only animation is a 0.55s CSS keyframe on the drawing’s container. Nothing on this page advances with time, so the 7-second preview is a rest state by construction rather than by tuning.
window.__heavyhaulageexposes the estimate’s inputs and every intermediate as plain numbers — band, day rate, per-kilometre rate, loaded-kilometre charge, which of the two was billed, mobilisation, the pilot charge, the subtotal, the rounding and the total — so verification reads state instead of scraping text.[hidden]{display:none!important}guards the confirmation panel against any authoreddisplayrule.- The estimate reaches three surfaces on every change: the ledger, the price plate painted inside the drawing, and a visually-hidden status sentence for screen readers.