Meridian Line AML Build notes ← Back to the site Index

Generative Assets · Industry demonstration 462

How Meridian Line AML was built

A fictional West Perth AML/CTF consultancy for principals of 3–10 person Perth agencies and practices who are being emailed by eight vendors and cannot tell whether the deadline is theirs. The page has one job: compute the date they must enrol by from their own start date, and be the only result on the first screen willing to say not yet and we cannot tell you you’re clear.

The palette

Indigo is the colour of a certified-copy stamp; the gold is the bullion dealers who are one of the five sectors AUSTRAC names. Gold is rationed hard: it appears only on the date apparatus — the 28-day run and its week marks, the flag, the day-of-week before the answer, the distance line, and the outlined pill on the two states that say wait. Everything else that wanted to be gold (eyebrows, list markers, step numerals, the required asterisk, the wordmark rule) is indigo. Ratios are measured, pasted from contrast-w61.log; the scene fills below it were minted for this build and measured the same way.

Page ground#F5F5F8A cool paper. Neutral enough that indigo reads as ink rather than as brand.
Surface#FFFFFFCards, the drawing, the form. Ink measures 17.65:1 on it.
Ink#16172A16.22:1 on ground, 17.65:1 on surface. Blue-black, not black.
Muted#4B4D637.60:1 on ground, 8.26:1 on surface. Body colour for second-rank copy.
Primary — ledger indigo#3B3D918.53:1 on ground, 9.28:1 on surface, and white on it at 9.28:1. Every CTA fill.
Accent — bullion gold#7A5C085.74:1 on ground, 6.25:1 on surface, white on it at 6.25:1. Dates only.
Band#191A2EFooter and the Sapience band. Only #EDEDF5 may sit on it — 14.68:1.
Verdict tint (minted)#ECECF4Ink 15.02:1, muted 7.03:1, primary 7.90:1, accent 5.32:1. The answer sits here.
Rail / flash (minted)#E4E4EEInk 13.97:1. Also the 380 ms tint the verdict takes when you change an input.
Map land (minted)#E7E7EFInk 14.35:1, muted 6.72:1, primary 7.55:1 — so suburb labels are body ink, never a mark colour.
Map water (minted)#CFD6E6Ink 12.11:1, muted 5.67:1. The rotated Indian Ocean label is muted, measured on this.
Hairline (minted)#D9D9E41.29:1 on ground — a decorative rule only. It never carries information and never carries a word.

Forbidden pairings from the same log were obeyed literally: ink, muted, primary and accent never land on the band, on the primary fill or on the accent fill; #EDEDF5 never lands on a light ground. Where a label crosses a map fill it also carries a 3.5 px surface-coloured halo via paint-order:stroke.

The type

Newsreader 600 for headings and for the answer itself. It is a serif built for reading aloud, and this page is quoting a regulator all the way down — a statutory voice rather than a consultancy one. The single moment of bravery is the enrol-by date, set at up to 2.7 rem with tabular figures and the day-of-week carried in gold at 0.56 em in front of it, so the whole string still reads as one line: Wed, 29 Jul 2026.

Inter Tight 400/500/600 for everything else. It is narrow enough that a 48-character quotation still sets on three lines inside a card at 375 px, which matters on a page that prints six verbatim quotations. Body copy is 17 px with a 15 px floor inside cards; nothing on the page is smaller than 11.5 px except the drawing’s own captions, which sit on white at 9.5 px in muted (7.65:1) and repeat in full-size text directly beneath.

The proof element and how it is drawn

Four inputs — business, what you do, first designated service date, size — answer in a fixed order: in scope or not yet, your enrol-by date, what you must have in place, the fee. When before how much, because the reader’s question is a date and not a price.

The arithmetic is one line: enrolBy = max(firstServiceDate, 1 Jul 2026) + 28 days, done in UTC with fixed day and month tables. toLocaleDateString is never called — en-AU ICU renders July as “July” and not “Jul”, so the printed string would change shape by month and by engine. Nothing on the page calls new Date(): the defaults are constants and the page states the date it checks against, so the 1200×750 capture is byte-identical at 7 s and at 15 s.

