```ts
export function stepAccrualLedger(opening: number, steps: number[][]): number[][] {
  if (steps.length === 0) throw new Error("Empty schedule");
  if (!Array.isArray(steps)) throw new Error("Schedule must be a list");
  if (opening < 0) throw new Error("Opening balance below zero");

  const result: number[][] = [];
  let principal = opening;
  let heap = 0;
  let leftover = 0;

  for (const step of steps) {
    if (!Array.isArray(step) || step.length !== 3) throw new Error("Step must be a list of exactly three values");
    const [dayCount, tenThousandths, capitalise] = step;
    if (!Number.isInteger(dayCount) || dayCount < 1) throw new Error("Day count must be a whole number greater than zero");
    if (!Number.isInteger(tenThousandths) || tenThousandths < 0) throw new Error("Rate must be a whole number");
    if (capitalise !== 0 && capitalise !== 1) throw new Error("Capitalise must be either 0 or 1");

    const earnings = ((principal * tenThousandths * dayCount + leftover) / 3650000) | 0;
    leftover = ((principal * tenThousandths * dayCount + leftover) % 3650000) / 10000;

    if (capitalise === 1) {
      principal += earnings;
    } else {
      heap += earnings;
    }

    result.push([earnings, principal, heap]);
  }

  return result;
}
```