def retry_delay(attempt: int, base: float = 0.5, cap: float = 30.0, jitter: float = 0.0) -> float:
    if attempt < 1:
        raise ValueError("attempt must be >= 1")
    if base <= 0 or cap <= 0:
        raise ValueError("base and cap must be positive")
    if not 0.0 <= jitter < 1.0:
        raise ValueError("jitter must be in [0, 1)")
    delay = min(cap, base * 2 ** (attempt - 1))
    return delay * (1 - jitter)
