I got the circuit working. My general advice for anyone with a similar issue/level of experience is to learn to use an oscilloscope and what your clock/data signals ought to look like.
Problem 1 - Pull-up resistor strength
Symptom: Slow rise times visible in the scope images above, highlighted by @SamGibson.
Cause: Pull-up resistors too strong.
Fix: Weaker pull-up resistors. Use the TI resource linked in @SamGibson's answer and/or use a scope to check the SDA/SCL signals.
Problem 2 - Inappropriate pull-up resistor wiring
Symptom: SDA/SCL idling at 5V when the sensor was disconnected which looked like a serious problem with the wiring.
Cause: The pull-ups were wired in such a way that they were only on the bus if the sensor was on the bus which caused the bus to behave differently when the sensor was connected. Likely wouldn't be a problem but generated a distracting symptom.
Fix: Wire the I2C bus so that the pull-up resistors always go to the correct power rail, even if the device is not connected to the bus.
Problem 3 - Broken power line
Symptoms: SDA/SCL would idl at ~2.6V then oscillate between 3.3V and 0V when transmitting. Voltage measured at the VDD input on the sensor was erratic or sitting around 2.6V, but fine at the edge of the PCB.
Cause: Broken power line on the PCB.
Fix: Soldered a piece of spare wire in to bridge the break in the line.
Problem 4 - Incorrect I2C address
Symptoms: Device NACK received by I2C master, but traces otherwise look correct.
Cause: The I2C address was incorrect so of course the device didn't acknowledge the transmission.
Fix: I checked the address which was being transmitted on the scope and realised it was wrong. I then checked the example code to confirm and set it to the correct address (the default used in the example was for a different sensor).
I can now read from my sensor. Trust nothing, check everything, change only one thing at a time. Thank you to everyone that responded!