The drawing is a plain SVG timeline built synchronously from that model — no library, no requestAnimationFrame loop anywhere on the page, so there is nothing to settle and nothing that can be caught mid-frame by a headless capture. It carries a statutory left half (enrolment opens 31 Mar 2026, obligations start 1 Jul 2026) and a moving right half: a marker for the first designated service, twenty-seven day ticks with every seventh drawn taller so the four weeks are countable, a gold pennant on the enrol-by day, and the distance from the page’s reference date under it. The second read is the snap: enter any date before 1 July 2026 and the clock marker jumps back onto the commencement anchor and takes a gold ring — the drawing performs the max() instead of explaining it.

Driven examples from the shipped page
First designated serviceBranchEnrol byToday
1 Jul 2026 (default)In scope — and the date has passedWed, 29 Jul 2026 · 49 days ago$4,800 + GST
10 Sep 2026In scopeThu, 8 Oct 2026 · in 22 days$4,800 + GST
14 Sep 2026In scopeMon, 12 Oct 2026$4,800 + GST
2 Feb 2026In scope — clock snaps to commencementWed, 29 Jul 2026$4,800 + GST
31 Dec 2026Not yet — $0 todayThu, 28 Jan 2027$0
Lease and manage onlyWe will not tell you you’re clear$0

Every date and every dollar in that table is asserted by figures-w61.mjs and re-driven in the browser by this build’s own harness (129 checks). The day counts are derived from the same dates and asserted alongside them.

The refusal, which is the whole page

A property manager searching this question gets a first screen of confident answers, and every one of them is attached to a subscription. So the strongest thing this page can do is decline to be the ninth. Choose lease and manage only and the card replaces the date, the checklist and the fee with three things and nothing else:

The drawing changes with it rather than disappearing: the 28-day window is still drawn, ghosted and unstarted, with a dashed ring and a question mark where the flag would go and the caption “we cannot start this clock for you”. The refusal gets the same design budget as the sell, and it terminates in something the reader can do today — a refusal that ends the conversation is a lost lead dressed as honesty.

Conversion decisions

Why the CTA sits where it does

Two CTAs above the fold at 375×667, both finishing 101 px clear of the sticky bar: a filled Book a free 15-minute scope call and a ghosted Get your enrol-by date. The ghost is deliberately the cheaper ask — a principal who will not fill in a form will change a date in a dropdown, and the card they land on carries the same CTA with the price attached to it. On phones the masthead button is dropped and the sticky bar owns the call and the form anchor, because at 375 a third element in the masthead collides with the wordmark.

Why these form fields

Seven required fields and two optional. Business type and what you do are optional-adjacent by design: the scope call is worth more when we already know whether there is a rent roll in the picture. The date field is optional because a principal who does not know their first designated service date is exactly the person who should still book. The phone field carries inputmode="tel" and a pattern escaped for the v flag — an unescaped (, ) or - inside the class is silently discarded by Chrome and the field then accepts “ring me maybe”, which the harness drives on every run.

Why the proof element answers a date

The fee is not the reader’s question. Eight vendors have already told them a price; none of them has told them whether the deadline is theirs. So the card answers in this order and the money is fourth — and in two of the four branches the money is $0. The services grid prices six things and two of them are free, including the enrolment itself, which is the cheap end of our own list.

Why the trust line reads as a refusal

“Not a law firm. Not a software subscription.” Every competitor on page one is one or the other, so the fastest way to be legible is to name what we are not. The hero then hands the floor to AUSTRAC: the commencement list is quoted as published, and a principal finds their own sector in it inside two seconds without us claiming anything.

Why this converts

A principal arrives with one question — is this deadline mine, and when — and this page answers it in the first screen with a date computed from their own file, not with a brochure. The call to action is free and small: a fifteen-minute scope call that ends in a written note either way, which is a far easier yes than a four-figure program build, and every CTA on the page says that rather than “get a quote”. The fees are published where the entire category says contact us, so a reader can price the decision without speaking to anyone and arrives at the call already knowing the number. Two of the four answers cost nothing — not yet, and we will not tell you you’re clear — and a business that visibly turns work away in public is the one a principal rings when the work is real. That is the whole argument for hiring us to build your page: we will find the number or the date your trade normally withholds, publish it, and then show your customer the case where they should not buy — because that is the paragraph they remember.

