```ts
/**
 * Parses a span text into total inches.
 */
export function parseSpan(text: string): number {
  if (typeof text !== 'string' || text.trim() === '') {
    throw new Error('Invalid input');
  }

  const parts = text.trim().split(/\s+/);
  let inches = 0;
  const unitsSeen = new Set<string>();

  for (const part of parts) {
    const match = /^(\d+)\s*(yd|ft|in)?$/i.exec(part);
    if (!match) {
      throw new Error('Invalid input');
    }

    const value = parseInt(match[1], 10);
    if (isNaN(value)) {
      throw new Error('Invalid input');
    }

    if (value < 0 || match[1].startsWith('0')) {
      throw new Error('Invalid input');
    }

    const unit = match[2]?.toLowerCase();
    if (!unit) continue;

    if (unitsSeen.has(unit)) {
      throw new Error('Invalid input');
    }
    unitsSeen.add(unit);

    switch (unit) {
      case 'yd':
        inches += value * 36;
        break;
      case 'ft':
        inches += value * 12;
        break;
      case 'in':
        inches += value;
        break;
      default:
        throw new Error('Invalid input');
    }
  }

  return inches;
}

/**
 * Renders a non-negative integer of total inches canonically.
 */
export function formatSpan(inches: number): string {
  if (typeof inches !== 'number' || inches < 0 || !Number.isInteger(inches)) {
    throw new Error('Invalid input');
  }

  let result = '';
  const yards = Math.floor(inches / 36);
  inches %= 36;
  const feet = Math.floor(inches / 12);
  inches %= 12;

  if (yards > 0) {
    result += `${yards}yd `;
  }
  if (feet > 0) {
    result += `${feet}ft `;
  }

  if (inches > 0) {
    result += `${inches}in`;
  } else {
    result = '0in';
  }

  return result.trim();
}

/**
 * Takes two span texts and returns their sum in that canonical form.
 */
export function addSpans(first: string, second: string): string {
  const totalInches = parseSpan(first) + parseSpan(second);
  return formatSpan(totalInches);
}
```