```python
def merge_markup(spans: list) -> list:
    if not all(isinstance(span, dict) for span in spans):
        raise ValueError("All elements must be dictionaries")
    
    for span in spans:
        if "start" not in span or "end" not in span or "tag" not in span:
            raise ValueError("Each dictionary must contain 'start', 'end', and 'tag'")
        
        start = span["start"]
        end = span["end"]
        tag = span["tag"]
        
        if not isinstance(start, int) or not isinstance(end, int):
            raise ValueError("Start and end must be integers")
        if start < 0:
            raise ValueError("Start must be non-negative")
        if start >= end:
            raise ValueError("Start must be strictly below its end")
        if not isinstance(tag, str) or len(tag) == 0:
            raise ValueError("Tag must be a non-empty string")
    
    spans = sorted(spans, key=lambda x: (x["start"], -x["end"]))
    merged = []
    
    for span in spans:
        if not merged or merged[-1]["tag"] != span["tag"] or merged[-1]["end"] < span["start"]:
            merged.append({"start": span["start"], "end": span["end"], "tag": span["tag"]})
        else:
            merged[-1]["end"] = max(merged[-1]["end"], span["end"])
    
    return [[span["start"], span["end"], span["tag"]] for span in merged]
```