/* global React, HeroDemo */ const { useState, useEffect, useRef } = React; // =================== SCROLL RAIL =================== function ScrollRail() { const items = [ { id: "hero", label: "Takeoff" }, { id: "how", label: "How it Works" }, { id: "why", label: "Aotearoa" }, { id: "pricing", label: "Pricing" }, { id: "how-tokens", label: "Tokens" }, { id: "faq", label: "FAQ" }]; return ( ); } // =================== MARQUEE =================== function Marquee() { const items = [ "Bunnings", "PlaceMakers", "ITM", "Carters", "Mico", "Plumbing World", "Mitre 10", "Bowers Brothers", "Fletcher"]; // Render twice for seamless loop const all = [...items, ...items]; return (
{all.map((m, i) => {m} )}
); } // =================== NAV =================== function Nav({ logoText }) { const [scrolled, setScrolled] = useState(false); const [tradesOpen, setTradesOpen] = useState(false); const tradesRef = useRef(null); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 8); window.addEventListener("scroll", onScroll); return () => window.removeEventListener("scroll", onScroll); }, []); // Close dropdown when clicking outside useEffect(() => { const onClick = (e) => { if (tradesRef.current && !tradesRef.current.contains(e.target)) { setTradesOpen(false); } }; document.addEventListener("mousedown", onClick); return () => document.removeEventListener("mousedown", onClick); }, []); const trades = [ "Building", "Roofing", "Plumbing", "Electrical", "Concrete", "Painting", "Decking", "Drainage", "Tiling"]; return (
); } // =================== HERO =================== function Hero({ headline, sub, cta }) { return (
Takeoff to quote · Built for NZ tradies

{headline}

{sub}

{cta} See how it works
Wellington, NZ No lock-in
); } // =================== HOW IT WORKS =================== function HowItWorks() { const steps = [ { n: "01", title: "Drop your pricebook in", body: "Excel, CSV, or PDF — your rates, your suppliers. No pricebook organised? Use our blank template.", art: }, { n: "02", title: "Add the takeoff", body: "You've done the measuring. Drop your takeoff spreadsheet in. Plans, aerials, or site photos as reference.", art: }, { n: "03", title: "Markup builds the quote", body: "Every line matched to your pricebook. Labour, markup, GST — applied automatically. Every number traces back to your file.", art: }, { n: "04", title: "Send it to the customer", body: "Branded PDF in your format. Out the door in minutes, not days.", art: }]; return (
How it works

From pricebook to quote in four steps.

{steps.map((s, i) =>
{s.n}

{s.title}

{s.body}

{s.art}
)}
); } // Step illustrations — abstract, monochrome with one orange accent function ArtPricebook() { return ( ); } function ArtTakeoff() { return ( 62 lm ); } function ArtBuild() { return ( ); } function ArtSend() { return ( ); } // =================== WHY NZ =================== function WhyNZ() { return (
BUILT HERE, IN AOTEAROA

Made for NZ tradies, not adapted from somewhere else.

Drop in your pricebook with your negotiated rates. No supplier feeds to break, no rate sheets to argue with. 15% NZ GST applied automatically on every quote. No workarounds, no US-style sales-tax confusion. Wellington-based. Talk to the people who built it. No support queue, no time zones. Flat monthly subscription. Cancel anytime.
); } function Point({ title, children, idx = 0 }) { return (

{title}

{children}

); } function NZVisual() { return (
New Zealand outline {/* Wellington dot — percentage positioned so it always lands on the city */}
Wellington HQ
); } // =================== TRADES =================== function Trades() { const trades = [ "Building", "Roofing", "Plumbing", "Electrical", "Concrete", "Painting", "Decking", "Drainage", "Tiling"]; return (
Trades supported

If you take off from a job, Markup quotes it.

Configured for the trades that quote from materials and measurements. Don't see yours? Get in touch — we add new trades regularly.

{trades.map((t, i) => {t} )}
); } // =================== PRICING =================== function Pricing() { return (
PRICING

Plans built for tradies of all sizes.

Every plan includes AI quote generation from your takeoffs, branded PDF quotes with every line traceable to its source. Tokens are consumed as you chat.

