# Python
__pycache__/
*.py[cod]
*.egg-info/
build/
dist/
.venv/
.mypy_cache/
.ruff_cache/
.pytest_cache/
.coverage
htmlcov/

# Secrets and per-installation state. A profile's baton.yaml is meant to be
# committed (to a *private* repo); the credentials beside it never are.
.env
*.env
!.env.example
secrets/
state/
data/
*.db

# Only the sample profile is public. Even with credentials externalized to
# env vars, a real profile's yaml still carries real learner names (contact
# aliases) and real page references — it belongs to the private overlay,
# never to this public repo.
profiles/*
!profiles/example/

# Editor / OS
.DS_Store
*.swp
.idea/
.vscode/

# Never commit these: they are what made the original workspace impossible to
# open-source without a scrubbing pass.
*.bak
*.bak.*
*.orig
tmp/

# Sidecar lock files from the atomic-write layer. They are transient and
# occasionally survive a killed process; they must never be committed.
*.lock

# Local-only review workspace. This repo is public; the review notes track
# known defects before they are fixed and stay on the machine.
/review/

# Screenshots dropped at the repo root by browser-driven sessions, and the
# Playwright MCP scratch directory that produces them. Nothing here is a
# project asset; a real doc image would live under docs/ and stay tracked.
.playwright-mcp/
/*.png
