Tandem StructuralBuild notes View the page Index

Generative Assets · industry demonstration 417

How this page was built, and what it refuses to say.

Tandem Structural is a fictional two-engineer practice in Victoria Park. The page has one job: turn a frightened mid-renovation homeowner into a written enquiry with the job type already attached, by answering the only two questions they have — what does it cost and how long does it take — before they pick up the phone.

Why this converts

The primary call to action is the enquiry form, not the phone, because this buyer is embarrassed about not knowing whether they need an engineer at all and would rather type it than say it — so the header button, the hero button, the proof card and the sticky mobile bar all land on the same form anchor, with the phone kept one tap away as the fallback. The form asks five things and only four of them are required, because every extra required field on a page like this is a lead someone abandons; the fifth, the builder or building designer’s name, is the highest-value field on the page, since a named builder means a repeat referrer rather than a one-off job. The proof element publishes a fee and a turnaround for six named jobs, which is the single thing every competitor in this trade refuses to do — and because the numbers are on the page, the enquiry that arrives has already self-qualified on price. The trust strip does not claim awards; it claims the three things this customer is actually frightened of — a fee that moves, a subcontractor turning up instead of the engineer, and a quote that takes a week — and answers each in one line. And the page argues against its own dearer option in public: it says out loud that priority buys one working day on a shed certificate and seven on a second-storey set, because a business that tells you when not to spend money is the one you ring.


The proof element: a fee and a date, not a calculator

Every other lead-gen page in this collection has shipped an estimator with three or four controls. This trade did not need one. A structural engineer’s fee does not scale with a stepper — it is a fixed price per kind of job, and the customer’s question is never “how much per square metre”, it is “is this a four-hundred-dollar thing or a two-thousand-dollar thing, and will it hold up my builder”. So the proof element has exactly two controls: which job and how fast. It answers with the fee, the turnaround in business days, what actually lands in the client’s inbox, and one sentence about whether paying for priority is worth it.

Money is held in integer cents and divided once at display, so no cell can ever print a floating-point artefact. The turnaround halves on priority and rounds up to the next whole day, which is the honest direction to round a promise about time.

JobStandardPriority (+$280)What $280 buys
Patio or shed footing certification$390 · 3 days$670 · 2 days1 working day
Footing or slab inspection and certificate$460 · 3 days$740 · 2 days1 working day
Beam over a removed wall (rest state)$680 · 5 days$960 · 3 days2 working days
Retaining wall design$850 · 7 days$1,130 · 4 days3 working days
Crack investigation report$1,150 · 10 days$1,430 · 5 days5 working days
Full second-storey structural set$2,400 · 15 days$2,680 · 8 days7 working days

Twelve cells, swept. Cheapest $390 (patio, standard) — which is exactly the services-grid “from $” floor, so the page cannot argue with itself. Dearest $2,680 (second storey, priority). The priority uplift is one number across the whole domain: new Set(fee(j,true) - fee(j,false)).size === 1. Priority is dearer and faster on every job, asserted rather than assumed. All of it is licensed by check-w52.mjs and independently re-derived in oracle-structuralengineer.mjs, which also asserts every figure that appears in prose on either page — 50 asserts, 0 failures.

The rest state is the thumbnail

Wall removal, standard turnaround: $680 and 5 business days, with the beam-over-an-opening section drawn beside it. Measured from the running page at the 7-second capture instant at 1200×750, then re-read at 15 seconds — no numeric field in window.__structuralengineer moves, so the thumbnail is a rest state rather than a frame of an animation.


The drawing is stylised, and says so

Six sections, one per job type, drawn procedurally in SVG: an opening with a steel beam and two point loads; a new storey over an existing house on a new post; an L-shaped retaining wall with hatched backfill; a slab and edge footing in an open excavation; a patio roof on pad footings; and a cracked wall with tell-tale gauges across the crack. There are no dimensions, no spans, no member sizes and no scale anywhere on any of them, and a caption under the sheet says exactly that. It illustrates what is being designed. It does not specify it, and an engineering page that pretended otherwise would be doing the one thing this trade cannot afford to do.

