{"spec_id":"histogram-stacked","library":"muix","language":"javascript","code":"// anyplot.ai\n// histogram-stacked: Stacked Histogram\n// Library: muix 7.29.1 | JavaScript 22.23.2\n// Quality: 92/100 | Created: 2026-09-05\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\n// --- Data (in-memory, deterministic fixed-seed LCG) -------------------------\n// Commute distance to work (km), binned, broken down by primary transport mode.\nfunction makeLcg(seed) {\n  let state = seed;\n  return () => {\n    state = (state * 1664525 + 1013904223) % 4294967296;\n    return state / 4294967296;\n  };\n}\n\nfunction sampleNormal(rand, mean, stdDev) {\n  const u1 = Math.max(rand(), 1e-9);\n  const u2 = rand();\n  const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n  return mean + z * stdDev;\n}\n\nconst rand = makeLcg(42);\n\nconst GROUPS = [\n  { label: \"Car\", mean: 19, stdDev: 6.5, count: 260, color: t.palette[0] },\n  { label: \"Public transit\", mean: 13, stdDev: 5, count: 220, color: t.palette[1] },\n  { label: \"Bike\", mean: 6, stdDev: 2.5, count: 160, color: t.palette[2] },\n];\n\nconst BIN_WIDTH = 3;\nconst BIN_COUNT = 12;\nconst MAX_DISTANCE = BIN_WIDTH * BIN_COUNT;\nconst binLabels = Array.from(\n  { length: BIN_COUNT },\n  (_, i) => `${i * BIN_WIDTH}-${(i + 1) * BIN_WIDTH}`,\n);\n\nconst groupCounts = GROUPS.map((group) => {\n  const counts = new Array(BIN_COUNT).fill(0);\n  for (let i = 0; i < group.count; i += 1) {\n    const distance = Math.min(\n      Math.max(sampleNormal(rand, group.mean, group.stdDev), 0),\n      MAX_DISTANCE - 0.01,\n    );\n    counts[Math.floor(distance / BIN_WIDTH)] += 1;\n  }\n  return counts;\n});\n\nconst dataset = binLabels.map((bin, i) => {\n  const row = { bin };\n  GROUPS.forEach((group, g) => {\n    row[group.label] = groupCounts[g][i];\n  });\n  return row;\n});\n\n// Dominant mode at the near and far ends of the commute-distance range, used\n// to surface the underlying mode-shift story in the subtitle.\nconst dominantGroupAt = (binIndex) => {\n  let bestGroup = GROUPS[0].label;\n  let bestCount = -1;\n  GROUPS.forEach((group, g) => {\n    if (groupCounts[g][binIndex] > bestCount) {\n      bestCount = groupCounts[g][binIndex];\n      bestGroup = group.label;\n    }\n  });\n  return bestGroup;\n};\nconst nearMode = dominantGroupAt(0);\nconst farMode = dominantGroupAt(BIN_COUNT - 1);\n\nconst TITLE_HEIGHT = 60;\nconst SUBTITLE_HEIGHT = 30;\n\n// --- Chart (default-exported component — the harness mounts it) ------------\nexport default function Chart() {\n  const { width, height } = window.ANYPLOT_SIZE;\n\n  return (\n    <Box sx={{ width, height, display: \"flex\", flexDirection: \"column\", paddingTop: \"20px\" }}>\n      <Typography\n        sx={{ color: t.ink, fontSize: 22, fontWeight: 600, textAlign: \"center\", lineHeight: 1.2 }}\n      >\n        histogram-stacked · javascript · muix · anyplot.ai\n      </Typography>\n      <Typography\n        sx={{\n          color: t.inkSoft,\n          fontSize: 14,\n          fontWeight: 400,\n          textAlign: \"center\",\n          lineHeight: 1.2,\n          marginTop: \"4px\",\n        }}\n      >\n        {`${nearMode} dominates short commutes, ${farMode} takes over as distance grows`}\n      </Typography>\n      <BarChart\n        width={width}\n        height={height - TITLE_HEIGHT - SUBTITLE_HEIGHT}\n        dataset={dataset}\n        colors={GROUPS.map((group) => group.color)}\n        skipAnimation\n        xAxis={[\n          {\n            scaleType: \"band\",\n            dataKey: \"bin\",\n            label: \"Commute Distance (km)\",\n            categoryGapRatio: 0.06,\n          },\n        ]}\n        yAxis={[{ label: \"Number of Commuters\" }]}\n        series={GROUPS.map((group) => ({\n          dataKey: group.label,\n          label: group.label,\n          stack: \"total\",\n          highlightScope: { highlight: \"series\", fade: \"global\" },\n        }))}\n        grid={{ horizontal: true }}\n        margin={{ top: 40, right: 40, bottom: 130, left: 100 }}\n        slotProps={{\n          legend: { position: { vertical: \"bottom\", horizontal: \"middle\" } },\n        }}\n        sx={{\n          \"& .MuiChartsAxis-tickLabel\": { fontSize: \"14px\" },\n          \"& .MuiChartsAxis-label\": { fontSize: \"16px\" },\n          \"& .MuiChartsLegend-label\": { fontSize: \"14px\" },\n          \"& .MuiChartsGrid-line\": { opacity: 0.5 },\n        }}\n      />\n    </Box>\n  );\n}\n"}