#include <bits/stdc++.h>
#pragma GCC optimize("O2")
using namespace std;
const int N = 2e3 + 10;
const long long mod = 1e9 + 7;
const long long mod2 = 998244353;
const long long inf = 8e18;
const int LOG = 22;
long long pw(long long a, long long b, long long M) {
  return (!b ? 1
             : (b & 1 ? (a * pw(a * a % M, b / 2, M)) % M
                      : pw(a * a % M, b / 2, M)));
}
long long tot, L2, L;
int n, k, X[N], Y[N], C[N], Sz[N], first[N];
vector<int> cmx, cmy, lev[N], col[N];
inline int lwrx(int x) {
  return lower_bound((cmx).begin(), (cmx).end(), x) - cmx.begin();
}
inline int lwry(int x) {
  return lower_bound((cmy).begin(), (cmy).end(), x) - cmy.begin();
}
unordered_map<int, int> mp;
multiset<int> st[N];
multiset<int>::iterator ptr[N];
long long seg[N << 2], lz[N << 2], mn[N << 2], mx[N << 2], size[N << 2];
inline void merge(int v) {
  seg[v] = (seg[v << 1] + seg[v << 1 | 1]) % mod;
  mn[v] = min(mn[v << 1], mn[v << 1 | 1]);
  mx[v] = max(mx[v << 1], mx[v << 1 | 1]);
}
void second(int v, int tl, int tr) {
  if (lz[v] == -1 || tl == tr) return;
  mn[v << 1] = mx[v << 1] = lz[v << 1] = mn[v << 1 | 1] = mx[v << 1 | 1] =
      lz[v << 1 | 1] = lz[v];
  seg[v << 1] = size[v << 1] * lz[v << 1] % mod;
  seg[v << 1 | 1] = size[v << 1 | 1] * lz[v << 1 | 1] % mod;
  lz[v] = -1;
}
void build(int v = 1, int tl = 0, int tr = (int)cmx.size() - 1) {
  lz[v] = -1;
  if (tl == tr) {
    seg[v] = 1ll * first[tl] * Sz[tl] % mod;
    mn[v] = mx[v] = first[tl];
    size[v] = Sz[tl];
    return;
  }
  int mid = (tl + tr) >> 1;
  build(v << 1, tl, mid);
  build(v << 1 | 1, mid + 1, tr);
  merge(v);
  size[v] = size[v << 1] + size[v << 1 | 1];
}
void upd(int l, int r, long long x, int v = 1, int tl = 0,
         int tr = (int)cmx.size() - 1) {
  second(v, tl, tr);
  if (l > tr || r < tl || l > r || mn[v] >= x) return;
  if (l <= tl && tr <= r && mx[v] <= x) {
    mn[v] = mx[v] = lz[v] = x;
    seg[v] = x * size[v] % mod;
    return;
  }
  int mid = (tl + tr) >> 1;
  upd(l, r, x, v << 1, tl, mid), upd(l, r, x, v << 1 | 1, mid + 1, tr);
  merge(v);
}
long long get(int p, int v = 1, int tl = 0, int tr = (int)cmx.size() - 1) {
  second(v, tl, tr);
  if (tl == tr) {
    return mx[v];
  }
  int mid = (tl + tr) >> 1;
  if (p <= mid) return get(p, v << 1, tl, mid);
  return get(p, v << 1 | 1, mid + 1, tr);
}
inline void erase(int id) {
  auto it = st[C[id]].find(X[id]);
  auto It = it, IT = it;
  int prv = (It == st[C[id]].begin() ? 0 : *(--It)), nxt = *(++it);
  upd(mp[prv] + 1, mp[X[id]], nxt);
  st[C[id]].erase(IT);
}
long long solve(int start, long long A) {
  long long ret =
      ((A * (A - 1) / 2ll) % mod) * ((L + 1) * (L) / 2ll % mod) % mod;
  for (int i = 1; i <= k; i++) st[i].clear(), st[i].insert(L + 1);
  for (int y = start; y < (int)cmy.size(); y++) {
    for (auto now : lev[y]) {
      st[C[now]].insert(X[now]);
    }
  }
  for (int i = 1; i <= k; i++) {
    ptr[i] = st[i].begin();
  }
  int Mx = 0;
  for (int i = 1; i <= k; i++) Mx = max(Mx, *ptr[i]);
  first[1] = Mx;
  for (int i = 2; i < (int)cmx.size(); i++) {
    first[i] = first[i - 1];
    for (auto cu : col[i - 1]) {
      if (Y[cu] < cmy[start]) continue;
      ptr[C[cu]]++;
      first[i] = max(first[i], *ptr[C[cu]]);
    }
  }
  build();
  for (int D = (int)cmy.size() - 1; D >= start; D--) {
    long long B;
    B = (D + 1 == (int)cmy.size() ? L + 1 : cmy[D + 1]) - cmy[D];
    ret = ret + (A * B % mod * (seg[1] - L2 + mod) % mod);
    if (ret >= mod) ret -= mod;
    if (D == start) break;
    for (auto now : lev[D]) {
      erase(now);
    }
  }
  return ret;
}
int main() {
  scanf("%d%d%lld", &n, &k, &L);
  for (int i = 1; i <= n; i++) {
    scanf("%d%d%d", &X[i], &Y[i], &C[i]);
    X[i]++;
    Y[i]++;
    cmx.push_back(X[i]);
    cmy.push_back(Y[i]);
  }
  cmx.push_back(0), cmx.push_back(L), sort((cmx).begin(), (cmx).end()),
      cmx.resize(unique((cmx).begin(), (cmx).end()) - cmx.begin());
  cmy.push_back(0), cmy.push_back(L), sort((cmy).begin(), (cmy).end()),
      cmy.resize(unique((cmy).begin(), (cmy).end()) - cmy.begin());
  for (int i = 1; i < (int)cmx.size(); i++) {
    Sz[i] = cmx[i] - cmx[i - 1];
  }
  for (int i = 0; i < (int)cmx.size(); i++) {
    mp[cmx[i]] = i;
  }
  for (int i = 1; i <= n; i++) {
    lev[lwry(Y[i])].push_back(i);
    col[lwrx(X[i])].push_back(i);
  }
  L2 = tot = (1ll * (L + 1) * (L) / 2ll) % mod;
  tot = tot * tot % mod;
  for (int Up = 1; Up < (int)cmy.size(); Up++) {
    tot = (tot - solve(Up, cmy[Up] - cmy[Up - 1]) + mod) % mod;
  }
  printf("%lld", tot);
  return 0;
}
