{!w ? No storm applies with these settings.
: w.breaksInMonth !== null
? <>First to break: {w.label}. Cash runs out in month {w.breaksInMonth} of {KEEL_HORIZON}, short by {keelMoney(keelShortfall(w, input.undrawnOverdraft))} that month.>
: <>Weakest point: {w.label}. Still standing after {KEEL_HORIZON} months; lowest cash {keelMoney(w.lowCash)} in month {w.lowMonth}.>}
{r.burning ? <> Before any storm the business spends more than it makes ({keelPerMonth(r.baseline.monthlyNet)}).> : null}
Red = at or after the month cash fell below the floor of −{keelMoney(input.undrawnOverdraft).replace('−', '')} (the undrawn overdraft).
{w ? (
Operating moves, each tried on its own
{r.levers.map(l =>
{l.label}:
)}
) : null}
Input
Value
{inputs.map(([k, v]) =>
{k}
{v}
)}
Educational working paper prepared with Keelvalue (keelvalue.com). Cash arithmetic only: not financial advice and not an assessment of the business by anyone.
All figures were entered by the preparer and have not been verified. Each storm runs on its own for {KEEL_HORIZON} months; balances are monthly flow × days ÷ 30;
stock falls a third of the way to its new level each month and never faster than it sells. Left out: seasonality, GST timing and bad debts.
A dozen numbers from your accounts, four storms: revenue falls, rates rise, your biggest customer leaves, customers pay a month late. See how many months your cash lasts in each, which one breaks first, and the one operating move that helps most. Nothing you type is sent anywhere — it is saved in this browser only.
{/* ── inputs ── */}
{sectionTitle('1 · Sales and costs, per month')}
{field('revenue', 'Average of the last 12 months: annual sales ÷ 12.', { unit: 'NZD', big: true, placeholder: '200,000' })}
{field('margin', '(Sales − cost of sales) ÷ sales.', { unit: '%', placeholder: '30' })}
{field('top', 'Their share of last year’s sales.', { unit: '%', placeholder: '25' })}
{field('fixed', 'Wages, rent and everything else that does not move with sales. Leave out interest and loan repayments.', { unit: 'NZD', placeholder: '40,000' })}
{field('drawings', 'What the owners take out each month, as salary or drawings.', { unit: 'NZD' })}
The unused overdraft is only the floor the check measures against. It is not a suggestion to draw on it.
{field('repay', 'Principal and interest, per month.', { unit: 'NZD' })}
{field('floating', 'Balance on a floating rate. Used only for the rate storm.', { unit: 'NZD' })}
Debtor days = trade debtors ÷ annual sales × 365 (0 if customers pay on the spot). Creditor days = trade creditors ÷ annual cost of sales × 365. Stock days = stock ÷ annual cost of sales × 365 (0 if you hold none).
Each storm is run on its own over {KEEL_HORIZON} months. Stock is cut a third of the way to its new level each month, never faster than it sells.
{/* ── results ── */}
{!r ? (
Your storms appear here
Still needed: {missing.map(k => KEEL_LABELS[k]).join(', ')}. Or load the teaching case to see how it reads.
) : !ok ? (
Check these
{errors.map((e, i) =>
{e}
)}
) : (
<>
{r.burning ? (
Before any storm: you spend more than you make ({keelPerMonth(r.baseline.monthlyNet)}).{' '}
{r.baseline.breaksInMonth !== null ? <>At today’s numbers cash runs out in month {r.baseline.breaksInMonth}.> : <>Cash in the bank covers it for now.>}
{w.breaksInMonth !== null
? <>Cash runs out in month {w.breaksInMonth} of {KEEL_HORIZON}, short by {keelMoney(keelShortfall(w, input.undrawnOverdraft))} that month.>
: <>Still standing after {KEEL_HORIZON} months. Lowest cash {keelMoney(w.lowCash)} in month {w.lowMonth}{w.monthlyNet < 0 ? <>, and still {keelPerMonth(w.monthlyNet)}> : null}.>}
>
) :
Every storm is switched off or does not fit this business.
{off ? keelNaReason(s, input, r.assumptions)
: breaks ? <>{keelPerMonth(s.monthlyNet)} once it settles · short by {keelMoney(keelShortfall(s, input.undrawnOverdraft))} in month {s.breaksInMonth}>
: <>{keelPerMonth(s.monthlyNet)} once it settles · low {keelMoney(s.lowCash)} (month {s.lowMonth})>}
);
})}
{/* ── the one operating move ── */}
{w ? (
The move that helps most
{best ? (
<>
{best.label}.
>
) :
No single operating move below changes the weakest storm on its own.
}
{r.levers.filter(l => l !== best).map(l => (
{l.label}:
))}
Operating moves only, each tried on its own as if already done. This check never suggests borrowing.
) : null}
{/* ── exports (paid) ── */}
{access.export ? `● Unlocked · ${access.name}` : 'Take it with you · Deal Pack or Complete'}
A one-page PDF with every storm, the moves and the inputs behind them, and an Excel file that recalculates month by month.
Two businesses with the same profit are not worth the same. A buyer prices a shallow keel — one big customer, slow debtors, thin cash — into the discount rate as specific-company risk.{' '}
Lesson 5.03 shows where →
>
)}
Cash arithmetic for education, not financial advice, and not an assessment of your business by anyone. Figures are yours and are not checked. v1 leaves out seasonality, GST timing and bad debts.