Generative Assets · Wave 25 — Industry Demos XIV · site 281

How the Paperbark Funerals demo was made

A fictional Cannington funeral directors, built as a conversion demonstration for the trade whose worst reputation is opaque bundled pricing — so the whole page argues one thing: the itemised ledger, shown before anyone asks.

Concept

Paperbark Funerals serves families arranging a funeral this week — often at 2am, often for the first time — people comparing direct-cremation prices under grief and time pressure, and over-60s arranging their own pre-paid plan. The page has one job: get the 24-hour line called, or the itemised ledger requested by email. The name is the WA tree that sheds its bark in soft layers — loss, held gently.

The art direction is a Cannington arrangement room at 9am: morning light, a linen table, one folder open with every cost written down, tea made. Calm, plain, zero salesmanship-theatre — the transparency is the sell.

Palette

Paperbark cream#F4EFE5Ground — shed bark in morning light.
Ironbark#2E3733Structure and primary ink — wet bark, deep green-brown.
River gum#4E7A63Line/mark only — ledger rules, sum lines, CTA fills. At 4.3:1 on cream it never sets body text.
Candle amber#B98A44Marks, chip borders, focus rings — the arrangement-room candle.
Amber-ink#7C5A1EDerived text-safe amber (5.5:1 on cream) for small labels — the W2/W5 ink/line split.
Eucalypt grey#5C6660Derived muted body ink, 5.2:1 on cream.

The wave's only green-led light site — argued from the tree, not from a template: cream is bark, not linen-brand cream; the green draws lines, it doesn't shout.

Type

The signature — the Arrangement Ledger

Package chips (direct cremation / chapel farewell / graveside burial), coffin chips ($850 / $1,450 / $2,400) and add-on toggles (viewing +$350 / livestream +$300 / flowers +$260) drive a procedural SVG ledger page that writes itself: each included line inks in down the paper — label, a dotted river-gum leader, the figure in mono — then a hand-drawn double sum rule and the honest total. The whole ledger is built in JS (SVG DOM, no libraries): geometry lives in attributes, animation runs through a single rAF timeline writing style.opacity and attribute positions — never CSS-animating a property an element also sets as a presentation attribute (LEARNINGS W16/W17). Leaders are clipped between the measured end of each label and the measured left edge of each figure (getComputedTextLength), drawn with butt caps so zero length shows nothing (W15).

The first write is paced slow (930ms stagger) so the 7-second thumbnail catches the ledger about two-thirds written — inked through celebrant, the add-ons still arriving, sum rule undrawn — then it completes and holds. Every subsequent chip/toggle rebuild redraws snappy (~0.7s, 32ms stagger) behind a firstDraw flag (W21), and window.__funeral exposes the state with a settled flag so QA gates on state, never seconds. Reduced motion renders the ledger complete immediately. A visually-hidden list mirrors every line for screen readers, and a noscript block carries the rest arrangement in plain text.

Honesty mechanics: for direct cremation, livestream and flowers disable with their reasons printed on-card (“there’s no service to stream…”) while viewing stays live — a control either changes the price honestly or visibly explains why it can’t (W18). For graveside burial the ledger prints a line with no number: cemetery fees, set by the Metropolitan Cemeteries Board, passed through at cost — the at-cost line is the honesty signature, and inventing a figure there would be the exact dishonesty the page argues against. The chosen arrangement pre-fills the enquiry form’s notes field (W12), backing off the moment the visitor types their own note.

Second-read details: the ledger’s stamp reads “prepared live at [the visitor’s actual clock time] — before anyone asked” (true, since it is), and faint paperbark layers peel down the paper’s left margin.

The pricing model, measured

The model’s shape: the package defines the line list (not a multiplier) — direct cremation carries transfer, coffin, crematorium fee and certificates; chapel farewell adds the chapel hour and celebrant; graveside swaps the crematorium fee for graveside coordination and the celebrant, and appends the at-cost cemetery line. All-in anchors, no after-hours loading — flatness by the hour is a deliberate, stated pricing statement (“the 3am price is the 3pm price”), not an omission. Every displayed figure below was verified against an independently reimplemented oracle in the QA harness — all six spec examples measured exact, zero corrections.

