{"spec_id":"feynman-basic","library":"echarts","language":"javascript","code":"// anyplot.ai\n// feynman-basic: Feynman Diagram for Particle Interactions\n// Library: echarts 5.5.1 | JavaScript 22.22.3\n// Quality: 93/100 | Created: 2026-06-03\n\n//# anyplot-orientation: landscape\nconst t = window.ANYPLOT_TOKENS;\n\nconst W = 1600, H = 900;\n\n// Imprint palette: four particle types, each a distinct Imprint colour\nconst C_FERMION = t.palette[0];  // #009E73 brand green\nconst C_PHOTON  = t.palette[2];  // #4467A3 blue\nconst C_GLUON   = t.palette[1];  // #DE8F05 amber\nconst C_BOSON   = t.palette[3];  // #CC4C38 red\n\nconst LW = 5, LW_OUT = 6.5;  // outgoing legs slightly thicker\nconst VR = 11, VR_RING = 20;\n\n// ── wavy photon beziers ──────────────────────────────────────────────────────\nfunction wavyBeziers(x1, y1, x2, y2, nWaves, amp, color, lw) {\n  var dx = x2-x1, dy = y2-y1, len = Math.sqrt(dx*dx+dy*dy);\n  var nx = -dy/len, ny = dx/len, n = nWaves*2, elems = [];\n  for (var i = 0; i < n; i++) {\n    var t0=i/n, t1=(i+1)/n, tm=(t0+t1)/2, sign=(i%2===0)?1:-1;\n    elems.push({ type:\"bezierCurve\", shape:{\n      x1:x1+dx*t0, y1:y1+dy*t0,\n      cpx1:x1+dx*tm+nx*amp*sign, cpy1:y1+dy*tm+ny*amp*sign,\n      x2:x1+dx*t1, y2:y1+dy*t1\n    }, style:{stroke:color, lineWidth:lw, fill:\"rgba(0,0,0,0)\"} });\n  }\n  return elems;\n}\n\n// ── curly gluon beziers (loops bulging to one side) ──────────────────────────\nfunction curlyBeziers(x1, y1, x2, y2, nLoops, amp, color, lw) {\n  var dx = x2-x1, dy = y2-y1, len = Math.sqrt(dx*dx+dy*dy);\n  var nx = -dy/len, ny = dx/len, elems = [];\n  for (var i = 0; i < nLoops; i++) {\n    var t0=i/nLoops, t1=(i+1)/nLoops;\n    var ta=t0+(t1-t0)*0.25, tb=t0+(t1-t0)*0.75;\n    elems.push({ type:\"bezierCurve\", shape:{\n      x1:x1+dx*t0, y1:y1+dy*t0,\n      cpx1:x1+dx*ta+nx*amp*2.2, cpy1:y1+dy*ta+ny*amp*2.2,\n      cpx2:x1+dx*tb+nx*amp*2.2, cpy2:y1+dy*tb+ny*amp*2.2,\n      x2:x1+dx*t1, y2:y1+dy*t1\n    }, style:{stroke:color, lineWidth:lw, fill:\"rgba(0,0,0,0)\"} });\n  }\n  return elems;\n}\n\n// ── dashed scalar boson line ─────────────────────────────────────────────────\nfunction dashedLine(x1, y1, x2, y2, dashLen, gapLen, color, lw) {\n  var dx=x2-x1, dy=y2-y1, len=Math.sqrt(dx*dx+dy*dy);\n  var ux=dx/len, uy=dy/len, elems=[], pos=0;\n  while (pos < len) {\n    var end=Math.min(pos+dashLen, len);\n    elems.push({ type:\"polyline\", shape:{ points:[\n      [x1+ux*pos, y1+uy*pos], [x1+ux*end, y1+uy*end]\n    ]}, style:{stroke:color, lineWidth:lw, fill:\"rgba(0,0,0,0)\"} });\n    pos += dashLen+gapLen;\n  }\n  return elems;\n}\n\n// ── arrowhead polygon ────────────────────────────────────────────────────────\nfunction arrow(x1, y1, x2, y2, sz) {\n  var dx=x2-x1, dy=y2-y1, len=Math.sqrt(dx*dx+dy*dy);\n  var ux=dx/len, uy=dy/len, px=-uy, py=ux;\n  var bx=x2-ux*sz, by=y2-uy*sz, w=sz*0.42;\n  return [[x2,y2],[bx+px*w,by+py*w],[bx-px*w,by-py*w]];\n}\n\nfunction lerp(p, q, f) { return [p[0]+(q[0]-p[0])*f, p[1]+(q[1]-p[1])*f]; }\n\n// ── vertex: semi-transparent highlight ring + solid dot ─────────────────────\nfunction vertexDot(cx, cy, ringFill) {\n  return [\n    { type:\"circle\", shape:{cx,cy,r:VR_RING}, style:{fill:ringFill||\"rgba(0,158,115,0.15)\",stroke:\"none\"} },\n    { type:\"circle\", shape:{cx,cy,r:VR}, style:{fill:t.ink} }\n  ];\n}\n\nvar elems = [];\n\n// ════════════════════════════════════════════════════════════════════════════\n// PANEL 1 — QED:  e⁻e⁺ → γ* → μ⁻μ⁺        (left half, x 0–950)\n// ════════════════════════════════════════════════════════════════════════════\nconst V1=[365,476], V2=[585,476];\nconst E_IN=[155,240], P_IN=[155,712];\nconst MU_OUT=[795,240], AP_OUT=[795,712];\n\nelems.push({ type:\"text\", style:{ text:\"QED: Electron-Positron Annihilation\", x:480, y:145,\n  textAlign:\"center\", font:\"bold 18px sans-serif\", fill:t.inkSoft } });\n\n// Incoming legs (particle forward, antiparticle reversed)\nelems.push({ type:\"polyline\", shape:{points:[[E_IN[0],E_IN[1]],[V1[0],V1[1]]]},\n  style:{stroke:C_FERMION,lineWidth:LW,fill:\"rgba(0,0,0,0)\"} });\nvar a=lerp(E_IN,V1,0.47), b=lerp(E_IN,V1,0.53);\nelems.push({ type:\"polygon\", shape:{points:arrow(a[0],a[1],b[0],b[1],24)}, style:{fill:C_FERMION,stroke:\"none\"} });\n\nelems.push({ type:\"polyline\", shape:{points:[[P_IN[0],P_IN[1]],[V1[0],V1[1]]]},\n  style:{stroke:C_FERMION,lineWidth:LW,fill:\"rgba(0,0,0,0)\"} });\na=lerp(P_IN,V1,0.53); b=lerp(P_IN,V1,0.47);\nelems.push({ type:\"polygon\", shape:{points:arrow(a[0],a[1],b[0],b[1],24)}, style:{fill:C_FERMION,stroke:\"none\"} });\n\n// Outgoing legs — slightly thicker to differentiate final-state particles\nelems.push({ type:\"polyline\", shape:{points:[[V2[0],V2[1]],[MU_OUT[0],MU_OUT[1]]]},\n  style:{stroke:C_FERMION,lineWidth:LW_OUT,fill:\"rgba(0,0,0,0)\"} });\na=lerp(V2,MU_OUT,0.47); b=lerp(V2,MU_OUT,0.53);\nelems.push({ type:\"polygon\", shape:{points:arrow(a[0],a[1],b[0],b[1],24)}, style:{fill:C_FERMION,stroke:\"none\"} });\n\nelems.push({ type:\"polyline\", shape:{points:[[V2[0],V2[1]],[AP_OUT[0],AP_OUT[1]]]},\n  style:{stroke:C_FERMION,lineWidth:LW_OUT,fill:\"rgba(0,0,0,0)\"} });\na=lerp(V2,AP_OUT,0.53); b=lerp(V2,AP_OUT,0.47);\nelems.push({ type:\"polygon\", shape:{points:arrow(a[0],a[1],b[0],b[1],24)}, style:{fill:C_FERMION,stroke:\"none\"} });\n\n// Virtual photon propagator (wavy)\nelems = elems.concat(wavyBeziers(V1[0],V1[1],V2[0],V2[1],7,28,C_PHOTON,LW));\n\n// Interaction vertices (ring highlights draw eye to interaction points)\nelems = elems.concat(vertexDot(V1[0],V1[1]));\nelems = elems.concat(vertexDot(V2[0],V2[1]));\n\n// Particle labels — shifted well inward from canvas edges\nelems.push({ type:\"text\", style:{ text:\"e⁻\", x:E_IN[0]-14, y:E_IN[1]-42,\n  font:\"bold 28px sans-serif\", fill:C_FERMION, textAlign:\"right\" } });\nelems.push({ type:\"text\", style:{ text:\"e⁺\", x:P_IN[0]-14, y:P_IN[1]+14,\n  font:\"bold 28px sans-serif\", fill:C_FERMION, textAlign:\"right\" } });\nelems.push({ type:\"text\", style:{ text:\"μ⁻\", x:MU_OUT[0]+14, y:MU_OUT[1]-42,\n  font:\"bold 28px sans-serif\", fill:C_FERMION } });\nelems.push({ type:\"text\", style:{ text:\"μ⁺\", x:AP_OUT[0]+14, y:AP_OUT[1]+14,\n  font:\"bold 28px sans-serif\", fill:C_FERMION } });\nelems.push({ type:\"text\", style:{ text:\"γ*\", x:(V1[0]+V2[0])/2-14, y:V1[1]-50,\n  font:\"bold 30px sans-serif\", fill:C_PHOTON } });\nelems.push({ type:\"text\", style:{ text:\"e⁻e⁺ → γ* → μ⁻μ⁺\", x:480, y:810,\n  textAlign:\"center\", font:\"19px sans-serif\", fill:t.inkSoft } });\n\n// ── Vertical panel divider ───────────────────────────────────────────────────\nelems.push({ type:\"polyline\", shape:{points:[[956,125],[956,830]]},\n  style:{stroke:t.grid,lineWidth:1.5,fill:\"rgba(0,0,0,0)\"} });\n\n// ════════════════════════════════════════════════════════════════════════════\n// PANEL 2a — QCD: Quark-Gluon Exchange       (right top, y 125–498)\n// ════════════════════════════════════════════════════════════════════════════\nconst V1g=[1110,312], V2g=[1390,312];\nconst q1in=[1000,192], q2in=[1000,432];\nconst q1out=[1490,192], q2out=[1490,432];\n\nelems.push({ type:\"text\", style:{ text:\"QCD: Quark-Gluon Exchange\", x:1274, y:145,\n  textAlign:\"center\", font:\"bold 18px sans-serif\", fill:t.inkSoft } });\n\n// Incoming quarks\nelems.push({ type:\"polyline\", shape:{points:[[q1in[0],q1in[1]],[V1g[0],V1g[1]]]},\n  style:{stroke:C_FERMION,lineWidth:LW,fill:\"rgba(0,0,0,0)\"} });\na=lerp(q1in,V1g,0.47); b=lerp(q1in,V1g,0.53);\nelems.push({ type:\"polygon\", shape:{points:arrow(a[0],a[1],b[0],b[1],20)}, style:{fill:C_FERMION,stroke:\"none\"} });\n\nelems.push({ type:\"polyline\", shape:{points:[[q2in[0],q2in[1]],[V1g[0],V1g[1]]]},\n  style:{stroke:C_FERMION,lineWidth:LW,fill:\"rgba(0,0,0,0)\"} });\na=lerp(q2in,V1g,0.53); b=lerp(q2in,V1g,0.47);\nelems.push({ type:\"polygon\", shape:{points:arrow(a[0],a[1],b[0],b[1],20)}, style:{fill:C_FERMION,stroke:\"none\"} });\n\n// Outgoing quarks\nelems.push({ type:\"polyline\", shape:{points:[[V2g[0],V2g[1]],[q1out[0],q1out[1]]]},\n  style:{stroke:C_FERMION,lineWidth:LW_OUT,fill:\"rgba(0,0,0,0)\"} });\na=lerp(V2g,q1out,0.47); b=lerp(V2g,q1out,0.53);\nelems.push({ type:\"polygon\", shape:{points:arrow(a[0],a[1],b[0],b[1],20)}, style:{fill:C_FERMION,stroke:\"none\"} });\n\nelems.push({ type:\"polyline\", shape:{points:[[V2g[0],V2g[1]],[q2out[0],q2out[1]]]},\n  style:{stroke:C_FERMION,lineWidth:LW_OUT,fill:\"rgba(0,0,0,0)\"} });\na=lerp(V2g,q2out,0.53); b=lerp(V2g,q2out,0.47);\nelems.push({ type:\"polygon\", shape:{points:arrow(a[0],a[1],b[0],b[1],20)}, style:{fill:C_FERMION,stroke:\"none\"} });\n\n// Gluon propagator (curly)\nelems = elems.concat(curlyBeziers(V1g[0],V1g[1],V2g[0],V2g[1],6,22,C_GLUON,LW));\n\n// Vertices\nelems = elems.concat(vertexDot(V1g[0],V1g[1],\"rgba(222,143,5,0.18)\"));\nelems = elems.concat(vertexDot(V2g[0],V2g[1],\"rgba(222,143,5,0.18)\"));\n\n// Labels\nelems.push({ type:\"text\", style:{ text:\"q\",  x:q1in[0]-12, y:q1in[1]-36,\n  font:\"bold 22px sans-serif\", fill:C_FERMION, textAlign:\"right\" } });\nelems.push({ type:\"text\", style:{ text:\"q̄\", x:q2in[0]-12, y:q2in[1]+12,\n  font:\"bold 22px sans-serif\", fill:C_FERMION, textAlign:\"right\" } });\nelems.push({ type:\"text\", style:{ text:\"q\",  x:q1out[0]+12, y:q1out[1]-36,\n  font:\"bold 22px sans-serif\", fill:C_FERMION } });\nelems.push({ type:\"text\", style:{ text:\"q̄\", x:q2out[0]+12, y:q2out[1]+12,\n  font:\"bold 22px sans-serif\", fill:C_FERMION } });\nelems.push({ type:\"text\", style:{ text:\"g\",  x:(V1g[0]+V2g[0])/2-10, y:V1g[1]-44,\n  font:\"bold 24px sans-serif\", fill:C_GLUON } });\n\n// ── Horizontal mini-panel divider ────────────────────────────────────────────\nelems.push({ type:\"polyline\", shape:{points:[[960,502],[1582,502]]},\n  style:{stroke:t.grid,lineWidth:1.5,fill:\"rgba(0,0,0,0)\"} });\n\n// ════════════════════════════════════════════════════════════════════════════\n// PANEL 2b — EW: Higgs Scalar Boson Decay  H → ff̄  (right bottom, y 510–830)\n// ════════════════════════════════════════════════════════════════════════════\nconst VH=[1240,660];\nconst Hstart=[1000,660];\nconst fout=[1490,548], fbout=[1490,772];\n\nelems.push({ type:\"text\", style:{ text:\"EW: Higgs Scalar Boson  H → ff̄\", x:1274, y:522,\n  textAlign:\"center\", font:\"bold 18px sans-serif\", fill:t.inkSoft } });\n\n// Incoming Higgs (dashed scalar boson)\nelems = elems.concat(dashedLine(Hstart[0],Hstart[1],VH[0],VH[1],16,10,C_BOSON,LW));\n\n// Outgoing fermion pair\nelems.push({ type:\"polyline\", shape:{points:[[VH[0],VH[1]],[fout[0],fout[1]]]},\n  style:{stroke:C_FERMION,lineWidth:LW_OUT,fill:\"rgba(0,0,0,0)\"} });\na=lerp(VH,fout,0.47); b=lerp(VH,fout,0.53);\nelems.push({ type:\"polygon\", shape:{points:arrow(a[0],a[1],b[0],b[1],20)}, style:{fill:C_FERMION,stroke:\"none\"} });\n\nelems.push({ type:\"polyline\", shape:{points:[[VH[0],VH[1]],[fbout[0],fbout[1]]]},\n  style:{stroke:C_FERMION,lineWidth:LW_OUT,fill:\"rgba(0,0,0,0)\"} });\na=lerp(VH,fbout,0.53); b=lerp(VH,fbout,0.47);\nelems.push({ type:\"polygon\", shape:{points:arrow(a[0],a[1],b[0],b[1],20)}, style:{fill:C_FERMION,stroke:\"none\"} });\n\n// Vertex\nelems = elems.concat(vertexDot(VH[0],VH[1],\"rgba(204,76,56,0.18)\"));\n\n// Labels\nelems.push({ type:\"text\", style:{ text:\"H\",  x:Hstart[0]-12, y:Hstart[1]-8,\n  font:\"bold 24px sans-serif\", fill:C_BOSON, textAlign:\"right\" } });\nelems.push({ type:\"text\", style:{ text:\"f\",  x:fout[0]+12, y:fout[1]-34,\n  font:\"bold 22px sans-serif\", fill:C_FERMION } });\nelems.push({ type:\"text\", style:{ text:\"f̄\", x:fbout[0]+12, y:fbout[1]+10,\n  font:\"bold 22px sans-serif\", fill:C_FERMION } });\n\n// ════════════════════════════════════════════════════════════════════════════\n// LEGEND — all four particle line styles\n// ════════════════════════════════════════════════════════════════════════════\nconst LY = 856;\n\n// Fermion (solid + arrow)\nelems.push({ type:\"polyline\", shape:{points:[[55,LY],[125,LY]]},\n  style:{stroke:C_FERMION,lineWidth:LW,fill:\"rgba(0,0,0,0)\"} });\nelems.push({ type:\"polygon\", shape:{points:arrow(83,LY,93,LY,18)}, style:{fill:C_FERMION,stroke:\"none\"} });\nelems.push({ type:\"text\", style:{ text:\"fermion\", x:136, y:LY-11, font:\"19px sans-serif\", fill:t.inkSoft } });\n\n// Photon (wavy)\nelems = elems.concat(wavyBeziers(360,LY,430,LY,3,14,C_PHOTON,LW));\nelems.push({ type:\"text\", style:{ text:\"photon (γ*)\", x:440, y:LY-11, font:\"19px sans-serif\", fill:t.inkSoft } });\n\n// Gluon (curly)\nelems = elems.concat(curlyBeziers(700,LY,770,LY,4,12,C_GLUON,LW));\nelems.push({ type:\"text\", style:{ text:\"gluon (g)\", x:780, y:LY-11, font:\"19px sans-serif\", fill:t.inkSoft } });\n\n// Scalar boson (dashed)\nelems = elems.concat(dashedLine(1040,LY,1110,LY,14,9,C_BOSON,LW));\nelems.push({ type:\"text\", style:{ text:\"scalar boson (H)\", x:1120, y:LY-11, font:\"19px sans-serif\", fill:t.inkSoft } });\n\n// Time axis\nelems.push({ type:\"polyline\", shape:{points:[[1390,LY],[1525,LY]]},\n  style:{stroke:t.inkSoft,lineWidth:2,fill:\"rgba(0,0,0,0)\"} });\nelems.push({ type:\"polygon\", shape:{points:arrow(1503,LY,1525,LY,12)}, style:{fill:t.inkSoft,stroke:\"none\"} });\nelems.push({ type:\"text\", style:{ text:\"time\", x:1380, y:LY-11, font:\"18px sans-serif\",\n  fill:t.inkSoft, textAlign:\"right\" } });\n\n// ── Render ───────────────────────────────────────────────────────────────────\nconst chart = echarts.init(document.getElementById(\"container\"));\nchart.setOption({\n  animation: false,\n  backgroundColor: t.pageBg,\n  title: {\n    text: \"feynman-basic · javascript · echarts · anyplot.ai\",\n    left: \"center\", top: 22,\n    textStyle: { color: t.ink, fontSize: 30, fontWeight: \"normal\" }\n  },\n  graphic: elems,\n});\n"}