Build guide · Industry demonstration

How Warden Fire Services was made

A fictional AS 1851 fire equipment testing business in Bibra Lake, built as a single conversion-focused landing page — every visual procedural, every price arithmetic you can check, and one signature element doing the selling: the Compliance Dial.

The concept

Warden Fire Services tests and tags fire equipment for cafés, workshops, offices and strata blocks across Perth. Its customers' real pain isn't the wrench — it's remembering the six-monthly cadence AS 1851 demands, so the page's single job is a servicing-schedule enquiry, and the signature sells the memory: an annual dial that plans the year's two tagged visits and prices them live, itemised per asset.

It's the wave's B2B compliance site and the strongest Sapience Analytics story of the five — the deliverable a real client would buy is the reminder system as much as the servicing, which is why the ledger carries "logbook, register & reminders" as its own line at $0, deliberately.

Palette — argued from the service tag and the placard

#F6F6F3 · logbook whitePage ground — the report paper the whole trade runs on.
#26282B · charcoalBody ink at 13.5:1 on the ground. Disciplined, never decorative.
#C8102E · signal redEquipment marks, the calendar's service dots, CTAs. Never small text, never a wash behind text.
#2E7D5B · tag greenThe "tested OK" colour: ticks, the dial's swept arc, links (body-text green deepened to #26654B for 4.5:1+).

The direction is compliance clinical — the page should feel like a well-kept logbook: ruled (the hero's 28px baseline ruling), dated, stamped. Red is spent only where a fire trade earns it; the ink/line token split keeps it off text entirely.

Type

IBM Plex Sans Condensed carries the display — standards-document neutrality with placard-caps confidence; the AS 1851 service months (JAN · JUL) are set in it as tag stamps around the dial, which is the page's typographic moment. IBM Plex Sans does the body work: legible at 16px on a phone, tabular numerals for every ledger figure.

The Compliance Dial — how it works

The dial is one runtime-built SVG. Month ticks and the JAN/JUL tag stamps are generated from day-of-year fractions (frac × 360° − 90°); the swept arc is a circle with pathLength="100" whose stroke-dasharray is plain percentage arithmetic — the year runs top-clockwise from January 1, and the rest state sweeps to mid-May (36.99 of 100), through the January service dot, with a red-pennant flag planted on the July dot and pulsing between opacity 0.58 and 1 — a never-invisible floor, so any thumbnail instant catches it alive.

Site-preset chips (café / workshop / office / strata) set the four asset steppers, which drive the dial's centre readout, the mini asset shelf, and the itemised ledger. Every handler bumps an animation token before swapping state, so a rapid-fire chip sequence can never leave a stale rAF closure painting a dead scene; the sweep runs 1.2s on first draw and 450ms on every subsequent change via a firstDraw flag. Reduced motion paints the settled frame immediately and kills the pulse. The chosen preset and counts pre-fill the enquiry form, so the demo interaction becomes a warmer lead.

The maths is deliberately checkable: window.__firesafety exposes the live state, and the QA harness re-implements the pricing model independently and asserts the rendered DOM figures against it for all four presets, the stepper floor, and two rapid-fire bursts.

Pinned pricing anchors

ServiceRateNotes
Scheduled service visit — metro$150Per visit, Joondalup–Rockingham
Extinguisher test & tag$11Each, six-monthly
Fire blanket test & tag$8Each, six-monthly
Fire hose reel flow test & tag$25Each, six-monthly
Emergency & exit light discharge test$9Per fitting, 90-minute test, six-monthly
Pressure test & refill$66Per extinguisher, 5-yearly when due — excluded from the annual ledger, itemised as a when-due line
Replacement 4.5 kg ABE extinguisher$135Supplied & installed
Logbook, asset register & reminders$0Included — a deliberate designed line, not missing data
Fire indicator panel & pump servicingQuoted on the system — a designed price-less state; panels and pumps sit under their own AS 1851 sections

Annual = 2 × the visit total ("two tagged visits a year" — all four asset classes are six-monthly under AS 1851). Asset floor: minimum 1 extinguisher, with the reason shown on the disabled control. All figures are whole-dollar by construction.

PresetAssetsPer visitPer year
Café (rest state)2 ext · 1 blanket · 4 fittings$216$432
Workshop6 ext · 2 hose reels · 8 fittings$338$676
Office4 ext · 6 fittings$248$496
Strata common area8 ext · 2 blankets · 4 hose reels · 12 fittings$462$924
Estimator floor1 extinguisher only$161$322

Every figure above was measured from the running page and cross-checked against an independently re-implemented oracle in the QA harness. The services grid's "from $322 a year" equals the one-extinguisher floor — the estimator's cheapest output and the grid floor agree by construction.

Conversion decisions

Local SEO we'd implement for the real business

The demo page carries only WebPage/WebSite structured data naming it a demonstration — fictional business schema in a real search index would be dishonest markup. For a real fire servicing client, this is the JSON-LD we'd ship, populated with their verified details and genuine review feed:

{
  "@context": "https://schema.org",
  "@type": "ProfessionalService",
  "name": "Warden Fire Services",
  "description": "Fire equipment testing, tagging and logbook servicing
    to AS 1851 across the Perth metropolitan area.",
  "url": "https://www.wardenfireservices.com.au",
  "telephone": "+61-8-XXXX-XXXX",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "Unit X, XX Example Way",
    "addressLocality": "Bibra Lake",
    "addressRegion": "WA",
    "postalCode": "6163",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -32.096, "longitude": 115.815 },
  "areaServed": "Perth metropolitan area",
  "openingHoursSpecification": {
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
    "opens": "07:00", "closes": "16:00"
  },
  "priceRange": "$$",
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.9",
    "reviewCount": "87"
  },
  "review": [{
    "@type": "Review",
    "author": { "@type": "Person", "name": "— from the live review feed —" },
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "reviewBody": "— genuine customer reviews only —"
  }]
}

