Straightedge

Build guide · Generative Assets

How Straightedge was made

Straightedge Line Marking is a fictional Welshpool car-park and warehouse marking operator — the wave's B2B industrial demo. The audience is strata and centre managers with a faded lot and warehouse managers facing an audit; the page has one job: a marking-quote enquiry with the bay count already computed. The signature Bay Planner draws the customer's car park bay by bay and prices it live, then hands the whole plan to the enquiry form.

Palette — argued from the asphalt and the stencil

The page is day-shift industrial: a concrete-light ground that the signature panel inverts into night-work asphalt. Yellow is paint, never prose; blue is the chalk line every marker snaps before painting.

Concrete#E9E8E4 — page ground, a broomed slab
Bitumen ink#26262A — body text at 13.0:1 on concrete
Safety yellow#E8B325 — CTAs, hazard chevrons, the bay pulse. Marks only, never small text
Setout blue#3D6B9E — chalk-line rules, links, dimension strokes
Asphalt#2A2C30 — panel-local ground; no body copy ever sits on it
Thermoplastic#F2F3F4 — the bays themselves, panel-local
Chalk#8FB4DC — panel-local setout annotation: bay numbers, dimensions

Type

Archivo Black is the display face — a stencil-weight block that reads like a painted lot numeral, used for the headline, the prices and the Bay Planner's big live count. Public Sans carries everything else: a government-grade workhorse that suits a trade quoting against Australian Standards. The display moment is the bay count set huge on the asphalt, stencilled like a painted lot number, counting up as the bays draw.

The Bay Planner — signature implementation

The planner is a top-down SVG setout drawing regenerated from state on every change. A layout pass distributes bays into one or two banks of slots (accessible bays take two slots — bay plus shared area — and sit nearest the entry; stencil work draws last, the way a crew actually paints: lines first, symbols after). Each bay is two nested SVG groups: the outer <g transform> owns position, the inner group owns the CSS draw-in animation — position and animation never share an element, so no presentation attribute is silently discarded.

The draw sequence is a single rAF timeline over the bay array with token invalidation in the control handlers: every stepper/mode handler bumps the token before it swaps state, so an in-flight sequence closed over the old bay array abandons on its next frame rather than indexing a rebuilt scene — the stale-closure race class caught in Wave 25, designed out from the first draw and verified with two rapid-fire drives (ten unsettled clicks in one evaluate, twice over). Redraws are dual-speed: the first render staggers at up to 55 ms per bay (entrance choreography, 1.5 s cap), every later state change at 11 ms per bay (~520 ms cap). The safety-yellow pulse on the active bay floor is a CSS opacity animation between 0.55 and 0.95 — a never-invisible floor, so the signature is alive at any capture instant — and the whole thing renders a settled static frame under prefers-reduced-motion. State is exposed at window.__linemarking (counts, mode, every computed figure, a settled flag) so verification gates on state, never on seconds.

In re-mark mode a second-read detail appears: the faded existing lot ghosts in beneath the fresh lines at 13% opacity, slightly offset — the old paint the crew is following.

Pricing model — anchors and measured figures

Every figure below was measured from the running page and cross-checked against an independently reimplemented oracle of the pinned rates. Totals display to the whole dollar; every anchor is integer-safe.

Pinned pricing anchors and measured outputs
ItemRateRule
Standard bay, set out & marked, two coats$38 new layout · $26 re-markMode toggle; re-mark follows the existing setout
Accessible bay to AS 2890.6$210 eachSymbol + shared-area hatching; additive above the clamp
EV bay stencil$150 eachAdditive above the clamp
Site establishment$480 flat per visitSetout, cones, signage — stated on every total
Minimum billing10 standard baysBilled at the selected mode rate; note shows below 10, none at exactly 10
Warehouse walkway & hatching, two-pack$9/lineal metreServices grid line — not in the planner
Bay numbering$14/stencilServices grid line
MRWA-spec / thermoplastic road worksNo numberQuoted per drawing — road-authority spec work is priced on the documents (designed price-less state)
ScenarioArithmeticMeasured
Rest state: 20 standard + 1 accessible, new layout480 + 760 + 210$1,450
Same plan, re-mark480 + 520 + 210$1,210
6 standard, new, no extras (clamp binds)480 + 10 × 38$860 + note
6 standard, re-mark (clamp bills at selected rate)480 + 10 × 26$740 + note
Exactly 10 standard, either moderaw = clampno note — boundary reachable on the stepper
Rest state + 2 EV stencils1,450 + 300$1,750

