THANKYOU gentlemen! This is good stuff - think I understand what I'm seeing from the O2 sensors now.
Armed with the information you've provided, I think I've fixed the problem by swapping out the throttle body with MAF sensor and TPS.
On the OBD scanner software I was reading the wrong screen - what I should have looked at was a graph of the O2 sensor voltages which properly shows the change between high and low values over the space of a few seconds. Doesn't read often enough to get graphs as good as yours, but enough to work with.
Here's my understanding - please challenge if any of this looks wrong. All tests were done with the car parked, not while driving.
With a properly warm engine at 3000rpm the upstream O2 sensor was reading 0.2v - 08.v, while the downstream was reading 0.7v -0.8v. From Frank's last diagram, this is consistent with a properly working cat (and presumably working O2 sensors). The downstream sensor voltage is higher than what you get, but I'm not worried there, as the car DID pass the fast idle test at this RPM. Also these figures are close to Agent Sm1th's graph - where was that from?
From Frank's link to www.PicoAuto.com: "An ECM will only control the fuelling in 'closed loop' when the appropriate conditions allow, which is normally during idle, light load and cruise operations. When the vehicle accelerates, the ECM allows overfuelling and ignores the lambda signals. This also happens during initial warm-up."
From that I take it the O2 upstream sensor voltage at idle on a warm engine should go up and down in a similar way to the same engine running at 3000rpm
But I wasn't getting that - the engine was idling at 640rpm and giving a steady 0.8v and 0.9v on the upstream and downstream sensors respectively.
Conclusion - although all components are old, the cat and O2 sensors are still OK, but something was preventing the ECU going into closed loop, so it was ignoring O2 sensor output and fuelling rich as if the engine was cold.
How's my logic so far?