Generative Assets · Wave 15 · Industry Demos IV

How Brightwork was made — the building at 9pm

Design and build notes for a demonstration landing page: a fictional Perth commercial cleaning company, one conversion job (book a walkthrough quote), and a floor plan that cleans itself while you scope it.

Concept

Brightwork Commercial Cleaning is a fictional after-hours commercial cleaner based in Belmont — offices, medical suites, gyms and strata common areas across the Perth metro. The audience is an office or practice manager whose current contractor keeps no-showing, and a strata council comparing quotes. The page has a single job: get a walkthrough quote booked, because commercial cleaning is never honestly priced off a webpage — and saying so out loud is the trust play.

The art direction is "the building at 9pm": nightshift navy, warm lit windows, the quiet pride of a floor done before anyone arrives. Premium facilities services, not a mop-and-bucket flyer.

Palette — argued from the night shift

Nightshift navy
#141C28 · ground

The CBD after close. Dark enough that lit windows read as warmth, blue enough to never feel like a void.

Foyer ivory
#EDE9E0 · body ink

The lit lobby. All body copy is set in this — 14.9:1 on the navy ground. The line/mark accent never carries a paragraph.

Citrus
#D9A72E · line/mark only

Lit-window gold and the citrus note of a cleaned surface. Floor tiles as they finish, the sweep dot, CTAs, price marks. 8.1:1 on navy, so short marks pass — but it never sets long text.

Eucalyptus mist
#5E9E8A · secondary

The disinfectant green. Completed ticks, form focus and links — brightened to #79BCA7 where it sits as small text on navy to hold ≥4.5:1.

Supporting tokens: card navy #1B2534, raised navy #233047, hairline #2A3850, muted ink #ABA89D (6.7:1 on ground — captions and secondary copy only, never below 0.85rem body scale).

Type

Outfit (500–700) carries the display voice — geometric facilities-services confidence, warm enough not to read corporate-cold. It sets the nameplate, headings, prices and the estimate figure. Karla carries body and UI: a humanist grotesque that stays friendly at small sizes, with font-variant-numeric: tabular-nums on every quote figure, caption and slider readout so the estimate never jitters as it updates. Body is 17px, and nothing interactive drops below 16px on mobile.

The signature — Night-Shift Scope Builder

Space-type chips, an 80–1,200 m² area slider and frequency chips drive a procedural SVG floor plan. The plan is a serpentine grid of tiles — the route a cleaner actually walks — and tiles flip to citrus as the sweep dot passes, with room outlines (meeting room, treatment rooms, lobby, studio) and furniture blocks redrawn per space type. The grid's column count scales with the slider (6 columns at 80 m² up to 16 at 1,200 m²), so size is something you see, not just read. A task manifest updates per frequency and space type, and the estimate renders live. At rest the page is already mid-demonstration: a 300 m² office at three visits a week, two-thirds swept — and when the floor completes, a "signed off — 11:42pm" stamp holds for a beat before the next set begins.

Everything is vanilla: no libraries, one rAF loop that pauses on document.hidden, tiles painted incrementally (only newly-cleaned cells touch the DOM each frame), and prefers-reduced-motion renders the plan fully swept and settled with the sign-off stamp showing. "Use this scope in the quote" copies the configured scenario straight into the walkthrough form — the demo interaction becomes a warmer lead.

The pricing model (so the numbers are checkable)

Space typeBase / visitRate / m²Floor (80 m², weekly)
Office suite$55$0.50$95 / visit
Medical & allied$85$0.75$145 / visit
Gym & studio$60$0.75$120 / visit
Strata common areas$48$0.50$380 / month

per-visit = base + rate × m² · monthly = round-to-$5(per-visit × visits/week × 52 ÷ 12). Strata is presented monthly (that is how strata contracts are actually let), so its card leads with the monthly figure. Worked anchors: 300 m² office × 3 visits/week → $55 + 0.50×300 = $205/visit; $205 × 3 × 52÷12 = $2,665 → $2,665/month. Every "from" price in the services grid is the exact floor of the matching builder scenario — office $95/visit, medical $145/visit, gym $120/visit, strata $380/month — so the page can never argue with itself. Frequency deliberately doesn't move the per-visit rate: that variation is real but building-specific, which is exactly why the copy says the final price is set at the walkthrough.

