// pricing-page.jsx — three tiers (Free / Deal Pack / Complete). No team tier, by decision (2026-10-10). // Buy buttons POST to /api/checkout (Stripe Checkout) once /api/status says payments are on; until then they say payment is opening soon. function V4Pricing() { const v4 = window.v4; const accent = v4.yellow; const access = window.useVCAccess(); const tiers = window.VC_TIERS; const [pay, setPay] = React.useState(null); // null = checking, true/false = Stripe on/off const [sending, setSending] = React.useState(false); // one click → one checkout page // Buy buttons need Stripe on AND a public contact email: buyers must have someone to write to (refunds, lost codes). React.useEffect(() => { if (window.VCAccess && window.VC_CONTACT_EMAIL) window.VCAccess.payments().then(p => setPay(p.enabled)); else setPay(false); }, []); const notice = { cancelled: 'Payment cancelled. Nothing was charged.', unavailable: 'Payment is not open yet. Nothing was charged.', error: 'Stripe could not start the payment. Nothing was charged; please try again in a minute.', unknown: 'That product was not recognised. Nothing was charged.' }[new URLSearchParams(location.search).get('payment')]; const owns = (id) => access.product === id || (id === 'deal' && access.product === 'full'); React.useEffect(() => { const id = (location.hash || '').slice(1); if (id) { const el = document.getElementById(id); if (el) setTimeout(() => el.scrollIntoView({ block: 'start' }), 60); } }, []); const btn = (bg, color, extra) => ({ display: 'block', textAlign: 'center', background: bg, color, border: `1.5px solid ${v4.ink}`, padding: '15px 16px', fontFamily: v4.mono, fontSize: 12.5, fontWeight: 700, letterSpacing: 1.5, textTransform: 'uppercase', textDecoration: 'none', cursor: 'pointer', ...extra }); const rows = [ ['Chapter I, in full', '✓', '✓', '✓'], ['The first lesson of every chapter', '✓', '✓', '✓'], ['The other 45 lessons', '—', '90 days', 'No expiry'], ['8 tools as CSV and print-ready pages', '✓', '✓', '✓'], ['Earnings-bridge calculator, on screen', '✓', '✓', '✓'], ['Calculator export: one-page PDF + Excel', '—', '✓', '✓'], ['Excel workbooks with live formulas', '—', '4', 'All 6'], ['Chapter quizzes', '—', '—', '7'], ['Printable completion records', '—', '—', '✓'], ]; const faqs = [ ['How does access work?', 'Pay by card through Stripe. You land straight on your Library page with an access code, already unlocked in that browser, and Stripe emails your receipt. To read on another device, paste the same code into its Library page. There is no account and no password.'], ['Can I get a refund?', 'Yes. Ask within 14 days of paying and we refund the full price, no questions asked. Details are on the Terms page.'], ['What happens when the Deal Pack’s 90 days end?', 'The paid lessons and the workbook downloads lock again. Workbooks and PDFs you have already downloaded are yours to keep. If you need longer, Complete has no expiry.'], ['Is the calculator result a valuation?', 'No. It is a working paper: your numbers, your reasons, arranged so they can be checked. It is not a valuation report and not financial advice.'], ['How long is the course?', 'About 3.5 hours of reading for all 59 lessons, at 200 words a minute. Each chapter quiz adds about five minutes. The time shown on each lesson is calculated the same way.'], ['Do the completion records count as CPD?', 'They are self-issued records that you passed a chapter quiz, with the chapter’s reading time. They are not accredited. Check your professional body’s CPD rules before claiming the hours.'], ['Where do my calculator numbers go?', 'Nowhere. They are saved in this browser only, and the exports are built in your browser too.'], ['Is there a team or firm licence?', 'Not at present. Each code is for one person.'], ]; return (
§ Pricing

Pay once.
Keep the work.

Chapter I and the first lesson of every chapter are free, along with the eight tools and the calculator. The paid tiers unlock the other 45 lessons, the Excel workbooks and the calculator exports. No subscription.

{notice ?
{notice}
: null}
{tiers.map((t, i) => { const hot = t.id === 'deal'; return (
{t.sub}
{t.name}
NZD {t.price} {t.per ? {t.per} : null}
{t.perks.map(p =>
+ {p}
)}
{t.id === 'free' ? ( {t.cta} ) : owns(t.id) ? ( ✓ In this browser · Library → ) : pay ? (
{ if (sending) { e.preventDefault(); return; } setSending(true); setTimeout(() => setSending(false), 15000); }}>
Card · Stripe · code right after payment
) : ( <> {pay === null ? 'One moment…' : 'Payment opening soon'} Have a code? Enter it below )}
); })}
Buying means you agree to the terms. Refunds: 14 days, no questions (how). Prices in NZD, including GST where it applies.
§ Side by side
{['', 'Free', 'Deal Pack', 'Complete'].map((h, i) =>
{h}
)}
{rows.map((r, i) => (
{r.map((c, j) =>
{c}
)}
))}
§ How access works
{[['01', 'Pay once', 'By card, through Stripe. NZD, no subscription.'], ['02', 'Get your code', 'It appears on your Library page right after payment, already unlocked. Stripe emails the receipt.'], ['03', 'Other devices', 'Paste the same code into the Library page there. No account, no password.']].map(([n, t, d]) => (
{n}
{t}
{d}
))}
§ Already have a code
Unlock this browser.
§ Questions
{faqs.map(([q, a], i) => (
1 ? `1px solid ${v4.lineSoft}` : 'none', borderLeft: i % 2 ? `1px solid ${v4.lineSoft}` : 'none', background: v4.paper }}>
{q}
{a}
))}
Keelvalue is educational material. Nothing on this site is a valuation of your business or financial advice.
); } window.V4Pricing = V4Pricing;