#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cstring>
#include <queue>

using namespace std;

#define rep(i, n) for(int i = 0; i < (n); i++)
#define MP make_pair
#define X first
#define Y second

typedef pair<int, int> P;

const int h = 12;
const int w = 6;
char field[h][w];
bool check[h][w];

int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
bool erase(){
	bool ret = false;
	memset(check, 0, sizeof(check));
	rep(i, h){
		rep(j, w){
			if(check[i][j]) continue;
			char c = field[i][j];
			if(c == 'O' || c == '.') continue;
			queue<P> q;
			q.push(MP(j, i));
			vector<P> bye;
			int cnt = 0;
			while(!q.empty()){
				P p = q.front();
				q.pop();

				if(check[p.Y][p.X]) continue;
				check[p.Y][p.X] = true;
				bye.push_back(p);
				cnt++;
				rep(i, 4){
					int nx = p.X + dx[i], ny = p.Y + dy[i];
					if(nx < 0 || nx >= w || ny < 0 || ny >= h) continue;
					if(field[ny][nx] == 'O') bye.push_back(MP(nx, ny));
					if(field[ny][nx] == c) q.push(MP(nx, ny));
				}
			}
			if(cnt >= 4){
				rep(k, bye.size()){
					field[bye[k].Y][bye[k].X] = '.';
				}
				ret = true;
			}
		}
	}
	return ret;
}

void drop(){
	char next[h][w];
	rep(i, h) rep(j, w) next[i][j] = '.';
	rep(i, h){
		rep(j, w){
			if(field[i][j] != '.'){
				int y = i;
				int height = h-1;
				while(++y<h){
					if(field[y][j] != '.') height--;
				}
				next[height][j] = field[i][j];
			}
		}
	}
	memcpy(field, next, sizeof(field));
	//rep(i, h){
	//	rep(j, w) cout << field[i][j];
	//	cout << endl;
	//}
	//cout << endl;
}

int main(){
	int T;
	cin >> T;
	while(T--){
		rep(i, h) rep(j, w) cin >> field[i][j];
		int ans = 0;
		while(erase()){
			ans++;
			drop();
		}
		cout << ans << endl;
	}

	return 0;
}