{"spec_id":"line-confidence","library":"chartjs","language":"javascript","code":"// anyplot.ai\n// line-confidence: Line Plot with Confidence Interval\n// Library: chartjs 4.4.7 | JavaScript 22.23.2\n// Quality: 86/100 | Created: 2026-09-05\n\n//# anyplot-orientation: landscape\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ---------------------------------------\n// Small fixed-seed LCG — the browser has no seeded Math.random.\nlet seed = 42;\nfunction nextRandom() {\n  seed = (seed * 1103515245 + 12345) % 2147483648;\n  return seed / 2147483648;\n}\n\nfunction hexToRgba(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\nconst monthNames = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"];\nconst horizon = 24;\nconst labels = Array.from({ length: horizon }, (_, i) => `${monthNames[i % 12]} ${i < 12 ? \"2025\" : \"2026\"}`);\n\nconst predicted = [];\nconst lowerBound = [];\nconst upperBound = [];\nfor (let i = 0; i < horizon; i++) {\n  const trend = 420 + i * 6.5;\n  const seasonal = 25 * Math.sin((i / 12) * 2 * Math.PI);\n  const noise = (nextRandom() - 0.5) * 12;\n  const value = trend + seasonal + noise;\n  // Forecast uncertainty widens further into the horizon.\n  const margin = 15 + i * 3.2;\n  predicted.push(Math.round(value));\n  lowerBound.push(Math.round(value - margin));\n  upperBound.push(Math.round(value + margin));\n}\n\n// --- Mount -------------------------------------------------------------\nconst canvas = document.createElement(\"canvas\");\ndocument.getElementById(\"container\").appendChild(canvas);\n\n// --- Chart ---------------------------------------------------------------\nnew Chart(canvas, {\n  type: \"line\",\n  data: {\n    labels,\n    datasets: [\n      {\n        label: \"Lower Bound\",\n        data: lowerBound,\n        borderColor: \"transparent\",\n        backgroundColor: \"transparent\",\n        pointRadius: 0,\n        fill: false,\n        tension: 0.3,\n      },\n      {\n        label: \"95% Confidence Interval\",\n        data: upperBound,\n        borderColor: \"transparent\",\n        backgroundColor: hexToRgba(t.palette[0], 0.25),\n        pointRadius: 0,\n        fill: \"-1\",\n        tension: 0.3,\n      },\n      {\n        label: \"Predicted Revenue\",\n        data: predicted,\n        borderColor: t.palette[0],\n        backgroundColor: t.palette[0],\n        borderWidth: 3.5,\n        pointRadius: 3.5,\n        pointBackgroundColor: t.palette[0],\n        pointBorderColor: t.pageBg,\n        pointBorderWidth: 1.5,\n        fill: false,\n        tension: 0.3,\n      },\n    ],\n  },\n  options: {\n    responsive: true,\n    maintainAspectRatio: false,\n    animation: false,\n    plugins: {\n      title: {\n        display: true,\n        text: \"line-confidence · javascript · chartjs · anyplot.ai\",\n        color: t.ink,\n        font: { size: 22 },\n        padding: { bottom: 20 },\n      },\n      legend: {\n        labels: {\n          color: t.ink,\n          font: { size: 16 },\n          filter: (item) => item.datasetIndex !== 0,\n        },\n      },\n    },\n    scales: {\n      x: {\n        ticks: { color: t.inkSoft, font: { size: 14 }, maxRotation: 0, autoSkip: true, maxTicksLimit: 12 },\n        grid: { color: t.grid },\n        title: { display: true, text: \"Month\", color: t.ink, font: { size: 16 } },\n      },\n      y: {\n        ticks: { color: t.inkSoft, font: { size: 14 } },\n        grid: { color: t.grid },\n        title: { display: true, text: \"Revenue ($K)\", color: t.ink, font: { size: 16 } },\n      },\n    },\n  },\n});\n"}