progressFraction

Maps a ContractCallStage to a 0..1 progress value for the bar.

Bands are weighted by typical duration, not evenly — proving is near-instant while finalization dominates, so finalization sits near-full (an evenly-spaced bar would stall there and read as a hang). Dust-sync sub-progress fills its own band so the user sees smooth motion without raw event counts. Callers should clamp the displayed value monotonic so a retry/recovery stage that reports a lower value never makes the bar visibly retreat — ContractCallProgressBar does this for you.