{"spec_id":"area-cumulative-flow","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// area-cumulative-flow: Cumulative Flow Diagram for Workflow Analytics\n// Library: highcharts 12.6.0 | JavaScript 22.23.2\n// Quality: 85/100 | Created: 2026-08-18\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Kanban delivery pipeline: cumulative item counts per stage over 90 days.\n// Each stage's exit capacity is a little tighter than the one before it, so\n// every band keeps a readable minimum WIP; Testing's exit rate (into Done) is\n// the most undersized relative to its inflow, so its band widens the most\n// over time — the dominant bottleneck a CFD is meant to surface.\nconst DAYS = 90;\nconst STAGES = [\"Backlog\", \"Analysis\", \"Development\", \"Testing\", \"Done\"];\nconst CAPACITIES = [Infinity, 11, 10, 9, 6];\nconst DAY_MS = 24 * 3600 * 1000;\nconst START = Date.UTC(2026, 0, 1);\n\nlet seed = 42;\nfunction lcg() {\n  seed = (seed * 1103515245 + 12345) % 2147483648;\n  return seed / 2147483648;\n}\n\nconst cumulative = STAGES.map(() => new Array(DAYS).fill(0));\nfor (let day = 0; day < DAYS; day++) {\n  const arrivals = 8 + Math.round(lcg() * 8);\n  cumulative[0][day] = (day === 0 ? 0 : cumulative[0][day - 1]) + arrivals;\n\n  for (let stage = 1; stage < STAGES.length; stage++) {\n    const prevDay = day === 0 ? 0 : cumulative[stage][day - 1];\n    const available = cumulative[stage - 1][day] - prevDay;\n    const capacityNoise = Math.round(lcg() * 3) - 1;\n    const throughput = Math.max(0, Math.min(available, CAPACITIES[stage] + capacityNoise));\n    cumulative[stage][day] = prevDay + throughput;\n  }\n}\n\n// WIP per stage = the gap between two adjacent cumulative curves (the count\n// currently sitting in that stage). Stacking these additively reconstructs\n// the cumulative-flow bands: Done (terminal, no next stage) is its own raw\n// cumulative count.\nconst wip = STAGES.map((name, i) =>\n  cumulative[i].map((value, day) => value - (i + 1 < STAGES.length ? cumulative[i + 1][day] : 0))\n);\n\n// Mark the day the Testing WIP band first crosses 100 items — the point\n// where the bottleneck stops being a minor lag and becomes a visible pileup.\nconst bottleneckDay = wip[3].findIndex((value) => value >= 100);\nconst bottleneckX = START + bottleneckDay * DAY_MS;\n\n// Highcharts stacks the *last* series in the array against the axis, so\n// natural workflow order (Backlog first) already puts Backlog's band at the\n// top of the stack and Done's band at the bottom, as the spec requires.\nconst series = STAGES.map((name, i) => ({\n  name,\n  type: \"area\",\n  data: wip[i].map((value, day) => [START + day * DAY_MS, value]),\n  color: t.palette[i],\n  lineColor: t.palette[i],\n  fillOpacity: 1,\n  lineWidth: 1.5,\n  marker: { enabled: false },\n}));\n\n// --- Chart -------------------------------------------------------------------\nHighcharts.chart(\"container\", {\n  chart: { type: \"area\", backgroundColor: \"transparent\", animation: false,\n           style: { fontFamily: \"inherit\" } },\n  credits: { enabled: false },\n  colors: t.palette,\n  title: { text: \"area-cumulative-flow · javascript · highcharts · anyplot.ai\",\n           style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" } },\n  xAxis: { type: \"datetime\", tickInterval: 14 * DAY_MS,\n           lineColor: t.inkSoft, tickColor: t.inkSoft,\n           labels: { style: { color: t.inkSoft, fontSize: \"14px\" } },\n           plotLines: [{ value: bottleneckX, color: t.inkSoft, width: 1.5, dashStyle: \"Dash\",\n                          zIndex: 5,\n                          label: { text: \"Testing backlog tops 100 items\", rotation: 0,\n                                   x: 6, y: 14,\n                                   style: { color: t.inkSoft, fontSize: \"12px\" } } }] },\n  yAxis: { title: { text: \"Cumulative Items\", style: { color: t.inkSoft, fontSize: \"16px\" } },\n           min: 0, gridLineColor: t.grid,\n           labels: { style: { color: t.inkSoft, fontSize: \"14px\" } } },\n  legend: { itemStyle: { color: t.inkSoft, fontSize: \"14px\" },\n            itemHoverStyle: { color: t.ink } },\n  tooltip: { shared: true, xDateFormat: \"%b %e, %Y\",\n             backgroundColor: t.elevatedBg, borderColor: t.grid,\n             style: { color: t.ink, fontSize: \"13px\" } },\n  plotOptions: { series: { animation: false, stacking: \"normal\" } },\n  series,\n});\n"}