The three passes

Each pass drove the enquiry form empty, filled and with junk in the phone field, and drove the proof element through all four dated examples plus the not-yet and lease-and-manage branches. Each pass ended by opening the real 1200×750 and 375×667 captures and looking at them.

Pass 1 — Craft

  1. The drawing’s own answer was clipped. “Enrol by / 29 Jul 2026” was drawn at y=115 inside a viewBox only 112 units tall, so the date under the flag was cut in half. One hundred and ten green assertions never saw it; the PNG did. viewBox raised.
  2. The drawing sat 11 px outside the thumbnail. Measured bottom 761 px at 1200 wide against a 750 px frame, because the explanatory paragraph was between the answer and the picture. Reordered to answer → drawing → caption → explanation, which is also the better read: 559–651 px.
  3. A quarter of the thumbnail was empty. The hero column ran out of copy at about 500 px. Filled it with the thing a scanner actually needs — AUSTRAC’s commencement line and its five sectors, quoted as a list, with the source and date under it. A reader now finds themselves in the thumbnail.
  4. Gold had leaked. The spec says gold marks dates only, and it was on eyebrows, list markers, step numerals, the required asterisk, the quotation rule and the wordmark. All moved to indigo. Gold is now five things, all of them dates.
  5. Broken sentence in two of three bands. The not-yet nudge composed “the build is $4,800 + GST for a 3–10 staff”. Added a noun phrase per band.
  6. Three map defects, none visible to an assert. “Swan River” overlapped “Nedlands”; “Indian Ocean” ran off the water onto the coast; and Mandurah was cut by the bottom of the viewBox. River label moved to the north-east reach, ocean label rotated −90° up the water strip, viewBox extended and the southern pins re-spaced.
  7. Map labels measured 7.8 px at 375. A fixed viewBox scaled the whole drawing down with the column. The map now crops to 44 30 500 436 below 700 px and steps its label size up, which lands at about 12 px on a phone; the crop restores on the way back up and is asserted in both directions.

Pass 2 — Depth

  1. The weeks became countable. Every seventh of the 27 day ticks is drawn taller and at full opacity, so the 28 days read as four weeks without a word of copy. Asserted at three week marks on every branch that has a run.
  2. The drawing now carries the distance. Under the flag: 49 days ago on the default, in 22 days for a 10 September start, once you start on the not-yet branch — the one thing a reader wants next after the date, inside the picture rather than in a paragraph below it.
  3. The “both” state earned its own sentence. Broking and managing now prints “that does not take you out of scope and it does not change the fee — it changes what the program has to cover, because your staff meet buyers and tenants through two different doors.” A control that changes the work and not the price is worth saying out loud.
  4. One micro-interaction. The verdict panel tints to the rail colour for 380 ms whenever the reader changes an input, so a change below the eye-line announces itself. It is gated on a user event, so it never fires on load and the 7-second capture is untouched; it is skipped entirely under prefers-reduced-motion. Asserted on and asserted off.
  5. Service tiles lift 2 px on hover and take a darker hairline. That is the entire hover budget for the page.

Pass 3 — Hardening

  1. 375×667 fold. h1, both CTAs and the trust line all finish above the sticky bar with 101 px of clearance against a 12 px floor; scrollWidth is exactly 375 and no element crosses the viewport box; the wordmark’s right edge clears the phone link.
  2. Reduced motion. Verified with an emulated media feature, not by reading the stylesheet: the hero is opaque and untranslated on arrival, the verdict renders in full, and the change-flash is skipped by a matchMedia test in JS as well as by the CSS.
  3. Resize. Counted visible marks in both drawings at 1200, 1000 and 375 — 72, 72, 72. Puppeteer’s clipped screenshot resizes the viewport under the page and fires resize, which has emptied scenes in this collection before; nothing here re-enters an entrance on resize because there is no entrance inside either SVG.
  4. The ornament that went. The service-area map had two concentric halo rings under West Perth. One of them was decoration about decoration; it is gone, and the survivor is slightly tighter.
  5. Both checks watched fire. Green is not evidence, so two defects were planted: a 900 px spacer pushed the answer to 1412 px and the in-frame check failed as it should; a capture-phase listener swallowing submit left the confirmation hidden and the confirmation check failed as it should.
  6. Final copy read. Every number in body copy re-derived from the model — six tiles under “six things”, four steps, three reviews, six FAQs, nine months of support to 30 June against $7,410, and every dollar string on the page checked against the licensed set so an unlicensed figure cannot appear by accident.

