The question mark, and the number you typed over it
A dish with no recipe showed an orange ? instead of a cost. There is a box to type one now, and the recipe still wins the moment a line is linked.
A dish with no ingredients linked to it has no cost. For a long time the product said exactly that: an orange question mark where the cost would be, no margin, no profit figure, and a report that counted the dish as uncosted. That was deliberate. A £0.00 in that column reads as pure profit, and a menu-engineering report built on pure profit tells you to push the dish you know least about.
A tester filed it as a bug. The owner of the hall was asked, and chose the middle path: let somebody type what a dish costs to make, per portion, and mark that figure as an estimate everywhere it shows up. Not a replacement for a recipe. A placeholder that admits what it is.
The rule, in one sentence
A typed cost is used only while nothing is linked. The moment one ingredient goes on the recipe, the recipe’s figure takes over and the typed number stops showing. An ingredient with no supplier price is still not known, not guessed: the estimate never fills that hole either, because a typed number papering over a missing price is the exact lie the question mark was there to refuse.
That gives the cost column a fifth answer. Costed from a recipe. No ingredients. An ingredient with no price. A price that depends on which option the guest picks. And now estimated, which counts as known for the reports and carries a small est. badge wherever the number is printed: the items list, the menu screen, the item editor, and the menu-engineering page, which says how many of the scored dishes are costed from a typed figure rather than hiding it in the average.
The save that must not wipe it
The item editor saves every field at once. If the estimate were just another field, a save from a screen that had never heard of it would have cleared it. So the server honours the typed figure only when the request names it: leave it out and the stored number survives, send it blank and it is cleared, send a negative and nothing is stored. The upsell run, which computes a margin for every pairing it suggests, reads the same rule from the same place, so a typed £2.40 on a £9 dish gives a 73% margin there too, and two buns at 42p linked to the same dish replace it with 84p.
We drove all of that through the real routes on a seeded database before it shipped: typed, cleared, outranked, and the unpriced-ingredient case that must stay unknown. The question mark is still there for anyone who has not typed anything. It was never the bug. The bug was giving people no way to answer it.