#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cassert>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<queue>
#include<stack>
#include<list>
#include <cstring>
#include <functional>
#include<unordered_map>
#include<unordered_set>
#include<bitset>
using namespace std;
#define MOD 1000000007
#define MOD2 998244353
#define INF ((1<<30)-1)
#define LINF ((Int)1<<60)
#define EPS (1e-10)
#define REP(i,n) for(int i=0; i<(int)(n); ++i)
#define RREP(i,n) for(int i=1; i<=(int)(n); ++i)
typedef long long Int;
typedef pair<Int, Int> PI;
typedef pair<int, int> pi;
typedef tuple<int, int, int> TP;
typedef vector<double> vec;
typedef vector<vec> mat;
const int N = 201005;
//////////////////////////////

int n, m;
int x[100], y[100], z[100];
Int dp[1 << 18];

void solve()
{
	cin >> n >> m;
	REP(i, m) cin >> x[i] >> y[i] >> z[i];

	dp[0] = 1;
	REP(mask, (1 << n)) {
		REP(nxt, n) {
			if (((1 << nxt) & mask) != 0) continue;
			int comb = (1 << nxt) | mask;
			vector<int> nums;
			REP(i, n) {
				if ((comb & (1 << i))) {
					nums.push_back(i + 1);
				}
			}
			int flag = 1;
			REP(j, m) {
				if (x[j] != nums.size()) continue;
				int cnt = 0;
				for (int a : nums) {
					if (a <= y[j]) cnt++;
				}
				if (cnt > z[j]) {
					flag = 0;
					break;
				}
			}
			if (flag) {
				dp[comb] += dp[mask];
			}
		}
	}

	cout << dp[(1 << n) - 1] << endl;
}

int main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout << fixed << setprecision(13);
	solve();
	return 0;
}
#include "bits/stdc++.h"
#include <bits/stdc++.h>
using namespace std;
// #include <atcoder/all> 
// using namespace atcoder;
using ll = long long;


template <typename T>
void print_vec2(const vector<vector<T>>& v){
  cout << endl; cout << "       ";
  for(ll i=0; i<v[0].size(); i++) cout << i << "   "; 
  cout << endl;
	for(ll i=0; i<v.size(); i++){
		cout << "i=" << i << ":   ";
		for(ll j=0; j<v[i].size(); j++){
			if(v[i][j] == 0) cout << "\x1B[0m" << v[i][j] << "   ";
      else cout << "\x1B[31m" << v[i][j] << "   ";//https://stackoverrun.com/ja/q/12618775
		}
		cout << "\x1B[0m" << endl;
	}
}
// auto mod int
// https://youtu.be/L8grWxBlIZ4?t=9858
// https://youtu.be/ERZuLAxZffQ?t=4807 : optimize
// https://youtu.be/8uowVvQ_-Mo?t=1329 : division
const int mod = 1000000007;
// const int mod = 998244353;
struct mint {
  ll x; // typedef long long ll;
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod-a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;}
  mint operator+(const mint a) const { return mint(*this) += a;}
  mint operator-(const mint a) const { return mint(*this) -= a;}
  mint operator*(const mint a) const { return mint(*this) *= a;}
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(mod-2);}
  mint& operator/=(const mint a) { return *this *= a.inv();}
  mint operator/(const mint a) const { return mint(*this) /= a;}
};
istream& operator>>(istream& is, mint& a) { return is >> a.x;}
ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}
int main(){
  int H, W;
  cin >> H >> W;
  vector<string> S(H);
  for(int i=0; i<H; i++) cin >> S[i];

  vector<vector<mint>> dp(H+1, vector<mint>(W+1, 0));
  dp[0][0] = 1;
  vector<vector<mint>> tate=dp, yoko=dp, naname=dp;//累積和
  for(int i=0; i<H; i++){
    for(int j=0; j<W; j++){
      if(S[i][j]=='#') continue;
      
      
      //もらうDP??
      if(i==0 && j==0) continue;//初期化で計算済み
      if(i-1>=0) tate[i][j] += tate[i-1][j];
      if(j-1>=0) yoko[i][j] += yoko[i][j-1];
      if(i-1>=0 && j-1>=0) naname[i][j] += naname[i-1][j-1];
      dp[i][j] += tate[i][j];
      dp[i][j] += yoko[i][j];
      dp[i][j] += naname[i][j];
      tate[i][j] += dp[i][j];
      yoko[i][j] += dp[i][j];
      naname[i][j] += dp[i][j];

      //配るDP?? できない　順番がおかしい?
      // tate[i+1][j] += tate[i][j];
      // yoko[i][j+1] += yoko[i][j];
      // naname[i+1][j+1] += naname[i][j];
      // dp[i+1][j] += tate[i+1][j];
      // dp[i][j+1] += yoko[i][j+1];
      // dp[i+1][j+1] += naname[i+1][j+1];
      // tate[i+1][j] += dp[i+1][j];
      // yoko[i][j+1] += dp[i][j+1];
      // naname[i+1][j+1] += dp[i+1][j+1];


      // if(i-1>=0) dp[i][j] += tate[i-1][j];
      // if(j-1>=0) dp[i][j] += yoko[i][j-1];
      // if(i-1>=0 && j-1>=0) dp[i][j] += naname[i-1][j-1];
      // // if(i-1>=0) tate[i][j] = tate[i-1][j] + dp[i][j];
      // // if(j-1>=0) yoko[i][j] = yoko[i][j-1] + dp[i][j];
      // // if(i-1>=0 && j-1>=0) naname[i][j] = naname[i-1][j-1] + dp[i][j];
      // if(i-1>=0) tate[i][j] += tate[i-1][j] + dp[i][j];
      // if(j-1>=0) yoko[i][j] += yoko[i][j-1] + dp[i][j];
      // if(i-1>=0 && j-1>=0) naname[i][j] += naname[i-1][j-1] + dp[i][j];
      
    }
  }
  // cout << " tate: " << endl; print_vec2(tate);
  // cout << " yoko: " << endl; print_vec2(yoko);
  // cout << " naname: " << endl; print_vec2(naname);
  // cout << " dp: " << endl; print_vec2(dp);
  cout << dp[H-1][W-1] << endl;
  return 0;
  
  // cout << fixed;//小数点を確実に10桁で表示するためのもの
  // cout << setprecision(10); 
}