#include <bits/stdc++.h>
using namespace std;
const int MAX = 100000;
const int MOD = 1000000007;
int mult(int a, int b) { return (int)(((long long)a * (long long)b) % MOD); }
vector<int> fact;
void build_fact(int m) {
  fact.resize(m + 10);
  fact[1] = 1;
  fact[2] = 2;
  for (int i = 3; i < m + 5; ++i) {
    fact[i] = mult(fact[i - 1], i);
  }
}
int main(int argc, char* argv[]) {
  ios::sync_with_stdio(false);
  int n, m;
  cin >> n >> m;
  vector<int> g(n);
  map<int, int>* p = new map<int, int>[n];
  for (int i = 0; i < n; ++i) {
    cin >> g[i];
    for (int j = 0; j < g[i]; ++j) {
      int curr;
      cin >> curr;
      --curr;
      ++p[i][curr];
    }
  }
  map<int, set<int> >* pr = new map<int, set<int> >[n];
  for (int i = 0; i < n; ++i) {
    for (map<int, int>::iterator it = p[i].begin(), end = p[i].end(); it != end;
         ++it) {
      pr[i][it->second].insert(it->first);
    }
    for (map<int, set<int> >::iterator it = pr[i].begin(), end = pr[i].end();
         it != end; ++it) {
      set<int>& curr = it->second;
    }
  }
  vector<string> ind(m);
  for (int i = 0; i < n; ++i) {
    int j = 0;
    for (map<int, set<int> >::iterator it = pr[i].begin(), end = pr[i].end();
         it != end; ++it, ++j) {
      set<int>& curr = it->second;
      for (set<int>::iterator it2 = curr.begin(), end2 = curr.end();
           it2 != end2; ++it2) {
        ostringstream strm;
        strm << "(" << i << ":" << j << ")";
        ind[*it2] += strm.str();
      }
    }
  }
  sort(ind.begin(), ind.end());
  ind.push_back("#");
  int res = 1;
  build_fact(m);
  for (int i = 1, prev = 0; i <= m; ++i) {
    if (ind[i] != ind[prev]) {
      if (i - prev > 1) res = mult(res, fact[i - prev]);
      prev = i;
    }
  }
  cout << res << endl;
  return 0;
}
