Generative Assets · Industry demonstration
A lead-generation landing page for a fictional Hamilton Hill family day care educator: one educator, four places, one house. Its whole job is a booked orientation visit, and its whole argument is that it publishes an hourly rate in an industry where every listing says “contact educator for fees”.
The concept
Kindling is a fictional family day care educator working out of her own house in Hamilton Hill, taking families from Spearwood, Coolbellup, Beaconsfield, White Gum Valley, South Fremantle, Bibra Lake and Yangebup. She is not a centre. Four children, one adult, one back garden.
The parent arriving on this page has usually just come off a childcare listing site where every educator’s fee line reads contact educator for fees. They cannot compare anybody, and they are trying to work out whether they can afford to go back to work. The page answers with a published hourly rate, a week they can build in ten seconds, and — this is the part that matters — their own gap, computed from a percentage they read off their own myGov and slide in themselves.
The single conversion is a booked orientation visit, not a form fill. Family day care is the one kind of care a parent can genuinely inspect before committing, because it is somebody’s house and they are allowed in it. So the form asks the five things a visit needs and nothing else, and the page says three separate times that the visit costs nothing.
The proof element
Three controls and one result card. Days a week (1–5), how long a day (short 8 hours, standard 10, long 11), and a subsidy percentage slider the parent supplies themselves, 0–95 in fives. The card prints the full weekly fee and the gap at the percentage they entered, side by side and at exactly the same type size.
The arithmetic is one line and it is deliberately something a parent could check on the back of an envelope: $13.20 an hour × the hours in the day × the days in the week, and then × (100 − your percentage) for the gap. Money is held as integer cents throughout and divided once at display, so nothing in the model can land on a floating-point cent.
| Figure | Where it comes from | Value |
|---|---|---|
| The rate | Kindling’s own hourly fee, published | $13.20 |
| Short day | 8 hours × the rate — the grid floor | $105.60 |
| Standard day | 10 hours × the rate | $132.00 |
| Long day | 11 hours × the rate | $145.20 |
| Rest-state week | 3 standard days — the thumbnail | $396.00 |
| Rest-state gap | $396.00 × (100 − 70) % | $118.80 |
| Cheapest week | one short day — equals the day floor | $105.60 |
| Dearest week | five long days | $726.00 |
| Short vs standard | constant, per day, at every day count | $26.40 |
| Long vs standard | one extra hour at the same rate | $13.20 |
It would convert better, in the short term, to show the gap big and the full fee small. We did the opposite on purpose, and the two figures share one CSS rule so they cannot drift apart.
The gap is the number a parent budgets against, but it is conditional on a percentage nobody on this page controls. Percentages change when income changes, when hours change, when a second child starts. If the page teaches a parent that Kindling costs $118.80 a week, the page has told them something that can stop being true without anybody doing anything. The full fee is Kindling’s actual price and it never moves. Showing both at the same weight says, in typography rather than in a footnote, this is what we charge, and this is what it happens to cost you today.
There is a second reason and it is commercial. A parent comparing four educators is comparing gaps, which are all computed from the same percentage — so the gap tells them nothing about who is cheaper. The full fee does.
The sum on this page applies the parent’s percentage to Kindling’s fee, and nothing else. Services Australia also caps the hourly rate it will subsidise, which means a real gap can be a little higher than the figure the card prints. We do not know that cap and we will not guess it, so the page does not publish it.
That caveat lives inside the result card, on the same white plate as the two figures, directly under them — it is the last thing a reader passes before the “book a visit” link. It is not in the FAQ, and that placement is the whole point. A limitation that materially changes the number is not a frequently asked question; it is part of the answer. Anything that would make the printed figure wrong belongs where the figure is, or the page is quietly overstating itself and hoping nobody opens the accordion. The harness asserts both halves: that the disclosure is inside the answer card and within 90 px of the gap figure, and that the phrase does not appear anywhere in the FAQ.
A short day is $26.40 cheaper than a standard one, on every single day you book — and the saving does not shrink as days are added, because it is the same $26.40 off each one. The page says so in the services grid and the estimate repeats it in the “in the hourly rate” card whenever the standard day is selected. It was swept over all five day counts before it was written down, not asserted from one cell.
The drawn subject
Five day cards, Monday to Friday, the booked ones filled and banded; underneath them, one booked day drawn as a bar across a fixed axis running 7:00am to 6:00pm — the hours the house is actually open. Because the axis is fixed, the long day fills it exactly, the standard day stops an hour short, and the short day is visibly a good deal shorter at both ends. That is the comparison the page exists to let a parent make, and it is made by the drawing rather than claimed in a caption.
Underneath the selected day sit the two lengths the parent did not pick, drawn to the same axis, each carrying its own day price inside the bar. That was added in Pass 2 and it is the single best change of the build: the $26.40 argument stops being a sentence and becomes a picture. The week total is printed inside the plate too, bottom right, so the drawing carries the commercial answer wherever it is screenshotted.
Everything is procedural SVG built as one synchronous string and handed to the DOM in a single write; the entrance choreography is then driven from the animation loop rather than by inserting nodes or toggling classes afterwards. Every vertical in the drawing — card height, bar height, ghost-row height, the whole viewBox — is a function of the measured CSS width, because the type size is too: laying a fixed geometry under a scaled font is exactly how a label ends up five pixels tall on a phone.
Motion is wall clock only. The reveal reads performance.now() deltas against a cold-load start stamp, never a per-frame accumulator, so it finishes in 1.15 real seconds whether the renderer is managing 60 frames a second or five. The loop pauses on document.hidden and resumes on visibilitychange. After the reveal the only thing still moving is the pick-up pip on the end of the hour bar, breathing between 0.72 and 1.0 opacity — a floor, not a fade, so the drawing is alive at any capture instant and never mid-disappearance. Under prefers-reduced-motion: reduce the loop never starts and the scene is drawn settled on the first frame.
Palette
Childcare sites default to one of two palettes: primary-colour nursery pastel, or medical blue. Neither is what a parent is buying here. They are buying somebody’s actual house, so the page is set on warm plaster with a eucalypt green and an ochre for figures. Every ratio below is measured, and the hex and the ratio are quoted from the same row of the wave’s contrast sweep.
#F7F3EE page ground#EAE1D6 cards, map land#241D1B 15.01:1 paper · 12.82:1 panel#5A4E4A 7.25:1 paper · 6.19:1 panel#1F4A43 8.97:1 paper · 7.66:1 panel#26564F paper reversed 7.52:1#1E463F paper reversed 9.49:1#1F3A34 paper reversed 11.1:1#7E5209 6.14:1 paper · 5.24:1 panel#8F5F0A 4.99:1 paper · 4.22:1 hour bar#D7E3DA ink 12.55:1 · teal mark 6.29:1#EFE8DE ink 13.63:1#EFE0C0 ink 12.71:1#A9B8AD hairline, 1.87:1 paper#CFC3B2 1.57:1 paper · 1.34:1 panel#6E645E 5.21:1 paper · 4.45:1 panel#C7D9D6 carries no text at all#4E7A72 3.73:1 land · 3.29:1 waterA ratio table that only measures inks against page grounds is the failure this collection keeps repeating, so the sweep this page was built from declares, per token, exactly which grounds it may land on. The rules that actually constrained the design:
#4E7A72.#1F4A43 is the text token and #26564F is the mark and CTA ground. Pass 1 caught the step numbers in the how-it-works block using the mark token for type and swapped them.#DADDD8 and measures 6.06:1 on the CTA teal and 7.52:1 on the hover teal. That is the declared floor and it is not taken lower.#484541 for 7.21:1 on the booked fill — a token declared for that one ground only, so open cards use full ink at a lighter weight instead.#7E5209, the ochre already carrying the figures — 6.14:1 on paper, and it reads as attention rather than alarm, which suits a page about a house.Type
Fraunces 600/700 carries every heading and every figure. It is soft, a little hand-cut, and it has warmth without being cute — which is the exact register a parent needs from an educator who is not a chain. Karla 400/500/600/700 carries the body at 17 px on a phone, because it is plain, wide-apertured and quietly friendly next to the display face.
The typographic move is the pair of figures: the full weekly fee and the parent’s gap set in Fraunces 700 at exactly the same clamp, side by side across a hairline, because the whole argument of the page is that a parent gets to see both. Everything else in the type system defers to that one moment — the services-grid prices are 27 px, the slider readout is 26, and nothing else on the page competes.
Conversion
The call button and the visit form are both above the fold at 375 px and a sticky bar carries the same two actions down the whole page, because a parent researching childcare is doing it one-handed at 9pm and will not scroll back up to find you. The form asks five things — name, phone, suburb, child’s age and days a week — and stops, because the conversion is an hour in the house rather than a quote, and every extra field on a childcare form is another reason to close the tab. The proof element is the reason a stranger stays: it publishes an hourly rate in an industry where every listing says “contact educator for fees”, then does the parent’s own arithmetic in front of them using a percentage they supply, so they leave with a weekly number instead of a callback promise. The trust strip works the same way — four places, one educator, seven years, and a placeholder registration line sitting where a real one would — because a page about somebody’s house has to look like it belongs to a person with a licence, not a lead-gen funnel. The line that closes it is the one that costs the seller money: the page tells you a short day is $26.40 cheaper and that you should take it if you finish at three, and a business that argues against its own dearer option is one you believe about everything else.
Honesty
Family day care sits inside a real Australian scheme whose numbers move, and this collection’s standing rule is blunt about the consequence: a figure about a real standard, scheme, regulator or price guide that cannot be verified does not get published, and does not get softened either. You decline, and you say that you declined. This page has the longest decline list in its wave, and the proof element exists in the shape it does precisely because of it — it consumes the reader’s own figure instead of the scheme’s.
FDC0000 and the ABN 00 000 000 423, both visibly patterned, and both labelled placeholder in the footer.Where the parent’s real question is a scheme question, the page answers with a place to look rather than a number: the myGov FAQ describes where the percentage is printed on their own account and says, in as many words, that a childcare business quoting Services Australia’s figures from memory is how families end up budgeting wrong.
(08) 9xxx occurrence is the reserved exchange.@type values against that allowlist recursively.Local SEO
None of the following is on the live page, and it must not be, because the business is fictional and fictional structured data in a real index is dishonest markup. For a real Kindling with a real registration, a real address and real reviews, this is what would go in — ChildCare is the correct schema.org subtype of LocalBusiness for family day care, and it is more precise than the generic type most agencies drop in.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "ChildCare",
"@id": "https://kindlingfdc.com.au/#business",
"name": "Kindling Family Day Care",
"description": "Family day care educator, four places, Hamilton Hill WA.",
"url": "https://kindlingfdc.com.au/",
"telephone": "+61 8 XXXX XXXX",
"image": "https://kindlingfdc.com.au/img/garden.jpg",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "REAL STREET ADDRESS",
"addressLocality": "Hamilton Hill",
"addressRegion": "WA",
"postalCode": "6163",
"addressCountry": "AU"
},
"geo": { "@type": "GeoCoordinates", "latitude": -32.08, "longitude": 115.77 },
"openingHoursSpecification": [{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
"opens": "07:00", "closes": "18:00"
}],
"areaServed": [
{ "@type": "City", "name": "Hamilton Hill" },
{ "@type": "City", "name": "Spearwood" },
{ "@type": "City", "name": "Coolbellup" },
{ "@type": "City", "name": "Beaconsfield" }
],
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.9", "reviewCount": "23"
},
"review": [{
"@type": "Review",
"author": { "@type": "Person", "name": "REAL REVIEWER NAME" },
"reviewRating": { "@type": "Rating", "ratingValue": "5" },
"reviewBody": "REAL REVIEW TEXT, WITH PERMISSION"
}]
}
</script>
Alongside it, for a real client: a verified Google Business Profile in the Child care agency category with the opening hours matching the markup exactly, the four closure weeks entered as special hours each January, the suburb pages that childcare searches actually resolve to (“family day care Spearwood” is a different query from “childcare Spearwood” and converts far better), and the review feed wired to the profile so the aggregateRating above is generated rather than typed.
The build
.focus() on a chip scrolls it into view — so the “thumbnail” being reviewed was the middle of the estimate panel, not the top of the page. Fixed in the harness: the thumbnail is captured before anything drives, clicks or focuses.innerText, never HTML source. Then the same probe failed this guide, because a page that quotes measured contrast ratios is full of digit-colon-digit. The check now looks for a ratio claim — a count of adults against a count of children, or a number sitting beside the word itself — rather than for punctuation.querySelectorAll(sel).length > 0. A compound selector that matches nothing is syntactically perfect, semantically dead, and invisible to every state probe.v flag, not eyeballed. [0-9 \(\)\+\-]{8,20} escapes every literal special inside the class; the check compiles it the way Chrome does, then proves it accepts a real number and rejects junk, and the form is driven three ways — empty, junk in the phone field, and good data. Empty flags all five fields and does not confirm; junk flags the phone field only and does not confirm; good data clears everything, hides the form and shows a personalised confirmation.scrollWidth, skipping SVG descendants, off-canvas skip links and anything inside a deliberately scrolling ancestor. Zero offenders on both pages.For the real client
aggregateRating markup above become legal to ship.