#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
const int MOD = 1e9 + 7;
int add(int x, int y) { return (x + y) % MOD; }
void addeq(int &x, int y) { x = add(x, y); }
int mult(int x, int y) { return 1ll * x * y % MOD; }
void multeq(int &x, int y) { x = mult(x, y); }
struct edge {
  int u, v;
  edge(int _u, int _v) : u(_u), v(_v) {}
  int oth(int x) {
    if (u == x) {
      return v;
    } else if (v == x) {
      return u;
    } else {
      assert(!"Bad oth");
    }
  }
};
int N, M;
bool W = 1;
vector<pair<int, int> > A[MAXN];
vector<int> where[MAXN];
vector<edge> edges;
vector<int> adj[MAXN];
bool vis[MAXN];
bool isrep[MAXN];
int ways[MAXN][2];
bool isneg(int cla, int x) {
  for (pair<int, int> p : A[cla]) {
    if (p.first == x) {
      return p.second;
    }
  }
  assert(!"var not found in clause");
}
bool eval(int cla, int x, bool val) { return val ^ isneg(cla, x); }
void dpchain(int comp) {
  vector<int> nodes;
  vector<int> links;
  nodes.push_back(comp);
  for (int pedge = -1, cur = comp;;) {
    bool nxt = false;
    for (int ed : adj[cur]) {
      if (ed != pedge) {
        cur = edges[ed].oth(cur);
        pedge = ed;
        nodes.push_back(cur);
        nxt = true;
        break;
      }
    }
    if (!nxt) {
      break;
    }
  }
  int dp[2][2][2];
  memset(dp, 0, sizeof(dp));
  for (int i = 0; i + 1 < nodes.size(); i++) {
    int s1 = nodes[i], s2 = nodes[i + 1];
    for (pair<int, int> x : A[s1]) {
      for (pair<int, int> y : A[s2]) {
        if (x.first == y.first) {
          links.push_back(x.first);
        }
      }
    }
  }
  assert(links.size() == nodes.size() - 1);
  int cur = 0, prv = 1;
  bool hasl = false;
  int pid = -1;
  for (auto p : A[nodes[0]]) {
    if (p.first != links[0]) {
      pid = p.first;
      dp[cur][0][0] = dp[cur][0][1] = 1;
    }
  }
  if (!hasl) {
    dp[cur][0][0] = 1;
  }
  vis[nodes[0]] = true;
  for (int ci = 1; ci < nodes.size(); ci++) {
    swap(cur, prv);
    vis[nodes[ci]] = true;
    memset(dp[cur], 0, sizeof(dp[cur]));
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) {
        bool pval = (pid == -1 ? j : eval(nodes[ci - 1], pid, j));
        for (int k = 0; k < 2; k++) {
          bool cval = eval(nodes[ci - 1], links[ci - 1], k);
          addeq(dp[cur][i ^ (pval || cval)][k], dp[prv][i][j]);
        }
      }
    }
    pid = links[ci - 1];
  }
  int fid = -1;
  for (pair<int, int> p : A[nodes.back()]) {
    if (p.first != pid) {
      fid = p.first;
      break;
    }
  }
  swap(cur, prv);
  memset(dp[cur], 0, sizeof(dp[cur]));
  if (fid == -1) {
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) {
        bool pval = eval(nodes.back(), pid, j);
        addeq(dp[cur][i ^ pval][0], dp[prv][i][j]);
      }
    }
  } else {
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) {
        bool pval = eval(nodes.back(), pid, j);
        for (int k = 0; k < 2; k++) {
          bool cval = eval(nodes.back(), fid, k);
          addeq(dp[cur][i ^ (pval || cval)][k], dp[prv][i][j]);
        }
      }
    }
  }
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      addeq(ways[comp][i], dp[cur][i][j]);
    }
  }
}
void dpcyc(int comp) {
  vector<int> nodes;
  vector<int> vars;
  for (int pedge = -1, cur = comp;;) {
    if (vis[cur]) {
      break;
    }
    vis[cur] = true;
    nodes.push_back(cur);
    for (int ed : adj[cur]) {
      if (ed != pedge) {
        cur = edges[ed].oth(cur);
        pedge = ed;
        break;
      }
    }
  }
  if (nodes.size() == 2) {
    vars = {A[nodes[0]][0].first, A[nodes[1]][1].first};
  } else {
    for (int i = 0; i < nodes.size(); i++) {
      int x = nodes[i], y = nodes[(i + nodes.size() - 1) % nodes.size()];
      for (pair<int, int> p1 : A[x]) {
        bool found = false;
        for (pair<int, int> p2 : A[y]) {
          if (p1.first == p2.first) {
            found = true;
            break;
          }
        }
        if (found) {
          vars.push_back(p1.first);
        }
      }
    }
  }
  assert(vars.size() == nodes.size());
  int cur = 0, prv = 1;
  int dp[2][2][2][2];
  memset(dp, 0, sizeof(dp));
  dp[cur][0][0][0] = dp[cur][1][0][1] = 1;
  for (int ci = 1; ci < nodes.size(); ci++) {
    swap(cur, prv);
    memset(dp[cur], 0, sizeof(dp[cur]));
    for (int fst = 0; fst < 2; fst++) {
      for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
          for (int k = 0; k < 2; k++) {
            if (ci + 1 == nodes.size()) {
              int lastv = vars.back();
              int slast1 = nodes.back(), slast2 = nodes[nodes.size() - 2];
              bool eval1 =
                  eval(slast1, vars[0], fst) || eval(slast1, vars.back(), k);
              bool eval2 = eval(slast2, lastv, k) ||
                           eval(slast2, vars[vars.size() - 2], j);
              addeq(dp[cur][fst][i ^ eval1 ^ eval2][k], dp[prv][fst][i][j]);
            } else {
              bool ev = eval(nodes[ci - 1], vars[ci - 1], j) ||
                        eval(nodes[ci - 1], vars[ci], k);
              addeq(dp[cur][fst][i ^ ev][k], dp[prv][fst][i][j]);
            }
          }
        }
      }
    }
  }
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        addeq(ways[comp][i], dp[cur][j][i][k]);
      }
    }
  }
}
int main() {
  scanf("%d %d", &N, &M);
  for (int i = 0; i < N; i++) {
    int sz;
    scanf("%d", &sz);
    A[i].resize(sz);
    for (auto &p : A[i]) {
      int x;
      scanf("%d", &x);
      p = pair<int, int>(abs(x) - 1, x < 0);
    }
    if (A[i].size() == 2) {
      if (A[i][0].first == A[i][1].first) {
        if (A[i][0].second == A[i][1].second) {
          A[i].resize(1);
        } else {
          i--;
          N--;
          W ^= 1;
          continue;
        }
      }
    }
    for (auto p : A[i]) {
      where[p.first].push_back(i);
    }
  }
  for (int i = 0; i < M; i++) {
    if (where[i].size() == 2) {
      int id = edges.size();
      edges.push_back(edge(where[i][0], where[i][1]));
      for (int j = 0; j < 2; j++) {
        adj[where[i][j]].push_back(id);
      }
    }
  }
  for (int i = 0; i < N; i++) {
    if (adj[i].size() == 0) {
      ways[i][0] = 1;
      ways[i][1] = (1 << A[i].size()) - 1;
      vis[i] = true;
      isrep[i] = true;
    } else if (adj[i].size() == 1) {
      if (vis[i]) {
        continue;
      }
      isrep[i] = true;
      dpchain(i);
    }
  }
  for (int i = 0; i < N; i++) {
    if (adj[i].size() == 2 && !vis[i]) {
      isrep[i] = true;
      dpcyc(i);
    }
  }
  for (int i = 0; i < N; i++) {
    assert(vis[i]);
  }
  int ans[2] = {1, 0};
  for (int i = 0; i < N; i++) {
    if (!isrep[i]) {
      continue;
    }
    int nans[2] = {0, 0};
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        addeq(nans[j ^ k], mult(ans[j], ways[i][k]));
      }
    }
    ans[0] = nans[0];
    ans[1] = nans[1];
  }
  for (int i = 0; i < M; i++) {
    if (where[i].empty()) {
      multeq(ans[W], 2);
    }
  }
  printf("%d\n", ans[W]);
}
