← Tamala Line Retaining Walls

Generative Assets · Industry Demos XXV · site 337 · how it was made

Tamala Line Retaining Walls — build notes

A retaining-wall contractor's landing page for Perth's northern and eastern sand corridors, built around one drawn instrument: a Wall Planner that prices a limestone or sleeper wall by length and height and hands the scenario to the site-measure form.

Concept

Tamala Line Retaining Walls is a fictional Wangara operator building reconstituted-limestone-block, natural-cut Tamala limestone and concrete-sleeper retaining walls for new-block owners in Alkimos and Brabham, established owners replacing a leaning pine wall, and pool builders' clients who need the level pad first. The page has one job: a site-measure booking that already carries the wall type, length and height — priced — so the first phone call is a confirmation, not a discovery.

The audience is a phone in one hand on a sand block. So the conversion path leads (name, promise, call, book, one trust line all inside 375×667), the drawing supports, and every number on the page comes from the same six pinned anchors.

Palette — a cut limestone bench, late afternoon

Argued from the materials: Tamala limestone for the ground, jarrah for the ink, the red-earth of a fresh cut for the calls to action, coastal scrub for the linework. Contrast was measured from the shipped tokens with WCAG 2.x arithmetic in Pass 1 — the spec's figures were hypotheses, these are the measurements.

Tamala cream#F6EFE0 — page ground
Jarrah dark#2B2A26 — body ink, 12.55:1 on cream, 14.36:1 on white
Red earth#8A5A2B — marks, plate rim, stars; white on it 5.87:1; on cream 5.13:1
Red-earth button fill#744A22 — white labels 7.65:1
Red-earth ink#67401D — links and accent copy, 7.88:1 on cream, 9.02:1 on white
Coastal scrub#7C8F6B — lines and marks only (3.06:1 on cream — never small text)
Scrub ink#48573C — eyebrows and drawing labels, 6.78:1 on cream, 7.77:1 on white
Soft ink#5A554A — secondary copy, 6.47:1 on cream

The ink/line split in practice: scrub #7C8F6B draws the string line, hatch and rules; anything you read in that hue is the darker scrub-ink. Red earth passes at 5.13:1 on cream, but buttons still use the pre-minted deeper fill (7.65:1 under white) and small accent copy uses red-earth ink (7.88:1) — the two-token remedy applied before it was needed, so the accent never sits near the 4.5 line. Trust strip on jarrah: cream 12.55:1, muted #D9CFB4 9.26:1.

Type

One metre high, twelve metres long

Bitter 700/800 — a slab serif with a mason's shoulders. Wordmark, headings, the display line over the drawing, the plate price, and every figure in the ledger. The display line is generated from the planner state ("750 millimetres high, twenty-one metres long") so the typographic moment is live, not decorative.

Holds the block, keeps the sand — reconstituted limestone, natural-cut Tamala and concrete-sleeper walls, priced by length and height.

Karla 400–700 — the workhorse: body at 17px (16px in the form fields at 375), labels, chips, the drawing annotations. Its slightly geometric shapes sit well against Bitter's slabs without competing.

Scale: 13/15/17/19/27 body-and-label rungs, then Bitter at 38 (ledger total), 40 (section heads) and 56 (h1) on desktop. Uppercase with tracking is used exactly twice — eyebrows and the display line — because both are categorical.

The signature — Wall Planner

An SVG cutaway of a retaining wall in elevation and section, drawn procedurally from the planner state. Left to right: the height dimension, the string line with drawn stakes and flags, a spirit level sitting on the top course, the wall face itself, then the cut end showing wall thickness, the blue-metal drainage column, the ag-line at the base, the hatched retained sand rising behind, and the compacted base and footing under everything. The length dimension runs below the footing and reads the course count.

How it is built

Pricing model — the pinned anchors

Supply and build per square metre of wall face (length × height). Excavation to footing depth, compacted base, 100 mm ag-line and blue-metal drainage are included in every wall. All three rates divide by four, so every 0.25 m step prices to a whole dollar; totals display to the whole dollar by construction, not rounding.

