...: Path) -> str:
    return p.read_text(encoding="utf-8", errors="replace")


def short(s: str, n: int = 500) -> str:
    s = (s or "").replace("\r\n", "\n")
    return s if len(s) <= n else s[:n] + " ...[cut]"


def safe_filename(s: str) -> str:
    bad = '<>:"/\\|?*'
    out = "".join("_" if c in bad else c for c in (s or ""))
    return out[:180] if len(out) > 180 else out


def head_tail(text: str...