Skip to content

Airdrop chart: inside-chart left-aligned milestone labels, generic numbering, CMC prefix, smooth curve, font system #1061

@realproject7

Description

@realproject7

Five fixes per user feedback on the live chart from #1060

1. Move milestone labels INSIDE the chart, anchored to the LEFT of each vertical line

Currently the 4-line label blocks (TIER / $value / unlocks Y% / ≈ #Z) sit ABOVE the chart in the pad.top area. The user wants them inside the chart area, anchored to the LEFT of each vertical milestone line — same simple style as the ETH benchmark, but mirrored left-of-line instead of right-of-line.

Implementation: each label block uses text-anchor="end" with x = toX(milestonePos) - 6 (6px gap left of the line), y near pad.top + 14. Text extends leftward from the line, fits inside the band that ENDS at that line.

2. Replace tier names "Bronze / Silver / Gold / Diamond" with "Milestone 1 / 2 / 3 / 4"

The user wrote: "the title may confuse users." Drop TIER_NAMES map. Each label now reads MILESTONE 1 / \$1M / unlocks 10% / CMC ≈ #1900. Also drop the bottom row of tier-name X-axis labels — they were redundant with the inside labels in the new layout.

Mobile legend: change tier names to M1 / M2 / M3 / M4 to keep it compact.

3. Add "CMC" prefix to rank lines + footnote

  • Rank line: ≈ #1900CMC ≈ #1900
  • Footnote at chart bottom currently reads MCap = PLOT price × 1M max supply. Append: · CMC = CoinMarketCap

4. Smooth out the curve kink between milestone 3 and 4

The current curve has a visible slope discontinuity at each milestone knot because the banded log-interp mcapToX is C¹-discontinuous: each band has a different log range (band 0 = 2 decades, band 1 = 1 decade, band 2 = 0.7 decades, band 3 = 0.3 decades), so the slope dx/d(log m) jumps at the knots.

Fix: replace the banded log-interp with a monotone cubic Hermite interpolation in (log10(mcap), X) space using Catmull-Rom slopes at each knot:

slopes[i] = (xs[i+1] - xs[i-1]) / (lms[i+1] - lms[i-1])  // interior
          = (xs[1] - xs[0]) / (lms[1] - lms[0])          // first knot
          = (xs[i] - xs[i-1]) / (lms[i] - lms[i-1])      // last knot

within segment [t0=lms[i-1], t1=lms[i]]:
  u = (t - t0) / (t1 - t0)
  X = h00·x0 + h10·dt·m0 + h01·x1 + h11·dt·m1   // standard cubic Hermite basis

This is C¹-continuous everywhere, passes exactly through all 5 milestone knots (so milestones still land at X=0/0.25/0.5/0.75/1.0), and makes the curve appear smooth at the knots without overshoot (the slopes are monotonic increasing for our data, so the spline stays monotonic).

The heartbeat dot uses the same mcapToX, so it still lies exactly on the curve.

5. Match PlotLink's font system

PlotLink uses Geist Mono for .font-mono (declared in src/app/globals.css:56-57). Currently SVG text uses inline fontFamily="monospace" which falls back to system mono. Replace with <g className="font-mono"> wrappers — SVG text inherits the parent's font-family, so the entire chart picks up Geist Mono.

Also drop hardcoded letterSpacing="2" in favor of more measured tracking-wider equivalent, and use Tailwind text size utilities consistently.

Files

  • src/components/airdrop/CampaignHero.tsx

Acceptance criteria

  • Milestone label blocks render INSIDE the chart, right edge of each block aligns just left of its vertical line.
  • Each block reads: MILESTONE N (small caps, bold) / \$value (bold) / unlocks Y% / CMC ≈ #Z.
  • No more bottom tier-name X-axis labels.
  • Footnote reads: MCap = PLOT price × 1M max supply · CMC = CoinMarketCap.
  • Curve smooth at all milestone knots (no visible kink), still passes through (0,0) → ($1M, 25%) → ($10M, 50%) → ($50M, 75%) → ($100M, 100%).
  • Heartbeat dot lies on the curve at current MCap.
  • All chart text uses Geist Mono (via font-mono class wrapper).
  • Mobile legend uses M1 / M2 / M3 / M4 short labels.

Reviewer note

Block this PR if it:

  • (a) leaves milestone labels above the chart
  • (b) keeps "Bronze/Silver/Gold/Diamond" anywhere in the chart UI
  • (c) keeps the visible slope discontinuity at any milestone knot
  • (d) uses inline fontFamily="monospace" instead of the project font system

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/T3Assigned to T3 builder agent

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions