#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
const ll mod = 998244353;

int n,m;
char f[12][12];
int rw[2][12],cl[2][12];
ll modpow(ll x,ll n){
	ll res=1;
	while(n>0){
		if(n&1) res=res*x%mod;
		x=x*x%mod;
		n>>=1;
	}
	return res;
}
ll F[55],R[55];
void make(){
	F[0] = 1;
	for(int i=1;i<55;i++) F[i] = F[i-1]*i%mod;
	for(int i=0;i<55;i++) R[i] = modpow(F[i],mod-2);
}
ll C(int a,int b){
	return F[a]*R[b]%mod*R[a-b]%mod;
}
ll D(int a,int b){
    if(a < b) return 0;
    ll ret = 0;
    for(int i=0;i<b;i++){
        ret += modpow(b-i,a) * C(b,i) % mod * (i%2==0?1:-1);
    }
    return ret%mod;
}
ll t[12][12];
ll s[12][12][12][12];
ll w[12][12];
ll dp[12][12][4][4];

ll rec(int a,int b,int c,int d){
	if(a == 0 || b == 0) return 1;
	if(dp[a][b][c][d] != -1) return dp[a][b][c][d];
	dp[a][b][c][d] = 0;
	//yoko
	//0
	if( (c&1) == 0 ){
		repn(x,a-1){
			dp[a][b][c][d] += rec(a-x,b,3,1) * C(a,x) % mod;
		}
	}
	//1
	if( (c&2) == 0 ){
		repn(x,a-1){
			dp[a][b][c][d] += rec(a-x,b,3,2) * C(a,x) % mod;
		}
	}
	//0 & 1
	if(c == 0){
		repn(x,a-1){
			repn(y,a-x){
				dp[a][b][c][d] += rec(a-x-y,b,3,0) * C(a,x) % mod * C(a-x,y) % mod;
			}
		}
	}
	//tate
	//0
	if( (d&1) == 0 ){
		repn(x,b-1){
			dp[a][b][c][d] += rec(a,b-x,1,3) * C(b,x) % mod;
		}
	}
	//1
	if( (d&2) == 0 ){
		repn(x,b-1){
			dp[a][b][c][d] += rec(a,b-x,2,3) * C(b,x) % mod;
		}
	}
	//0 & 1
	if(d == 0){
		repn(x,b-1){
			repn(y,b-x){
				dp[a][b][c][d] += rec(a,b-x-y,0,3) * C(b,x) % mod * C(b-x,y) % mod;
			}
		}
	}
	//yoko & tate
	//0
	if( (c&1) == 0 && (d&1) == 0 ){
		repn(x,a-1) repn(y,b-1){
			dp[a][b][c][d] += rec(a-x,b-y,1,1) * C(a,x) % mod * C(b,y) % mod;
		}
	}
	//1
	if( (c&2) == 0 && (d&2) == 0 ){
		repn(x,a-1) repn(y,b-1){
			dp[a][b][c][d] += rec(a-x,b-y,2,2) * C(a,x) % mod * C(b,y) % mod;
		}
	}
	//all
	if( (c&1) == 0 && (d&1) == 0 ) dp[a][b][c][d]++;
	if( (c&2) == 0 && (d&2) == 0 ) dp[a][b][c][d]++;
	dp[a][b][c][d] = (dp[a][b][c][d]%mod+mod)%mod;
	return dp[a][b][c][d];
}
void prepare(){
	rep(i,12) rep(j,12){
		if(i == 0 || j == 0){
			w[i][j] = 1;
			continue;
		}
		repn(x,24){
			int a = (x+2)/2;
			int b = (x+1)/2;
			//i,j
			if(i >= a && j >= b){
				w[i][j] += D(i,a) * D(j,b) % mod;
			}
			//j,i
			if(i >= b && j >= a){
				w[i][j] += D(i,b) * D(j,a) % mod;
			}
			w[i][j]%=mod;
		}
	}
	rep(a,11) rep(b,11) rep(c,11) rep(d,11){
		s[a][b][c][d] = w[b][c] * w[a][d] % mod;
	}
	rep(a,11) rep(b,11){
		//t[a][b]
		if(a >= n || b >= m) continue;
		rep(x,a+1) rep(y,b+1){
			t[a][b] += C(a,x) * C(b,y) % mod * s[x][a-x][y][b-y] % mod;
			t[a][b] %= mod;
		}
	}
	//t[n][m]
	t[n][m] = rec(n,m,0,0);
}
int main(){
	memset(dp,-1,sizeof(dp));
	make();
	scanf("%d%d",&n,&m);
	prepare();
	rep(i,n) scanf("%s",&f[i]);
	rep(i,n){
		rep(j,m){
			rw[(f[i][j]=='#')][i] |= (1<<j);
		}
	}
	rep(j,m){
		rep(i,n){
			cl[(f[i][j]=='#')][j] |= (1<<i);
		}
	}
	ll ans = t[n][m]; 
	//203949910
	rep(a,(1<<n)-1){
		rep(b,(1<<m)-1){
			bool bad = 0;
			rep(x,n){
				if(((a>>x)&1)) continue;
				int A = rw[0][x] & ((1<<m)-1-b);
				int B = rw[1][x] & ((1<<m)-1-b);
				if(A == 0 || B == 0) bad = 1;
			}
			rep(x,m){
				if(((b>>x)&1)) continue;
				int A = cl[0][x] & ((1<<n)-1-a);
				int B = cl[1][x] & ((1<<n)-1-a);
				if(A == 0 || B == 0) bad = 1;
			}
			if(bad) continue;
			int aa = __builtin_popcount(a);
			int bb = __builtin_popcount(b);
			ans += t[aa][bb];
		}
	}
	cout << (ans%mod+mod)%mod << endl;
}


Measured memory_bytes: 384