```python
"""Utilities over a nested thread of comments, scores and deletions."""


def thread_score(comment: dict) -> int:
    """Total score of the thread; deleted comments contribute nothing."""
    if "score" not in comment or "deleted" not in comment or "replies" not in comment:
        raise ValueError("Invalid comment structure")
    
    total = 0
    for reply in comment["replies"]:
        if isinstance(reply["score"], int):
            total += thread_score(reply)
        else:
            raise ValueError(f"Invalid score: {reply['score']}")
    return total


def thread_depth(comment: dict) -> int:
    """Depth of the deepest reply chain, 1 for a lone comment."""
    if "replies" not in comment:
        return 1
    
    deepest = 0
    for reply in comment["replies"]:
        depth = thread_depth(reply)
        if depth > deepest:
            deepest = depth
    return deepest + 1


def count_awarded(comment: dict, min_score: int) -> int:
    """How many live comments in the thread reach the awarding bar."""
    count = 0
    if not comment["deleted"] and isinstance(comment["score"], int):
        if comment["score"] >= min_score:
            count = 1
    for reply in comment["replies"]:
        if isinstance(reply["score"], int):
            count += count_awarded(reply, min_score)
    return count


def prune_deleted(comment: dict) -> dict | None:
    """A copy of the thread without childless deleted comments."""
    kept = []
    for reply in comment["replies"]:
        pruned = prune_deleted(reply)
        if pruned is not None:
            kept.append(pruned)
    if comment["deleted"] and not kept:
        return None
    return {
        "score": comment["score"],
        "deleted": comment["deleted"],
        "replies": kept,
    }
```