HARBOUR OFFICE / LOCAL REPORT HANDOVER
Scope: fictional September 2026 data, EUR, one row per campaign.
Owner role: the learner operating this local teaching project.
Start from extracted companion/javascript/j17:
  python server.py
Windows alternative: py server.py
Open http://127.0.0.1:8000/ . Stop with Ctrl+C.
If port 8000 is occupied: python server.py --port 8001
Use the URL printed by the server. Do not expose this teaching server publicly.

Automated checks from companion/javascript/j18:
  python run_checks.py
Node >=22 must already be installed. No npm install is needed.

Manual browser acceptance record (fill in date/browser/result):
[ ] All channels: 3 rows, EUR 620.00, 18 enquiries, EUR 34.44.
[ ] Email: 1 row, EUR 120.00, 6 enquiries, EUR 20.00.
[ ] Social: EUR 200.00, 0 enquiries, Not available.
[ ] Tab to select and button; operate with keyboard alone; focus visible.
[ ] At narrow width, controls remain usable and table can scroll.
[ ] Stop server after page loads, press Load: error replaces old report.
[ ] Restart server and press Load: report recovers.
[ ] Inspect Network: requests go to 127.0.0.1 only.

Triage:
No connection -> check terminal is still running and URL/port matches.
503 -> check database file exists and is readable; do not invent zero totals.
400 -> inspect requested filter in Network; use documented channel values.
Wrong totals -> compare API JSON and row sums before editing display code.
Console error -> record message, file/line, input, browser, expected/actual.

Recovery:
Keep a copy before changing files. Restore the last working source copy,
then rerun tests and manual acceptance. This app makes no database writes
through HTTP. It creates sample campaigns.sqlite only if missing at start.
To reset fictional sample data, stop the server, move campaigns.sqlite
out of j17 as a backup, then restart. Do this only for the lab dataset.

Limits:
Local teaching server only; no login, HTTPS, production deployment,
access-control system, data import pipeline or continuous monitoring.
No proof of marketing causality; attribution is a fictional definition.
No real people, passwords, accounts, payments or live campaign actions.
