{"spec_id":"feynman-basic","library":"d3","language":"javascript","code":"// anyplot.ai\n// feynman-basic: Feynman Diagram for Particle Interactions\n// Library: d3 7.9.0 | JavaScript 22.22.3\n// Quality: 92/100 | Created: 2026-06-03\n\nconst t = window.ANYPLOT_TOKENS;\nconst { width, height } = window.ANYPLOT_SIZE;\n\n// Imprint palette — data colors identical across themes\nconst FERMION = t.palette[0];  // #009E73 green    — all fermion/quark lines\nconst PHOTON  = t.palette[1];  // #C475FD lavender — photon propagator\nconst GLUON   = t.palette[2];  // #4467A3 blue     — gluon propagator\nconst BOSON   = t.palette[3];  // #BD8233 ochre    — scalar boson (Higgs)\n\n// Wavy line for photon propagator — sine wave perpendicular to path\nfunction wavyPath(x1, y1, x2, y2, waves, amp) {\n  const dx = x2 - x1, dy = y2 - y1;\n  const len = Math.sqrt(dx * dx + dy * dy);\n  const cx = dx / len, cy = dy / len;\n  const n = waves * 24;\n  return d3.line()(Array.from({ length: n + 1 }, (_, i) => {\n    const u = i / n;\n    const p = amp * Math.sin(u * waves * 2 * Math.PI);\n    return [x1 + u * len * cx - p * cy, y1 + u * len * cy + p * cx];\n  }));\n}\n\n// Looped curly path for gluon — cycloidal arches perpendicular to path\nfunction gluonPath(x1, y1, x2, y2, nLoops, radius) {\n  const dx = x2 - x1, dy = y2 - y1;\n  const len = Math.sqrt(dx * dx + dy * dy);\n  const cx = dx / len, cy = dy / len;\n  const n = nLoops * 72;\n  return d3.line()(Array.from({ length: n + 1 }, (_, i) => {\n    const theta = (i / n) * nLoops * 2 * Math.PI;\n    const along = (i / n) * len + radius * Math.sin(theta);\n    const perp  = radius * (1 - Math.cos(theta)); // 0..2r, arches above the path\n    return [x1 + along * cx + perp * cy, y1 + along * cy - perp * cx];\n  }));\n}\n\nconst svg = d3.select(\"#container\").append(\"svg\")\n  .attr(\"width\", width).attr(\"height\", height);\nconst defs = svg.append(\"defs\");\n\n// Arrow marker for fermion direction\ndefs.append(\"marker\").attr(\"id\", \"arrow-f\")\n  .attr(\"markerWidth\", 14).attr(\"markerHeight\", 10)\n  .attr(\"refX\", 14).attr(\"refY\", 5)\n  .attr(\"orient\", \"auto\").attr(\"markerUnits\", \"userSpaceOnUse\")\n  .append(\"polygon\").attr(\"points\", \"0 0, 14 5, 0 10\").attr(\"fill\", FERMION);\n\n// Arrow marker for time axis\ndefs.append(\"marker\").attr(\"id\", \"arrow-t\")\n  .attr(\"markerWidth\", 10).attr(\"markerHeight\", 7)\n  .attr(\"refX\", 10).attr(\"refY\", 3.5)\n  .attr(\"orient\", \"auto\").attr(\"markerUnits\", \"userSpaceOnUse\")\n  .append(\"polygon\").attr(\"points\", \"0 0, 10 3.5, 0 7\").attr(\"fill\", t.inkSoft);\n\nconst SW = 3.5;\n\n// Fermion line with directional arrow at midpoint.\n// Particle flows a→b (forward in time); antiparticle: pass (vertex, leg) so arrow points away.\nfunction fermionLine(ax, ay, bx, by) {\n  const mx = (ax + bx) / 2, my = (ay + by) / 2;\n  svg.append(\"line\")\n    .attr(\"x1\", ax).attr(\"y1\", ay).attr(\"x2\", mx).attr(\"y2\", my)\n    .attr(\"stroke\", FERMION).attr(\"stroke-width\", SW)\n    .attr(\"marker-end\", \"url(#arrow-f)\");\n  svg.append(\"line\")\n    .attr(\"x1\", mx).attr(\"y1\", my).attr(\"x2\", bx).attr(\"y2\", by)\n    .attr(\"stroke\", FERMION).attr(\"stroke-width\", SW);\n}\n\n// ── LEFT PANEL: QED  e⁻ e⁺ → γ* → μ⁻ μ⁺ ──────────────────────────────\n\nconst v1x = width * 0.22, v1y = height * 0.50;\nconst v2x = width * 0.44, v2y = height * 0.50;\n\nfermionLine(width * 0.05, height * 0.33, v1x, v1y);       // e⁻ → vertex\nfermionLine(v1x, v1y, width * 0.05, height * 0.67);       // vertex → e⁺ (antiparticle)\nfermionLine(v2x, v2y, width * 0.59, height * 0.33);       // vertex → μ⁻\nfermionLine(width * 0.59, height * 0.67, v2x, v2y);       // μ⁺ → vertex (antiparticle)\n\n// Virtual photon γ* (wavy)\nsvg.append(\"path\")\n  .attr(\"d\", wavyPath(v1x, v1y, v2x, v2y, 7, 14))\n  .attr(\"stroke\", PHOTON).attr(\"stroke-width\", SW).attr(\"fill\", \"none\");\n\n// Interaction vertex dots\nsvg.append(\"circle\").attr(\"cx\", v1x).attr(\"cy\", v1y).attr(\"r\", 7).attr(\"fill\", t.ink);\nsvg.append(\"circle\").attr(\"cx\", v2x).attr(\"cy\", v2y).attr(\"r\", 7).attr(\"fill\", t.ink);\n\n// Particle labels at external legs\n[\n  [width * 0.05 - 16, height * 0.33 - 10, \"e⁻\", \"end\",    FERMION],\n  [width * 0.05 - 16, height * 0.67 + 20, \"e⁺\", \"end\",    FERMION],\n  [width * 0.59 + 16, height * 0.33 - 10, \"μ⁻\", \"start\",  FERMION],\n  [width * 0.59 + 16, height * 0.67 + 20, \"μ⁺\", \"start\",  FERMION],\n  [(v1x + v2x) / 2,   height * 0.50 - 28, \"γ*\", \"middle\", PHOTON],\n].forEach(([x, y, text, anchor, color]) => {\n  svg.append(\"text\").attr(\"x\", x).attr(\"y\", y).attr(\"text-anchor\", anchor)\n    .attr(\"fill\", color).style(\"font-size\", \"20px\").style(\"font-weight\", \"700\").text(text);\n});\n\n// QED section label\nsvg.append(\"text\").attr(\"x\", (v1x + v2x) / 2).attr(\"y\", height * 0.14)\n  .attr(\"text-anchor\", \"middle\").attr(\"fill\", t.inkSoft)\n  .style(\"font-size\", \"15px\").text(\"QED  ·  e⁻e⁺ → γ* → μ⁻μ⁺\");\n\n// Time axis\nconst tY = height * 0.87;\nsvg.append(\"line\")\n  .attr(\"x1\", width * 0.05).attr(\"y1\", tY)\n  .attr(\"x2\", width * 0.59).attr(\"y2\", tY)\n  .attr(\"stroke\", t.inkSoft).attr(\"stroke-width\", 1.5)\n  .attr(\"marker-end\", \"url(#arrow-t)\");\nsvg.append(\"text\").attr(\"x\", width * 0.59 + 14).attr(\"y\", tY + 5)\n  .attr(\"fill\", t.inkSoft).style(\"font-size\", \"17px\").text(\"time\");\n\n// ── VERTICAL PANEL DIVIDER ──────────────────────────────────────────────\nsvg.append(\"line\")\n  .attr(\"x1\", width * 0.625).attr(\"y1\", height * 0.10)\n  .attr(\"x2\", width * 0.625).attr(\"y2\", height * 0.92)\n  .attr(\"stroke\", t.grid).attr(\"stroke-width\", 1)\n  .attr(\"stroke-dasharray\", \"6,4\");\n\n// ── RIGHT TOP: QCD  q q̄ → g ────────────────────────────────────────────\n\nconst vGx = width * 0.75, vGy = height * 0.30;\n\nfermionLine(width * 0.65, height * 0.18, vGx, vGy);    // q → vertex\nfermionLine(vGx, vGy, width * 0.65, height * 0.42);    // vertex → q̄ (antiparticle)\n\n// Gluon propagator (curly)\nsvg.append(\"path\")\n  .attr(\"d\", gluonPath(vGx, vGy, width * 0.95, height * 0.30, 6, 16))\n  .attr(\"stroke\", GLUON).attr(\"stroke-width\", SW).attr(\"fill\", \"none\");\n\nsvg.append(\"circle\").attr(\"cx\", vGx).attr(\"cy\", vGy).attr(\"r\", 7).attr(\"fill\", t.ink);\n\n[\n  [width * 0.65 - 14, height * 0.18 - 10, \"q\",   \"end\",   FERMION],\n  [width * 0.65 - 14, height * 0.42 + 20, \"q̅\", \"end\",   FERMION],\n  [width * 0.95 + 14, height * 0.30 +  4, \"g\",   \"start\", GLUON],\n].forEach(([x, y, text, anchor, color]) => {\n  svg.append(\"text\").attr(\"x\", x).attr(\"y\", y).attr(\"text-anchor\", anchor)\n    .attr(\"fill\", color).style(\"font-size\", \"20px\").style(\"font-weight\", \"700\").text(text);\n});\n\nsvg.append(\"text\").attr(\"x\", width * 0.80).attr(\"y\", height * 0.12)\n  .attr(\"text-anchor\", \"middle\").attr(\"fill\", t.inkSoft)\n  .style(\"font-size\", \"15px\").text(\"QCD  ·  q q̅ → g\");\n\n// ── HORIZONTAL DIVIDER (right panel) ────────────────────────────────────\nsvg.append(\"line\")\n  .attr(\"x1\", width * 0.64).attr(\"y1\", height * 0.50)\n  .attr(\"x2\", width * 0.97).attr(\"y2\", height * 0.50)\n  .attr(\"stroke\", t.grid).attr(\"stroke-width\", 1)\n  .attr(\"stroke-dasharray\", \"4,4\");\n\n// ── RIGHT BOTTOM: Higgs  q q̄ → H ────────────────────────────────────────\n\nconst vHx = width * 0.75, vHy = height * 0.70;\n\nfermionLine(width * 0.65, height * 0.58, vHx, vHy);    // q → vertex\nfermionLine(vHx, vHy, width * 0.65, height * 0.82);    // vertex → q̄ (antiparticle)\n\n// Scalar Higgs propagator (dashed straight line)\nsvg.append(\"line\")\n  .attr(\"x1\", vHx).attr(\"y1\", vHy)\n  .attr(\"x2\", width * 0.95).attr(\"y2\", height * 0.70)\n  .attr(\"stroke\", BOSON).attr(\"stroke-width\", SW)\n  .attr(\"stroke-dasharray\", \"14,8\");\n\nsvg.append(\"circle\").attr(\"cx\", vHx).attr(\"cy\", vHy).attr(\"r\", 7).attr(\"fill\", t.ink);\n\n[\n  [width * 0.65 - 14, height * 0.58 - 10, \"q\",   \"end\",   FERMION],\n  [width * 0.65 - 14, height * 0.82 + 20, \"q̅\", \"end\",   FERMION],\n  [width * 0.95 + 14, height * 0.70 +  4, \"H\",   \"start\", BOSON],\n].forEach(([x, y, text, anchor, color]) => {\n  svg.append(\"text\").attr(\"x\", x).attr(\"y\", y).attr(\"text-anchor\", anchor)\n    .attr(\"fill\", color).style(\"font-size\", \"20px\").style(\"font-weight\", \"700\").text(text);\n});\n\nsvg.append(\"text\").attr(\"x\", width * 0.80).attr(\"y\", height * 0.54)\n  .attr(\"text-anchor\", \"middle\").attr(\"fill\", t.inkSoft)\n  .style(\"font-size\", \"15px\").text(\"Higgs  ·  q q̅ → H\");\n\n// ── LEGEND — all four line types ────────────────────────────────────────\nconst lY = height * 0.93;\n[\n  { x: width * 0.07,  color: FERMION, type: \"fermion\", text: \"Fermion\" },\n  { x: width * 0.27,  color: PHOTON,  type: \"wavy\",    text: \"Photon (γ)\" },\n  { x: width * 0.47,  color: GLUON,   type: \"gluon\",   text: \"Gluon (g)\" },\n  { x: width * 0.67,  color: BOSON,   type: \"dashed\",  text: \"Scalar Boson (H)\" },\n].forEach(({ x, color, type, text }) => {\n  const x2 = x + 60;\n  if (type === \"fermion\") {\n    const mx = (x + x2) / 2;\n    svg.append(\"line\").attr(\"x1\", x).attr(\"y1\", lY).attr(\"x2\", mx).attr(\"y2\", lY)\n      .attr(\"stroke\", color).attr(\"stroke-width\", 3).attr(\"marker-end\", \"url(#arrow-f)\");\n    svg.append(\"line\").attr(\"x1\", mx).attr(\"y1\", lY).attr(\"x2\", x2).attr(\"y2\", lY)\n      .attr(\"stroke\", color).attr(\"stroke-width\", 3);\n  } else if (type === \"wavy\") {\n    svg.append(\"path\").attr(\"d\", wavyPath(x, lY, x2, lY, 3, 7))\n      .attr(\"stroke\", color).attr(\"stroke-width\", 3).attr(\"fill\", \"none\");\n  } else if (type === \"gluon\") {\n    svg.append(\"path\").attr(\"d\", gluonPath(x, lY, x2, lY, 3, 9))\n      .attr(\"stroke\", color).attr(\"stroke-width\", 3).attr(\"fill\", \"none\");\n  } else {\n    svg.append(\"line\").attr(\"x1\", x).attr(\"y1\", lY).attr(\"x2\", x2).attr(\"y2\", lY)\n      .attr(\"stroke\", color).attr(\"stroke-width\", 3).attr(\"stroke-dasharray\", \"10,6\");\n  }\n  svg.append(\"text\").attr(\"x\", x2 + 12).attr(\"y\", lY + 5)\n    .attr(\"fill\", t.inkSoft).style(\"font-size\", \"17px\").text(text);\n});\n\n// ── TITLE & SUBTITLE ────────────────────────────────────────────────────\nsvg.append(\"text\").attr(\"x\", width / 2).attr(\"y\", 44)\n  .attr(\"text-anchor\", \"middle\").attr(\"fill\", t.ink)\n  .style(\"font-size\", \"22px\").style(\"font-weight\", \"600\")\n  .text(\"feynman-basic · javascript · d3 · anyplot.ai\");\n\nsvg.append(\"text\").attr(\"x\", width / 2).attr(\"y\", 74)\n  .attr(\"text-anchor\", \"middle\").attr(\"fill\", t.inkSoft).style(\"font-size\", \"16px\")\n  .text(\"QED & QCD Feynman Diagrams  ·  All Four Particle Types\");\n"}