#include <bits/stdc++.h>
using namespace std;
inline int in() {
  int x;
  cin >> x;
  return x;
}
template <typename T>
istream &operator>>(istream &in, vector<T> &vec) {
  for (int i = 0; i < vec.size(); ++i) in >> vec[i];
  return in;
}
template <typename T>
ostream &operator<<(ostream &out, const vector<T> &vec) {
  for (int i = 0; i < vec.size(); ++i) out << vec[i] << " ";
  return out;
}
vector<bool> used;
vector<vector<int>> graf;
vector<int> mark;
queue<int> que;
priority_queue<int> pq;
int main() {
  long long tor = 1e9 + 7;
  long long cos1 = 1;
  long long b = 1;
  long long a = in(), c = in(), d, m = 0;
  vector<int> s(1e6 + 1);
  s[0] = 1, s[1] = 1;
  for (long long i = 2; i <= 1e6; ++i) s[i] = (i * s[i - 1]) % tor;
  vector<vector<int>> f(c);
  for (int i = 0; i < a; ++i) {
    d = in();
    for (int j = 0; j < d; ++j) {
      f[in() - 1].push_back(i);
    }
  }
  for (int i = 0; i < c; ++i) sort((f[i]).begin(), (f[i]).end());
  sort((f).begin(), (f).end());
  for (int i = 1; i < c; ++i) {
    if (f[i] == f[i - 1])
      ++cos1;
    else {
      b = (b * s[cos1]) % tor;
      cos1 = 1;
    }
  }
  b = (b * s[cos1]) % tor;
  cout << b;
  return 0;
}
