{"spec_id":"line-arrhenius","library":"d3","language":"javascript","code":"// anyplot.ai\n// line-arrhenius: Arrhenius Plot for Reaction Kinetics\n// Library: d3 7.9.0 | JavaScript 22.22.3\n// Quality: 90/100 | Created: 2026-06-24\n\nconst t = window.ANYPLOT_TOKENS;\nconst { width, height } = window.ANYPLOT_SIZE;\n\nconst margin = { top: 120, right: 60, bottom: 80, left: 88 };\nconst iw = width - margin.left - margin.right;\nconst ih = height - margin.top - margin.bottom;\n\n// N2O decomposition kinetics — 10 experimental measurements (Ea ≈ 80 kJ/mol, A ≈ 1×10¹³ s⁻¹)\n// x = 1000/T (10⁻³ K⁻¹), y = ln(k / s⁻¹); noise added to simulate real experiments\nconst data = [\n  { temp: 300, x: 1000 / 300, y: -2.006 },\n  { temp: 320, x: 1000 / 320, y: -0.366 },\n  { temp: 340, x: 1000 / 340, y:  1.834 },\n  { temp: 370, x: 1000 / 370, y:  3.804 },\n  { temp: 400, x: 1000 / 400, y:  6.114 },\n  { temp: 430, x: 1000 / 430, y:  7.464 },\n  { temp: 470, x: 1000 / 470, y:  9.634 },\n  { temp: 510, x: 1000 / 510, y: 10.904 },\n  { temp: 550, x: 1000 / 550, y: 12.554 },\n  { temp: 600, x: 1000 / 600, y: 13.744 },\n];\n\n// Pre-computed Arrhenius linear regression: ln(k) = slope·(1000/T) + intercept\nconst regSlope     = -9.607;   // units: (10⁻³ K⁻¹)⁻¹\nconst regIntercept = 29.915;   // ln(A)\nconst r2           = 0.999;\nconst eaOverR      = 9607;     // K  (= −slope × 1000)\nconst ea_kJmol     = 80;       // kJ mol⁻¹\n\nconst xDomain = [1.55, 3.45];\nconst yDomain = [-4, 16];\n\n// SVG\nconst svg = d3.select(\"#container\")\n  .append(\"svg\")\n  .attr(\"width\", width)\n  .attr(\"height\", height);\n\nconst g = svg.append(\"g\")\n  .attr(\"transform\", `translate(${margin.left},${margin.top})`);\n\n// Scales\nconst xScale = d3.scaleLinear().domain(xDomain).range([0, iw]);\nconst yScale = d3.scaleLinear().domain(yDomain).range([ih, 0]);\n\n// Y-axis grid lines (horizontal, subtle)\nyScale.ticks(10).forEach(tick => {\n  g.append(\"line\")\n    .attr(\"x1\", 0).attr(\"x2\", iw)\n    .attr(\"y1\", yScale(tick)).attr(\"y2\", yScale(tick))\n    .attr(\"stroke\", t.grid)\n    .attr(\"stroke-width\", 1);\n});\n\n// Regression line — Imprint blue (palette[2]), dashed\ng.append(\"path\")\n  .datum([\n    [xDomain[0], regSlope * xDomain[0] + regIntercept],\n    [xDomain[1], regSlope * xDomain[1] + regIntercept],\n  ])\n  .attr(\"d\", d3.line().x(d => xScale(d[0])).y(d => yScale(d[1])))\n  .attr(\"fill\", \"none\")\n  .attr(\"stroke\", t.palette[2])\n  .attr(\"stroke-width\", 2.5)\n  .attr(\"stroke-dasharray\", \"10,5\");\n\n// Data points — Imprint brand green (palette[0]), drawn on top of regression line\ng.selectAll(\".dot\")\n  .data(data)\n  .join(\"circle\")\n  .attr(\"cx\", d => xScale(d.x))\n  .attr(\"cy\", d => yScale(d.y))\n  .attr(\"r\", 9)\n  .attr(\"fill\", t.palette[0])\n  .attr(\"stroke\", t.pageBg)\n  .attr(\"stroke-width\", 2.5);\n\n// Primary X axis (bottom)\nconst xAxisEl = g.append(\"g\")\n  .attr(\"transform\", `translate(0,${ih})`)\n  .call(d3.axisBottom(xScale).ticks(8).tickFormat(d3.format(\".2f\")));\nxAxisEl.selectAll(\"text\").attr(\"fill\", t.inkSoft).style(\"font-size\", \"14px\");\nxAxisEl.selectAll(\"line\").attr(\"stroke\", t.inkSoft);\nxAxisEl.select(\".domain\").attr(\"stroke\", t.inkSoft);\n\n// Y axis (left)\nconst yAxisEl = g.append(\"g\")\n  .call(d3.axisLeft(yScale).ticks(10));\nyAxisEl.selectAll(\"text\").attr(\"fill\", t.inkSoft).style(\"font-size\", \"14px\");\nyAxisEl.selectAll(\"line\").attr(\"stroke\", t.inkSoft);\nyAxisEl.select(\".domain\").attr(\"stroke\", t.inkSoft);\n\n// Secondary x-axis at top of plot area — Temperature (K) reference ticks\nconst tempTicks = [300, 350, 400, 500, 600];\nconst secG = g.append(\"g\");\n\nsecG.append(\"line\")\n  .attr(\"x1\", 0).attr(\"x2\", iw)\n  .attr(\"y1\", 0).attr(\"y2\", 0)\n  .attr(\"stroke\", t.inkSoft)\n  .attr(\"stroke-width\", 1);\n\ntempTicks.forEach(temp => {\n  const xp = xScale(1000 / temp);\n  secG.append(\"line\")\n    .attr(\"x1\", xp).attr(\"x2\", xp)\n    .attr(\"y1\", 0).attr(\"y2\", -8)\n    .attr(\"stroke\", t.inkSoft)\n    .attr(\"stroke-width\", 1);\n  secG.append(\"text\")\n    .attr(\"x\", xp).attr(\"y\", -16)\n    .attr(\"text-anchor\", \"middle\")\n    .attr(\"fill\", t.inkSoft)\n    .style(\"font-size\", \"13px\")\n    .text(`${temp} K`);\n});\n\n// Secondary axis header label\nsvg.append(\"text\")\n  .attr(\"x\", margin.left + iw / 2)\n  .attr(\"y\", margin.top - 40)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.inkSoft)\n  .style(\"font-size\", \"14px\")\n  .text(\"Temperature (K)\");\n\n// X axis label\nsvg.append(\"text\")\n  .attr(\"x\", margin.left + iw / 2)\n  .attr(\"y\", height - 22)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.ink)\n  .style(\"font-size\", \"16px\")\n  .text(\"1/T × 10³  (K⁻¹)\");\n\n// Y axis label (rotated)\nsvg.append(\"text\")\n  .attr(\"transform\", \"rotate(-90)\")\n  .attr(\"x\", -(margin.top + ih / 2))\n  .attr(\"y\", 22)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.ink)\n  .style(\"font-size\", \"16px\")\n  .text(\"ln(k / s⁻¹)\");\n\n// Annotation box — upper-right area of plot (empty: high 1/T region, high y is unoccupied)\nconst boxX = xScale(2.65);\nconst boxY = yScale(14.0);\nconst boxW = 255;\nconst boxH = 90;\n\ng.append(\"rect\")\n  .attr(\"x\", boxX).attr(\"y\", boxY)\n  .attr(\"width\", boxW).attr(\"height\", boxH)\n  .attr(\"fill\", t.elevatedBg)\n  .attr(\"stroke\", t.grid)\n  .attr(\"stroke-width\", 1)\n  .attr(\"rx\", 6);\n\ng.append(\"text\")\n  .attr(\"x\", boxX + 14).attr(\"y\", boxY + 27)\n  .attr(\"fill\", t.ink)\n  .style(\"font-size\", \"15px\")\n  .style(\"font-weight\", \"600\")\n  .text(`R² = ${r2.toFixed(3)}`);\n\ng.append(\"text\")\n  .attr(\"x\", boxX + 14).attr(\"y\", boxY + 52)\n  .attr(\"fill\", t.ink)\n  .style(\"font-size\", \"15px\")\n  .text(`Ea/R = ${eaOverR.toLocaleString()} K`);\n\ng.append(\"text\")\n  .attr(\"x\", boxX + 14).attr(\"y\", boxY + 74)\n  .attr(\"fill\", t.inkSoft)\n  .style(\"font-size\", \"13px\")\n  .text(`Ea ≈ ${ea_kJmol} kJ mol⁻¹`);\n\n// Small legend in bottom-left (T≈590K region, ln(k)≈−1 — no data or line here)\nconst legX = xScale(1.7);\nconst legY = yScale(-1.0);\n\ng.append(\"circle\")\n  .attr(\"cx\", legX + 10).attr(\"cy\", legY)\n  .attr(\"r\", 7)\n  .attr(\"fill\", t.palette[0])\n  .attr(\"stroke\", t.pageBg)\n  .attr(\"stroke-width\", 2);\ng.append(\"text\")\n  .attr(\"x\", legX + 24).attr(\"y\", legY + 5)\n  .attr(\"fill\", t.inkSoft)\n  .style(\"font-size\", \"13px\")\n  .text(\"Experimental data\");\n\ng.append(\"line\")\n  .attr(\"x1\", legX + 2).attr(\"x2\", legX + 18)\n  .attr(\"y1\", legY + 22).attr(\"y2\", legY + 22)\n  .attr(\"stroke\", t.palette[2])\n  .attr(\"stroke-width\", 2.5)\n  .attr(\"stroke-dasharray\", \"6,3\");\ng.append(\"text\")\n  .attr(\"x\", legX + 24).attr(\"y\", legY + 27)\n  .attr(\"fill\", t.inkSoft)\n  .style(\"font-size\", \"13px\")\n  .text(\"Arrhenius fit\");\n\n// Title\nsvg.append(\"text\")\n  .attr(\"x\", width / 2)\n  .attr(\"y\", 44)\n  .attr(\"text-anchor\", \"middle\")\n  .attr(\"fill\", t.ink)\n  .style(\"font-size\", \"22px\")\n  .style(\"font-weight\", \"600\")\n  .text(\"line-arrhenius · javascript · d3 · anyplot.ai\");\n"}