feat(web): line-numbered unified prose diff replaces the block cards (spec-by6.3.5) The block-card renderer was reviewed against a live proposal and rejected: "ADDED PARAGRAPH" outweighed the content on every row, every block carried identical chrome, and on a new file the whole page is one change, so the cards added noise and no signal. Two columns of digits say the same thing and then get out of the way, which is what a gutter is for. Selection is by line, anchoring is by block. Lines are what the cursor lands on; block hashes are what survive a reflow. The web layer maps a selected line range onto its enclosing prosediff block and stores the existing core.CommentAnchor unchanged — service/, db/ and core/ do not move and the POST wire format is untouched. The composer states which block it will anchor to before anything is typed, so the indirection is visible rather than magic. A line number is never guessed. A modified prose block goes through prosediff.WordsByLine, whose ok=false contract is honoured with a paired old/new region stating a line RANGE; a block rewritten past the similarity threshold takes that path too. An equal block that was rewrapped states an old number only for the lines the old revision really holds — equal line counts were the first rule and were not proof, which a property test over 2800 generated document/edit pairs found within seventeen cases. The markup is a table because prose wraps and a number has to stay on the first visual line of the line it names. One rail ground behind both number tracks with a single hairline against the content; the change tint starts at the sign column so the gutter never reads as part of the change; heading rows pin themselves as the section readout, replacing the per-hunk breadcrumb that only restated a heading three rows above. Folding and commenting both work with JavaScript off — the fold is a checkbox, and every block keeps a visible composer. With the script in, that per-block composer is hidden and reached by selecting lines instead, because sixteen identical "comment on this block" rows are the chrome this port removes. A composer holding typed text is never hidden by anything. Two pre-existing prosediff faults are fixed here because line numbers are what made them visible: a thematic break reported line 1 for every rule in the document, and a document whose entire content is "---" panicked in splitFrontmatter.