← Back to Rumpus Play Co.

How this page was built

Concept, palette, type, techniques and the three passes behind the Rumpus Play Co. demonstration.

Concept

The brief in three sentences

Rumpus Play Co. is a fictional indoor play centre in Balcatta, read by a parent doing party admin on a phone at 9pm while comparing three venues. The page's single job is to turn that visit into an enquiry with a date and a headcount already attached, so the pricing, the minimum-charge behaviour and the enquiry form all sit within the first two scrolls. The reference is a good bakery rather than a play centre's usual visual language — no primary colours, no clip-art, no exclamation marks — because the reader is an adult doing a chore, not a child choosing a venue.

Palette

Ground, ink, two marks

Every hex below and its ratios are pasted from contrast-w56.log, not recomputed by hand.

Paper #FFFBF4Page ground. Ink reads 15.86:1.
Panel #F6EEE0Card ground. Ink reads 14.19:1.
Band #123832Dark ground for header/footer/how-it-works. Paper-on-dark reads 12.43:1.
Band hover #0B2823Hover state for dark surfaces. 15.17:1.
Coral #C7452FOne of two marks. CTA fill; paper-on-dark reads 4.71:1.
Deep teal #14554AThe other mark. Map pins, icons, headings on paper: 8.38:1.
Map land #F5EFE3Service-area fill. Ink reads 14.28:1.
Map water #CCDDD9Coastline fill. Ink reads 11.61:1.

Why: a bakery palette argues that the business is calm and well run before a single word is read. Coral and deep teal are the only two saturated colours on the page — coral carries the call to action, teal carries the map pin and the small trust marks — so joy is rationed rather than sprayed. coralInk #A83218 is the paper-safe cut of coral used for price figures and headline emphasis; the coral ground itself only ever takes paper-on-dark text, and per the log this is a hard rule, not a style choice — several near-passing combinations (e.g. deep teal at 6.14:1 on map water) are declared FORBIDDEN and were left unused even though the number would pass, because the log licenses tokens by declared role, not by arithmetic.

Type

Bricolage Grotesque + Nunito Sans

Contained chaos, booked in two minutes.

Nunito Sans carries every paragraph at a 16px floor with generous line height, because the reader is scanning on a phone at the end of a long day.

Bricolage Grotesque (600/700) has enough personality for a headline without reading as childish — it is used only for headings, prices and the proof card's figures, never for body copy. Nunito Sans (400/600) is the workhorse: warm enough not to feel corporate, plain enough not to compete with the numbers it is printing.

Techniques

What is actually running

No canvas, no WebGL, no external JS library — the lead-gen brief asks for speed and calm, and this page has nothing to animate continuously. The hero illustration and the service-area map are both hand-authored inline SVG: the hero draws an abstract slide-and-net motif using a single stroked arc, a grid of thin lines and a loose cluster of circles, two of which carry the coral and teal marks. The map draws a rounded land shape, a coastline wedge, two dashed drive-time rings and ten labelled suburb pins, all positioned by hand rather than generated, because the geography only needs to read as plausible, not as a real base map.

The proof element, Party maths, is plain HTML: a native <input type="range"> for headcount (8–30) and a radio-based segmented control for the day. Every keystroke runs compute(), which applies charged = max(n, 10), total = charged × rate, effective = total / n, and a weekday-vs-weekend saving computed as the difference between both totals at the same headcount — never hand-typed. The live model is written to window.__playcentre on every change so it can be asserted without reading pixels.

Minimum charge

What "minimum 10" actually does

Below ten children, charged stays pinned at 10 while n keeps falling, so the total stops moving but the effective per-child figure keeps climbing — at 8 children on a weekday the card shows $33.75 a head, not $27, because ten seats are being paid for regardless. The card does not hide this: under ten it swaps its usual message for "you are paying for empty seats," which is the plain description of what the arithmetic is doing.

The give-away

Why the card argues for the cheaper day against the venue's own interest

Weekends are Rumpus Play Co.'s highest-demand slot — the venue would rather fill every Saturday than push families to a quieter Tuesday. The card does the opposite of what a seller would naturally do: whenever weekend is selected at ten or more children, it prints the exact dollar amount a weekday would have saved and tells the visitor to book midweek instead. That sentence costs the business a booking every time a visitor listens to it. It is included anyway because a number that visibly costs the seller money is what makes the rest of the page's prices believable — a parent who reads "book the cheaper day instead" stops assuming every other figure on the page is padded in the venue's favour.

Why this converts

For the prospect deciding whether to hire Sapience

