P44 OCR Viewer — Remove diff system, add Pass 2 split panel view
Scope: p44-ocr-viewer.js, p44-ocr-viewer.css, p44-ocr-viewer.html. Complete removal of all diff logic, replace with a simple toggleable split panel for Pass 2.

PART 1 — Remove diff entirely
HTML — remove these elements:

<button id="btn-diff" ...>⇄ Diff</button>
<div id="diff-toolbar" ...></div>
<div id="diff-reference" ...></div>
<div id="editor-bottom"> wrapper — move its children (#line-numbers and #text-editor) back up directly inside #editor-wrap

CSS — remove all rules for:

#diff-toolbar
#diff-toolbar .diff-legend
#diff-toolbar .diff-count
.diff-swatch
.diff-swatch-del
.diff-swatch-ins
.diff-del
.diff-ins
#diff-reference
#diff-reference-label
#editor-bottom

JS — remove these functions entirely:

buildInlineDiff()
renderInlineDiff()
showDiffToolbar()
applyDiffToDisplay()
applyDiffToReference()
toggleDiff()

JS — remove these DOM refs:

const btnDiff
const diffToolbar
const diffReference
const editorBottom

JS — remove state.diffMode from the state object.
JS — in showOCRPage() remove the entire block added for diff auto-enable and toolbar display — the block starting with const corrForPage = state.corrections && state.corrections[pageNum] down to the closing } of the Pass 2 auto-diff block. Restore the original Pass 2 block at the bottom of showOCRPage():
javascript  if (currentRole === 'pass2') {
if (!state.editMode) enterEditMode();
updatePass2NavButtons();
}
JS — in enterEditMode() remove the line applyDiffToReference(pageNum);
JS — in exitEditMode() remove:

diffReference.style.display = 'none';
if (state.diffMode) applyDiffToDisplay(pageNum);

JS — in goToPage() remove the four lines:
javascript  state.diffMode = false;
btnDiff.classList.remove('active');
diffToolbar.style.display = 'none';
diffReference.style.display = 'none';

PART 2 — HTML (p44-ocr-viewer.html)
In the right panel header, add a toggle button immediately before #btn-edit:
html<button id="btn-split" class="tb-btn" title="Toggle split view — shows original OCR above for reference (Pass 2 only)" style="display:none;">⊟ Split</button>
Inside #text-panel-body, immediately before #text-output, add the original OCR reference pane:
html<div id="split-pane" style="display:none;">
  <div id="split-pane-header">ORIGINAL OCR</div>
  <div id="split-ocr-wrap">
    <div id="split-line-numbers"></div>
    <div id="split-ocr-output"></div>
  </div>
</div>
<div id="split-divider" style="display:none;"></div>

PART 3 — CSS (p44-ocr-viewer.css)
Add at the end of the file:
css/* ── Split panel layout ───────────────────────────────────────── */
#text-panel-body {
display: flex;
flex-direction: column;
overflow: hidden;
}

#split-pane {
display: none;
flex-direction: column;
flex: 1;
min-height: 0;
overflow: hidden;
}

#split-pane-header {
font-size: 9px;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--gold-dim);
padding: 5px 16px;
border-bottom: 1px solid var(--border);
flex-shrink: 0;
background: var(--surface);
}

#split-ocr-wrap {
display: flex;
flex: 1;
min-height: 0;
overflow-y: auto;
padding: 12px 0;
}

#split-line-numbers {
width: 48px;
flex-shrink: 0;
padding: 0 8px 0 12px;
text-align: right;
font-size: 11px;
line-height: 1.75;
color: var(--gold-dim);
font-family: 'Courier New', monospace;
user-select: none;
border-right: 1px solid var(--border);
margin-right: 12px;
}

#split-ocr-output {
flex: 1;
min-width: 0;
font-size: 12.5px;
line-height: 1.75;
color: var(--text);
white-space: pre-wrap;
font-family: 'Georgia', 'Times New Roman', serif;
padding-right: 16px;
}

#split-divider {
height: 4px;
background: var(--border);
flex-shrink: 0;
cursor: row-resize;
border-top: 1px solid var(--gold-dim);
border-bottom: 1px solid var(--gold-dim);
}

/* When split is active, text-output and editor-wrap each take half */
#text-panel-body.split-active #text-output,
#text-panel-body.split-active #editor-wrap {
flex: 1;
min-height: 0;
overflow-y: auto;
}

#text-panel-body.split-active {
display: flex;
flex-direction: column;
}

