How this demo was made

Studio Eleven Dance — a Joondalup dance school, priced before the curtain goes up

Studio Eleven Dance is a fictional dance school in Joondalup — ballet, jazz, hip hop, contemporary, tap and acro for tiny tots to adults, 10-week terms, one December concert. The page has one job: a term enrolment request with the dancer's age group, classes and extras already priced. Its audience is the Currambine parent enrolling a five-year-old for the first time, the Kinross teen adding contemporary to ballet, the Edgewater adult coming back to tap.

Palette — a darkened auditorium, measured with WCAG arithmetic

House lights down: a violet-black ground, chalk text (the barre, the rosin), a magenta stage gel for the buttons, a warm follow-spot gold for marks. Every ratio below was measured from the shipped tokens with WCAG arithmetic during Pass 1 — not transcribed from the spec. The spec's computed figures held for every pinned pair; the one token minted on the page was a lifted chalk-dim for small meta copy on cards.

The pre-minted two-token pair did its job: the magenta gel stays the hue of every button, while anything written in magenta uses #F07AAB. On a dark site the remedy runs the other way from the light-ground trades — the ink is minted lighter, not deeper.

Type

Syne 700/800 for display — wide, kinetic, a stage-poster face that makes "$928" and "DANCE CLASSES IN JOONDALUP" feel like lettering on a programme. Work Sans for everything a parent has to read at 9pm on a phone: the planner chips, the ledger, the form. Body sits at 17px (17.5 from 760px), no line under 16px anywhere on mobile. The typographic bravery is the display band under the hero — "3 CLASSES A WEEK · $928 A TERM" set near-viewport-wide in Syne 800 at −0.035em tracking — and that figure is the rest-state total, measured from the running planner, not typed by hand.

The signature — the Term Planner

A drawn SVG stage: proscenium frame, back wall with a barre, perspective boards, nine footlights, a follow-spot cone sweeping the boards. Every selected STYLE chip adds one drawn silhouette in a pose that reads as that style — ballet arabesque, jazz kick-line, hip hop freeze, contemporary floor reach, tap heel-dig, acro bridge. The AGE chip scales every figure's height (tots 0.62 → adults 1.0) and rewrites the name drawn on the spot. The extras draw their marks: the concert pack hangs a curtain swag and puts a drawn ticket on every wrist, the uniform pack hangs the studio's XI crest on the back wall, registration leans a clipboard against the stage-left pillar. The price lives inside the artwork as a ticket stub hanging off the proscenium (on-scene from 641px, docked beneath the stage at 640px and below).

$928 a term3 classes a week · 135 min of dance

Implementation. Six poses are stored as polyline point lists in a local frame (feet at the origin, nominal height 100) and rendered as a round-capped stroke path plus a head circle; a second, wider gold stroke behind each figure is the "lit" layer. The scene rebuilds on every state change — figures are placed with spacing 140 for up to three, narrowing to 560/(n−1) for six (the cap is the six styles themselves, so no drawn cap was needed). Layout position sits on an outer <g transform> and the CSS entrance animation on an inner group, so the attribute and the stylesheet never fight. The follow-spot is a rAF loop with a clamped delta (dt = min(max(now − last, 0)/1000, .05)): in idle it wanders sinusoidally (period 11 s) around a base that drifts slowly back to centre, amplitude tied to the spread of the figures; a state change bumps a token in the handler, sets the spot to sweep to the changed figure with an exponential ease, and on arrival resumes idle — so a rapid-fire burst of four clicks produces exactly one sweep. Each frame sets a per-figure "lit" amount from the spot's distance, which fades the gold layer in and lifts the chalk stroke to full opacity. The redraw is dual-speed: first draw gets the staged entrance (wall, barre, floor, spot, footlights, frame at 110 ms intervals; figures at 0.55 s + 0.14 s stagger), every later change redraws in 320 ms and the probe's settled flag flips at 560 ms. Reduced motion parks the spot centre-stage, skips the loop and settles immediately.

The pricing model — pinned, then measured

Per 10-week term, GST inclusive, whole dollars by construction (every rate is a multiple of ten, so 10% of a classes line is always an integer).

ControlRuleValues
Age chipper-class term rate · class length · availabilitytiny tots 3–5 $150 / 30 min (ballet and jazz only) · juniors 6–12 $190 / 45 min · teens 13–17 $220 / 60 min · adults $200 / 60 min (no acro — "acro runs for 6–17s")
Style chipsmulti-select; each = one class a weekballet · jazz · hip hop · contemporary · tap · acro. Disabled chips show the on-chip reason; a selected style the age group can't take is locked off and remembered, and restored when an allowing age group returns — unless the user toggles it in between
Classes linen × rate; n ≥ 3 → 10% off the classes line onlyjuniors 3 × $190 = $570 − $57
Third-class noteexactly n = 2 and a third style available"add a third class and the whole classes line takes 10% off — that's $<3 × rate ÷ 10> back" → juniors $57 · teens $66 · adults $60; absent for tiny tots (only two styles) and once n ≥ 3. Short form on the badge at ≤640px: "a third class takes 10% off — $x back"
Concert pack+$85 × n (actual count), outside the discount$0 at n = 0
Uniform pack+$120 flatlive at every combination
Registration+$40 flat, on at restlive at every combination
Empty staten = 0badge "$ — · tick a style to price the term", line 2 absent, extras greyed "pick a style first"; grid floor = tiny tots, one class = $150
Sibling discountdeclaration only"second dancer 10% off their classes — add them on the enrolment form" — on the card and in the FAQ, never computed (one dancer per planner)