Techniques

Conversion decisions

Local SEO we'd implement for the real business

This demo deliberately ships only WebPage schema naming itself a demonstration — fictional LocalBusiness or Review markup in a real search index would be dishonest. For a real client, we'd ship this (with their real details, real review feed, and per-suburb service pages):

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "@id": "https://brightworkcleaning.com.au/#business",
  "name": "Brightwork Commercial Cleaning",
  "description": "After-hours commercial cleaning for offices,
    medical suites, gyms and strata across Perth.",
  "telephone": "+61-8-XXXX-XXXX",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "Unit X, XX Example St",
    "addressLocality": "Belmont",
    "addressRegion": "WA",
    "postalCode": "6104",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.96, "longitude": 115.93 },
  "areaServed": ["Perth CBD","West Perth","East Perth","Subiaco",
    "Belmont","Victoria Park","South Perth","Osborne Park","Cannington"],
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
    "opens": "18:00", "closes": "02:00"
  }],
  "priceRange": "$$",
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.9", "reviewCount": "87"
  },
  "review": [{
    "@type": "Review",
    "author": { "@type": "Person", "name": "Real Customer" },
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "reviewBody": "Pulled live from the client's Google Business Profile."
  }]
}
</script>

Plus: Google Business Profile with service categories per suburb, review acquisition wired into job completion, and location pages for the suburbs that actually convert.

What would change for the real client

Iteration log

Pass 1 · Craft

  • Full headless sweep (42 asserts) on first run: empty submit flagged all five required fields (aria-invalid ×5, no confirmation, probe form:'invalid'); filled submit rendered the "Thanks — request received / we'd call you back within one business day" state; every chip, the slider, the FAQ accordion, the sticky bar and the scope→form handoff driven as dispatched MouseEvents, never el.click().
  • Oracle check — the pricing model re-implemented independently in the harness, never asserting the page against its own function: office 300 m² ×3 displayed ≈$205/visit · ≈$2,665/month; medical 500 m² ×5 displayed ≈$460/visit · ≈$9,965/month; office 1,200 m² ×5 ≈$655/visit · ≈$14,190/month. All matched to the dollar, as did the four grid floors ($95/$145/$120 per visit, $380/month strata).
  • Screenshot review caught what the asserts couldn't: on the service-area map the "Perth CBD" label ran into "East Perth" — moved East Perth's label above its dot; the trust strip wrapped its fourth item alone to a second row — switched to an auto-fit grid; form placeholders read too dim — lifted from #6E6C63 to #83816F.

Pass 2 · Depth

  • Added the fresh-wipe trail: the last three cleaned tiles glow at double strength before settling to the standard clean tint, so the frontier reads as wiping, not toggling. (Sweep pace ≈2 minutes per floor means the 66% rest state never completes inside a 7-second thumbnail settle.)
  • Micro-interactions: the estimate figure flashes citrus for a beat whenever its value changes (suppressed under reduced motion), and chips compress 4% on press.
  • Mobile screenshot review: the wordmark's "Commercial Cleaning" sub-line wrapped at 375px — hidden below 480px; the plan header's caption crowded the "Tonight's set" readout — stacked below 560px.
  • Drove a space-type change mid-sweep and asserted the plan rebuilt (tile count 42 → 112 across the slider range) with the probe's perVisit/monthly updated in the same interaction.

Pass 3 · Hardening

  • Chanel rule: the sweep frontier had three emphasis devices stacked — dot, halo and fresh trail. Removed the halo; the dot and trail carry it better alone.
  • 375×812 verified by probe and screenshot: scrollWidth = 375, wordmark and call button fully inside the viewport box with no overlap, h1 + primary CTA above the fold, sticky bar fixed at the bottom with both tap targets at 56px.
  • Reduced-motion via CDP emulation (not just the media query): plan renders fully swept (56/56 tiles clean), sign-off stamp showing, entrance settled at opacity 1, no sweep loop started — zero console errors in all three browser contexts.
  • Final cross-surface read: the $95/$145/$120/$380 floors, the $205/$2,665 worked example and the $46–$52/hr honesty line agree across hero, builder, grid and this guide; the reserved-phone sweep found only (08) 9000 0234 in every occurrence.