Halftone Print Works

Generative Assets · Industry Demos XXVI · site 343

Halftone Print Works — how it was made

A conversion-first landing page for a fictional Malaga commercial printer, built as the pattern Sapience Analytics would ship for a real Perth print shop: price the run on the page, then send the file.

Concept

Halftone Print Works prints business cards, flyers and posters for Perth businesses from a press room and trade counter in Malaga — digital under about two thousand pieces, offset above, same-day rush and next-day metro delivery. The audience is the tradie who needs 500 cards before the expo, the café owner with a seasonal menu flyer, the school P&C with a fete poster and the marketing coordinator ordering the quarterly run. The page has one job: a print-quote request with the product, quantity and finish already priced, so the first phone call is about the file and the day, not "how much".

Art direction is the press room at 3pm: uncoated-stock white ground, registration-black ink, press-magenta actions and process-cyan crop-mark linework. Bright, exact, a little loud — the whole page reads like a proof sheet with the marks still on.

Palette — measured, not assumed

#F7F6F2 uncoated stockPage ground.
#141517 registration blackBody ink. Measured 16.90:1 on the stock, 18.27:1 on paper white.
#B5175B press magentaButtons, links, prices, the drawn ink layer. White labels 6.48:1; on the stock 6.00:1.
#951249 deep magentaButton hover. White labels 8.53:1. Pre-minted, held in reserve — the base cleared 6.
#82103F magenta inkSelected chip names, tier notes, ledger CTA text. 9.27:1 on the stock.
#3FA9C9 process cyanCrop marks, registration targets, colour bar, rules, focus rings. 2.51:1 — lines and marks only, never text.
#1B6F86 cyan inkEyebrows, control-block headings, on-sheet labels, reviewer names. 5.30:1 on the stock, 5.73:1 on paper.
#7FCBE0 light cyanLedger notes and links on registration black. 10.02:1.

The spec's contrast figures were hypotheses; every one was measured with WCAG relative-luminance arithmetic from the shipped hex values in Pass 1. Press magenta landed at 6.00:1 on the stock (spec ≈6) and 6.48:1 under white labels (spec ≈6.4), so no two-token remedy was needed for the accent — the pre-minted deep fill and text-ink pair still exist as hover and small-copy tokens. Process cyan carries no text anywhere: every cyan-coloured word uses cyan ink at 5.30:1. Secondary body copy uses #4A4D53 at 7.84:1.

Type

Space Grotesk (700) for the wordmark, headings, the display line, the money and the job-ticket total — a grotesque with a typesetter's ink traps, the face a print shop's own signage would carry. IBM Plex Sans for everything else, a workhorse that stays legible at 13px inside the ledger and at 10.5 units in the sheet's slug line. Body is 17px on mobile. The typographic moment is the display line above the sheet — "ONE THOUSAND FLYERS, ON THE PRESS BY FOUR" — set in caps at up to 34px, where the quantity is written in words from the live stepper (two hundred and fifty … fifteen hundred … two and a half thousand … fifty) and the second half follows the toggles: on the press by four at rest, same-day, collect from four with rush on, in your hands tomorrow with delivery on.

The signature — the Press Sheet

A drawn SVG press sheet built from JavaScript on every state change, so the product chips genuinely re-impose the sheet rather than toggling layers. Business cards impose 21-up (7 × 3 of 55 × 90 mm on a 450 × 320 mm SRA3, drawn landscape); A5 flyers impose 8-up (4 × 2 of 148 × 210 mm on a 640 × 450 mm SRA2 — eight A5s are an A2 of paper, which is why the flyer sheet is the bigger one and why the drawn sheet swaps size with the product); A2 posters draw 1-up on a 610 mm wide-format roll with the core at the left. Every item is drawn twice: a ghost keyline version (unprinted stock) and a full-colour version — a magenta halftone block, black headline bars, grey body lines, a cyan rule — clipped by a four-point <clipPath> polygon whose right edge is the roller line, leaning 3 units so it reads as a wet edge, with a 50-unit magenta wet-ink gradient behind the roller.