What this page declined to publish

A page about a regulator is only worth reading if it is disciplined about what it does not know. None of the following appears on the site, and none of it appears here either:

One verified figure was left off the site on taste rather than doubt: AUSTRAC writes that “Financial crime happens in Australia every day and it costs up to $82 billion a year.” It is true and it is quotable, and it is also the sentence every vendor email opens with. The copy angle for this audience is to lower the temperature, so it stayed out of the hero and lives here instead.

Local SEO we’d implement for the real business

The demonstration carries only a WebPage block naming it a demonstration, with Sapience credited through creditText and no nested organisation — publishing LocalBusiness or Review markup for a business that does not exist would pollute a real index. For a real client we would ship the following, with real reviews pulled from their Google Business Profile and never hand-written.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "ProfessionalService",           // FinancialService also fits an AML/CTF advisory
  "@id": "https://meridianlineaml.com.au/#business",
  "name": "Meridian Line AML",
  "description": "AML/CTF program builds and outsourced compliance officer services for
                  real estate agencies, conveyancers, accountants, law practices and
                  bullion dealers across Perth, Western Australia.",
  "url": "https://meridianlineaml.com.au/",
  "telephone": "+61 8 XXXX XXXX",
  "email": "hello@meridianlineaml.com.au",
  "priceRange": "$$",
  "image": "https://meridianlineaml.com.au/img/office.jpg",
  "logo": "https://meridianlineaml.com.au/img/logo.png",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "Suite N, NNN Example Street",
    "addressLocality": "West Perth",
    "addressRegion": "WA",
    "postalCode": "6005",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.94XX, "longitude": 115.84XX },
  "areaServed": [
    { "@type": "City", "name": "Perth" },
    { "@type": "State", "name": "Western Australia" }
  ],
  "openingHoursSpecification": [
    { "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday"],
      "opens": "08:00", "closes": "17:30" },
    { "@type": "OpeningHoursSpecification",
      "dayOfWeek": "Friday", "opens": "08:00", "closes": "16:00" }
  ],
  "hasOfferCatalog": {
    "@type": "OfferCatalog",
    "name": "AML/CTF services",
    "itemListElement": [
      { "@type": "Offer",
        "itemOffered": { "@type": "Service", "name": "AML/CTF program build" },
        "priceSpecification": { "@type": "PriceSpecification",
          "minPrice": 2950, "priceCurrency": "AUD",
          "valueAddedTaxIncluded": false } },
      { "@type": "Offer",
        "itemOffered": { "@type": "Service", "name": "Outsourced AML/CTF compliance officer" },
        "priceSpecification": { "@type": "UnitPriceSpecification",
          "price": 290, "priceCurrency": "AUD",
          "unitCode": "MON", "valueAddedTaxIncluded": false } }
    ]
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.9", "reviewCount": "37"   // synced from Google, never typed
  },
  "review": [{
    "@type": "Review",
    "author": { "@type": "Person", "name": "<real reviewer name>" },
    "datePublished": "2026-08-14",
    "reviewRating": { "@type": "Rating", "ratingValue": "5", "bestRating": "5" },
    "reviewBody": "<verbatim from the Google Business Profile>"
  }]
}
</script>

Beside the markup: one Google Business Profile in the primary category with West Perth service areas listed; a page per sector (AML/CTF for Perth real estate agencies, … for conveyancers) rather than one page trying to rank for all five; the enrol-by tool as the link-earning asset, because a date calculator is the thing an industry body will link to and a subscription page is not; and the FAQ block kept as prose on the page rather than as FAQPage markup, which Google now rarely shows for non-authority sites.

What would change for the real client