"""Build a portable event-preparation worksheet with Python's standard library."""
import html
import json
from pathlib import Path

ROOT = Path(__file__).resolve().parent
data = json.loads((ROOT / "worksheet.json").read_text(encoding="utf-8"))
esc = html.escape
sections = []
for index, step in enumerate(data["steps"]):
    fields = []
    for field in step["fields"]:
        fid = field["id"]
        hint = field.get("hint", "")
        description = f' aria-describedby="{fid}-hint"' if hint else ""
        if field.get("type") == "select":
            options = "".join(f'<option>{esc(option)}</option>' for option in data["classification"])
            control = f'<select id="{fid}" name="{fid}"{description}>{options}</select>'
        else:
            control = f'<textarea id="{fid}" name="{fid}" rows="2" placeholder="Unknown" autocomplete="off" spellcheck="true"{description}></textarea>'
        helper = f'<span class="hint" id="{fid}-hint">{esc(hint)}</span>' if hint else ""
        fields.append(f'<div class="field {"wide" if field.get("wide") else ""}"><label for="{fid}">{esc(field["label"])}</label>{helper}{control}<div class="printed-entry" data-for="{fid}">Unknown</div></div>')
    sections.append(f'<section class="step" aria-labelledby="step-{index}" data-step="{index}"><h2 id="step-{index}" tabindex="-1"><span>{index + 1:02}</span> {esc(step["title"])}</h2><p class="prompt">{esc(step["prompt"])}</p><div class="fields">{"".join(fields)}</div></section>')