Why ProfessionalService: a compliance servicing firm is a professional-services organisation, not a construction trade — schema.org has no fire-protection subtype, so the honest pick is the LocalBusiness-family parent that matches what the business is. Rating and review nodes ship only when fed by the client's real, verifiable review source.

What changes for the real client

Iteration log

Pass 1 Craft

  • First full harness run: 34 asserts green first try — rest state $216/$432, all four presets against the independent oracle, the 1-extinguisher floor ($161/$322) with its on-control reason, both rapid-fire bursts, empty/filled submit transitions, and the 375px masthead (wordmark right edge 133.5px vs CTA left edge 236.4px — no collision).
  • The 1200×750 screenshot LOOK caught two dial collisions no assert saw: the JAN "✓ tagged" microlabel was drawn inward, colliding with the ring and the red service dot, and the July flag pennant — drawn outside the ring — sat on top of the JUL tag stamp. Moved both microlabels outside their stamps (viewBox stretched 360→368 so the JUL label isn't clipped) and replanted the flag inside the ring, its pole rising from the July dot with a pulsing halo ring around the dot itself.
  • 375px LOOK: the hero eyebrow wraps to two lines and its red bullet was vertically centred across both — realigned it to the first line.

Pass 2 Depth

  • Added the value-flash micro-interaction: when a drive changes the totals, both ledger figures flash tag-green for 0.55s (animation restarted via a reflow read, suppressed on first draw so the entrance stays calm).
  • Drove the dial by keyboard — focus a preset chip, press Enter — and asserted strata lands at $462 with focus retained; the second-read detail (the asset shelf redrawing its silhouettes per drive, the JAN stamp turning green as the sweep passes it) verified in the close-up captures.
  • Verified the reduced-motion path under emulation: settled flag true immediately, arc painted at its rest value (36.99/100), flag pulse animation none, no stuck opacity anywhere.
  • One harness artifact found and fixed in the harness, not the site: a backgrounded tab throttles rAF, so a settle-wait timed out until the driver brought the tab to front.

Pass 3 Hardening

  • Chanel rule: removed the dial card's punched-hole ornament — the tag motif already earns its keep on the six service cards; twice was decoration.
  • Reworded the dial CTA from "from $216 a visit" to the exact "— $216 a visit": "from" implies floor semantics that belong to the services grid, and the dial's figure is the configured price, not a floor.
  • Final sweep re-run across both pages and three viewports: zero console errors, one h1 per page, scrollWidth ≤ 375 on both, sticky tel bar fixed inside the bottom 140px, live JSON-LD types confined to the WebPage/WebSite allowlist, every (08) 9xxx number on the reserved 9000 exchange, and the confirmation panel's hidden→hidden→visible transition asserted on the element itself.