{"spec_id":"bar-heart-rate-zones","library":"muix","language":"javascript","code":"// anyplot.ai\n// bar-heart-rate-zones: Time in Heart Rate Zones Bar Chart\n// Library: muix 7.29.1 | JavaScript 22.22.3\n// Quality: 91/100 | Created: 2026-06-14\n//# anyplot-orientation: landscape\n// anyplot.ai\n// bar-heart-rate-zones: Time in Heart Rate Zones Bar Chart\n// Library: MUI X Charts | React | Node 22\n// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope.\n// Quality: pending | Created: 2026-06-14\n\nimport { BarChart } from \"@mui/x-charts/BarChart\";\nimport Box from \"@mui/material/Box\";\nimport Typography from \"@mui/material/Typography\";\n\nconst t = window.ANYPLOT_TOKENS;\n\nconst zoneLabels = [\"Z1 Recovery\", \"Z2 Endurance\", \"Z3 Aerobic\", \"Z4 Threshold\", \"Z5 Maximum\"];\nconst hrRanges   = [\"< 125 bpm\", \"126–145 bpm\", \"146–162 bpm\", \"163–174 bpm\", \"> 174 bpm\"];\nconst minutes    = [8, 22, 15, 12, 3];\n\n// Semantic zone colors: fitness-industry grey/blue/green/ochre/red → nearest Imprint members.\n// Z2 Endurance dominates at 22/60 min (37%) — rendered full opacity.\n// Remaining zones at 75% opacity (hex alpha BF) to direct the eye toward the dominant bar.\nconst zoneColors = [\n  \"#6B6A63BF\",  // Z1 Recovery  — muted anchor, 75%\n  \"#4467A3\",    // Z2 Endurance — position 3 blue, full opacity (dominant)\n  \"#009E73BF\",  // Z3 Aerobic   — position 1 green, 75%\n  \"#BD8233BF\",  // Z4 Threshold — position 4 ochre, 75%\n  \"#AE3030BF\",  // Z5 Maximum   — position 5 matte red, 75%\n];\n\nexport default function Chart() {\n  const W = window.ANYPLOT_SIZE.width;   // 1600 CSS px (landscape mount)\n  const H = window.ANYPLOT_SIZE.height;  // 900 CSS px\n  const CHART_TOP = 84;\n\n  return (\n    <Box sx={{ position: \"relative\", width: W, height: H, bgcolor: t.pageBg }}>\n\n      {/* Title + subtitle */}\n      <Box sx={{ position: \"absolute\", top: 22, left: 56, right: 56 }}>\n        <Typography sx={{ color: t.ink, fontSize: 22, fontWeight: 500, lineHeight: 1.25 }}>\n          bar-heart-rate-zones · javascript · muix · anyplot.ai\n        </Typography>\n        <Typography sx={{ color: t.inkSoft, fontSize: 14, mt: 0.5 }}>\n          60-minute tempo run — time spent in each training intensity zone\n        </Typography>\n      </Box>\n\n      {/* Bar chart */}\n      <Box sx={{ position: \"absolute\", top: CHART_TOP, left: 0, right: 0, bottom: 0 }}>\n        <BarChart\n          width={W}\n          height={H - CHART_TOP}\n          skipAnimation\n          xAxis={[{\n            scaleType: \"band\",\n            data: zoneLabels,\n            colorMap: {\n              type: \"ordinal\",\n              values: zoneLabels,\n              colors: zoneColors,\n            },\n            disableLine: true,\n            disableTicks: true,\n            tickLabelStyle: { fontSize: 15, fill: t.ink, fontWeight: 500 },\n            categoryGapRatio: 0.38,\n          }]}\n          yAxis={[{\n            label: \"Time (minutes)\",\n            labelStyle: { fontSize: 14, fill: t.inkSoft },\n            tickLabelStyle: { fontSize: 13, fill: t.inkSoft },\n            disableTicks: true,\n            max: 28,\n          }]}\n          series={[{\n            data: minutes,\n            label: \"Time in zone\",\n            valueFormatter: (v, ctx) => {\n              const i = ctx?.dataIndex ?? 0;\n              return `${v} min | HR: ${hrRanges[i]}`;\n            },\n          }]}\n          barLabel={(item) => (item.value !== null ? `${item.value} min` : null)}\n          margin={{ top: 30, right: 60, bottom: 80, left: 76 }}\n          grid={{ horizontal: true }}\n          sx={{\n            \"& .MuiBarLabel-root\": {\n              fill: \"#F0EFE8\",  // warm white — readable on all zone colors in both themes\n              fontSize: \"16px\",\n              fontWeight: 700,\n            },\n            \"& .MuiChartsAxis-line\": { stroke: t.inkSoft },\n            \"& .MuiChartsGrid-line\": { stroke: t.grid },\n            \"& .MuiChartsLegend-root\": { display: \"none\" },\n          }}\n        />\n      </Box>\n\n      {/* HR boundary ranges below each zone (bottom strip) */}\n      <Box\n        sx={{\n          position: \"absolute\",\n          bottom: 12,\n          left: 76 + 60,\n          right: 60,\n          display: \"flex\",\n          justifyContent: \"space-around\",\n          pointerEvents: \"none\",\n        }}\n      >\n        {hrRanges.map((range, i) => (\n          <Typography\n            key={i}\n            sx={{ color: t.inkSoft, fontSize: 12, textAlign: \"center\" }}\n          >\n            {range}\n          </Typography>\n        ))}\n      </Box>\n    </Box>\n  );\n}\n"}