#include <bits/stdc++.h>
using namespace std;
mt19937 Rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
template <typename T>
inline void chkmax(T &x, T y) {
  if (x < y) x = y;
}
template <typename T>
inline void chkmin(T &x, T y) {
  if (x > y) x = y;
}
inline int read() {
  int x = 0;
  char c = getchar();
  while (c < 48) c = getchar();
  while (c > 47) x = x * 10 + (c ^ 48), c = getchar();
  return x;
}
const int maxn = 2010, P = 1e9 + 7;
int Inc(int x, int y) { return x + y < P ? x + y : x + y - P; }
int n, k, L;
struct node {
  int x, y, col;
} A[maxn];
vector<int> data[maxn][maxn];
int totx, toty, arr[maxn], Vx[maxn], Vy[maxn];
int cov[maxn << 2], mn[maxn << 2], mx[maxn << 2], sum[maxn << 2];
void pushtag(int k, int x, int l, int r) {
  mn[k] = mx[k] = cov[k] = x, sum[k] = 1ll * (Vy[r + 1] - Vy[l]) * x % P;
}
void pushdown(int k, int l, int r) {
  int &t = cov[k];
  if (t == -1) return;
  pushtag(k << 1, t, l, ((l + r) >> 1)),
      pushtag(k << 1 | 1, t, ((l + r) >> 1) + 1, r), t = -1;
}
void maintain(int k) {
  mn[k] = min(mn[k << 1], mn[k << 1 | 1]);
  mx[k] = max(mx[k << 1], mx[k << 1 | 1]);
  sum[k] = Inc(sum[k << 1], sum[k << 1 | 1]);
}
void build(int k, int l, int r) {
  cov[k] = -1;
  if (l == r) {
    mn[k] = mx[k] = Vy[arr[l]];
    sum[k] = 1ll * (Vy[l + 1] - Vy[l]) * mn[k] % P;
    return;
  }
  build(k << 1, l, ((l + r) >> 1)), build(k << 1 | 1, ((l + r) >> 1) + 1, r),
      maintain(k);
}
void upd(int k, int l, int r, int ql, int qr, int x) {
  if (l == r) {
    if (mn[k] >= x && mx[k] <= Vy[ql])
      mn[k] = mx[k] = x, sum[k] = 1ll * (Vy[l + 1] - Vy[l]) * x % P;
    return;
  }
  if (ql <= l && r <= qr && mn[k] >= x && mx[k] <= Vy[ql]) {
    pushtag(k, x, l, r);
    return;
  }
  pushdown(k, l, r);
  if (ql <= ((l + r) >> 1)) upd(k << 1, l, ((l + r) >> 1), ql, qr, x);
  if (qr > ((l + r) >> 1)) upd(k << 1 | 1, ((l + r) >> 1) + 1, r, ql, qr, x);
  maintain(k);
}
void solve() {
  cin >> n >> k >> L;
  for (int i = (1), iend = (n); i <= iend; ++i) {
    int x = read() + 1, y = read() + 1;
    Vx[i] = x, Vy[i] = y, A[i] = {x, y, read()};
  }
  sort(Vx + 1, Vx + n + 1);
  totx = unique(Vx + 1, Vx + n + 1) - Vx - 1;
  sort(Vy + 1, Vy + n + 1);
  toty = unique(Vy + 1, Vy + n + 1) - Vy - 1;
  for (int i = (1), iend = (n); i <= iend; ++i) {
    A[i].x = lower_bound(Vx + 1, Vx + totx + 1, A[i].x) - Vx;
    A[i].y = lower_bound(Vy + 1, Vy + toty + 1, A[i].y) - Vy;
    data[A[i].x][A[i].y].push_back(A[i].col);
  }
  Vx[totx + 1] = Vy[toty + 1] = L + 1;
  sort(A + 1, A + n + 1,
       [](node P, node Q) { return P.x < Q.x || (P.x == Q.x && P.y < Q.y); });
  int ans = 0;
  static set<int> pos[maxn];
  static map<int, int> seq[maxn];
  for (int D = (1), Dend = (totx); D <= Dend; ++D) {
    for (int i = (1), iend = (maxn - 1); i <= iend; ++i) {
      pos[i].clear(), seq[i].clear();
      pos[i].insert(0), pos[i].insert(toty + 1);
    }
    for (int i = (1), iend = (n); i <= iend; ++i) {
      if (A[i].x > D) break;
      seq[A[i].y][A[i].col]++;
      pos[A[i].col].insert(A[i].y);
    }
    int now = 0;
    static int cnt[maxn];
    memset(cnt, 0, sizeof cnt);
    auto it = seq[0].begin();
    for (int i = 1, j = 0; i <= toty; arr[i++] = j) {
      for (pair<int, int> p : seq[i]) {
        int c = p.first, s = p.second;
        now += !cnt[c], cnt[c] += s;
        bool flg = now == k;
        while (flg && j < i) {
          if (it == seq[j].end()) it = seq[++j].begin();
          while (it != seq[j].end()) {
            int tc = it->first, ts = it->second;
            if (cnt[tc] <= ts) {
              flg = 0;
              break;
            }
            cnt[tc] -= ts, ++it;
          }
        }
      }
    }
    build(1, 1, toty);
    for (int U = 1, i = 1; U <= D; U++) {
      for (; i <= n && A[i].x < U; i++) {
        if (--seq[A[i].y][A[i].col] > 0) continue;
        pos[A[i].col].erase(A[i].y);
        int prep = *--pos[A[i].col].lower_bound(A[i].y),
            nxtp = *pos[A[i].col].upper_bound(A[i].y);
        upd(1, 1, toty, A[i].y, nxtp - 1, Vy[prep]);
      }
      int tmp = sum[1];
      ans =
          (ans + 1ll * (Vx[U] - Vx[U - 1]) * (Vx[D + 1] - Vx[D]) % ::P * tmp) %
          ::P;
    }
  }
  cout << ans << endl;
}
signed main() {
  solve();
  return 0;
}
