#include <bits/stdc++.h>
const long long INF = (long long)1e18 + 123;
const int inf = (int)2e9 + 123;
const int mod = 1e9 + 7;
using namespace std;
struct pok {
  int old, nw, cnt, id;
  pok() {
    old = cnt = 0;
    id = nw = 0;
  }
  pok(int a, int b, int c, int d) {
    old = a;
    nw = b;
    cnt = c;
    id = d;
  }
};
int n, m;
vector<int> g[500011];
int d[5000011];
vector<pok> v;
int f[5000011], col[5000011];
bool cmp(pok x, pok y) {
  if (x.old != y.old) return x.old < y.old;
  if (x.cnt != y.cnt) return x.cnt < y.cnt;
  if (x.nw != y.nw) return x.nw < y.nw;
  return x.id < y.id;
}
int size = 0;
long long fact[5000011];
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    v.clear();
    int k;
    cin >> k;
    for (int j = 1; j <= k; j++) {
      int x;
      cin >> x;
      f[x]++;
      g[i].push_back(x);
    }
    for (int j = 0; j < k; j++) {
      if (f[g[i][j]] > 0) {
        v.push_back(pok(d[g[i][j]], 0, f[g[i][j]], g[i][j]));
        f[g[i][j]] = 0;
      }
    }
    sort(v.begin(), v.end(), &cmp);
    v[0].nw = ++size;
    for (int j = 1; j < v.size(); j++) {
      if (v[j].old == v[j - 1].old) {
        if (v[j].cnt != v[j - 1].cnt)
          v[j].nw = ++size;
        else
          v[j].nw = v[j - 1].nw;
      }
      if (!v[j].nw) v[j].nw = ++size;
    }
    for (int j = 0; j < v.size(); j++) d[v[j].id] = v[j].nw;
  }
  for (int i = 1; i <= m; i++) {
    col[d[i]]++;
  }
  fact[0] = fact[1] = 1;
  for (int i = 2; i <= 1000000; i++) {
    fact[i] = (fact[i - 1] * i) % mod;
  }
  long long ans = 1;
  for (int i = 0; i <= size; i++) {
    ans = (ans * fact[col[i]]) % mod;
  }
  cout << ans;
  return 0;
}
