{"spec_id":"energy-level-atomic","library":"highcharts","language":"javascript","code":"// anyplot.ai\n// energy-level-atomic: Atomic Energy Level Diagram\n// Library: highcharts 12.6.0 | JavaScript 22.23.2\n// Quality: 89/100 | Updated: 2026-08-25\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data: hydrogen atom energy levels (E_n = -13.6 / n^2 eV) ---------------\n// `energy` is the real physical value (shown in labels); `yPos` is a\n// schematic plotting position — levels above n=3 sit within ~1 eV of each\n// other and would collide on a literal linear axis, so yPos compresses the\n// lower levels and keeps generous, legible spacing near the ionization limit\n// while preserving the true ordering and the visual sense of convergence.\n// n=1 is pulled up from its literal -13.6 to -10.6 to shrink the otherwise\n// empty gap below n=2 while it still reads as clearly the most-isolated level.\nconst LEVEL_X0 = 0.6;\nconst LEVEL_X1 = 5.6;\n\nconst levels = [\n  { n: 1, energy: -13.6, yPos: -10.6 },\n  { n: 2, energy: -3.4, yPos: -5.9 },\n  { n: 3, energy: -1.51, yPos: -3.5 },\n  { n: 4, energy: -0.85, yPos: -2.2 },\n  { n: 5, energy: -0.54, yPos: -1.3 },\n  { n: 6, energy: -0.38, yPos: -0.6 },\n];\n\n// --- Data: spectral transitions, grouped into series (emission/absorption) -\n// Each transition is drawn as a short vertical segment at its own x column;\n// the marker on the target point renders as the arrowhead.\nconst transitionFamilies = [\n  {\n    name: \"Lyman series (n → 1, emission)\",\n    color: t.palette[0],\n    dashStyle: \"Solid\",\n    transitions: [\n      { x: 7.0, fromN: 2, toN: 1, label: \"121.6 nm\", highlight: true },\n      { x: 8.0, fromN: 3, toN: 1, label: \"102.6 nm\" },\n    ],\n  },\n  {\n    name: \"Balmer series (n → 2, emission)\",\n    color: t.palette[1],\n    dashStyle: \"Solid\",\n    transitions: [\n      { x: 9.2, fromN: 3, toN: 2, label: \"656.3 nm\" },\n      { x: 10.2, fromN: 4, toN: 2, label: \"486.1 nm\" },\n    ],\n  },\n  {\n    name: \"Paschen series (n → 3, emission)\",\n    color: t.palette[2],\n    dashStyle: \"Solid\",\n    transitions: [{ x: 11.2, fromN: 4, toN: 3, label: \"1875 nm\" }],\n  },\n  {\n    name: \"Absorption (1 → 3)\",\n    color: t.palette[3],\n    dashStyle: \"ShortDash\",\n    transitions: [{ x: 12.2, fromN: 1, toN: 3, label: \"102.6 nm\" }],\n  },\n];\n\nconst yPosOf = (n) => levels.find((lvl) => lvl.n === n).yPos;\n\n// Build one line series per family: real point pairs separated by a null\n// point so unrelated transitions in the same family don't get connected.\nconst transitionSeries = transitionFamilies.map((family) => {\n  const data = [];\n  family.transitions.forEach((tr, i) => {\n    const yFrom = yPosOf(tr.fromN);\n    const yTo = yPosOf(tr.toN);\n    const emission = yTo < yFrom;\n    const topY = Math.max(yFrom, yTo);\n    const label = tr.highlight ? `<b>${tr.label} (Ly-α)</b>` : tr.label;\n    data.push(\n      {\n        x: tr.x,\n        y: yFrom,\n        marker: { enabled: false },\n        dataLabels: {\n          enabled: yFrom === topY,\n          custom: { label },\n        },\n      },\n      {\n        x: tr.x,\n        y: yTo,\n        marker: {\n          enabled: true,\n          symbol: emission ? \"triangle-down\" : \"triangle\",\n          radius: tr.highlight ? 12 : 9,\n          fillColor: family.color,\n          lineWidth: 0,\n        },\n        dataLabels: {\n          enabled: yTo === topY,\n          custom: { label },\n        },\n      }\n    );\n    if (i < family.transitions.length - 1) {\n      data.push({ x: tr.x, y: null });\n    }\n  });\n  return {\n    type: \"line\",\n    name: family.name,\n    color: family.color,\n    dashStyle: family.dashStyle,\n    lineWidth: 3,\n    showInLegend: true,\n    marker: { enabled: false },\n    dataLabels: {\n      formatter: function () {\n        return this.point.options.dataLabels &&\n          this.point.options.dataLabels.custom\n          ? this.point.options.dataLabels.custom.label\n          : \"\";\n      },\n      rotation: -90,\n      align: \"left\",\n      x: 10,\n      y: 0,\n      style: { color: t.inkSoft, fontSize: \"13px\", textOutline: \"none\" },\n    },\n    data,\n  };\n});\n\n// Level lines: structural reference elements, not categorical data — drawn\n// in the neutral/ink tone so they read as part of the chart's chrome.\nconst levelSeries = levels.map((lvl) => ({\n  type: \"line\",\n  name: `n = ${lvl.n}`,\n  color: t.ink,\n  lineWidth: 3,\n  showInLegend: false,\n  enableMouseTracking: false,\n  marker: { enabled: false },\n  data: [\n    { x: LEVEL_X0, y: lvl.yPos },\n    {\n      x: LEVEL_X1,\n      y: lvl.yPos,\n      dataLabels: {\n        enabled: true,\n        format: `n = ${lvl.n}  (${lvl.energy.toFixed(2)} eV)`,\n        align: \"left\",\n        x: 10,\n        style: { color: t.ink, fontSize: \"14px\", textOutline: \"none\" },\n      },\n    },\n  ],\n}));\n\nconst ionizationSeries = {\n  type: \"line\",\n  name: \"Ionization limit\",\n  color: t.ink,\n  dashStyle: \"Dash\",\n  lineWidth: 2,\n  showInLegend: false,\n  enableMouseTracking: false,\n  marker: { enabled: false },\n  data: [\n    { x: LEVEL_X0, y: 0 },\n    {\n      x: LEVEL_X1,\n      y: 0,\n      dataLabels: {\n        enabled: true,\n        format: \"Ionization limit (0 eV)\",\n        align: \"left\",\n        x: 10,\n        style: { color: t.inkSoft, fontSize: \"14px\", textOutline: \"none\" },\n      },\n    },\n  ],\n};\n\n// --- Chart -------------------------------------------------------------\nHighcharts.chart(\"container\", {\n  chart: {\n    type: \"line\",\n    backgroundColor: \"transparent\",\n    animation: false,\n    style: { fontFamily: \"inherit\" },\n    spacing: [20, 60, 20, 20],\n  },\n  credits: { enabled: false },\n  colors: t.palette,\n  title: {\n    text: \"energy-level-atomic · javascript · highcharts · anyplot.ai\",\n    style: { color: t.ink, fontSize: \"22px\", fontWeight: \"600\" },\n  },\n  subtitle: {\n    text: \"Hydrogen atom: quantized energy levels (axis compressed schematically near the ionization limit — see eV labels) and spectral transitions\",\n    style: { color: t.inkSoft, fontSize: \"14px\" },\n  },\n  xAxis: {\n    min: 0,\n    max: 14,\n    lineWidth: 0,\n    tickLength: 0,\n    gridLineWidth: 0,\n    labels: { enabled: false },\n    title: { text: null },\n  },\n  yAxis: {\n    min: -11.6,\n    max: 1.3,\n    lineColor: t.inkSoft,\n    tickColor: t.inkSoft,\n    gridLineWidth: 0,\n    title: {\n      text: \"Energy (eV, increasing ↑, non-linear scale)\",\n      style: { color: t.inkSoft, fontSize: \"16px\" },\n    },\n    labels: { enabled: false },\n  },\n  legend: {\n    enabled: true,\n    itemStyle: { color: t.inkSoft, fontSize: \"14px\" },\n    itemHoverStyle: { color: t.ink },\n  },\n  tooltip: { enabled: false },\n  plotOptions: {\n    series: { animation: false, states: { hover: { enabled: false } } },\n  },\n  series: [...levelSeries, ionizationSeries, ...transitionSeries],\n});\n"}