Generative Assets · Industry demonstration guide

How Marri Lane Early Learning was made

A conversion-focused landing page for a fictional Bassendean long day care centre — every pixel procedural, every price argued from the Perth market, and a Fee & CCS estimator honest enough to survive an accountant parent.

The concept

Marri Lane Early Learning is a fictional single-site long day care centre in Bassendean, pitched at working parents of 0–5s comparing centres and weighing days-per-week against the Child Care Subsidy. The page has one job: book a centre tour. The art direction is a premium school prospectus — morning-garden milk light, mud kitchen and sun-hats, zero primary-colour kindergarten clip-art — because parents choosing childcare are buying calm competence, not balloons.

Everything on the page routes toward the tour form: the hero CTA, the estimator's "book a tour with this week" handoff, the sticky mobile call/tour bar, and the FAQ answers that end at "we'll walk you through your actual rate at a tour".

Palette — the yard at 9am

Warm milk#FAF4E8 ground — morning light on a cream wall
Garden green#33523B structure & primary ink — shade trees, veggie patch
Marigold#E3A83A LINE/MARK only — fee arcs, day cells, CTAs; never body text on milk
Plum crayon#7C4E68 secondary — links, focus rings, active states

Per the ink/line token split, marigold never sets type on milk (it measures ~1.9:1). Body copy runs in a derived ink pair — #2C3F31 for primary text and #57614F for secondary, both clearing 4.5:1 on the milk ground. The one marigold "typographic" moment — the word unhurried in the h1 — is a highlighter bar under green text, so marigold stays a mark, not a letterform.

Type

Baloo 2 (display) carries rounded warmth that stays typeset rather than babyish — it does the wordmark, headings, prices and the gap figure. Mulish (body/UI) reads clean and parental at 16.5px. Scale is deliberate: 50/36/28 display steps, 16.5 body, 13.5 hedges and captions, with weight and letter-spacing doing the eyebrow work.

The signature — Fee & CCS Estimator

Room toggle (nursery $148 / toddler $142 / kindy $138 a day — the same figures as the rooms grid, one source of truth), a 1–5 days chip row, and a $60k–$220k+ family income slider. Every input redraws a procedural SVG week strip — booked days blossom with a marri leaf (a wrapper <g> holds the SVG translate; the CSS bloom scale lives on an inner group with transform-box:fill-box, because a CSS transform overrides an SVG transform attribute on the same node) — and recomputes a donut of subsidy-vs-gap plus the headline "full fee $426/wk → estimated gap $90/wk" readout, with a count-up tween on the gap figure (instant under reduced motion). At rest it sits mid-demonstration: toddler room, 3 days, $120k. A state probe window.__childcare exposes inputs, computed and displayed outputs, and form status on every interaction.

The simplified CCS taper — QA source of truth

The estimator implements a deliberately simplified model of the 2026 Child Care Subsidy, shaped from the real scheme:

fees = { nursery: $148, toddler: $142, kindy: $138 } per day
basePct(i) = clamp( 90 − max(0, i − 85,000) / 5,000, 0, 90 ) // −1pp per $5k over $85k
effective = basePct × 0.95 // standard 5% withholding, shown honestly
gap/day = fee × (1 − effective/100)
gap/week = gap/day × days   (rounded to the dollar at display, weekly from the unrounded daily)

What is deliberately not modelled, and hedged on-page instead: the hourly rate cap (≈$14.63/hr against an 11-hour session ⇒ a $160.93/day ceiling that none of our fees reach, so it never binds), the activity test and the 2026 3 Day Guarantee (mentioned honestly in the FAQ), the higher CCS rate for second-and-younger children under 5, and the taper's continuation beyond the slider's $220k+ top (called out in the hedge line). The on-page hedge — "estimate only — Services Australia sets your actual Child Care Subsidy" — is doing real work, not decoration.

An honest-numbers correction to the spec sketch. The wave spec's illustrative line guessed that a $120k family, 3 days toddler, lands "subsidised to roughly a third of the full fee". Running the 2026-shaped taper honestly, $120k computes an 83% rate (90 − 35,000/5,000), effective 78.85% after withholding — a gap of $90/wk against the $426/wk full fee, about a fifth, not a third. Per the honest-numbers rule the displayed figure is the measured model output, and this derivation is the record of why it differs from the sketch.

Oracle scenarios verified in the harness

ScenarioBase % → effectiveFull feeDisplayed gap
Rest state — toddler, 3 days, $120k83% → 78.85%$426 / week$30 / day · $90 / week
Driven A — nursery, 5 days, $60k90% → 85.5%$740 / week$21 / day · $107 / week
Driven B — kindy, 2 days, $220k+63% → 59.85%$276 / week$55 / day · $111 / week

The verification harness reimplements this model independently (separate code, same spec) and asserts the page's displayed strings — full fee, gap/week, gap/day and donut percentage — against the oracle at rest and across both driven scenarios, never against the page's own function. The estimator's cheapest full fee (kindy $138/day) equals the rooms grid's floor, so the page never argues with itself.

