#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
long long mod = 1e9 + 7;
long long x[2005], y[2005], dis[2005], c[2005], lx, ly, p[2005], r[2005],
    maxi = 1e18;
long long lst[2005];
vector<pair<long long, long long> > g[2005];
multiset<long long> cg[2005];
vector<long long> v[2005];
struct node {
  long long fi[5000], se[5000], ans[5000], tag[5000], st[5000];
  void pu(long long x) {
    if (fi[(x << 1)] < fi[((x << 1) | 1)]) {
      fi[x] = fi[(x << 1)];
      st[x] = st[(x << 1)];
      se[x] = min(se[(x << 1)], fi[((x << 1) | 1)]);
    } else if (fi[(x << 1)] > fi[((x << 1) | 1)]) {
      fi[x] = fi[((x << 1) | 1)];
      st[x] = st[((x << 1) | 1)];
      se[x] = min(fi[(x << 1)], se[((x << 1) | 1)]);
    } else {
      fi[x] = fi[(x << 1)];
      st[x] = st[(x << 1)] + st[((x << 1) | 1)];
      se[x] = min(se[(x << 1)], se[((x << 1) | 1)]);
    }
    ans[x] = ans[(x << 1)] + ans[((x << 1) | 1)];
  }
  void beat(long long x, long long to) {
    if (to <= fi[x]) return;
    if (to < se[x]) {
      tag[x] = max(tag[x], to);
      ans[x] += st[x] * (to - fi[x]);
      fi[x] = to;
      return;
    }
    beat((x << 1), to);
    beat(((x << 1) | 1), to);
    pu(x);
  }
  void pd(long long x) {
    beat((x << 1), tag[x]);
    beat(((x << 1) | 1), tag[x]);
  }
  void build(long long x, long long l, long long r) {
    tag[x] = -maxi;
    if (l == r) {
      ans[x] = dis[l] * p[l];
      st[x] = dis[l];
      fi[x] = p[l];
      se[x] = maxi;
      return;
    }
    long long mid = (l + r) >> 1;
    build((x << 1), l, mid);
    build(((x << 1) | 1), mid + 1, r);
    pu(x);
  }
  void update(long long x, long long l, long long r, long long tl, long long tr,
              long long to) {
    if (r < tl || tr < l) return;
    if (l >= tl && r <= tr) {
      beat(x, to);
      return;
    }
    pd(x);
    long long mid = (l + r) >> 1;
    update((x << 1), l, mid, tl, tr, to);
    update(((x << 1) | 1), mid + 1, r, tl, tr, to);
    pu(x);
  }
  void update(long long l, long long r, long long x) {
    update(1, 1, ly, l, r, x);
  }
  void init() { build(1, 1, ly); }
} T;
long long ans;
signed main() {
  long long k, n, l;
  cin >> n >> k >> l;
  vector<long long> vx, vy;
  for (long long i = 1; i <= n; i++) {
    cin >> x[i] >> y[i] >> c[i];
    x[i]++;
    y[i]++;
    vx.emplace_back(x[i]);
    vy.emplace_back(y[i]);
  }
  sort(vx.begin(), vx.end());
  vx.erase(unique(vx.begin(), vx.end()), vx.end());
  lx = vx.size();
  sort(vy.begin(), vy.end());
  vy.erase(unique(vy.begin(), vy.end()), vy.end());
  ly = vy.size();
  for (long long i = 1; i <= n; i++) {
    x[i] = lower_bound(vx.begin(), vx.end(), x[i]) - vx.begin() + 1;
    y[i] = lower_bound(vy.begin(), vy.end(), y[i]) - vy.begin() + 1;
    g[x[i]].emplace_back(make_pair(y[i], c[i]));
  }
  dis[1] = vy[0];
  for (long long i = 2; i <= ly; i++) dis[i] = vy[i - 1] - vy[i - 2];
  for (long long i = 1; i <= lx; i++) {
    for (long long j = 1; j <= ly; j++) v[j].clear();
    multiset<long long> sr;
    for (long long j = 1; j <= i; j++) {
      for (auto u : g[j]) {
        cg[u.second].insert(u.first);
        v[u.first].emplace_back(u.second);
      }
    }
    for (long long j = 1; j <= k; j++) {
      r[j] = l + 1;
      sr.insert(-r[j]);
    }
    for (long long j = ly; j >= 1; j--) {
      for (auto u : v[j]) {
        sr.erase(sr.find(-r[u]));
        r[u] = j;
        sr.insert(-r[u]);
      }
      p[j] = -(*sr.begin());
      if (p[j] != l + 1) p[j] = vy[p[j] - 1];
    }
    T.init();
    long long tr;
    if (i == lx) {
      tr = l + 1 - vx[i - 1];
    } else
      tr = vx[i] - vx[i - 1];
    for (long long j = 1; j <= i; j++) {
      long long now =
          tr * ((j == 1) ? vx[j - 1] : (vx[j - 1] - vx[j - 2])) % mod;
      ans = (ans + (vy.back() * (l + 1) - T.ans[1] + mod) % mod * now) % mod;
      for (auto u : g[j]) {
        cg[u.second].erase(cg[u.second].find(u.first));
        if (!cg[u.second].count(u.first)) {
          auto it = cg[u.second].lower_bound(u.first);
          long long nxt =
              ((it == cg[u.second].end()) ? (l + 1) : vy[(*it) - 1]);
          if (it == cg[u.second].begin())
            T.update(1, u.first, nxt);
          else
            T.update(*(--it) + 1, u.first, nxt);
        }
      }
    }
  }
  cout << ans;
  return 0;
}