The call-to-action sits in the header, the hero and a mobile sticky bar, so a parent never scrolls looking for how to book. The enquiry form asks only for what is needed to hold a date — name, phone, date, child's age, headcount and an optional note — because every extra field is a reason to close the tab. The Party maths calculator answers the first question every parent has, the real cost, before they have typed a word, which is the single strongest trust signal a services page can carry. The trust strip states a practice rather than a certification, so nothing on the page claims a standard nobody has verified. Every price on the page, in the grid and in the calculator, is the same number, which a comparison-shopping parent checks whether or not they say so out loud.

Local SEO for a real client

What we would ship in production (not here)

This demonstration deliberately carries no LocalBusiness, Review or AggregateRating structured data, because the reviews and the business are fictional. For a real client, the schema below is what we would add.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "ChildCare",
  "name": "Rumpus Play Co.",
  "image": "https://example.com/rumpus-play-co.jpg",
  "telephone": "+61-8-XXXX-XXXX",
  "priceRange": "$$",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Balcatta",
    "addressRegion": "WA",
    "postalCode": "6021",
    "addressCountry": "AU"
  },
  "openingHoursSpecification": [
    { "@type": "OpeningHoursSpecification", "dayOfWeek": ["Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"], "opens": "09:00", "closes": "14:00" }
  ],
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.9",
    "reviewCount": "128"
  }
}
</script>
For a real client

What would change

The seven service-grid photos would be real interior shots, not SVG line-art, and the reviews would pull from a live Google feed rather than demo copy. Bookings would connect to a real calendar rather than a local confirmation panel — Roller is the natural fit for a venue like this (waivers, party packages and casual-play check-in in one system), with Bookeo as the lighter-weight alternative if the client only needs appointment-style party slot booking without Roller's membership and POS layer. Either integration would replace the local confirmation state with a real availability check and a deposit charge at the point of booking.

Process

Three passes

Pass 1 — Craft

Tightened the hero's vertical rhythm so the h1, subline, CTA row and trust line clear the mobile sticky bar at 375px without scrolling. Rebuilt the services grid price typography (Bricolage for the number, small Nunito Sans for the unit) so all seven cards read at a glance rather than as a wall of text. Evened the card radii (16px) and hairline colours across services, proof card, reviews and form so nothing in the page uses an unlicensed border colour. Re-read all seven service descriptions and the FAQ answers for filler; cut two sentences that repeated the price already shown above them.

Pass 2 — Depth

Drove the calculator across all 46 reachable cells (8–30 children × weekday/weekend) against check-w56.mjs and confirmed every total and effective figure matches. Added the two dashed drive-time rings to the service-area map as a second-read detail — easy to miss on first look, and they explain why some suburbs are labelled closer to the centre than others. Refined the day-toggle's checked-state transition and the range thumb's shadow so the one interactive control on the page feels considered rather than default. Added the confirmation panel's autofocus so screen-reader users land on the result instead of a silent DOM swap.

Pass 3 — Hardening

Verified 375/768/1440 with no horizontal overflow; confirmed [hidden] plus display:none!important on the confirmation panel and that no SVG element in the page ever needs the hidden IDL property, since none is toggled. Checked the phone field's pattern compiles under the v flag with escaped parentheses and hyphen, then drove the form with junk text ("ring me maybe") to confirm it is rejected. Confirmed prefers-reduced-motion: reduce removes the load-in animation via both the CSS media query and a matchMedia check, scanned both files for curly quotes inside attributes, and removed one extra divider rule from the proof card that was fighting the dashed message border above it.

Post-QA fix — wave 56 sweep

Two defects raised in the wave-56 sweep. First, the live JSON-LD's isPartOf node carried a nested Organization publisher, which is a business-shaped @type and not permitted in a live block per the honesty rules — swapped it for a plain WebSite reference to the collection, matching the other four sites in this wave; the ChildCare/AggregateRating sample above was already the correct home for business-shaped schema and needed no change. Second, at 1200px wide the Party maths result sat below the first 750px, so the thumbnail carried no answer — folded the services grid and the proof card into the hero's grid as named areas (copy, svc, proof) so the proof card occupies the hero's second column at ≥1024px, with its total, per-child figure and honest line inside the first 750px at 1200 wide, while the stacking order below 1024px stays copy → services → proof, unchanged from before the fix.

Disagreement

Where this build departs from the wave documents

LEARNINGS.md (W51) recommends moving the proof element beside the hero headline at desktop widths, with the services grid following. This site's own task brief states the layout order "exactly": masthead → hero → services grid → proof element → why-us → reviews → map → FAQ → enquiry → footer, for both breakpoints. Because that instruction was explicit and specific to this build, the literal order was kept rather than the general wave pattern — the hero instead carries its own SVG illustration so the thumbnail still shows a drawn subject without needing the proof element inside the first viewport. Flagging this rather than quietly picking one.