{"spec_id":"line-reaction-coordinate","library":"muix","language":"javascript","code":"// anyplot.ai\n// line-reaction-coordinate: Reaction Coordinate Energy Diagram\n// Library: muix 7.29.1 | JavaScript 22.22.3\n// Quality: 88/100 | Created: 2026-06-24\n//# anyplot-orientation: landscape\n// anyplot.ai\n// line-reaction-coordinate: Reaction Coordinate Energy Diagram\n// Library: MUI X Charts | React | Node 22\n// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope.\n// Quality: pending | Created: 2026-06-24\n\nimport { ChartContainer } from \"@mui/x-charts/ChartContainer\";\nimport { LinePlot } from \"@mui/x-charts/LineChart\";\nimport { ChartsXAxis } from \"@mui/x-charts/ChartsXAxis\";\nimport { ChartsYAxis } from \"@mui/x-charts/ChartsYAxis\";\nimport { ChartsReferenceLine } from \"@mui/x-charts/ChartsReferenceLine\";\nimport { useDrawingArea } from \"@mui/x-charts/hooks\";\nimport Box from \"@mui/material/Box\";\nimport Typography from \"@mui/material/Typography\";\n\nconst t = window.ANYPLOT_TOKENS;\nconst FONT = \"system-ui, -apple-system, sans-serif\";\n\n// Energy diagram: single-step exothermic reaction (kJ/mol)\nconst E_REACTANTS  = 50;\nconst E_TRANSITION = 120;\nconst E_PRODUCTS   = 20;\nconst X_PEAK       = 0.4;   // reaction coordinate at transition state\n\n// Y-axis bounds — must match yAxis min/max below for correct coordinate mapping\nconst Y_MIN = 0;\nconst Y_MAX = 145;\n\n// Smooth energy curve: baseline from 50→20, Gaussian peak at TS (200 points)\n// E(x) = (50 + (20-50)*x) + 82 * exp(-0.5 * ((x - 0.4) / 0.12)^2)\n// At x=0: ≈50.3  |  x=0.4: 120.0  |  x=1: ≈20.0\nconst N = 200;\nconst xData = Array.from({ length: N }, (_, i) => i / (N - 1));\nconst yData = xData.map((x) => {\n  const baseline = E_REACTANTS + (E_PRODUCTS - E_REACTANTS) * x;\n  const peak = 82 * Math.exp(-0.5 * Math.pow((x - X_PEAK) / 0.12, 2));\n  return Math.round((baseline + peak) * 10) / 10;\n});\n\n// Custom SVG annotations: labels + double-headed arrows for Ea and ΔH.\n// Renders inside ChartContainer's SVG; uses useDrawingArea for coordinate mapping.\nfunction EnergyAnnotations() {\n  const { left, top, width, height } = useDrawingArea();\n\n  // Linear mapping: data coords → SVG pixel position\n  const toX = (x) => left + x * width;\n  const toY = (y) => top + ((Y_MAX - y) / (Y_MAX - Y_MIN)) * height;\n\n  const yR  = toY(E_REACTANTS);   // pixel y for reactant level (50)\n  const yTS = toY(E_TRANSITION);  // pixel y for transition state (120)\n  const yP  = toY(E_PRODUCTS);    // pixel y for product level (20)\n\n  // Arrow x positions (in data-coordinate space)\n  const xEa  = toX(0.53);  // Ea annotation — right of peak, descending area\n  const xDH  = toX(0.85);  // ΔH annotation — flat product region\n\n  const AW = 5;  // arrowhead half-width (px)\n  const AH = 9;  // arrowhead height (px)\n\n  const ink     = t.ink;\n  const inkSoft = t.inkSoft;\n  const green   = t.palette[0];\n\n  return (\n    <g fontFamily={FONT}>\n      {/* ── Transition state peak marker — hollow circle on the curve ── */}\n      <circle\n        cx={toX(X_PEAK)}\n        cy={yTS}\n        r={7}\n        fill={t.pageBg}\n        stroke={green}\n        strokeWidth={2.5}\n      />\n\n      {/* ── Ea arrow: reactant level → transition state ── */}\n      <line\n        x1={xEa} y1={yTS + AH + 1}\n        x2={xEa} y2={yR - AH - 1}\n        stroke={ink} strokeWidth={1.5}\n      />\n      {/* Upper tip (at TS level, pointing up) */}\n      <polygon\n        points={`${xEa - AW},${yTS + AH} ${xEa + AW},${yTS + AH} ${xEa},${yTS}`}\n        fill={ink}\n      />\n      {/* Lower tip (at reactant level, pointing down) */}\n      <polygon\n        points={`${xEa - AW},${yR - AH} ${xEa + AW},${yR - AH} ${xEa},${yR}`}\n        fill={ink}\n      />\n      <text\n        x={xEa + 11} y={(yTS + yR) / 2}\n        fill={ink} fontSize={18} dominantBaseline=\"middle\" fontWeight=\"500\"\n      >\n        Ea = 70 kJ/mol\n      </text>\n\n      {/* ── ΔH arrow: reactant level → product level ── */}\n      <line\n        x1={xDH} y1={yR + AH + 1}\n        x2={xDH} y2={yP - AH - 1}\n        stroke={inkSoft} strokeWidth={1.5} strokeDasharray=\"6 3\"\n      />\n      {/* Upper tip (at reactant level, pointing up) */}\n      <polygon\n        points={`${xDH - AW},${yR + AH} ${xDH + AW},${yR + AH} ${xDH},${yR}`}\n        fill={inkSoft}\n      />\n      {/* Lower tip (at product level, pointing down) */}\n      <polygon\n        points={`${xDH - AW},${yP - AH} ${xDH + AW},${yP - AH} ${xDH},${yP}`}\n        fill={inkSoft}\n      />\n      <text\n        x={xDH + 11} y={(yR + yP) / 2}\n        fill={inkSoft} fontSize={18} dominantBaseline=\"middle\"\n      >\n        ΔH = −30 kJ/mol\n      </text>\n\n      {/* ── Transition State label (above peak marker) ── */}\n      <text\n        x={toX(X_PEAK)} y={yTS - 22}\n        fill={ink} fontSize={18} textAnchor=\"middle\" fontWeight=\"500\"\n      >\n        Transition State ‡\n      </text>\n\n      {/* ── Reactants label — offset 22px above dashed reference line ── */}\n      <text\n        x={toX(0.03)} y={yR - 22}\n        fill={ink} fontSize={18} textAnchor=\"start\"\n      >\n        Reactants (50 kJ/mol)\n      </text>\n\n      {/* ── Products label ── */}\n      <text\n        x={toX(0.72)} y={yP - 18}\n        fill={ink} fontSize={18} textAnchor=\"start\"\n      >\n        Products (20 kJ/mol)\n      </text>\n    </g>\n  );\n}\n\nexport default function Chart() {\n  const { width, height } = window.ANYPLOT_SIZE;\n  const titleH = 52;\n\n  return (\n    <Box\n      sx={{\n        width,\n        height,\n        bgcolor: t.pageBg,\n        display: \"flex\",\n        flexDirection: \"column\",\n        pt: \"14px\",\n      }}\n    >\n      <Typography\n        sx={{\n          color: t.ink,\n          fontSize: 22,\n          fontWeight: 500,\n          textAlign: \"center\",\n          lineHeight: 1.2,\n          mb: \"4px\",\n          fontFamily: \"inherit\",\n        }}\n      >\n        line-reaction-coordinate · javascript · muix · anyplot.ai\n      </Typography>\n\n      <ChartContainer\n        width={width}\n        height={height - titleH}\n        margin={{ left: 110, right: 70, top: 44, bottom: 72 }}\n        series={[\n          {\n            type: \"line\",\n            id: \"energy\",\n            data: yData,\n            color: t.palette[0],  // Imprint brand green — first series\n            showMark: false,\n            curve: \"natural\",\n            label: \"Energy profile\",\n          },\n        ]}\n        xAxis={[{\n          data: xData,\n          scaleType: \"linear\",\n          min: 0,\n          max: 1,\n        }]}\n        yAxis={[{\n          min: Y_MIN,\n          max: Y_MAX,\n          valueFormatter: (v) => `${v}`,\n        }]}\n        sx={{\n          \"& .MuiLineElement-root\": { strokeWidth: 3 },\n          \"& .MuiChartsAxis-line\": { stroke: t.inkSoft, strokeWidth: 0.7 },\n          \"& .MuiChartsAxis-tick\": { stroke: t.inkSoft, strokeWidth: 0.7 },\n        }}\n      >\n        {/* Horizontal dashed reference lines at reactant and product energy levels */}\n        <ChartsReferenceLine\n          y={E_REACTANTS}\n          lineStyle={{\n            stroke: t.inkSoft,\n            strokeDasharray: \"8 5\",\n            strokeWidth: 1.2,\n            opacity: 0.65,\n          }}\n        />\n        <ChartsReferenceLine\n          y={E_PRODUCTS}\n          lineStyle={{\n            stroke: t.inkSoft,\n            strokeDasharray: \"8 5\",\n            strokeWidth: 1.2,\n            opacity: 0.65,\n          }}\n        />\n\n        {/* Energy curve */}\n        <LinePlot skipAnimation />\n\n        {/* Axes */}\n        <ChartsXAxis\n          label=\"Reaction Coordinate\"\n          tickLabelStyle={{ fontSize: 14, fill: t.inkSoft, fontFamily: FONT }}\n          labelStyle={{ fontSize: 16, fontWeight: \"500\", fill: t.inkSoft, fontFamily: FONT }}\n          disableLine\n          disableTicks\n        />\n        <ChartsYAxis\n          label=\"Potential Energy (kJ/mol)\"\n          tickLabelStyle={{ fontSize: 14, fill: t.inkSoft, fontFamily: FONT }}\n          labelStyle={{ fontSize: 16, fontWeight: \"500\", fill: t.inkSoft, fontFamily: FONT }}\n          disableLine\n          disableTicks\n        />\n\n        {/* Custom annotations: peak marker, labels, and measurement arrows */}\n        <EnergyAnnotations />\n      </ChartContainer>\n    </Box>\n  );\n}\n"}