For sole traders doing 5-10 quotes a month, <>200 tokens per month, <>65¢ per token, <>AI quote generation from Excel or PDF takeoffs, <>Branded PDF quotes with full line-item editing, <>Email support] } /> For small crews doing 10-25 quotes a month, <>500 tokens per month — best rate before Elite, <>50¢ per token, <>AI quote generation from Excel or PDF takeoffs, <>Branded PDF quotes with full line-item editing, <>Priority email + phone support] } /> For big teams running 30+ quotes a month, <>1,200 tokens per month — lowest rate, <>42¢ per token, <>Fergus integration (book a call to set up), <>Branded PDF quotes with full line-item editing, <>Dedicated account manager + phone support] } />

All prices in NZD. Tokens scale with the size of the job — a small Excel quote uses ~5; a big multi-page architect quote uses ~50+.

); } // =================== HOW TOKENS WORK =================== function HowTokensWork() { const cards = [ { icon: ( ), title: "You drop, tokens flow", body: "Tokens get used as Markup reads your files — pricebook, takeoff, plans. A small Excel-only quote uses fewer tokens than a multi-page architect PDF." }, { icon: ( ), title: "Bigger jobs use more", body: "More files, more chat, more revisions = more tokens. A handful of small renovation quotes costs less than three commercial reroofs — like phone data, you pay for the work you actually do." }, { icon: ( ), title: "Top up anytime", body: "Running low? Buy 60 more tokens for $39, no plan change required. Your balance is always visible — we never charge a surprise." }]; return (
HOW TOKENS WORK

Like phone data, but for quotes.

Your plan gives you a monthly token allowance. Each quote uses tokens based on its size and complexity — you only pay for the work you actually do.

{cards.map((c, i) =>
{c.icon}

{c.title}

{c.body}

)}

Running 100+ quotes a month?

For high-volume tradies we offer custom pricing, dedicated onboarding, and Fergus integration. Talk to us about a plan that fits.

Request Enterprise Pricing

Start free with 30 trial tokens — no credit card required. Need more? Top up or subscribe at any time.

); } function Plan({ name, price, tokens, perToken, features, popular, idx = 0 }) { return (
{popular && Most popular}
{name}
$ {price} / month
{tokens} tokens · {perToken}¢ per token
    {features.map((f, i) =>
  • {f}
  • )}
Choose {name}
); } // =================== FAQ =================== function FAQ() { const faqs = [ { q: "Do I need to use a specific pricebook?", a: "No — Markup uses your pricebook, not generic supplier feeds. Drop in your existing rates as Excel, CSV, or PDF and Markup reads every line. Don't have one organised? Use our blank template — fill it in, upload it, and you're set." }, { q: "Does Markup measure off architect plans?", a: "No — you do the measuring (that's your expertise and your liability). Markup reads the takeoff you've already done. Drop in your takeoff spreadsheet or PDF and Markup matches every priced line against your pricebook. Plans and aerial photos can come along as reference." }, { q: "What's a token, and how many do I need?", a: "A token is a unit of AI work. A small Excel-based quote uses around 5 tokens. A typical mid-size job with a PDF takeoff uses ~20-30. A big architect job with multiple drawings can use 50+. Your balance is always visible, and you can top up anytime — we never charge a surprise." }, { q: "Does it integrate with Fergus?", a: "Yes, on the Elite plan. Fergus integration is custom-set-up per business, so book a call with us once you're on Elite and we'll wire your accepted quotes to push straight into Fergus as jobs. No double entry." }, { q: "Can I cancel anytime?", a: "Yes. Monthly billing, no contract, no lock-in. Cancel from your dashboard. Your pricebook and quote history stay yours and you can export everything." }, { q: "Is there a free trial?", a: "Yes — sign up gets you 30 free trial tokens on the house, no credit card required. That's enough to build a real Excel-based quote start to finish, or sample a couple of smaller quotes. Pick a plan or top up when you're ready." }]; return (
Frequently asked

Questions, answered.

{faqs.map((f, i) =>
{f.q}
{f.a}
)}
); } // =================== MONEY ON THE TABLE — closing CTA =================== function MoneyOnTable() { return (

Your team is leaving money on the table. Let's fix that.

Start free. No credit card required.

Try it free
); } function Footer({ logoText }) { return ( ); } Object.assign(window, { Nav, Hero, HowItWorks, WhyNZ, Trades, Pricing, HowTokensWork, FAQ, MoneyOnTable, Footer });