ScenarioArithmeticSpecMeasured
Direct cremation, simple coffin1,150 + 850 + 640 + 160$2,800$2,800 ✓ (equals the services-grid floor)
Chapel farewell, simple coffin+ 950 + 500$4,250$4,250
Graveside burial, simple coffin1,150 + 850 + 160 + 1,250 + 500$3,910 + at cost$3,910 + cemetery at cost ✓ (line list changes — no crematorium fee)
Rest state: chapel, select, viewing + flowers1,150 + 1,450 + 640 + 160 + 950 + 500 + 350 + 260$5,460$5,460
…chipped to handcrafted+ 950 over select$6,410$6,410
…dropped to direct cremation2,800 + 350 viewing$3,150$3,150 ✓ with flowers/livestream disabled, reasons showing

The cemetery line deliberately has no number anywhere on the page — MCB fees vary by cemetery and by lawn/monumental/wall section, so the honest render is the at-cost declaration plus the offer to show the current schedule.

Conversion decisions

Local SEO we’d implement for the real business

This demo page emits only WebPage schema naming it a demonstration — fictional structured data in a real index is dishonest markup. For a real funeral home we’d ship the precise schema.org subtype with real NAP, hours and review feed:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FuneralHome",
  "name": "Paperbark Funerals",
  "telephone": "+61-8-9000-0281",
  "url": "https://paperbarkfunerals.com.au",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Cannington",
    "addressRegion": "WA",
    "postalCode": "6107",
    "addressCountry": "AU"
  },
  "openingHoursSpecification": {
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],
    "opens": "00:00", "closes": "23:59"
  },
  "areaServed": "Perth metropolitan area",
  "priceRange": "$2,800–$6,500",
  "aggregateRating": {
    "@type": "AggregateRating", "ratingValue": "4.9", "reviewCount": "180"
  },
  "review": {
    "@type": "Review",
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "author": { "@type": "Person", "name": "A real family, with consent" },
    "reviewBody": "The ledger came by email an hour after the first call…"
  }
}
</script> // would-ship only — never emitted on this demonstration

What would change for the real client

Iteration log

Pass 1 — Craft

The 375px masthead collided exactly as LEARNINGS W18 predicts: the wordmark’s right edge (212px) crossed the phone block’s left edge (185px), caught by the explicit rect-edge probe and confirmed on the header screenshot. Fixed by stepping the masthead scale down and trimming the phone sub-label to “24 hours” below 430px. Screenshot review at 375 also showed the hero’s background gum leaves scaling into muddy blobs behind the CTAs (hidden below 700px), and the ledger’s dotted leaders running under both the labels and the right-aligned figures — leaders are now measured and clipped between label end and figure start.

Pass 2 — Depth

The 7-second thumbnail sample measured all eight rest rows already inked — faster than the specced “two-thirds written” — so the first-write stagger was slowed 780→930ms: measured at 7s the ledger is now inked through the viewing line, flowers still arriving, sum rule undrawn (measured 7 of 8 rows at 7s). Added the total’s re-ink micro-interaction (amber flash, 3px settle on a crafted cubic-bezier), the live “prepared at [actual time]” stamp and the paperbark margin layers as second-read details, and tightened panel spacing so the ledger paper’s header and first line share the 1200×750 fold (bounding-box asserted, screenshot reviewed).

Pass 3 — Hardening

Masthead re-checked first at 375 (clean), scrollWidth 375 on both pages, sticky call bar ≥48px with a tel: link inside the bottom 140px. Empty submit on a fresh load raises four validation signals with aria-invalid; filled submit renders the local confirmation. Subsequent-redraw timeline tightened to ~0.7s to honour the dual-speed cap; reduced-motion path asserted to render the completed ledger instantly (sum rule dashoffset 0, settled true). Removed one excess ornament (the third amber bark curve in the hero) per the Chanel rule. Final run: 37/37 harness asserts, zero console errors, every displayed figure matched the independent oracle.