PART 4 — JS (p44-ocr-viewer.js)
4a — DOM refs
Add:
javascriptconst btnSplit        = document.getElementById('btn-split');
const splitPane       = document.getElementById('split-pane');
const splitDivider    = document.getElementById('split-divider');
const splitOcrOutput  = document.getElementById('split-ocr-output');
const splitLineNums   = document.getElementById('split-line-numbers');
4b — State flag
Add to the state object:
javascriptsplitMode: false,
4c — Line number generator for split pane
Add this new function above showOCRPage():
javascriptfunction buildSplitLineNumbers(text) {
const lines = (text || '').split('\n');
return lines.map((_, i) => i + 1).join('\n');
}
4d — showSplitPane(pageNum)
Add this new function:
javascriptfunction showSplitPane(pageNum) {
const corr         = state.corrections && state.corrections[pageNum];
const originalText = (corr && corr.original) || state.ocrPages[pageNum] || '';

splitOcrOutput.textContent  = originalText;
splitLineNums.textContent   = buildSplitLineNumbers(originalText);

splitPane.style.display      = 'flex';
splitDivider.style.display   = 'block';
textPanelBody.classList.add('split-active');
}
4e — hideSplitPane()
Add this new function:
javascriptfunction hideSplitPane() {
splitPane.style.display    = 'none';
splitDivider.style.display = 'none';
textPanelBody.classList.remove('split-active');
}
4f — toggleSplit()
Add this new function:
javascriptfunction toggleSplit() {
state.splitMode = !state.splitMode;
btnSplit.classList.toggle('active', state.splitMode);

if (state.splitMode) {
showSplitPane(state.currentPage);
} else {
hideSplitPane();
}
}
Add the event listener immediately after:
javascriptbtnSplit.addEventListener('click', toggleSplit);
4g — applyRole()
In applyRole(), in the pass2 branch add:
javascript  btnSplit.style.display = 'inline-block';
In the pass1 branch add:
javascript  btnSplit.style.display = 'none';
state.splitMode = false;
hideSplitPane();
4h — goToPage()
At the start of goToPage(), after if (state.editMode) exitEditMode();, add:
javascript  if (state.splitMode) showSplitPane(n);
This refreshes the split pane content for the new page without toggling it off.
4i — showOCRPage()
At the end of showOCRPage(), after updatePass2NavButtons(), add:
javascript  if (state.splitMode) showSplitPane(pageNum);

VERIFICATION CHECKLIST:

Pass 1 role: Split button not visible
Pass 2 role: Split button visible in panel header
Clicking Split in Pass 2: right panel splits into original OCR on top and editor on bottom, both with line numbers, both scroll independently
Clicking Split again: collapses back to single panel, editor fills full height
Navigating to a new page while split is on: both panes update to the new page's content, split stays on
Switching from Pass 2 to Pass 1 while split is on: split closes, button hides
Original OCR pane shows raw unedited text — not the Pass 1 corrected version
Line numbers visible in both panes and match the text lines
You said: Review this code.p44-ocr-viewer.jsjsp44-ocr-viewer.csscssp44-ocr-viewer.html140 lineshtmlReview this code. I have asked copilot numerous times to fix a bug but it cant figure it outThe text is not aligning properly or showing the wrong line breaks. this page is unedited, so the OCR and the editable text should look and behave the same exact way:2:24 p.m.Claude responded: Let me read the current files first.Let me read the current files first.Viewed 3 filesViewed 3 filesFound it. The bug is on line 602:
javascriptif (currentRole === 'pass2') {
if (!state.editMode) enterEditMode();
Pass 2 auto-enters edit mode on every showOCRPage() call. That means the split pane's top half is showing the original OCR in a read-only div, but the bottom half is the textarea — and the textarea uses a completely different rendering path (wrap measurement, line numbers calculated differently) than the read-only display div. They look different because they literally ARE different elements with different sizing, padding, and line-break behaviour.
The line number mismatch and text wrap differences you're seeing are all caused by this — the two panes are never showing text the same way.
Here's the Copilot fix:

P44 OCR Viewer — Fix split pane text rendering mismatch
Scope: p44-ocr-viewer.js only. Two targeted changes.
Fix 1 — Remove Pass 2 auto-edit on showOCRPage()
Find in showOCRPage() at the bottom:
javascript  if (currentRole === 'pass2') {
if (!state.editMode) enterEditMode();
updatePass2NavButtons();
if (state.splitMode) showSplitPane(pageNum);
}
Replace with:
javascript  if (currentRole === 'pass2') {
updatePass2NavButtons();
if (state.splitMode) showSplitPane(pageNum);
}
Fix 2 — Make split pane top use identical rendering to #text-output
Find in showSplitPane():
javascript  splitOcrOutput.textContent = originalText;
updateSplitLineNumbers(originalText);
Replace with:
javascript  splitOcrOutput.innerHTML =
'<pre style="white-space:pre-wrap;font-family:inherit;font-size:12.5px;' +
'line-height:1.75;color:var(--text);padding:16px 20px;">' +
escH(originalText) + '</pre>';
updateSplitLineNumbers(originalText);