The second read is in the arrows. They are the only warm colour on the page and they are reserved for forces alone — and they change direction with the physics: down onto the beam and the slab for gravity, sideways into the stem for earth pressure, and up off the patio roof, because wind uplift is what actually governs a patio and every builder who reads this page will recognise that. They are the one animated element: a wall-clock sine breathing between 0.80 and 1.00 opacity, paused on document.hidden, held flat at full opacity under prefers-reduced-motion. There is no per-frame accumulator anywhere in the file.

Two techniques worth naming. First, text is laid out in CSS pixels, not sheet units: the sheet is a fixed 560×210 design space, so a label written at 12 units would render at about 7 px on a phone. Each redraw measures the container and sets label font sizes to 12 × viewBoxWidth / measuredWidth, so a label is 12 px on every screen. Second, below 430 px the sheet crops its own viewBox to 40 0 480 210 rather than shrinking, so the subject gets bigger on the phone instead of smaller, and the labels switch to pinned short forms.

Ground is drawn the way a drawing office draws it — a solid surface band with hatching below, not a flood fill. That is not only convention: it keeps the load arrows on paper, where they measure 5.09:1, instead of on the soil fill, where they would measure 2.79:1 and be undeclared. Every label is a knocked-out tag — a paper plate under the text, the way a draftsperson would do it — so no word on any sheet ever sits on hatching, on soil or on steel, and every one of them is ink on paper at 15.74:1.


Palette

A drawing office, not corporate navy. Every ratio below is quoted with its hex from the same row of contrast-w52.log, regenerated after the last palette change.

Paper#F2F3F5Page ground.
Panel#E2E6EACard ground, and the map’s land fill — the same hex, so map marks read off the panel row.
Ink#151A2115.74:1 on paper · 13.93:1 on panel · 12.19:1 on the masonry fill · 8.61:1 on soil.
Muted#4A535C7.05:1 on paper · 6.24:1 on panel. Forbidden on every drawing fill.
Indigo#2C3C869.02:1 as ink on paper, 7.98:1 on panel, and paper reversed on it is 9.02:1. Marks on the masonry fill: 6.98:1.
Band#141A22Paper reversed on it: 15.75:1.
Masonry#D3D8DEWall and concrete fill. Carries ink at 12.19:1.
Steel#5A6673Beams and posts. Ink is forbidden on it (2.98:1); it carries paper reversed at 5.28:1.
Soil#C4B49BThe surface band. Ink on it: 8.61:1.
Load arrow#B0451C5.09:1 on paper · 4.51:1 on panel · 3.94:1 on masonry. Forces and nothing else.
Hairline#B5BEC71.70:1 on paper · 1.50:1 on panel. Paper and panel only.
Field#66717CInput borders. 4.48:1 on paper · 3.97:1 on panel.
Map water#C3D3DAOcean and the Swan. No text ever sits on it — every suburb label is on land.
Coast#5C76813.84:1 on the land fill · 3.13:1 on water. A mark, never text.
Chip sub-label#F2F3F5 at 86% → #D6D9E5Swept as its blended hex on indigo: 7.11:1. Do not take the opacity below 86%.
Error ink (minted)#8C1F2F8.04:1 on paper · 7.12:1 on panel. Added to the wave sweep during this build.

The one colour this build minted

The spec palette had no token for form validation. Reusing the load arrow was not an option — it is reserved for forces, and an engineering page that draws its error messages in the same colour as its point loads has just made both meaningless. So a deep oxblood #8C1F2F was minted, added to contrast-w52.mjs as errInk (text) and errMark (the invalid-field border), and the sweep re-run: 0 failures across every declared pair in the wave, with the new token measuring 8.04:1 on paper and 7.12:1 on panel. It appears nowhere on the page except an invalid form field and its message.

