(() => { const key='rugby-dispatch-match-notebook-v1'; const byId=id=>document.getElementById(id); let state={title:'',source:'',notes:[]}; let storageError=false; try { const saved=JSON.parse(localStorage.getItem(key)||'null'); if(saved && typeof saved.title==='string' && typeof saved.source==='string' && Array.isArray(saved.notes) && saved.notes.every(n=>['clock','area','observation','interpretation'].every(k=>typeof n[k]==='string'))) state=saved; } catch { storageError=true; } function save(){ try {localStorage.setItem(key,JSON.stringify(state));storageError=false;}catch{storageError=true;} byId('save-status').textContent=storageError?'Browser storage is unavailable. Export your notes before leaving this page.':'Saved in this browser only.'; } function text(tag,value){const el=document.createElement(tag);el.textContent=value;return el;} function render(){ byId('notes-list').replaceChildren(); byId('note-count').textContent=state.notes.length?`${state.notes.length} ${state.notes.length===1?'observation':'observations'} — your sample, not a full-match statistic.`:'No observations yet. Add your first sequence above.'; state.notes.forEach((note,index)=>{ const article=document.createElement('article');article.className='notebook-entry'; article.append(text('h3',`${note.clock} · ${note.area}`),text('p',`Observed: ${note.observation}`)); if(note.interpretation)article.append(text('p',`Interpretation / question: ${note.interpretation}`)); const remove=text('button','Remove note');remove.type='button';remove.setAttribute('aria-label',`Remove note ${index+1} at ${note.clock}`); remove.addEventListener('click',()=>{state.notes.splice(index,1);save();render();});article.append(remove);byId('notes-list').append(article); }); } byId('match-title').value=state.title;byId('match-source').value=state.source; for(const [id,field] of [['match-title','title'],['match-source','source']])byId(id).addEventListener('input',e=>{state[field]=e.target.value;save();}); byId('note-form').addEventListener('submit',e=>{ e.preventDefault();const data=new FormData(e.target);const note=Object.fromEntries(['clock','area','observation','interpretation'].map(k=>[k,String(data.get(k)||'').trim()])); if(!note.clock || !note.observation)return; state.notes.push(note);save();render();e.target.reset();e.target.elements.clock.focus(); }); byId('clear-notes').addEventListener('click',()=>{ if(!confirm('Clear this notebook? Export first if you want to keep a copy.'))return; byId('export-preview').hidden=true;byId('export-text').value='';state={title:'',source:'',notes:[]};byId('match-title').value='';byId('match-source').value='';save();render(); }); byId('export-notes').addEventListener('click',()=>{ const content=['Rugby Dispatch — personal match notebook',state.title,state.source,'These are personal observations, not official match statistics.','',...state.notes.map(n=>`${n.clock} | ${n.area}\nObserved: ${n.observation}\nInterpretation / question: ${n.interpretation}\n`) ].join('\n'); byId('export-text').value=content;byId('export-preview').hidden=false;byId('export-preview').open=true; const url=URL.createObjectURL(new Blob([content],{type:'text/plain;charset=utf-8'}));const a=document.createElement('a');a.href=url;a.download='rugby-match-notes.txt';a.click();setTimeout(()=>URL.revokeObjectURL(url),1000); }); render();byId('save-status').textContent=storageError?'Existing notes could not be read. Export any new notes before leaving.':'Your notes stay on this device.'; })();