```ts
export function canHop(pond: string[], from: number[], to: number[]): boolean {
  if (!Array.isArray(pond) || pond.length !== 5 || !pond.every(row => typeof row === 'string' && row.length === 5)) {
    throw new Error('Invalid pond format');
  }

  const [fromRow, fromCol] = from;
  const [toRow, toCol] = to;

  if (typeof fromRow !== 'number' || typeof fromCol !== 'number' || typeof toRow !== 'number' || typeof toCol !== 'number') {
    throw new Error('Invalid square coordinates');
  }

  if (fromRow < 0 || fromRow > 4 || fromCol < 0 || fromCol > 4 || toRow < 0 || toRow > 4 || toCol < 0 || toCol > 4) {
    throw new Error('Square coordinates out of bounds');
  }

  const isWater = (row: number, col: number): boolean => pond[row][col] === '.';

  if (!isWater(toRow, toCol)) {
    return false;
  }

  // Step move
  if (
    (Math.abs(fromRow - toRow) === 1 && fromCol === toCol) ||
    (Math.abs(fromCol - toCol) === 1 && fromRow === toRow)
  ) {
    return true;
  }

  // Vault move
  const midRow = Math.floor((fromRow + toRow) / 2);
  const midCol = Math.floor((fromCol + toCol) / 2);

  if (
    (Math.abs(fromRow - toRow) === 2 && fromCol === toCol && isWater(midRow, midCol)) ||
    (Math.abs(fromCol - toCol) === 2 && fromRow === toRow && isWater(midRow, midCol)) ||
    (Math.abs(fromRow - toRow) === 2 && Math.abs(fromCol - toCol) === 2 && isWater(midRow, midCol))
  ) {
    return true;
  }

  return false;
}
```