LineRuleRate
Reconstituted limestone blocksper m² face, minimum 8 m² billed at the selected type$280/m²
Natural-cut Tamala limestoneper m² face, minimum 8 m²$360/m²
Concrete sleepers on galvanised postsper m² face, minimum 8 m²$240/m²
Engineer's design & building permitflat; FORCED ON (locked) at every height ≥ 0.75 m — "walls over 500 mm need a building permit in most Perth councils — we design and lodge it"; OFF and DISABLED at 0.5 m — "under 500 mm — no permit needed". Height fully owns the toggle: nothing to restore.+$650
Colorbond fence on top× wall length in metres — multiplies length, never the billed face minimum; live at every type × height+$95/lm
Remove & dispose of the old timber wall× wall length; live at every combination+$45/lm
Steps, corner returns, curves, walls over 1.5 mno number — "measured on site, quoted from the engineer's drawing" (ledger line, services grid, FAQ)

Worked examples (all measured from the running page and matched against an independent oracle)

ScenarioArithmeticTotalNotes
Rest: blocks, 12 m × 1.0 m12 × 280 + 650$4,010permit locked on, fence off, removal off — the thumbnail plate
Natural-cut, 10 m × 1.25 m12.5 × 360 + 650$5,150+ fence 10 × 95 = 950 → $6,100
Sleepers, 20 m × 0.5 m10 × 240$2,400permit off and disabled
Blocks, 6 m × 1.0 m8 (min) × 280 + 650$2,890note "billed at the 8 m² minimum" present
Blocks, 8 m × 1.0 m8 × 280 + 650$2,890boundary cell — no note
Blocks, 16 m × 0.5 m8 × 280$2,240the no-permit floor cell, no note
Blocks, 12 m × 1.0 m + removal4,010 + 12 × 45$4,550
Grid floors8 m² × rate, 0.5 m, no permit$1,920 · $2,240 · $2,880sleepers · blocks · natural-cut = the services grid "from" prices
Sleepers, 3 m × 0.5 m + fence8 × 240 + 3 × 95$2,205fence multiplies the 3 m length, not the 8 m² billed face

The harness set the full control vector for every scenario (type chip, both steppers, both toggles) before reading the plate, ledger and probe, then swept the whole grid — 3 types × 5 heights × 10 lengths × fence/removal on and off — against the oracle: zero mismatches. Rapid-fire drives (15 and 14 control clicks in one evaluate, no settle between) ended settled and consistent with the oracle.

Conversion decisions

Local SEO we'd implement for the real business

The live page emits only WebPage / WebSite / BreadcrumbList / ListItem schema naming it a demonstration — fictional business data in a real index would be dishonest markup. For the real client we would ship the block below (top-level type GeneralContractor, the schema.org organisation subtype for a wall builder), fed by their real reviews, hours and service area:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "GeneralContractor",
  "name": "Tamala Line Retaining Walls",
  "description": "Limestone block, natural-cut Tamala limestone and concrete-sleeper retaining walls across Perth's northern and eastern suburbs.",
  "url": "https://www.example-client-domain.com.au/",
  "telephone": "+61 8 9000 0337",
  "address": { "@type": "PostalAddress", "addressLocality": "Wangara", "addressRegion": "WA", "postalCode": "6065", "addressCountry": "AU" },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.79, "longitude": 115.83 },
  "areaServed": ["Alkimos", "Butler", "Joondalup", "Kingsley", "Wanneroo", "Landsdale", "Ellenbrook", "Brabham", "Aveley", "Midland", "Bassendean", "Forrestfield"],
  "openingHoursSpecification": [
    { "@type": "OpeningHoursSpecification", "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"], "opens": "06:30", "closes": "16:00" }
  ],
  "priceRange": "$$",
  "hasOfferCatalog": {
    "@type": "OfferCatalog",
    "name": "Retaining walls",
    "itemListElement": [
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Limestone block retaining walls" }, "priceSpecification": { "@type": "UnitPriceSpecification", "price": "280", "priceCurrency": "AUD", "unitText": "per m² of wall face" } },
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Natural-cut Tamala limestone walls" }, "priceSpecification": { "@type": "UnitPriceSpecification", "price": "360", "priceCurrency": "AUD", "unitText": "per m² of wall face" } },
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Concrete sleeper retaining walls" }, "priceSpecification": { "@type": "UnitPriceSpecification", "price": "240", "priceCurrency": "AUD", "unitText": "per m² of wall face" } }
    ]
  },
  "aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.9", "reviewCount": "63" },
  "review": [
    {
      "@type": "Review",
      "author": { "@type": "Person", "name": "Real customer name (from the client's Google profile)" },
      "datePublished": "2026-03-14",
      "reviewRating": { "@type": "Rating", "ratingValue": "5" },
      "reviewBody": "Real review text pulled from the client's Google Business Profile."
    }
  ]
}
</script>

