P44 OCR Viewer — War diary landing page (p44-landing.html) Create a new standalone file p44-landing.html in the same directory as p44-ocr-viewer.html. Served by launch_viewer.py on the same localhost server. No frameworks, vanilla JS only. PART 1 — Data config At the top of the script, define the three war diaries as a static array. Progress is calculated from localStorage keys written by the viewer: javascriptconst DIARIES = [ { id: 'calgary-highlanders', title: 'Calgary Highlanders', subtitle: 'War Diary — September 1944', tags: ['Infantry', 'Sep 1944', '343 pages'], totalPages: 343, viewerUrl: 'p44-ocr-viewer.html', flagsKey: 'p44-flags', pass2FlagsKey: 'p44-pass2-flags', }, { id: 'black-watch', title: 'Black Watch (RHR) of Canada', subtitle: 'War Diary — September 1944', tags: ['Infantry', 'Sep 1944', '211 pages'], totalPages: 211, viewerUrl: 'p44-ocr-viewer.html', flagsKey: 'p44-flags', pass2FlagsKey: 'p44-pass2-flags', }, { id: '5cib', title: '5th Canadian Infantry Brigade', subtitle: 'War Diary — September 1944', tags: ['Brigade HQ', 'Sep 1944', '178 pages'], totalPages: 178, viewerUrl: 'p44-ocr-viewer.html', flagsKey: 'p44-flags', pass2FlagsKey: 'p44-pass2-flags', }, ]; Note: All three diaries currently share the same localStorage keys since the viewer only supports one diary at a time. This is a known limitation — flagsKey and pass2FlagsKey are included in the config so they're easy to make per-diary later when the server handles multiple diaries. PART 2 — Progress calculation javascriptfunction getProgress(diary) { let pass1Done = 0, pass2Done = 0; try { const flags = JSON.parse(localStorage.getItem(diary.flagsKey) || '{}'); pass1Done = Object.values(flags).filter(f => f === 'done').length; } catch (_) {} try { const pass2Flags = JSON.parse(localStorage.getItem(diary.pass2FlagsKey) || '{}'); pass2Done = Object.values(pass2Flags).filter(f => f === 'done').length; } catch (_) {} return { pass1Pct: Math.round((pass1Done / diary.totalPages) * 100), pass2Pct: Math.round((pass2Done / diary.totalPages) * 100), pass1Done, pass2Done, }; } PART 3 — Role detection javascriptfunction getCurrentRole() { return localStorage.getItem('p44-role') || 'pass1'; } PART 4 — Card renderer javascriptfunction renderCard(diary) { const role = getCurrentRole(); const prog = getProgress(diary); const pass1Complete = prog.pass1Pct === 100; const isViewOnly = role === 'pass1' && pass1Complete; const tagHtml = diary.tags.map(t => '' + t + '' ).join(''); const actionBtn = isViewOnly ? '' : ''; return `