Here's the refactored package structure with clean separation of concerns, proper type hints, and relative imports.

### `queue/__init__.py`
```python
"""
Job Queue Package

Provides a structured job queue system with FIFO and priority ordering,
along with built-in retry logic and exponential backoff.
"""

from .core import Job, JobQueue
from .priority import PriorityQueue
from .retry import process_with_retry

__all__ = ["Job", "JobQueue", "PriorityQueue", "process_with_retry"]
```

### `queue/core.py`
```python
"""
Core module: Job dataclass and basic FIFO queue operations.
"""

from dataclasses import dataclass
from typing import Any, Optional
from collections import deque


@dataclass
class Job:
    """Represents a unit of work to be processed."""
    id: str
    payload: Any
    status: str = "pending"
    attempts: int = 0
    max_retries: int = 3


class JobQueue:
    """Basic FIFO job queue with O(1) enqueue/dequeue operations."""

    def __init__(self) -> None:
        self._queue: deque[Job] = deque()
        self._index: dict[str, Job] = {}

    def enqueue(self, job: Job) -> None:
        """Add a job to the back of the queue."""
        self._queue.append(job)
        self._index[job.id] = job

    def dequeue(self) -> Optional[Job]:
        """Remove and return the job at the front of the queue."""
        if not self._queue:
            return None
        job = self._queue.popleft()
        self._index.pop(job.id, None)
        return job

    def remove(self, job_id: str) -> Optional[Job]:
        """Remove a specific job by ID. O(n) operation."""
        job = self._index.pop(job_id, None)
        if job:
            self._queue.remove(job)
        return job

    def __len__(self) -> int:
        return len(self._queue)

    def __contains__(self, job_id: str) -> bool:
        return job_id in self._index
```

### `queue/priority.py`
```python
"""
Priority queue module: Priority-based job ordering with lazy removal.
"""

import heapq
from typing import Any, Optional
from .core import Job


class PriorityQueue:
    """
    Priority queue implementation using a min-heap.
    Lower priority values are processed first.
    """

    def __init__(self) -> None:
        self._heap: list[tuple[int, int, Job]] = []
        self._index: dict[str, Job] = {}
        self._counter: int = 0
        self._removed: set[str] = set()

    def enqueue(self, job: Job, priority: int = 0) -> None:
        """
        Add a job with a given priority.
        Ties are broken by insertion order.
        """
        self._counter += 1
        heapq.heappush(self._heap, (priority, self._counter, job))
        self._index[job.id] = job

    def dequeue(self) -> Optional[Job]:
        """
        Remove and return the highest priority job.
        Uses lazy deletion to avoid O(n) heap operations.
        """
        while self._heap:
            priority, counter, job = heapq.heappop(self._heap)
            if job.id not in self._removed and job.id in self._index:
                self._index.pop(job.id, None)
                return job
        return None

    def remove(self, job_id: str) -> Optional[Job]:
        """Mark a job for removal. Actual cleanup happens on next dequeue."""
        if job_id in self._index:
            self._removed.add(job_id)
            return self._index.pop(job_id)
        return None

    def __len__(self) -> int:
        return len(self._index)

    def __contains__(self, job_id: str) -> bool:
        return job_id in self._index
```

### `queue/retry.py`
```python
"""
Retry module: Exponential backoff and retry logic for job processing.
"""

import time
from typing import Any, Callable, Optional
from .core import Job


def process_with_retry(
    job: Job,
    handler: Callable[[Job], Any],
    base_delay: float = 1.0,
    max_delay: float = 60.0,
    max_retries: Optional[int] = None,
) -> Any:
    """
    Execute a job handler with exponential backoff on failure.

    Args:
        job: The job to process.
        handler: Callable that accepts a Job and returns its result.
        base_delay: Initial delay in seconds between retries.
        max_delay: Maximum delay cap in seconds.
        max_retries: Overrides job.max_retries if provided.

    Returns:
        The result of the handler if successful.

    Raises:
        The last exception raised by the handler after all retries are exhausted.
    """
    attempts = max_retries if max_retries is not None else job.max_retries
    last_exception: Optional[BaseException] = None

    for attempt in range(attempts + 1):
        try:
            job.attempts = attempt + 1
            job.status = "processing"
            return handler(job)
        except Exception as e:
            last_exception = e
            if attempt == attempts:
                break

            # Exponential backoff with jitter cap
            delay = min(base_delay * (2 ** attempt), max_delay)
            time.sleep(delay)
            job.status = "retrying"

    job.status = "failed"
    if last_exception is not None:
        raise last_exception
    raise RuntimeError("Handler failed without raising an exception.")
```

### Key Refactoring Improvements:
1. **Single Responsibility**: Each file handles exactly one concern (data/queue, priority ordering, retry logic)
2. **Clean Public API**: `__init__.py` explicitly controls what users import, hiding internal helpers
3. **Modern Python**: Uses `dataclasses`, `collections.deque`, `heapq`, and modern type hints (`dict[str, Job]` instead of `typing.Dict`)
4. **Performance**: 
   - `JobQueue` uses `deque` for O(1) enqueue/dequeue
   - `PriorityQueue` uses lazy deletion to avoid O(n) heap removals
5. **Safety**: `process_with_retry` properly tracks attempts, caps backoff delays, and preserves exception chains