```ts
export function nameStepDistances(steps: any[]): { names: string[], lifts: number[], colours: string[], tally: Record<string, number>, widest: number } {
    if (!Array.isArray(steps) || steps.length === 0) {
        throw new Error("Input must be a non-empty list of steps.");
    }

    const stepNames = ["unison", "minor second", "major second", "minor third", "major third", "perfect fourth", "tritone", "perfect fifth", "minor sixth", "major sixth", "minor seventh", "major seventh"];
    const sweetLeftovers = new Set([0, 3, 4, 5, 7, 8, 9]);
    const sharpLeftovers = new Set([1, 2, 6, 10, 11]);

    const names: string[] = [];
    const lifts: number[] = [];
    const colours: string[] = [];
    const tally: Record<string, number> = {};
    let widestReach = -Infinity;
    let widestIndex = -1;

    for (let i = 0; i < steps.length; i++) {
        if (!Array.isArray(steps[i]) || steps[i].length !== 2) {
            throw new Error("Each step must be a list of exactly two pitch marks.");
        }

        const [mark1, mark2] = steps[i];
        if (typeof mark1 !== "number" || typeof mark2 !== "number" || !Number.isInteger(mark1) || !Number.isInteger(mark2)) {
            throw new Error("Each pitch mark must be a whole number.");
        }

        const reach = Math.abs(mark1 - mark2);
        const lift = Math.floor(reach / 12);
        const leftover = reach % 12;
        const name = stepNames[leftover];
        const colour = sweetLeftovers.has(leftover) ? "sweet" : sharpLeftovers.has(leftover) ? "sharp" : "";

        names.push(name);
        lifts.push(lift);
        colours.push(colour);

        tally[name] = (tally[name] || 0) + 1;

        if (reach > widestReach) {
            widestReach = reach;
            widestIndex = i;
        }
    }

    return { names, lifts, colours, tally, widest: widestIndex };
}
```