#include <bits/stdc++.h>
using namespace std;
long long read() {
  long long a = 0;
  char c = getchar();
  while (c > '9' || c < '0') c = getchar();
  while ('0' <= c && c <= '9') {
    a = a * 10 + c - 48;
    c = getchar();
  }
  return a;
}
struct data {
  long long x, y, c;
  data(long long X = 0, long long Y = 0, long long C = 0) {
    x = X;
    y = Y;
    c = C;
  }
} w[2005], e[2005];
long long n, k, L;
bool cmp(data a, data b) { return a.x < b.x; };
bool cmp2(data a, data b) { return a.y < b.y; }
long long nxt[2005], f[2005];
multiset<long long> Set[2005];
long long sum[2005 << 2], Max[2005 << 2], tag[2005 << 2];
void pushup(long long x) {
  sum[x] = (sum[(x << 1)] + sum[(x << 1 | 1)]) % 1000000007;
  assert(Max[(x << 1)] <= Max[(x << 1 | 1)]);
  Max[x] = Max[(x << 1 | 1)];
}
void build(long long x, long long l, long long r) {
  tag[x] = 0;
  if (l == r) {
    sum[x] = f[l] * (e[l].y - e[l - 1].y) % 1000000007;
    Max[x] = f[l];
    return;
  }
  build((x << 1), l, ((l + r) >> 1));
  build((x << 1 | 1), ((l + r) >> 1) + 1, r);
  pushup(x);
}
void ptag(long long x, long long l, long long r, long long v) {
  assert(Max[x] <= v);
  sum[x] = v * (e[r].y - e[l - 1].y) % 1000000007;
  tag[x] = Max[x] = v;
}
void pushdown(long long x, long long l, long long r) {
  if (tag[x]) {
    ptag((x << 1), l, ((l + r) >> 1), tag[x]);
    ptag((x << 1 | 1), ((l + r) >> 1) + 1, r, tag[x]);
    tag[x] = 0;
  }
}
void chkmax(long long x, long long l, long long r, long long b, long long e,
            long long v) {
  if (r < b || l > e) return;
  if (l == r && Max[x] > v) return;
  if (Max[x] <= v && b <= l && r <= e) {
    ptag(x, l, r, v);
    return;
  }
  bool flag = (v > Max[(x << 1)]);
  pushdown(x, l, r);
  chkmax((x << 1), l, ((l + r) >> 1), b, e, v);
  if (flag) chkmax((x << 1 | 1), ((l + r) >> 1) + 1, r, b, e, v);
  pushup(x);
}
signed main() {
  n = read();
  k = read();
  L = read();
  for (long long i = 1; i <= n; ++i) {
    w[i].x = read() + 1;
    w[i].y = read() + 1;
    w[i].c = read();
    e[i] = w[i];
  }
  sort(w + 1, w + 1 + n, cmp);
  sort(e + 1, e + 1 + n, cmp2);
  e[n + 1].y = L + 1;
  w[n + 1].x = w[n + 2].x = L + 1;
  w[n + 1].y = L + 1;
  long long ans = 0;
  for (long long i = n; i; --i) {
    long long tmp = (w[i].x - w[i - 1].x);
    if (!tmp) continue;
    multiset<long long> S;
    S.clear();
    for (long long i = 1; i <= k; ++i) {
      S.insert(L + 1), nxt[i] = L + 1;
      Set[i].clear();
      Set[i].insert(L + 1);
      Set[i].insert(0);
    }
    for (long long j = n; j; --j) {
      if (e[j].x >= w[i].x) {
        S.erase(S.find(nxt[e[j].c]));
        nxt[e[j].c] = e[j].y;
        S.insert(nxt[e[j].c]);
        Set[e[j].c].insert(e[j].y);
      }
      f[j] = (*(--S.end()));
    }
    build(1, 1, n);
    for (long long j = n + 1; j > i; --j) {
      if (w[j].c) {
        assert(Set[w[j].c].find(w[j].y) != Set[w[j].c].end());
        Set[w[j].c].erase(Set[w[j].c].find(w[j].y));
        multiset<long long>::iterator it = --Set[w[j].c].upper_bound(w[j].y),
                                      ir = it;
        ++ir;
        long long ll = lower_bound(e, e + 1 + n, data(0, *it, 0), cmp2) - e;
        if (ll) assert(e[ll].y != e[ll - 1].y);
        chkmax(1, 1, n, ll + 1, n, *ir);
      }
      long long res = ((L + 1) * e[n].y - sum[1] + 1000000007) % 1000000007;
      ans =
          (ans + (res * tmp % 1000000007 * (w[j].x - w[j - 1].x))) % 1000000007;
    }
  }
  printf("%lld\n", ans);
  return 0;
}