One declared token went unused: dimNote@78, a 78 % ink wash for dimension notes on the masonry fill. There are no dimension notes, so there was nothing for it to do — every drawing label is full-strength ink on a measured ground instead. The earth hatch is drawn in full-strength ink at 0.65 units, spaced 11 apart, which reads optically as a light grey without introducing an undeclared blend.


Type

IBM Plex Sans 600/700 carries the headings, the figures and every label that behaves like a stamp on a drawing — it is a drawing-office face without being a costume, and its tabular figures keep the fee and the turnaround from shuffling as they change. Inter 400/500 carries body copy at 17 px on a phone, which is the smallest this page will let anyone read.

The one typographic move is the pair: the fee figure and the turnaround figure set at the same size, separated by a single hairline, at the top of the proof card. They are the same size because they are the same question asked twice, and putting one above the other — or one at display size and the other at body size — would have said that one of them mattered more. It does not. The rest of the scale is deliberately narrow: a 12 px tracked eyebrow, 14.5 px secondary copy, 17 px body, a clamped 31–49 px headline, and the 33–44 px figure pair. Nothing else on the page is allowed to be large.


The three passes

Every pass drove the enquiry form (empty submit, then filled submit) and drove the proof element across all twelve cells, reading window.__structuralengineer and asserting against an independently re-implemented oracle rather than against the page’s own function. The harness ran headless Chrome against a private port, never a shared one.

Pass 1 — Craft

Four defects, three of which only a screenshot could see.

  • The wordmark vanished below 390 px. A rule written as .brand span{display:none} to hide the tagline matched the wrapper span as well, so the phone masthead showed a logo and nothing else. Every layout assert stayed green — a hidden element cannot overflow. Fixed by naming the tagline and scoping the rule to it.
  • The ordered list rendered its own numbers, and the review cards were inset by 40 px. The CSS reset covered ul but not ol or figure, so the how-it-works grid carried browser markers in its gutter and every review sat 40 px inside the section’s own left edge, out of alignment with everything above it.
  • The fee figure fell out of the thumbnail. At 1200×750 the proof panel ran to 968 px and the fee landed at y 787 — below the frame that is the collection’s sales asset. Restructured: the answer pair moved above the drawing, so the thumbnail now carries the headline, the fee, the turnaround and the drawn section together.
  • The desktop hero column ended 400 px above the proof panel, leaving a dead half-page. Filled with the three promises the trust line used to try to carry on one line, plus the page’s actual argument for publishing a fee at all.

Also in this pass: a full-width em-dash sanity read of every number rendered on the page (ten dollar strings, one phone pattern, five turnaround strings, no NaN, no undefined), and two illustrative figures in body copy were replaced with the page’s own licensed endpoints so that every dollar sign on the page is a number the oracle proves.

Pass 2 — Depth

The card learned to say more, and the estimate learned to hand over.

  • A site-attendance tag on the answer card, driven from the job record: five of the six jobs read “Site attendance included”; the patio and shed certification reads “Worked from your kit plan”, because it is the one job we do not attend. The FAQ makes the same claim in words, and the oracle asserts the claim is true of the table rather than of the sentence.
  • The proof element hands the job to the form. A link in the answer card jumps to the enquiry and pre-selects the job type — but only on an explicit click, never on load, because a pre-filled required field would quietly mask the empty-submit validation probe. Driven both ways in the harness.
  • The answer card became an aria-live region and the figures got a 130 ms dip on change — enough to register that something moved, short enough not to read as lag, and skipped entirely under reduced motion.
  • The drawings got their engineering back. A pad footing under the new post in the second-storey section (the label had been promising one that was not drawn), a beam under the patio roof the posts were pretending to hold up, the retaining wall moved left so the backfill carries the sheet, and the settlement arrow in the crack section moved off the empty margin and onto the masonry beside the crack — where it also lands on a declared ground.
  • The map was redrawn twice. The first Swan River started in open water and ran through Victoria Park; the second starts at the Fremantle mouth, widens at Perth Water and finishes at Midland, with Perth north of it and Victoria Park south, which is where they are.
