[WIP] Be smarter about how we line up markdown code with the live preview

*UNFINISHED. There's a case where the ends of the scroll panes don't line up. Submitted for review + comments*

Fixes #481
Fixes #535

Currently we sync these two panes by working out how many % the user is down the left pane, and extending that ratio to the right side. This is good enough for text, but in long posts, or those with elements like images it can go askew.

These changes split both the markdown and the preview into sections (divided by headings). It determines that the user is X percent through section Y, and then applies that same scroll to the other pane.

### Complications

Rather than interfacing with CodeMirror itself, it scans the HTML that CodeMirror creates. For optimisation reasons, CodeMirror pages content in and out as you scroll (see the viewportMargin option) - meaning that all the content isn't output as HTML at the same time.

To combat this, there is now a 'shadow' CodeMirror on the page which is a direct copy of the main one, except that it's full-size, invisible and used only for measurements. Regenerating the entire HTML of a CodeMirror can slow down on long documents, so this can't be regenerated with every scroll event. In order to make scrolling silky smooth, the shadow is therefore only regenerated when the user makes a change that affects the height of either pane.

It is now bi-directional - you can scroll either side. This feels awesome to use, but means that you can't scroll them independently. If for some reason our calculations screwed up, you wouldn't be able to manually scroll the preview to where it should be. I suggest that we include a little lock icon that fades in when you scroll the preview. Clicking the lock would 'unlock' the preview, so that you can move it independently. Obviously this is a design detail and is up to @JohnONolan

It's not throttled/debounced at the moment. Need to test across browsers and devices, and see whether this is needed (expect it is, even if it's with a tiny duration). Otherwise, it could be a good move to use requestAnimationFrame.