```
/** Tape-measure spans: parse to inches, format canonically, and add. */

const INCHES: Record<string, number> = { yd: 36, ft: 12, in: 1 };
const ORDER = ["yd", "ft", "in"];

export function parseSpan(text: string): number {
  if (typeof text !== 'string' || text.trim() === '') {
    throw new Error('Invalid span text');
  }

  const parts = text.split(/\s+/).map(part => part.replace(/in$/, ''));
  const unitMap = { yd: 36, ft: 12 };

  if (parts.some(part => !unitMap[part])) {
    throw new Error('Unknown unit');
  }

  if (parts.length < 2 || parts.some((part, i) => i > 0 && part === '')) {
    throw new Error('Invalid span format');
  }

  const validParts = parts.filter(part => part !== '');
  const values: number[] = validParts.map(Number);
  const units = validParts.map(unit => unitMap[unit]);

  if (units.some((unit, i) => i > 0 && unit <= units[i - 1])) {
    throw new Error('Units must be in ascending order');
  }

  return values.reduce((acc, value, index) => acc + value * units[index], 0);
}

export function formatSpan(inches: number): string {
  if (!Number.isInteger(inches) || inches < 0) {
    throw new Error('inches must be a non-negative integer');
  }
  if (inches === 0) {
    return "0in";
  }

  const parts = [];
  const yards = Math.floor(inches / 36);
  const feet = Math.floor((inches % 36) / 12);
  const rest = inches % 12;

  if (yards > 0) {
    parts.push(`${yards}yd`);
  }
  if (feet > 0) {
    parts.push(`${feet}ft`);
  }
  if (rest > 0) {
    parts.push(`${rest}in`);
  }

  return parts.join(" ");
}

export function addSpans(first: string, second: string): string {
  const total = parseSpan(first) + parseSpan(second);
  return formatSpan(total);
}
```