The roller rides that edge on a requestAnimationFrame loop: inkFrac = 0.5 + 0.15·sin(0.7t), so the inked region always covers between 35% and 65% of the sweep — the never-invisible floor is coverage rather than opacity: at any capture instant the sheet is visibly half ghost, half ink, at full opacity. The delta is clamped both ways (dt = min(max(now − last, 0)/1000, 0.05)), the loop pauses on document.hidden, and reduced-motion skips the loop and paints the 0.5 frame once. The halftone itself is a 4.2-unit <pattern> of white dots rotated 15°, laid over the magenta blocks so the screen shows in the artwork the way it does on a real proof.

Finish chips draw the sheet's surface without touching the price: gloss (cards gloss cello / flyers gloss) lays a hard diagonal specular sweep at 62% over the inked region; satin and silk lay the same sweep at 34%; matt cello and matt lay none; uncoated adds a fine grey paper-tooth pattern over the whole sheet. Setup draws a rotated cyan-ink "PROOF APPROVED · HALFTONE · MALAGA" stamp on the sheet's top-right corner; rush draws a clock at four o'clock on the press bed; delivery draws a courier satchel with a magenta flap and a cyan-edged label. Cyan crop marks sit at the sheet corners, registration targets in the side margins, a C/M/K colour bar along the gripper edge, and a slug line prints the imposition, the stock and — the second-read detail — the number of sheets the run actually needs (1,000 flyers 8-up = 125 sheets; 500 cards 21-up = 24 sheets; posters one print each).

The job ticket is drawn on the sheet like a real sticker — white plate, magenta header strip, "JOB TICKET · #0343", the total in Space Grotesk, a sub-line naming quantity, finish and whichever extras are on — tilted 2° and set inset from the bottom-right corner so it never covers the crop marks or the slug. Below 600px it ships a tight 160 × 62 variant (total only) so it never covers the imposed items at 375. Every control handler bumps a token before touching state; the rebuild is synchronous and the loop reads scene references refreshed by each render, so a rapid-fire chip sequence never leaves a stale closure alive. First draw staggers the drawn groups at 90 ms (1.3 s cap); every later redraw runs at 26 ms (460 ms cap) via a firstDraw flag. window.__printing exposes product, quantity, finish, toggle states, rate, tier flag, note, ledger lines, total, sheets, badge text and sub-line, run line, an integer-safety flag, ink fraction, frame count and a settled flag.

Pricing model — pinned anchors, measured outputs

LineRateRule
Business cards, 350 gsm, double-sided$22 per 100Stepper 250–2,000 ×250, rest 500. Volume tier $18 per 100 from 1,000, applied to the whole run, with the note "volume tier: $18 per 100 from a thousand cards". 750 → list, 1,000 → tier
A5 flyers, 150 gsm, double-sided$18 per 100Stepper 500–5,000 ×500, rest 1,000. Tier $16 per 100 from 2,500 — "volume tier: $16 per 100 from two and a half thousand". 2,000 → list, 2,500 → tier
A2 posters, 200 gsm, single-sided$14 eachStepper 5–50 ×5, rest 10. Tier $11 each from 20 — "volume tier: $11 each from twenty". 15 → list, 20 → tier
Product chipresetSwitching product RESETS the quantity to that product's rest quantity (the grids share no values, so restore has no meaning). Toggles are NOT reset. Each product remembers its own finish; re-clicking the selected product changes nothing
Finish chips$0Cards: matt cello / gloss cello / uncoated. Flyers: gloss / silk / uncoated. Posters: satin / matt. Live at every combination, no price change — "the finish changes the feel, not the price at these runs" on the card and in the ledger; the drawing changes
Artwork & design setup+$90 flatLive everywhere; default ON at rest. Draws the proof stamp. Pre-sets the form's print-ready checkbox to unticked until the visitor touches it
Same-day rush+$80 flatLive everywhere. Draws the clock; the display line becomes "same-day, collect from four"
Metro delivery+$15 flatLive everywhere. Draws the satchel; OFF prints a "Collection from Malaga — free" ledger line instead
Minimumsstepper floors250 cards, 500 flyers, 5 posters — stated as the minimum run under the stepper; no minimum note needed
Booklets, signage, packaging, letterpressno number"Quoted on the file — send us the artwork and the run" — a designed price-less line in the grid, under the ledger and in the FAQ

Toggle matrix

