#include <bits/stdc++.h>
using namespace std;
const signed long long Infinity = 1000000100;
const long double Epsilon = 1e-9;
template <typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
  return os << "(" << p.first << "," << p.second << ")";
}
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& V) {
  os << "[";
  for (int(i) = (0); (i) < (int(V.size())); (i)++)
    os << V[i] << ((i == int(V.size()) - 1) ? "" : ",");
  return os << "]";
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& S) {
  os << "(";
  for (__typeof(S.begin()) i = S.begin(); i != S.end(); ++i)
    os << *i << (*i == *S.rbegin() ? "" : ",");
  return os << ")";
}
template <typename T, typename U>
ostream& operator<<(ostream& os, const map<T, U>& M) {
  os << "{";
  for (__typeof(M.begin()) i = M.begin(); i != M.end(); ++i)
    os << *i << (*i.first == M.rbegin()->first ? "" : ",");
  return os << "}";
}
vector<signed long long> K[100100];
int sp[100100];
vector<int> G[100100];
vector<int> WTF;
int n, m;
long long ans;
const signed long long MOD = 1000000007;
void mul(signed long long x) {
  ans = (ans * x);
  if (ans > MOD) ans %= MOD;
}
int pos(int a) { return abs(a); }
int neg(int a) { return -abs(a); }
void transform() {
  for (int(i) = (1); (i) <= (m); (i)++) {
    if (K[i].size() == 0) {
      mul(2);
    } else if (K[i].size() == 1) {
      sp[abs(K[i][0])]++;
    } else if (K[i].size() == 2) {
      if (K[i][0] * K[i][1] > 0) {
        G[pos(K[i][0])].push_back(pos(K[i][1]));
        G[pos(K[i][1])].push_back(pos(K[i][0]));
      } else {
        WTF.push_back(i);
        G[pos(K[i][0])].push_back(neg(K[i][1]));
        G[pos(K[i][1])].push_back(neg(K[i][0]));
      }
    } else {
      assert(false);
    }
  }
}
int O[100100];
signed long long aa0, aa1;
bool ignore_update;
signed long long cc0, cc1;
vector<pair<int, int> > U;
void update(signed long long j, signed long long z) {
  if (ignore_update) {
    cc0 = z;
    cc1 = j;
    return;
  } else {
    z += cc0;
    j += cc1;
    cc0 = 0;
    cc1 = 0;
  }
  j %= MOD;
  z %= MOD;
  U.emplace_back(j, z);
  signed long long b0 = (aa0 * z + aa1 * j) % MOD;
  signed long long b1 = (aa1 * z + aa0 * j) % MOD;
  aa0 = b0;
  aa1 = b1;
}
struct state {
  signed long long a0, a1;
  signed long long b0, b1;
  state() : a0(0), a1(0), b0(0), b1(0) {}
  state(int a, int b, int c, int d) : a0(a), a1(b), b0(c), b1(d) {}
  void norm() {
    a0 = a0 % MOD;
    a1 = a1 % MOD;
    b0 = b0 % MOD;
    b1 = b1 % MOD;
  }
  signed long long sum() const { return a1 + a0 + b1 + b0; }
  bool next(const state& S) const { return this->sum() == 2 * S.sum(); }
};
ostream& operator<<(ostream& os, const state& s) {
  return os << "state { a0:" << s.a0 << " a1:" << s.a1 << " b0:" << s.b0
            << " b1:" << s.b1 << "}";
  return os;
}
vector<int> pth;
void go_p(int w, state s) {
  O[w] = 1;
  int nxt = 0;
  for (int g : G[w]) {
    if (!O[pos(g)]) {
      assert(nxt == 0);
      nxt = g;
    }
  }
  if (nxt == 0) {
    if (sp[w]) {
      update(s.a1 * 2 + s.b0 + s.b1, s.a0 * 2 + s.b0 + s.b1);
    } else {
      update(s.a1 + s.b1, s.a0 + s.b0);
    }
  } else {
    state s2;
    s2.a0 = s2.b1 = s.a1;
    s2.a1 = s2.b0 = s.a0;
    if (nxt > 0) {
      s2.a0 += s.b0;
      s2.a1 += s.b1;
      s2.b0 += s.b0;
      s2.b1 += s.b1;
    } else {
      s2.a0 += s.b1;
      s2.a1 += s.b0;
      s2.b0 += s.b1;
      s2.b1 += s.b0;
    }
    s2.norm();
    pth.push_back(pos(nxt));
    go_p(pos(nxt), s2);
  }
}
vector<int> proc;
void process(int w) {
  proc.push_back(w);
  O[w] = 1;
  if (sp[w] == 2) {
    update(3, 1);
    return;
  }
  if (sp[w] == 1 and G[w].size() == 0) {
    update(1, 1);
    return;
  }
  if (G[w].size() == 1) {
    state start(0, sp[w], 1, 0);
    go_p(w, start);
    return;
  }
  if (G[w].size() == 2) {
    if (pos(G[w][0]) == w) {
      if (G[w][0] < 0) {
        update(2, 0);
      } else {
        update(1, 1);
      }
      return;
    }
    if (pos(G[w][0]) == pos(G[w][1])) {
      if (G[w][0] > 0 and G[w][1] > 0) {
        update(0, 4);
      } else if (G[w][0] < 0 and G[w][1] < 0) {
        update(2, 2);
      } else {
        update(1, 3);
      }
      O[pos(G[w][0])] = 1;
    } else {
      int w1 = pos(G[w][1]);
      int tp = G[w][1];
      G[w].pop_back();
      int w2 = pos(G[w1][0]);
      if (w2 == w) w2 = pos(G[w1][1]);
      if (tp > 0) {
        ignore_update = true;
        pth.clear();
        go_p(w, state(0, 0, 1, 0));
        for (auto p : pth) O[p] = 0;
        O[w1] = 1;
        sp[w2] = 1;
        ignore_update = false;
        go_p(w, state(1, 0, 0, 0));
      } else {
        ignore_update = true;
        pth.clear();
        go_p(w, state(0, 1, 0, 0));
        for (auto p : pth) O[p] = 0;
        O[w1] = 1;
        sp[w2] = 1;
        ignore_update = false;
        go_p(w, state(0, 0, 0, 1));
      }
    }
    return;
  }
  cout << w << ": " << G[w] << endl;
  assert(false);
}
int main() {
  int x;
  ans = aa0 = 1;
  scanf("%d%d", &n, &m);
  for (int(i) = (1); (i) <= (n); (i)++) {
    int k;
    scanf("%d", &k);
    for (int(j) = (1); (j) <= (k); (j)++) {
      int a;
      scanf("%d", &a);
      int sgn = 1;
      if (a < 0) {
        sgn = -1;
        a = -a;
      }
      K[a].push_back(i * sgn);
      if (i == 1) x = a;
    }
  }
  transform();
  for (int(i) = (1); (i) <= (n); (i)++) {
    if (O[i] == 0 and G[i].size() <= 1) {
      process(i);
    }
  }
  for (int(i) = (1); (i) <= (n); (i)++) {
    if (O[i] == 0) {
      process(i);
    }
  }
  printf("%lld\n", (aa1 * ans) % MOD);
  if ((aa1 * ans) % MOD == 303861760 and m == 100000 and x == 45664) {
    printf("%lld %lld\n", aa1, aa0);
    for (auto u : U) {
      cout << "update: " << u << "\n";
    }
    for (auto p : proc) {
      cout << "process: " << p << "\n";
    }
    for (int w : WTF) printf("%d ", w);
    printf("\n");
  }
  return 0;
}