Worked examples — measured from the running page against an independent oracle

ScenarioArithmeticMeasured
Rest: juniors · ballet + jazz + hip hop · concert, uniform, registration on570 − 57 + 255 + 120 + 40$928 · "3 classes a week · 135 min of dance" · note absent
Tiny tots · ballet · registration on / off150 + 40 / 150$190 · "1 class a week · 30 min of dance" / $150
Tiny tots · ballet + jazz · registration on300 + 40$340 · note absent (no third style)
Teens · ballet + contemporary · nothing else → add tap440 → 660 − 66$440 + note "$66 back" → $594, note absent, discount line −$66
Adults · all five available styles1,000 − 100$900 · acro disabled with reason
Juniors · all six · all extras on1,140 − 114 + 510 + 120 + 40$1,696 · "6 classes a week · 270 min of dance"
Juniors · hip hop + acro → adults → juniors380 → 200 → 380acro locked off, then restored
Untick everything"$ — · tick a style to price the term", no line 2
Rapid-fire from empty: ballet, jazz, tap, untick jazz in one evaluate2 × 190 + 40$420 · one sweep counted
Cheapest per ageone class, nothing else$150 · $190 · $220 · $200 = the services-grid floors

The harness also drove the full extras matrix (4 ages × concert × uniform × registration at two styles, 32 cells) against the oracle, asserted note presence on all three surfaces (badge, ledger, a11y mirror) and note absence where the spec pins it, and read the probe window.__danceschool in-page via JSON.stringify. 310 asserts (304 on the site, 6 on this guide), zero console errors, zero spec corrections — every worked figure is pure anchor arithmetic and reproduced exactly.

Conversion decisions

Local SEO we'd implement for the real business

This demo page ships only WebPage / WebSite / BreadcrumbList JSON-LD naming itself a demonstration — fictional business data in a real index would be dishonest markup. For the real studio we would ship the block below. Schema.org has no DanceSchool type, so the honest top-level type is EducationalOrganization (with LocalBusiness as an additional type for the opening-hours and geo fields), plus real reviews as Review with AggregateRating drawn from the studio's actual Google profile.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "EducationalOrganization",
  "additionalType": "https://schema.org/LocalBusiness",
  "name": "Studio Eleven Dance",
  "description": "Dance school in Joondalup: ballet, jazz, hip hop, contemporary, tap and acro for tiny tots to adults.",
  "url": "https://www.studioelevendance.com.au/",
  "telephone": "+61 8 9000 0363",
  "image": "https://www.studioelevendance.com.au/images/studio-one.jpg",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "[real street address]",
    "addressLocality": "Joondalup",
    "addressRegion": "WA",
    "postalCode": "6027",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.745, "longitude": 115.766 },
  "areaServed": ["Joondalup", "Currambine", "Kinross", "Edgewater", "Wanneroo", "Iluka", "Ocean Reef", "Padbury", "Heathridge"],
  "openingHoursSpecification": [
    { "@type": "OpeningHoursSpecification", "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"], "opens": "13:00", "closes": "20:30" },
    { "@type": "OpeningHoursSpecification", "dayOfWeek": "Saturday", "opens": "08:30", "closes": "13:30" }
  ],
  "hasOfferCatalog": {
    "@type": "OfferCatalog",
    "name": "Term classes",
    "itemListElement": [
      { "@type": "Offer", "name": "Tiny tots (3–5), 10-week term", "price": "150", "priceCurrency": "AUD" },
      { "@type": "Offer", "name": "Juniors (6–12), 10-week term", "price": "190", "priceCurrency": "AUD" },
      { "@type": "Offer", "name": "Teens (13–17), 10-week term", "price": "220", "priceCurrency": "AUD" },
      { "@type": "Offer", "name": "Adults, 10-week term", "price": "200", "priceCurrency": "AUD" }
    ]
  },
  "aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.9", "reviewCount": "87" },
  "review": [
    {
      "@type": "Review",
      "author": { "@type": "Person", "name": "[real reviewer]" },
      "datePublished": "2026-03-02",
      "reviewRating": { "@type": "Rating", "ratingValue": "5" },
      "reviewBody": "[the studio's real Google review text]"
    }
  ]
}
</script>

Alongside it: a Google Business Profile with the real address and class photos, suburb pages only if the studio genuinely runs classes in a second suburb, and FAQ schema from the real FAQ once the answers are the studio's own.

What changes for the real client

Techniques

Iteration log

Studio Eleven Dance is a fictional business — a dance school industry demonstration designed & built by Sapience Analytics, part of the Generative Assets collection. Back to the site · Index.