{"spec_id":"area-elevation-profile","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// area-elevation-profile: Terrain Elevation Profile Along Transect\n// Library: highcharts 12.6.0 | JavaScript 22.22.3\n// Quality: 90/100 | Created: 2026-06-10\n\n//# anyplot-orientation: landscape\n\nconst t = window.ANYPLOT_TOKENS;\n\n// Convert hex color to rgba string for gradient stops\nfunction rgba(hex, alpha) {\n  const r = parseInt(hex.slice(1, 3), 16);\n  const g = parseInt(hex.slice(3, 5), 16);\n  const b = parseInt(hex.slice(5, 7), 16);\n  return `rgba(${r},${g},${b},${alpha})`;\n}\n\n// Cosine interpolation for smooth elevation transitions between waypoints\nfunction cosineInterp(a, b, u) {\n  return a + (b - a) * (1 - Math.cos(u * Math.PI)) / 2;\n}\n\n// Control points for a 120 km alpine trail: [distance (km), elevation (m)]\nconst WAYPOINTS = [\n  [0,   892],  [8,   975],  [15, 1085],  [18, 1145],  [24, 1430],\n  [30, 1790],  [35, 2075],  [38, 2178],  [43, 2095],  [48, 2050],\n  [52, 2015],  [55, 2034],  [60, 2280],  [65, 2610],  [70, 2847],\n  [76, 2580],  [82, 2405],  [88, 2310],  [93, 2090],  [98, 1810],\n  [105, 1620], [110, 1375], [115, 1185], [120, 1005],\n];\n\nfunction getElevation(d) {\n  for (let i = 0; i < WAYPOINTS.length - 1; i++) {\n    const [d0, e0] = WAYPOINTS[i];\n    const [d1, e1] = WAYPOINTS[i + 1];\n    if (d >= d0 && d <= d1) {\n      return cosineInterp(e0, e1, (d - d0) / (d1 - d0));\n    }\n  }\n  return WAYPOINTS[WAYPOINTS.length - 1][1];\n}\n\n// Seeded LCG for deterministic terrain noise (no Math.random)\nfunction makeLCG(seed) {\n  let s = seed >>> 0;\n  return function () {\n    s = (Math.imul(s, 1664525) + 1013904223) >>> 0;\n    return s / 4294967296;\n  };\n}\nconst rng = makeLCG(42);\n\n// 241 sample points at 0.5 km intervals (total 120 km)\nconst seriesData = [];\nfor (let i = 0; i <= 240; i++) {\n  const d = Math.round(i * 5) / 10;  // 0.0, 0.5, 1.0, ..., 120.0\n  const noise = (rng() - 0.5) * 28;\n  const elev = Math.round(Math.max(700, getElevation(d) + noise));\n  seriesData.push([d, elev]);\n}\n\n// Key landmarks with name, distance, and elevation for annotation\n// elev shown on start/end points and summit per spec requirement\nconst LANDMARKS = [\n  { dist: 0,   name: \"Trailhead\",      elev: \"892 m\",  align: \"left\",   x: 6,  y: 16 },\n  { dist: 18,  name: \"River Crossing\", elev: null,     align: \"center\", x: 0,  y: 16 },\n  { dist: 38,  name: \"Falcon Pass\",    elev: null,     align: \"center\", x: 0,  y: 16 },\n  { dist: 55,  name: \"Alpine Hut\",     elev: null,     align: \"center\", x: 0,  y: 16 },\n  { dist: 70,  name: \"Summit Peak\",    elev: \"2847 m\", align: \"center\", x: 0,  y: 16 },\n  { dist: 88,  name: \"Glacier View\",   elev: null,     align: \"center\", x: 0,  y: 16 },\n  { dist: 105, name: \"Valley Camp\",    elev: null,     align: \"center\", x: 0,  y: 16 },\n  { dist: 120, name: \"Journey's End\",  elev: \"1005 m\", align: \"right\",  x: -6, y: 32 },\n];\n\nconst plotLines = LANDMARKS.map(lm => ({\n  value: lm.dist,\n  color: t.inkSoft,\n  width: 1,\n  dashStyle: \"Dash\",\n  zIndex: 5,\n  label: {\n    text: lm.elev ? `${lm.name}<br/>${lm.elev}` : lm.name,\n    useHTML: !!lm.elev,\n    rotation: 0,\n    textAlign: lm.align,\n    verticalAlign: \"top\",\n    x: lm.x,\n    y: lm.y,\n    style: { color: t.inkSoft, fontSize: \"13px\", fontWeight: \"normal\" },\n  },\n}));\n\nHighcharts.chart(\"container\", {\n  chart: {\n    type: \"area\",\n    backgroundColor: \"transparent\",\n    animation: false,\n    style: { fontFamily: \"inherit\" },\n  },\n  credits: { enabled: false },\n  colors: t.palette,\n  title: {\n    text: \"area-elevation-profile · javascript · highcharts · anyplot.ai\",\n    style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" },\n  },\n  subtitle: {\n    text: \"Alpine Trail Transect — 120 km  ·  Vertical exaggeration ≈10×\",\n    style: { color: t.inkSoft, fontSize: \"14px\" },\n  },\n  xAxis: {\n    title: {\n      text: \"Distance (km)\",\n      style: { color: t.inkSoft, fontSize: \"16px\" },\n    },\n    labels: { style: { color: t.inkSoft, fontSize: \"14px\" } },\n    lineColor: t.inkSoft,\n    tickColor: t.inkSoft,\n    gridLineWidth: 0,\n    tickInterval: 20,\n    min: 0,\n    max: 120,\n    plotLines: plotLines,\n  },\n  yAxis: {\n    title: {\n      text: \"Elevation (m)\",\n      style: { color: t.inkSoft, fontSize: \"16px\" },\n    },\n    labels: { style: { color: t.inkSoft, fontSize: \"14px\" } },\n    gridLineColor: t.grid,\n    gridLineWidth: 1,\n    tickInterval: 500,\n    min: 600,\n    max: 3200,\n  },\n  legend: { enabled: false },\n  tooltip: { enabled: false },\n  plotOptions: {\n    series: { animation: false },\n    area: {\n      lineWidth: 2.5,\n      marker: { enabled: false },\n      fillColor: {\n        linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },\n        stops: [\n          [0, rgba(t.palette[0], 0.55)],\n          [1, rgba(t.palette[0], 0.13)],\n        ],\n      },\n      states: { hover: { enabled: false } },\n      threshold: null,\n    },\n  },\n  series: [\n    {\n      name: \"Elevation\",\n      data: seriesData,\n      color: t.palette[0],\n    },\n  ],\n});\n"}