# Python
__pycache__/
*.py[cod]
*$py.class
*.egg-info/
.eggs/
*.egg
build/
dist/
.Python

# Virtual environment
.venv/
venv/

# Environment & secrets
.env
.env.local
.env.*.local
.env.prod
.env.prod.local
.env.prod.bak
secrets/
*.p8
*.pem
*.key

# Django
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
media/
staticfiles/

# uv
# keep uv.lock committed; ignore caches
.uv/

# Testing / type-checking
.pytest_cache/
.mypy_cache/
.ruff_cache/
htmlcov/
.coverage
.coverage.*
coverage.xml

# Docker volumes (if ever bind-mounted locally)
postgres-data/

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

# age secrets: the broad `secrets/` rule above also matches deploy/secrets/,
# so re-include the two artifacts the pipeline needs committed (the encrypted
# blob + the public recipient key), then re-ignore the private identity.
# Order matters: negations first, private-key re-ignore last (last match wins).
!deploy/secrets/
!deploy/secrets/env.prod.age
!deploy/secrets/recipients.txt
deploy/secrets/age-key.txt
deploy/secrets/*.key

# MaxMind GeoLite2 DB — large binary, license-restricted; fetched via refresh_geolite
data/*.mmdb