Conversion decisions

Local SEO we'd implement for the real business

This demo page ships only a WebPage schema naming it a demonstration — fictional LocalBusiness or Review markup in a real search index would be dishonest. For a real centre we would ship:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "ChildCare",
  "name": "Marri Lane Early Learning",
  "description": "Long day care in Bassendean — nursery, toddler and kindy rooms.",
  "telephone": "+61-8-XXXX-XXXX",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "[real street address]",
    "addressLocality": "Bassendean",
    "addressRegion": "WA",
    "postalCode": "6054",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": "[lat]", "longitude": "[lng]" },
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
    "opens": "06:30", "closes": "18:15"
  }],
  "priceRange": "$138–$148 per day before CCS",
  "aggregateRating": { "@type": "AggregateRating",
    "ratingValue": "[from live review feed]", "reviewCount": "[live]" },
  "review": [{ "@type": "Review",
    "author": { "@type": "Person", "name": "[verified parent]" },
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "reviewBody": "[real review, with permission]" }]
}
</script>

Plus a Google Business Profile with room photos, suburb landing copy for Ashfield/Eden Hill/Bayswater, and FAQ schema mirrored from the on-page questions.

What would change for the real client

Their photography would replace the SVG scenes (though the illustration system stays for the estimator). The waitlist and tour bookings would wire into their CCMS — Xplor Home/Playground, OWNA or QikKids — with enrolment status flowing back to the page; family documentation via Storypark or KindyHub; the estimator would read the centre's live fee schedule and current CCS rates (the real entitlement runs through PRODA / Services Australia); reviews would come from a verified feed; and educator rostering against ratios via Employment Hero. That's the difference between a demo and a system.

Techniques

Fully self-contained single file: inline CSS/JS, Google Fonts only, no raster images. The hero garden, service-area map and week strip are hand-built SVG; the donut is two dashed circles with eased stroke-dasharray transitions; the entrance is a staggered rise gated on document.fonts.ready with a 700ms fallback and a no-JS guard class so content never strands at opacity 0. Reduced motion renders everything settled and complete — leaves pre-bloomed, no tweens, no smooth scroll. Focus states run on plum :focus-visible outlines throughout.

Iteration log

Pass 1 — Craft

  • Driven, on a fresh load: empty submit (all 4 required fields flagged with visible errors + aria-invalid), filled submit (confirmation rendered in the required lexicon), estimator driven to both oracle scenarios, FAQ, chips, slider, sticky bar — 50-assert suite.
  • Found: invalid phone pattern. pattern="[0-9 ()+]{8,}" throws under Chrome's v-flag regex — unescaped parens in a character class — killing checkValidity() with a console error. Escaped the class.
  • Found via the 375 screenshot: the trust signal sat behind the sticky bar (bottom 702px vs bar top 651px) while the naive ≤720 probe passed. Reordered trust above the CTAs at ≤560px and hardened the probe to measure against the sticky bar's top edge.
  • Found: marigold h1 word ~1.9:1 on milk. Restyled as green text over a marigold highlighter bar — the marigold moment survives as a mark.
  • Fixed a stray character invalidating the tour section's background gradient. Re-ran: 50/50, screenshots reviewed at desktop and 375.

Pass 2 — Depth

  • The screenshot caught a silent dead signature detail: the week strip's marri leaves rendered collapsed at the SVG origin — the CSS bloom scale() was overriding the positioning transform attribute on the same group. Every state assert (leaf count, bloom class) stayed green; only the rendered image showed it. Fixed with a wrapper group + transform-box:fill-box.
  • Zoom review of the hero read the verandah as a gallows-like "F" and the sun-hat as a flat mound — redrew the corner as a timber post-and-beam with the hat hanging from a peg and the paint-smock on a beam hook.
  • Enriched the signature: eased donut arc morphing, a 420ms count-up tween on the gap figure (instant under reduced motion), chip press micro-interaction, marigold-stroked blossoms so they read on the cream day cells.
  • Second-read details: quenda tracks in the hero sand, and a honey-blossom burst on Friday when a full 5-day week is booked. Re-ran the suite: 50/50, both oracle scenarios re-asserted.

Pass 3 — Hardening

  • Chanel rule: removed the decorative dotted inner stroke on the river — the ribbon reads cleaner alone.
  • Re-verified 375 (wordmark, tel link and nav fully inside the viewport box; h1 + CTA + trust above the sticky bar; scrollWidth 375; tap targets 48px), reduced-motion (hero settled at opacity 1, leaves pre-bloomed, estimate rendered), and keyboard driving of chips (focus + Enter).
  • Honesty sweeps: positive phone sweep — every (08) 9xxx number on the page uses the 9000 exchange; a single JSON-LD block typed WebPage only; the fictional-business colophon present; exactly one h1 per page.
  • Final copy read and cross-surface number grep: $148/$142/$138 agree across rooms grid, estimator chips, FAQ and probe; the estimator floor equals the grid floor. Final suite: 50/50 with fresh screenshots reviewed.