I've written the December 2025 narrative to `output/mbr-narrative.md`. The figures it uses are in `output/mbr.json`. The script ran without errors and its checks passed: the lines rebuild operating income exactly, the monthly revenue adds up to the year-to-date total, and the revenue KPI equals P&L revenue.

**Main points:**
- **Month:** revenue was $827K against a $824K budget, slightly ahead. Operating income was $8K against $13K, a ($5K) shortfall. Gross margin was (0.7) points below budget, and operating expenses were on budget.
- **What drove the month:** two lines each came in ($6K) over budget, other operating and cost of goods sold. Technology spend was $4K under budget. The narrative says the P&L doesn't show why other operating was over budget; that line's transaction detail would.
- **Year to date:** the full year doesn't follow December's revenue beat. Revenue was ($362K) behind budget and operating income ($195K) behind, at $388K against $583K. The cost of goods sold line came in $196K under budget and offset part of the revenue shortfall.
- **KPIs:** 4 of the 8 were off target. Days sales outstanding and on-time delivery have each missed for 3 months in a row. Active customers has missed for 2 months, and inventory turns missed for the first time.

The year-to-date "Cost of goods sold" figure ($7.9M) is lower than the cost of goods sold subtotal in the table ($8.3M). The subtotal presumably includes more than one cost-of-sales line. I kept them separate rather than reconcile them by hand.