#include <bits/stdc++.h>
using namespace std;
namespace IO {
const int Rlen = 1 << 22 | 1;
inline char gc() {
  static char buf[Rlen], *p1, *p2;
  (p1 == p2) && (p2 = (p1 = buf) + fread(buf, 1, Rlen, stdin));
  return p1 == p2 ? EOF : *p1++;
}
int gi() {
  int x = 0;
  char c = gc();
  bool f = false;
  while (!isdigit(c)) f = c == '-', c = gc();
  while (isdigit(c)) x = (((x << 2) + x) << 1) + (c ^ 48), c = gc();
  return f ? -x : x;
}
}  // namespace IO
using namespace IO;
const int Mod = 1e9 + 7;
int add(int a, int b) { return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b) { return 1ll * a * b % Mod; }
int dec(int a, int b) { return a - b < 0 ? a - b + Mod : a - b; }
void Add(int &a, int b) { a = add(a, b); }
void Mul(int &a, int b) { a = mul(a, b); }
void Dec(int &a, int b) { a = dec(a, b); }
const int N = 2e3 + 50;
int n, k, L, a[N], b[N];
int x[N], y[N], ca, cb, c[N];
vector<int> A[N], B[N];
struct dat {
  int l, r, v;
  dat(int _l = 0, int _r = 0, int _v = 0) { l = _l, r = _r, v = _v; }
  bool operator<(const dat &z) const {
    return v > z.v || (v == z.v && l < z.l);
  }
};
set<dat> S[N];
vector<dat> mdf[N];
int v[N];
namespace SGT {
const int N = ::N << 2;
int mn[N], mx[N], t[N], sm[N], c[N];
void up(int x) {
  c[x] = add(c[(x << 1)], c[(x << 1 | 1)]);
  sm[x] = add(sm[(x << 1)], sm[(x << 1 | 1)]);
  mn[x] = min(mn[(x << 1)], mn[(x << 1 | 1)]);
  mx[x] = max(mx[(x << 1)], mx[(x << 1 | 1)]);
}
void build(int x, int l, int r) {
  t[x] = -1;
  if (l == r)
    return sm[x] = mul(mn[x] = mx[x] = v[l], c[x] = b[l + 1] - b[l]), void();
  build((x << 1), l, ((l + r) >> 1)),
      build((x << 1 | 1), ((l + r) >> 1) + 1, r), up(x);
}
void put(int x, int v) {
  mn[x] = mx[x] = t[x] = v;
  sm[x] = mul(c[x], v);
}
void down(int x) {
  if (t[x] >= 0) put((x << 1), t[x]), put((x << 1 | 1), t[x]), t[x] = -1;
}
void upt(int x, int l, int r, int L, int R, int v) {
  if (v <= mn[x]) return;
  if (L <= l && r <= R) {
    if (v >= mx[x]) return put(x, v), void();
    upt((x << 1), l, ((l + r) >> 1), L, R, v);
    upt((x << 1 | 1), ((l + r) >> 1) + 1, r, L, R, v);
    up(x);
    return;
  }
  down(x);
  if (L <= ((l + r) >> 1)) upt((x << 1), l, ((l + r) >> 1), L, R, v);
  if (R > ((l + r) >> 1)) upt((x << 1 | 1), ((l + r) >> 1) + 1, r, L, R, v);
  up(x);
}
int qry(int x, int l, int r, int L, int R) {
  if (L <= l && r <= R) return sm[x];
  down(x);
  int ans = 0;
  if (L <= ((l + r) >> 1)) Add(ans, qry((x << 1), l, ((l + r) >> 1), L, R));
  if (R > ((l + r) >> 1))
    Add(ans, qry((x << 1 | 1), ((l + r) >> 1) + 1, r, L, R));
  return ans;
}
void output(int x, int l, int r) {
  if (l == r) return cout << mx[x] << " ", void();
  down(x);
  output((x << 1), l, ((l + r) >> 1));
  output((x << 1 | 1), ((l + r) >> 1) + 1, r);
}
}  // namespace SGT
int work(int lm) {
  for (int i = 1; i <= k; i++) S[i].clear(), S[i].insert(dat(cb, cb, L));
  for (int i = cb - 1, rp; i >= 1; i--)
    for (int z : B[i])
      if (a[x[z]] >= lm) {
        auto nxt = S[c[z]].begin();
        if (i < nxt->l)
          S[c[z]].insert(dat(i, nxt->l - 1, L)), nxt = S[c[z]].begin();
        while (true) {
          if (nxt == S[c[z]].end()) {
            rp = L + 1;
            break;
          }
          rp = nxt->l;
          if (nxt->v < a[x[z]]) break;
          if (nxt->l < cb) mdf[i].push_back(*nxt);
          S[c[z]].erase(nxt++);
        }
        if (i < rp) S[c[z]].insert(dat(i, rp - 1, a[x[z]]));
      }
  static int mn[N];
  for (int i = 1; i <= k; i++) mn[i] = L;
  for (int i = 1; i <= cb; i++) {
    for (int z : B[i])
      if (a[x[z]] >= lm) mn[c[z]] = min(mn[c[z]], a[x[z]]);
    int mx = 0;
    for (int j = 1; j <= k; j++) mx = max(mx, mn[j]);
    v[i] = mx;
  }
  SGT ::build(1, 1, cb - 1);
  int ans = 0;
  for (int i = 1; i < cb; i++) {
    int c = mul(L, L - b[i]);
    Dec(c, SGT ::qry(1, 1, cb - 1, i, cb - 1));
    Add(ans, mul(c, b[i] - b[i - 1]));
    for (dat z : mdf[i]) SGT ::upt(1, 1, cb - 1, z.l, z.r, z.v);
    mdf[i].clear();
  }
  return ans;
}
int main() {
  n = gi(), k = gi(), L = gi();
  for (int i = 1; i <= n; i++) {
    a[++ca] = x[i] = gi();
    b[++cb] = y[i] = gi();
    c[i] = gi();
  }
  sort(a + 1, a + ca + 1);
  sort(b + 1, b + ca + 1);
  ca = unique(a + 1, a + ca + 1) - a - 1;
  cb = unique(b + 1, b + cb + 1) - b - 1;
  a[++ca] = b[++cb] = L;
  a[0] = b[0] = -1;
  for (int i = 1; i <= n; i++) {
    x[i] = lower_bound(a + 1, a + ca + 1, x[i]) - a;
    y[i] = lower_bound(b + 1, b + cb + 1, y[i]) - b;
    A[x[i]].push_back(i), B[y[i]].push_back(i);
  }
  int ans = 0;
  for (int i = 1; i < ca; i++) Add(ans, mul(a[i] - a[i - 1], work(a[i])));
  cout << ans;
  return 0;
}
