{"spec_id":"area-basic","library":"chartjs","language":"javascript","code":"// anyplot.ai\n// area-basic: Basic Area Chart\n// Library: chartjs 4.4.7 | JavaScript 22.22.3\n// Quality: 92/100 | Created: 2026-06-02\n\n//# anyplot-orientation: landscape\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data: daily website visitors over a 30-day month -----------------------\n// Deterministic seeded LCG so the silhouette is identical across renders.\nconst SEED = 42;\nlet _s = SEED;\nconst rand = () => {\n  _s = (_s * 1664525 + 1013904223) >>> 0;\n  return _s / 0x100000000;\n};\n\nconst days = 30;\nconst labels = [];\nconst visitors = [];\nconst baseline = 2200;\nconst growth = 38;\nconst weekendLift = 520;\nfor (let i = 0; i < days; i++) {\n  const date = new Date(2025, 8, i + 1);\n  labels.push(date.toLocaleDateString(\"en-US\", { month: \"short\", day: \"numeric\" }));\n  const dow = date.getDay();\n  const weekend = dow === 0 || dow === 6 ? weekendLift : 0;\n  const noise = (rand() - 0.5) * 600;\n  visitors.push(Math.round(baseline + growth * i + weekend + noise));\n}\n\n// --- Imprint brand-green fill, vertical gradient for depth ------------------\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}\nconst BRAND = t.palette[0];\n// CanvasGradient: opaque brand green at the line, fading to transparent at the axis.\nconst areaGradient = (ctx) => {\n  const { chartArea } = ctx.chart;\n  if (!chartArea) return hexToRgba(BRAND, 0.35);\n  const g = ctx.chart.ctx.createLinearGradient(0, chartArea.top, 0, chartArea.bottom);\n  g.addColorStop(0, hexToRgba(BRAND, 0.7));\n  g.addColorStop(1, hexToRgba(BRAND, 0.05));\n  return g;\n};\n\n// --- Peak annotation: highlight Sep 28 with a leader line + label -----------\nconst peakIdx = visitors.indexOf(Math.max(...visitors));\nconst peakLabel = `Peak: ${visitors[peakIdx].toLocaleString(\"en-US\")} on ${labels[peakIdx]}`;\nconst peakAnnotation = {\n  id: \"peakAnnotation\",\n  afterDatasetsDraw(chart) {\n    const { ctx, scales } = chart;\n    const x = scales.x.getPixelForValue(peakIdx);\n    const y = scales.y.getPixelForValue(visitors[peakIdx]);\n    const leaderEnd = y - 70;\n    ctx.save();\n    // Leader line\n    ctx.strokeStyle = t.inkSoft;\n    ctx.lineWidth = 1.2;\n    ctx.setLineDash([4, 3]);\n    ctx.beginPath();\n    ctx.moveTo(x, y - 6);\n    ctx.lineTo(x, leaderEnd);\n    ctx.stroke();\n    ctx.setLineDash([]);\n    // Peak dot\n    ctx.fillStyle = BRAND;\n    ctx.beginPath();\n    ctx.arc(x, y, 5.5, 0, Math.PI * 2);\n    ctx.fill();\n    // Label\n    ctx.font = \"500 16px system-ui, -apple-system, sans-serif\";\n    ctx.fillStyle = t.ink;\n    ctx.textBaseline = \"bottom\";\n    const textWidth = ctx.measureText(peakLabel).width;\n    const padX = 10, padY = 6;\n    const boxLeft = Math.min(x - textWidth / 2, scales.x.right - textWidth - padX);\n    const labelX = Math.max(boxLeft, scales.x.left + padX);\n    // Subtle pill background for legibility over the gradient\n    ctx.fillStyle = t.elevatedBg;\n    ctx.strokeStyle = t.grid;\n    ctx.lineWidth = 1;\n    const boxY = leaderEnd - 24;\n    ctx.beginPath();\n    ctx.rect(labelX - padX / 2, boxY, textWidth + padX, 24);\n    ctx.fill();\n    ctx.stroke();\n    ctx.fillStyle = t.ink;\n    ctx.textBaseline = \"middle\";\n    ctx.fillText(peakLabel, labelX, boxY + 12);\n    ctx.restore();\n  },\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: \"Daily visitors\",\n        data: visitors,\n        borderColor: BRAND,\n        backgroundColor: areaGradient,\n        fill: { target: \"origin\", above: areaGradient },\n        borderWidth: 3.5,\n        pointRadius: 0,\n        pointHoverRadius: 6,\n        pointHoverBackgroundColor: BRAND,\n        pointHoverBorderColor: t.pageBg,\n        pointHoverBorderWidth: 2,\n        tension: 0.3,\n      },\n    ],\n  },\n  options: {\n    responsive: true,\n    maintainAspectRatio: false,\n    animation: false,\n    layout: { padding: { top: 24, right: 32, bottom: 12, left: 12 } },\n    plugins: {\n      title: {\n        display: true,\n        text: \"area-basic · javascript · chartjs · anyplot.ai\",\n        color: t.ink,\n        font: { size: 24, weight: \"500\" },\n        padding: { top: 8, bottom: 28 },\n      },\n      legend: { display: false },\n      tooltip: {\n        backgroundColor: t.elevatedBg,\n        titleColor: t.ink,\n        bodyColor: t.inkSoft,\n        borderColor: t.grid,\n        borderWidth: 1,\n        padding: 12,\n        titleFont: { size: 16 },\n        bodyFont: { size: 14 },\n      },\n    },\n    scales: {\n      x: {\n        title: {\n          display: true,\n          text: \"Date (September 2025)\",\n          color: t.ink,\n          font: { size: 20 },\n          padding: { top: 14 },\n        },\n        ticks: {\n          color: t.inkSoft,\n          font: { size: 16 },\n          maxRotation: 0,\n          autoSkip: true,\n          maxTicksLimit: 10,\n        },\n        grid: { display: false },\n        border: { color: t.grid },\n      },\n      y: {\n        title: {\n          display: true,\n          text: \"Visitors per day\",\n          color: t.ink,\n          font: { size: 20 },\n          padding: { bottom: 14 },\n        },\n        ticks: {\n          color: t.inkSoft,\n          font: { size: 16 },\n          padding: 8,\n          callback: (v) => v.toLocaleString(\"en-US\"),\n        },\n        grid: { color: t.grid, drawTicks: false },\n        border: { display: false },\n        beginAtZero: true,\n        suggestedMax: Math.max(...visitors) * 1.1,\n      },\n    },\n    interaction: { mode: \"index\", intersect: false },\n  },\n  plugins: [peakAnnotation],\n});\n"}