Pass 3 — Hardening

375 px, reduced motion, focus, resize, and one ornament removed.

  • 375 px: no element escapes the viewport box (measured per element, not by scrollWidth, which masks exactly this class of defect), the wordmark’s right edge clears the phone link, and the headline, subline, both buttons and the trust line all sit above the sticky bar on a 375×667 screen with nothing scrolled.
  • Reduced motion: the arrows hold at full opacity and the loop never starts — asserted by reading the same inline opacity 1.2 s apart under an emulated prefers-reduced-motion: reduce, not by trusting the media query.
  • Focus and keyboard: both chip groups are real radio groups — arrow keys move the selection and roving tabindex keeps one stop per group. The harness drives the estimate by keyboard as well as by dispatched click.
  • Resize: redraws are debounced and gated on a real width change, and nothing re-enters an entrance animation on resize — there is no entrance animation on the sheet at all, which is the safest answer to a defect class that has bitten this collection twice.
  • One ornament removed (the Chanel rule): five decorative rib lines across the patio roof sheeting. They said nothing the section did not already say and they were the noisiest thing on any of the six sheets. The unused --ease custom property went with them.
  • Final copy read: every attribute on both pages scanned for typographic quotes (a smart quote inside a class attribute parses as part of the class name and silently kills the rule), one h1 per page confirmed, and the colophon checked on both.

What this page declined to publish

This trade sits on top of real rules that this page cannot verify, and the wrong number about a real standard is worse than no number. Everything below was considered and left off deliberately.

  • No National Construction Code clause numbers and no figure quoted from one.
  • No Australian Standard clause numbers and no figure quoted from one. Standards are named only in passing, as the thing the computations are done to, and no page on this site quotes a value out of one.
  • No retaining-wall trigger height. No “walls over X metres need engineering”, no local-government threshold, no exemption. That number varies and it is not ours to publish.
  • No detail of the Western Australian engineer registration scheme — not its name, its categories, its dates, its fees or its requirements. The registration line on the page is the visible placeholder Reg. PE0000 and the page says so in the FAQ.
  • No claim about when an engineer is legally required. The FAQ answers “do I need an engineer for this?” by naming who decides — your building surveyor or your local government — and then saying what we would look at. It never quotes a threshold.
  • No soil classification or site class figures, no bearing capacities, no wind region designations.
  • No professional-body fee scale and no claim about what engineers in Perth charge. Every dollar on the page is this fictional practice’s own price.
  • No dimensions, spans or member sizes on any drawing, and no claim of scale.
  • No real phone number, ABN or address. The phone is the reserved (08) 9000 0xxx pattern, the ABN is a placeholder, and the address is suburb-level only.
  • No LocalBusiness, Review, AggregateRating, Organization, Service or Offer structured data. The only live JSON-LD on the site page is WebPage, CreativeWork, WebSite and BreadcrumbList, and the WebPage names the page a demonstration. The reviews are demonstration copy and are labelled as such on the page itself.

Local SEO we would implement for the real practice

This is the schema a real Tandem Structural would ship, and the reason this demonstration does not: publishing structured data for a business that does not exist puts fiction into a real search index. It is printed here as a code sample and nowhere on the site as a live block.

