Topography continuous legend redesign
====================================

This version removes the old class-based topography legend model.

Backend changes:
- backend/renderers/elevation_renderer.py now uses ELEVATION_RAMP as continuous ramp stops, not classes.
- calculate_display_range() computes true min/max and a mild 2-98 percentile display stretch.
- render_elevation_png() evaluates a continuous colormap for every DEM pixel.
- build_continuous_legend() returns a continuous legend object:
  { type: "continuous", colors, min_ft, max_ft, display_min_ft, display_max_ft }
- backend/layers/topography.py returns that continuous legend object to the browser.
- backend/services/statistics_service.py no longer adds "Elevation class" rows.

Frontend changes:
- js/app.js reads the continuous legend object.
- addElevationGradientLegend() draws one CSS linear-gradient bar instead of color boxes.
- index.html has a cache-busting version string so the browser loads the new JS/CSS.

The map is still not using hillshade in this version. This step focuses only on:
1) continuous colormap evaluation;
2) continuous legend model;
3) gradient bar legend instead of class boxes.
