#include <bits/stdc++.h>
using namespace std;
const int N = 2000 + 10, MOD = 1e9 + 7;
int n, m, L;
struct Point {
  int x, y, c;
} p[N];
int numx[N], totx, numy[N], toty;
vector<int> vx[N], vy[N];
struct List {
  int l[N], r[N];
  void del(int x) {
    l[r[x]] = l[x];
    r[l[x]] = r[x];
  }
} q, nq;
int last[N];
bool vis[N];
int f[N], cnt[N];
long long mn[N << 2], mx[N << 2], sum[N << 2], tag[N << 2], ans;
bool cmp(Point a, Point b) { return a.y == b.y ? a.x < b.x : a.y < b.y; }
void update(int x) {
  sum[x] = (sum[x << 1] + sum[x << 1 | 1]) % MOD;
  mn[x] = mn[x << 1];
  mx[x] = mx[x << 1 | 1];
}
void upd(int x, int l, int r, int C) {
  sum[x] = 1ll * (numy[r] - numy[l - 1]) * (L - numy[C]) % MOD;
  mn[x] = mx[x] = tag[x] = C;
}
void build(int x, int l, int r) {
  if (l == r) {
    upd(x, l, r, f[l]);
    return;
  }
  int mid = (l + r) >> 1;
  build(x << 1, l, mid);
  build(x << 1 | 1, mid + 1, r);
  update(x);
}
void pushdown(int x, int l, int r) {
  if (!tag[x]) return;
  int mid = (l + r) >> 1;
  upd(x << 1, l, mid, tag[x]);
  upd(x << 1 | 1, mid + 1, r, tag[x]);
  tag[x] = 0;
}
void modify(int x, int l, int r, int L, int C) {
  if (r < L || mn[x] >= C) return;
  if (l == L && mx[x] <= C) {
    upd(x, l, r, C);
    return;
  }
  pushdown(x, l, r);
  int mid = (l + r) >> 1;
  if (L <= mid) modify(x << 1, l, mid, L, C);
  modify(x << 1 | 1, mid + 1, r, max(L, mid + 1), C);
  update(x);
}
int main() {
  scanf("%d%d%d", &n, &m, &L);
  for (int i = 1; i <= n; ++i) {
    scanf("%d%d%d", &p[i].y, &p[i].x, &p[i].c);
    numx[++totx] = p[i].x;
    numy[++toty] = p[i].y;
  }
  sort(numx + 1, numx + totx + 1);
  sort(numy + 1, numy + toty + 1);
  totx = unique(numx + 1, numx + totx + 1) - numx - 1;
  toty = unique(numy + 1, numy + toty + 1) - numy - 1;
  numx[totx + 1] = numy[toty + 1] = L;
  numx[0] = numy[0] = -1;
  sort(p + 1, p + n + 1, cmp);
  p[0].y = 0;
  p[n + 1].y = toty + 1;
  for (int i = 1; i <= n; ++i) {
    p[i].x = lower_bound(numx + 1, numx + totx + 1, p[i].x) - numx;
    p[i].y = lower_bound(numy + 1, numy + toty + 1, p[i].y) - numy;
    vx[p[i].x].push_back(i);
    vy[p[i].y].push_back(i);
    q.l[i] = last[p[i].c];
    q.r[i] = n + 1;
    q.r[last[p[i].c]] = i;
    last[p[i].c] = i;
  }
  for (int i = 1; i <= totx; ++i) {
    memset(cnt, 0, sizeof(cnt));
    int tot = 0;
    for (int l = 1, r = 1; l <= toty; ++l) {
      for (; r <= toty && tot < m; ++r) {
        for (int j = 0; j < vy[r].size(); ++j) {
          int t = vy[r][j];
          if (vis[t]) continue;
          if (!cnt[p[t].c]) tot++;
          cnt[p[t].c]++;
        }
      }
      if (tot == m)
        f[l] = r - 1;
      else
        f[l] = toty + 1;
      for (int j = 0; j < vy[l].size(); ++j) {
        int t = vy[l][j];
        if (vis[t]) continue;
        cnt[p[t].c]--;
        if (!cnt[p[t].c]) tot--;
      }
    }
    memset(tag, 0, sizeof(tag));
    build(1, 1, toty);
    nq = q;
    for (int j = totx; j >= i; --j) {
      long long add = 1ll * sum[1] * (numx[j + 1] - numx[j]) % MOD *
                      (numx[i] - numx[i - 1]) % MOD;
      ans = (ans + add) % MOD;
      for (int k = 0; k < vx[j].size(); ++k) {
        int t = vx[j][k];
        modify(1, 1, toty, p[nq.l[t]].y + 1, p[nq.r[t]].y);
        nq.del(t);
      }
    }
    for (int j = 0; j < vx[i].size(); ++j) vis[vx[i][j]] = 1, q.del(vx[i][j]);
  }
  printf("%lld", ans);
  return 0;
}
