```python
"""Drain labelled items across planned lanes, round by round."""


def drain_lanes(plan: list, items: list) -> dict:
    """Drain items from lanes according to the plan, returning order and round count."""
    if not plan:
        raise ValueError("Plan cannot be empty")

    queues = {}
    seen_lanes = set()
    for entry in plan:
        if not isinstance(entry, (list, tuple)) or len(entry) != 2:
            raise ValueError("Each plan entry must be a pair (lane, quota)")
        lane, quota = entry
        if not isinstance(lane, str) or not lane:
            raise ValueError("Lane must be a non-empty string")
        if not isinstance(quota, int) or quota <= 0:
            raise ValueError("Quota must be a positive integer")
        if lane in seen_lanes:
            raise ValueError(f"Duplicate lane in plan: {lane}")
        seen_lanes.add(lane)
        queues[lane] = []

    for item in items:
        if not isinstance(item, (list, tuple)) or len(item) != 2:
            raise ValueError("Each item must be a pair (label, lane)")
        label, lane = item
        if not isinstance(label, str) or not isinstance(lane, str):
            raise ValueError("Item label and lane must be strings")
        if lane not in queues:
            raise ValueError(f"Unknown lane in item: {lane}")
        queues[lane].append(label)

    order = []
    rounds = 0
    while any(queues[lane] for lane in queues):
        rounds += 1
        for lane, quota in plan:
            queue = queues[lane]
            taken = 0
            while taken < quota and queue:
                order.append(queue.pop(0))
                taken += 1
            # If taken < quota, simply move on to the next lane (do not return)

    return {"order": order, "rounds": rounds}
```