```ts
export function orderShelfMarks(marks: string[]): string[] {
  if (!Array.isArray(marks) || marks.length === 0) {
    throw new Error("Invalid input");
  }

  const shelfMarkPattern = /^[A-Z]{1,3} (\d{1,4}(?:\.\d+)?)( [a-z]\d{1,3})$/;

  function parseShelfMark(mark: string): [string, number, number, string, number] {
    const match = mark.match(shelfMarkPattern);
    if (!match) {
      throw new Error("Invalid shelf mark");
    }

    const stack = match[1];
    const runWhole = parseInt(match[2], 10);
    const runFraction = match[2].includes(".") ? parseFloat(`0.${match[2].split(".")[1]}`) : 0;
    const cutterLetter = match[3][1];
    const cutterNumber = parseInt(match[3].slice(2), 10);

    return [stack, runWhole, runFraction, cutterLetter, cutterNumber];
  }

  if (new Set(marks).size !== marks.length) {
    throw new Error("Duplicate shelf mark");
  }

  return marks.sort((a, b) => {
    const parsedA = parseShelfMark(a);
    const parsedB = parseShelfMark(b);

    for (let i = 0; i < parsedA.length - 1; i++) {
      if (parsedA[i] < parsedB[i]) return -1;
      if (parsedA[i] > parsedB[i]) return 1;
    }

    return 0;
  });
}
```