<!-- SAMPLE ONLY. Never live on a demonstration page. -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "ProfessionalService",
  "additionalType": "https://schema.org/EngineeringBusiness",
  "name": "Tandem Structural",
  "description": "Residential and small commercial structural engineering across the Perth metropolitan area.",
  "url": "https://tandemstructural.com.au/",
  "telephone": "+61 8 9xxx xxxx",
  "priceRange": "$$",
  "image": "https://tandemstructural.com.au/img/office.jpg",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "Suite 3, 000 Albany Highway",
    "addressLocality": "Victoria Park",
    "addressRegion": "WA",
    "postalCode": "6100",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.97, "longitude": 115.90 },
  "areaServed": [
    { "@type": "City", "name": "Perth" },
    { "@type": "AdministrativeArea", "name": "Perth metropolitan area" }
  ],
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
    "opens": "07:30", "closes": "17:00"
  }],
  "hasOfferCatalog": {
    "@type": "OfferCatalog",
    "name": "Residential structural engineering",
    "itemListElement": [
      { "@type": "Offer",
        "itemOffered": { "@type": "Service", "name": "Beam design for a removed wall" },
        "priceCurrency": "AUD", "price": "680" },
      { "@type": "Offer",
        "itemOffered": { "@type": "Service", "name": "Retaining wall design" },
        "priceCurrency": "AUD", "price": "850" }
    ]
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.9", "reviewCount": "63"
  },
  "review": [{
    "@type": "Review",
    "author": { "@type": "Person", "name": "A real, verifiable client" },
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "reviewBody": "Real review text, pulled from the practice's own Google Business Profile."
  }]
}
</script>

Alongside it for the real client: a verified Google Business Profile with the service list and the service area matching this markup exactly; suburb landing pages only where there is genuinely different content to say (Victoria Park, Fremantle and Armadale get different retaining-wall ground, which is a real reason to write three pages, unlike the usual doorway-page approach); FAQPage markup on the FAQ block, which is the one piece of rich-result real estate this trade reliably wins; and the aggregate rating pulled from the live profile rather than typed, so it can never drift from what a searcher sees.


What would change for the real practice

  • The fee proposal stops being a promise and becomes a document. The enquiry drops into a proposal template and out through Xero as a quote the client accepts with a click, which is what converts an enquiry into a job number the same afternoon rather than the next week. The deposit and the progress invoice come from the same record.
  • Time goes on the job, not in a notebook. A practice this size runs time recording against the job — Deltek, ProjectWorks or WorkflowMax-class tooling — because a fixed-fee model only stays honest if you know what each job type actually costs to deliver. The six numbers on this page are the output of that data in a real practice, reviewed quarterly, not a guess that never moves.
  • The drawings become their own. The six procedural sections are placeholders for the practice’s own issued details, redacted and cleaned. That is a stronger page: a real beam detail from a real Victoria Park job carries more weight than anything drawn to illustrate.
  • The reviews become real. Pulled live from the Google Business Profile with the aggregate rating, so the page and the search result can never disagree.
  • The registration line becomes true. The real registration number, the real professional indemnity insurer and the real certificate of currency, all of which this demonstration deliberately refuses to invent.
  • The enquiry goes somewhere. Right now the form validates and confirms locally and sends nothing, on purpose. For the real practice it posts to the job system and the inbox, with a same-day acknowledgement that names the job type the enquirer picked.

Notes on the spec

  • The wave’s arithmetic licence names the crack-investigation job with the internal key underpin while the concept and the page call it a crack investigation. The fee and the turnaround are identical either way ($1,150 and 10 business days); only the identifier differs, and the page uses the concept’s wording.
  • The concept names three drawings — the opening with a beam, the first floor over posts, and the L-shaped retaining wall. The page ships six, one per job type, because a chip that changes the fee, the turnaround, the deliverables and nothing on the drawing reads as a broken control.
  • The concept’s layout order is the mobile stack. At desktop the proof element sits beside the hero headline and the services grid follows underneath, which is the wave rule; on a phone the order is exactly as written — masthead, hero, services grid, proof element, and so on.
  • No short forms are pinned for the answer card’s strings, and none were needed: the fee pair, the site tag and the priority note carry their full text at every width, including 375 px. Only the drawing labels have short forms, and those are switched on the measured sheet width, not on a media query.
  • The contrast log lists indigoMark on mapLand as a forbidden pair, but mapLand and panel are the same hex — #E2E6EA — so the suburb dots on the map are the passing indigoMark on panel row at 7.98:1. Flagged rather than assumed.