css = """
*{box-sizing:border-box}html{color-scheme:light}body{margin:0;background:#f0f4f3;color:#182c28;font:16px/1.5 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}.sheet{max-width:900px;margin:24px auto;padding:32px 40px;background:white;border:1px solid #d0dfda;border-radius:18px}h1{font-size:clamp(1.6rem,5vw,2.1rem);line-height:1.15;margin:8px 0 14px;letter-spacing:-.035em}.eyebrow{font-size:.75rem;font-weight:750;text-transform:uppercase;letter-spacing:.12em;color:#306856;margin:0}.intro{max-width:68ch;margin:0 0 12px}.privacy{font-size:.85rem;color:#4d645d;margin:0}.toolbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:18px 0;border-bottom:1px solid #d0dfda}.toolbar[hidden]{display:none}.status{font-size:.875rem;flex:1 1 100%;color:#46635a}button{font:inherit;font-size:.9rem;min-height:44px;padding:8px 15px;background:#f1f6f4;border:1px solid #96b4a8;border-radius:7px;color:#163d2f;cursor:pointer}button.primary{background:#174e3a;color:white;border-color:#174e3a}button:disabled{opacity:.48;cursor:default}button:focus-visible,textarea:focus-visible,select:focus-visible{outline:3px solid #765200;outline-offset:3px}.step{padding:24px 0;border-bottom:1px solid #d0dfda}.step[hidden]{display:none}h2{font-size:1.15rem;line-height:1.35;margin:0 0 5px;letter-spacing:-.015em}h2 span{display:inline-block;color:#2f7158;background:#edf5f1;border-radius:5px;padding:3px 7px;margin-right:6px;font-size:.9rem;font-variant-numeric:tabular-nums}.prompt{font-size:.875rem;color:#4d645d;margin:0 0 16px}.fields{display:grid;grid-template-columns:1fr 1fr;gap:14px 20px}.field{min-width:0}.wide{grid-column:1/-1}label{display:block;font-size:.875rem;font-weight:650;margin-bottom:4px}.hint{display:block;color:#50695f;font-size:.8rem;margin:0 0 5px}textarea,select{display:block;font:inherit;font-size:.9rem;line-height:1.4;background:#fbfdfc;border:1px solid #aac0b6;border-radius:6px;width:100%;padding:9px 10px;min-height:44px;color:#182c28}textarea{resize:vertical;min-height:66px}textarea::placeholder{color:#667d74;opacity:1}select{height:44px}.printed-entry{display:none}footer{font-size:.8rem;color:#50695f;padding-top:20px}footer p{margin:0}noscript p{font-size:.85rem;background:#edf5f1;padding:10px;border-radius:6px}@media(max-width:550px){body{background:white}.sheet{margin:0;padding:24px 18px;border:0;border-radius:0}.fields{grid-template-columns:1fr}.wide{grid-column:auto}.toolbar button{flex:1 1 auto}}@page{size:A4;margin:13mm}@media print{body{background:white;color:#111;font-size:10pt}.sheet{max-width:none;border:0;border-radius:0;margin:0;padding:0}h1{font-size:20pt;margin-bottom:8px}.eyebrow{font-size:8pt}.intro{font-size:10pt}.privacy{font-size:8pt}.toolbar,noscript,textarea,select{display:none!important}.step,.step[hidden]{display:block!important;padding:13px 0;break-inside:avoid}.step[data-step="2"]{break-before:page}h2{font-size:12pt}.prompt{font-size:9pt;margin-bottom:9px}.fields{gap:9px 16px}label{font-size:9pt}.hint{font-size:8pt;color:#333}.printed-entry{display:block;white-space:pre-wrap;overflow-wrap:anywhere;min-height:48px;border-bottom:1px solid #a4afa9;padding:3px 0;font-size:9pt}footer{font-size:8pt;padding-top:10px}.no-js .printed-entry{display:none}.no-js textarea,.no-js select{display:block!important;border:0;border-bottom:1px solid #a4afa9;padding:3px 0;background:white;font-size:9pt;min-height:35px;height:40px}.no-js select{height:30px}}
"""
script = """
(() => {
  'use strict';
  document.documentElement.classList.remove('no-js');
  const form = document.querySelector('#profile');
  const steps = Array.from(document.querySelectorAll('.step'));
  const toolbar = document.querySelector('.toolbar');
  const status = document.querySelector('#step-status');
  let current = 0;
  let all = true;
  const previous = document.querySelector('#previous');
  const next = document.querySelector('#next');
  const showAll = document.querySelector('#show-all');
  function render(focus) {
    steps.forEach((step, i) => { step.hidden = !all && i !== current; });
    status.textContent = all ? 'All 4 steps shown' : `Step ${current + 1} of 4`;
    previous.disabled = all || current === 0;
    next.disabled = !all && current === steps.length - 1;
    next.textContent = all ? 'Start walkthrough' : 'Next';
    showAll.textContent = all ? 'One step at a time' : 'Show all steps';
    if (focus) steps[current].querySelector('h2').focus();
  }
  function syncPrint() {
    form.querySelectorAll('.printed-entry').forEach(output => {
      output.textContent = document.getElementById(output.dataset.for).value.trim() || 'Unknown';
    });
  }
  previous.addEventListener('click', () => { current = all ? 0 : Math.max(0, current - 1); all = false; render(true); });
  next.addEventListener('click', () => { current = all ? 0 : Math.min(steps.length - 1, current + 1); all = false; render(true); });
  showAll.addEventListener('click', () => { all = !all; render(!all); });
  document.querySelector('#reset').addEventListener('click', () => { form.reset(); current = 0; all = true; syncPrint(); render(false); });
  document.querySelector('#print').addEventListener('click', () => { syncPrint(); window.print(); });
  form.addEventListener('input', syncPrint);
  form.addEventListener('change', syncPrint);
  form.addEventListener('submit', event => event.preventDefault());
  window.addEventListener('beforeprint', syncPrint);
  window.addEventListener('pageshow', () => { form.reset(); syncPrint(); });
  toolbar.hidden = false;
  syncPrint(); render(false);
})();
"""
page = f'''<!doctype html>
<html lang="en" class="no-js"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="An offline preparation worksheet for one exact poker event’s clock rules."><title>{esc(data["title"])}</title><style>{css}</style></head>
<body><main class="sheet"><header><p class="eyebrow">GTO Gecko · Event preparation worksheet</p><h1>{esc(data["title"])}</h1><p class="intro">{esc(data["description"])}</p><p class="privacy">This worksheet does not store your entries. Print to keep a copy. With JavaScript, reload or Reset clears the page.</p></header>
<nav class="toolbar" aria-label="Worksheet controls" hidden><span class="status" id="step-status" role="status" aria-live="polite">All 4 steps shown</span><button type="button" id="previous">Previous</button><button type="button" id="next">Next</button><button type="button" id="show-all">One step at a time</button><button type="button" id="reset">Reset</button><button type="button" id="print" class="primary">Print / save PDF</button></nav>
<noscript><p>All four steps are available below. Use your browser’s print command for a copy. Without JavaScript, form restoration and printing depend on your browser; use short entries or print a blank worksheet.</p></noscript><form id="profile" autocomplete="off">{"".join(sections)}</form><footer><p>Original preparation worksheet. Unknown fields are open questions for the event staff. This page does not run a clock or decide a ruling. Created September 29, 2026.</p></footer></main><script>{script}</script></body></html>'''
(ROOT / "worksheet.html").write_text(page, encoding="utf-8", newline="\n")
print("Built worksheet.html")