Alongside it: a Google Business Profile with the Wangara service-area setting (not a storefront pin), suburb landing sections for the two corridors, and an FAQ block mirroring the permit / drainage / boundary questions above.

What would change for the real client

Iteration log

Pass 1 — Craft

  • Measured every palette pair (table above). Red earth cleared 4.5:1 on cream at 5.13:1, so it stays for marks; buttons and accent copy still use the deeper pair so nothing sits near the line.
  • First render put the wall in a 920×520 box at 80 units/m — roughly 40% empty sky and 11px annotation text at 1200 wide. Moved to an 800-wide box, 100 units/m, 13–14px annotations, and a bottom-anchored viewBox crop inside a fixed aspect box so the drawing fills its frame at every height without layout shift.
  • The string line at yTop−30 touched the plate's top edge; lifted it to yTop−38 and moved the "string line" label above the stakes. Section labels moved from following the cut end to a fixed legend column with scrims and leader lines, so a 0.5 m wall doesn't stack four labels into 50 units.
  • 375 masthead: the wordmark wrapped to two lines and "Book a site measure" wrapped in the header — nowrap wordmark, "Site measure" short label, subtitle hidden. Wordmark right edge now measures 125px against the call button's left edge at 164px.
  • 375 fold: the trust line ended at 710px (below 667). Dropped the ghost phone button on mobile, tightened the lede and hero padding — first trust signal now ends at 588px, primary CTA at 497px.
  • Copy read: replaced "we handle it" throughout with what actually happens ("we design and lodge it", "you sign, we chase").

Pass 2 — Depth

  • Mobile plate variant: at ≤640px the plate takes a shorter subtitle and lifts onto a drawn post above the top course, so the coursing stays visible at 375 (plate 81px wide against a 345px scene).
  • Locked permit toggle no longer reads as a broken 50% dimmed control — it holds full opacity in red earth with a lock glyph in the knob; the 0.5 m state dims with its reason.
  • Second-read details: the level's vial glows green when the bubble passes centre; natural-cut coursing is seeded so the same wall always draws the same stones; the "old pine wall — out and tipped" tag sits inside the ghost on the bottom course, clear of the level and the plate.
  • Micro-interaction: subsequent redraws pop the plate (scale .92 → 1.03 → 1) — on an inner group, because the outer group carries the SVG transform attribute and a CSS transform animation would discard it.
  • Chips at 375 became a three-column grid so the wall types read as one row instead of three stacked pills.

Pass 3 — Hardening

  • Tap-target sweep at 375 measured the toggle switch at 28px tall — rebuilt the toggle as a 52×44 button with the 46×28 track drawn as a pseudo-element; minimum tap target now 44px across chips, steppers, toggles, buttons, sticky bar and header call.
  • Reduced motion: no rAF loop, no entrance or pop animations, courses render at opacity 1 on the first frame with the plate at $4,010; asserted headlessly.
  • Harness artifact caught and ruled out: clipped screenshots after a scroll captured every CSS-animated element at its pre-delay frame (opacity 0) — puppeteer's beyond-viewport capture re-renders the page; the same frames captured with captureBeyondViewport:false show the settled scene. Diagnosed as capture, not site (the settled flag and course counts agreed).
  • Label-collision sweep at native resolution (1200×1 and 375×2) across five driven states (rest; sleepers 2 m with removal; natural-cut 10 m with fence and removal; blocks 40 m with fence; blocks 3 m × 1.5 m with fence and removal). Two collisions found and fixed: on a 2 m wall the straddling plate covered the cut end, the drainage column and the legend's leader dots — walls under 300 drawing units now use the elevated plate-on-a-post variant with a minimum offset that clears the level and the "string line" label; and with the fence on, the "string line" label ran across the fence's left post — the label is dropped when the fence is drawn (the stakes and flags still read). The ghost pine wall was also too faint against natural-cut stone at 0.42 — now 0.5 with a darker outline.
  • Chanel rule: removed the scrub-green gradient wash under the hero — the drawing already carries the colour.
  • Final: zero console errors, both pages at 375 scroll-width clean, guide tables in .table-scroll, one h1 per page, live JSON-LD allowlist clean, reserved phone pattern only.

This is a demonstration build by Sapience Analytics. Want one pointed at your customers?

sapienceanalytics.com.au danny@sapienceanalytics.com.au