ToggleCards (any finish, any qty)Flyers (any finish, any qty)Posters (any finish, any qty)
Artwork & design setup +$90livelivelive
Same-day rush +$80livelivelive
Metro delivery +$15livelivelive
Finish chipslive, $0live, $0live, $0

Worked examples — all measured from the running page and cross-checked against an independent oracle

ScenarioArithmeticMeasured
Rest: A5 flyers, 1,000, gloss, setup ON, rush OFF, delivery OFF10 × 18 + 90$270
Business cards, 250, matt cello, no toggles2.5 × 22$55
Cards 750 (list, no note) · 1,000 (tier + note)7.5 × 22 · 10 × 18$165 · $180
Flyers 2,000 (list) · 2,500 (tier + note) · 5,00020 × 18 · 25 × 16 · 50 × 16$360 · $400 · $800
Posters 10 satin · + rush · 15 (list) · 20 (tier + note)140 · 140 + 80 · 15 × 14 · 20 × 11$140 · $220 · $210 · $220
Rest + delivery · rest + rush + delivery270 + 15 · 270 + 80 + 15$285 · $365
Product reset: rest → cards chip (500, setup stays ON) → posters chip (10)5 × 22 + 90 · 140 + 90$200 · $230
Rest, finish silk / uncoatedunchanged, drawing changes$270
Grid floors: cards $55 per 250 · flyers $90 per 500 · posters $70 per 5stepper floor × list ratematch

Zero spec corrections: every pinned figure landed exactly. Every quantity on every grid is a multiple of 250, 500 or 5 and every tier applies to the whole run, so every product line is a whole dollar by construction (250 cards = 2.5 hundreds × $22 = $55). The harness swept all 8 + 10 + 10 grid quantities against the oracle and asserted no decimal ever reaches the badge or the ledger; the probe carries an integerSafe flag that would go false if one ever did.

Conversion decisions

Local SEO we'd implement for the real business

The live page carries only WebPage, WebSite, CreativeWork and a BreadcrumbList — a fictional business must not put business-shaped structured data into a real index. For the real client we would ship Store: schema.org has no print-shop type, and a printer with a trade counter that sells finished goods over it is a retail LocalBusiness subtype — Store is the honest organisation type, more precise than bare LocalBusiness and not a specialty token. With the real ABN, address, hours, delivery area and a live review feed:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Store",
  "name": "Halftone Print Works",
  "url": "https://example.com.au/",
  "telephone": "+61 8 9000 0343",
  "address": { "@type": "PostalAddress", "addressLocality": "Malaga", "addressRegion": "WA", "postalCode": "6090", "addressCountry": "AU" },
  "areaServed": ["Malaga", "Balcatta", "Osborne Park", "Morley", "Joondalup", "Perth", "Fremantle", "Cannington"],
  "openingHoursSpecification": [{ "@type": "OpeningHoursSpecification", "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"], "opens": "08:00", "closes": "17:00" }],
  "priceRange": "$$",
  "hasOfferCatalog": { "@type": "OfferCatalog", "name": "Printing", "itemListElement": [
    { "@type": "Offer", "itemOffered": { "@type": "Product", "name": "Business cards, 350 gsm" } },
    { "@type": "Offer", "itemOffered": { "@type": "Product", "name": "A5 flyers, 150 gsm" } },
    { "@type": "Offer", "itemOffered": { "@type": "Product", "name": "A2 posters, 200 gsm" } },
    { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Artwork and design setup" } }
  ]},
  "aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.9", "reviewCount": "141" },
  "review": [{
    "@type": "Review",
    "author": { "@type": "Person", "name": "Real customer name" },
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "reviewBody": "Pulled from the Google Business Profile feed, never hand-typed."
  }]
}
</script>

Plus: a Google Business Profile with the delivery area set to the metro and "in-store pickup" on, product entries for cards, flyers and posters with the real from-prices, suburb landing sections for the industrial belt (Malaga, Osborne Park, Balcatta, Wangara), and the FAQ marked up as FAQPage once the answers are the client's own.

What would change for the real client

Iteration log

Pass 1 — Craft

Pass 2 — Depth

Pass 3 — Hardening

Rest-state price measured from the running page: $270 (1,000 A5 flyers, gloss, with artwork setup). Zero console errors, one <h1> per page, live JSON-LD limited to WebPage / WebSite / CreativeWork / BreadcrumbList / ListItem.