{"spec_id":"gauge-basic","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// gauge-basic: Basic Gauge Chart\n// Library: highcharts 12.6.0 | JavaScript 22.23.0\n// Quality: 91/100 | Created: 2026-06-30\n//# anyplot-orientation: square\n// anyplot.ai\n// gauge-basic: Basic Gauge Chart\n// Library: Highcharts 12.6.0 | Node 22\n// License: Highcharts — commercial license, free for non-commercial use (highcharts.com/license)\n// Quality: pending | Created: 2026-06-30\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (Customer Satisfaction Score) ------------------------------------\nconst MIN_VAL   = 0;\nconst MAX_VAL   = 100;\nconst CUR_VAL   = 72;\nconst THRESH_LO = 30;\nconst THRESH_HI = 70;\n\nconst arcRed   = THRESH_LO - MIN_VAL;         // 30\nconst arcAmber = THRESH_HI - THRESH_LO;       // 40\nconst arcGreen = MAX_VAL   - THRESH_HI;       // 30\n\nconst TITLE   = \"gauge-basic · javascript · highcharts · anyplot.ai\";\nconst titleFs = Math.max(15, Math.round(22 * Math.min(1, 67 / TITLE.length))) + \"px\";\n\n// --- Chart -----------------------------------------------------------------\nconst chart = Highcharts.chart(\"container\", {\n  chart: {\n    backgroundColor: \"transparent\",\n    animation: false,\n    style: { fontFamily: \"inherit\" },\n    margin: [60, 40, 140, 40]\n  },\n  credits: { enabled: false },\n  colors: t.palette,\n  title: {\n    text: TITLE,\n    style: { color: t.ink, fontSize: titleFs, fontWeight: \"600\" }\n  },\n  plotOptions: {\n    pie: {\n      animation: false,\n      startAngle: -90,\n      endAngle: 90,\n      center: [\"50%\", \"70%\"],\n      dataLabels: { enabled: false },\n      borderWidth: 0\n    },\n    series: { animation: false }\n  },\n  tooltip: { enabled: false },\n  legend: { enabled: false },\n  series: [{\n    type: \"pie\",\n    name: \"CSAT Zones\",\n    innerSize: \"62%\",\n    size: \"90%\",\n    data: [\n      { y: arcRed,   color: \"#AE3030\" },\n      { y: arcAmber, color: \"#DDCC77\" },\n      { y: arcGreen, color: \"#009E73\" }\n    ]\n  }]\n});\n\n// --- SVG overlays (needle, value, legend) ----------------------------------\nconst ps     = chart.series[0];\nconst cx     = chart.plotLeft + ps.center[0];\nconst cy     = chart.plotTop  + ps.center[1];\nconst outerR = ps.center[2] / 2;\nconst innerR = ps.center[3] / 2;\n\n// Needle angle: -90° (left/MIN) to +90° (right/MAX), clockwise from 12 o'clock\nconst pct      = (CUR_VAL - MIN_VAL) / (MAX_VAL - MIN_VAL);\nconst angleDeg = -90 + pct * 180;\nconst angleRad = angleDeg * Math.PI / 180;\n\n// SVG coords: x = cx + r·sin(θ), y = cy - r·cos(θ)\nconst needleLen = outerR * 0.82;\nconst tipX      = cx + needleLen * Math.sin(angleRad);\nconst tipY      = cy - needleLen * Math.cos(angleRad);\n\n// Needle line\nchart.renderer.path([\"M\", cx, cy, \"L\", tipX, tipY])\n  .attr({ stroke: t.ink, \"stroke-width\": 5, \"stroke-linecap\": \"round\", zIndex: 5 })\n  .add();\n\n// Hub dot at pivot\nchart.renderer.circle(cx, cy, outerR * 0.065)\n  .attr({ fill: t.ink, zIndex: 6 })\n  .add();\n\n// Large value inside donut hole\nconst valY = cy - innerR * 0.45;\nchart.renderer.text(CUR_VAL.toString(), cx, valY)\n  .attr({ align: \"center\", zIndex: 5 })\n  .css({ fontSize: \"66px\", fontWeight: \"700\", color: t.ink, fontFamily: \"inherit\" })\n  .add();\n\nchart.renderer.text(\"/ 100\", cx, valY + 38)\n  .attr({ align: \"center\", zIndex: 5 })\n  .css({ fontSize: \"18px\", color: t.inkSoft, fontFamily: \"inherit\" })\n  .add();\n\n// Metric name below gauge\nchart.renderer.text(\"Customer Satisfaction Score\", cx, cy + 52)\n  .attr({ align: \"center\", zIndex: 5 })\n  .css({ fontSize: \"18px\", fontWeight: \"600\", color: t.ink, fontFamily: \"inherit\" })\n  .add();\n\n// Zone legend (3 columns)\nconst zoneBaseY = cy + 112;\nconst colW      = chart.chartWidth / 3;\n[\n  { range: \"0 – 30\",   label: \"Needs Improvement\", color: \"#AE3030\" },\n  { range: \"30 – 70\",  label: \"Satisfactory\",       color: \"#DDCC77\" },\n  { range: \"70 – 100\", label: \"Excellent\",           color: \"#009E73\" }\n].forEach((z, i) => {\n  const zx = colW * i + colW / 2;\n  chart.renderer.text(z.range, zx, zoneBaseY)\n    .attr({ align: \"center\", zIndex: 5 })\n    .css({ fontSize: \"15px\", fontWeight: \"700\", color: z.color, fontFamily: \"inherit\" })\n    .add();\n  chart.renderer.text(z.label, zx, zoneBaseY + 24)\n    .attr({ align: \"center\", zIndex: 5 })\n    .css({ fontSize: \"14px\", color: t.inkSoft, fontFamily: \"inherit\" })\n    .add();\n});\n"}