The planner's cheapest outputs equal the services grid floors — new car parks from $860, re-marks from $740 — so the page never argues with itself.

Conversion decisions

Local SEO we'd implement for the real business

This demo page carries only WebPage/CreativeWork schema naming it a demonstration — fictional structured data in a real index would be dishonest markup. For a real client we'd ship LocalBusiness schema wired to their actual details and live review feed:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "name": "Straightedge Line Marking",
  "description": "Car-park and warehouse line marking across the Perth
    metropolitan area — bay layout and re-marking to AS 2890, accessible
    bays to AS 2890.6, EV stencils and warehouse walkways.",
  "telephone": "+61 8 9000 0304",
  "url": "https://www.example-straightedge.com.au",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Welshpool",
    "addressRegion": "WA",
    "postalCode": "6106",
    "addressCountry": "AU"
  },
  "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"
  }
}
</script>

Type note: schema.org's LocalBusiness hierarchy has no line-marking subtype — the nearest branches (HomeAndConstructionBusiness and its children) don't honestly describe pavement marking — so the correct would-ship top-level @type is the parent LocalBusiness itself, not a borrowed trade subtype or a specialty enumeration token.

Iteration log

Pass 1 — Craft

The first 1200×750 render failed the thumbnail read: the hero ran 343 px tall and the planner columns were stretch-aligned, so the panel grew to match the controls card and pushed the big numeral to y≈886 — copy without a signature. Compacted the hero (two-line headline, trimmed lede), switched the planner grid to start alignment, visually hid the controls heading and tightened the card. Measured after: strip bottom 645, numeral top 671, ledger total top 692 — the whole rest state inside the frame.

Screenshot review also caught the shared-area hatch drawn in safety yellow over the safety-yellow pulse — invisible precisely when the pulse parks on the accessible bay, which is the rest state. Hatch is now thermoplastic white (also what a crew actually lays). Fixed a dead setout-length expression to max(bank units) × 2.6 m.

Pass 2 — Depth

Added the re-mark ghost: toggling to re-mark fades the existing lot in beneath the fresh lines (13% opacity, 1.6 px offset) so the mode change reads as a story, not a price switch. Drove every control against an independent oracle of the pinned rates: rest $1,450, re-mark $1,210, clamp $860/$740 with note at 6 bays and silence at exactly 10, rest + 2 EV $1,750 — plus two rapid-fire volleys (ten unsettled clicks in one evaluate) to prove the token-invalidation holds; final states matched the oracle to the dollar with zero console errors.

Pass 3 — Hardening

Masthead first at 375: wordmark right edge vs call-chip left edge measured with no collision, and the icon-only chip gained an aria-label. Sticky call/quote bar verified fixed in the bottom 140 px with 48 px targets; empty submit after a hard reload raises native validation with the confirmation panel still hidden; the phone pattern is v-flag-safe. Reduced-motion renders the settled frame instantly with the pulse static at 0.7. Chanel rule: removed the dashed aisle centreline — car parks don't mark one, so the drawing is more honest without it — and a dead header element.

What changes for the real client

Their photography where the procedural asphalt panel now stands (though the planner stays — it earns the enquiry), a live Google Business Profile review feed instead of demo copy, real ABN/registration numbers, and quoting wired into their job system — for WA marking crews that's typically AroFlo, Simpro, ServiceM8 or Tradify, with invoicing through Xero. The Bay Planner's plan payload would post straight into the job record so the estimator's counts arrive as line items, and MRWA prequalification documents would get their own indexed page.