Files
neuron-web/src/comparison.el
T
will.anderson 2553a6b7ac
Dev — Build & local smoke test / build-smoke (pull_request) Failing after 4m48s
feat(native-el-ui): convert all component files to el-html vessel API
Replaced raw HTML heredoc returns with native el_ function calls across
all 21 component files. styles.el intentionally excluded.
2026-05-08 22:35:41 -05:00

180 lines
17 KiB
EmacsLisp

// components/comparison.el - Neuron vs the field comparison section.
extern fn el_section(attrs: String, children: String) -> String
extern fn el_div(attrs: String, children: String) -> String
extern fn el_span(attrs: String, children: String) -> String
extern fn el_h2(attrs: String, text: String) -> String
extern fn el_p(attrs: String, children: String) -> String
extern fn el_img(src: String, alt: String, attrs: String) -> String
extern fn el_em(children: String) -> String
extern fn el_br() -> String
fn comparison_header() -> String {
el_div(
"class=\"comparison-header\" style=\"text-align:center;margin-bottom:4rem\"",
el_div(
"style=\"display:flex;align-items:center;justify-content:center;gap:1.5rem;margin-bottom:2rem\"",
el_div("class=\"navy-line-left\" style=\"width:4rem;flex-shrink:0;transform:scaleX(-1)\"", "") +
el_span("class=\"label reveal\" style=\"color:var(--navy-85)\"", "How we compare") +
el_div("class=\"navy-line-left\" style=\"width:4rem;flex-shrink:0\"", "")
) +
el_h2(
"class=\"display-lg reveal\" style=\"transition-delay:80ms;max-width:36rem;margin:0 auto 1.25rem\"",
"Every other AI forgets you." + el_br() + el_span("class=\"gold\"", "Neuron doesn't.")
) +
el_p("class=\"reveal\" style=\"transition-delay:160ms;font-family:var(--body);font-weight:300;font-size:1rem;color:var(--t2);line-height:1.7;max-width:32rem;margin:0 auto\"",
"The others are tools. Neuron is a relationship. Here's the difference."
)
)
}
fn comparison_table_head() -> String {
let neuron_th: String = "<th style=\"text-align:center;padding:0.75rem 1rem;font-weight:600;color:var(--navy);font-size:0.875rem;width:18%\">" +
"<div style=\"display:inline-flex;flex-direction:column;align-items:center;gap:0.35rem\">" +
el_img("/assets/neuron-icon.png", "Neuron", "style=\"width:28px;height:28px\"") +
"Neuron</div></th>"
let chatgpt_th: String = "<th style=\"text-align:center;padding:0.75rem 1rem;font-weight:400;color:var(--t3);font-size:0.8rem;width:13.5%\">" +
"<div style=\"display:flex;flex-direction:column;align-items:center;gap:0.35rem\">" +
el_img("/assets/brand/openai.svg", "ChatGPT", "style=\"width:28px;height:28px\"") +
"ChatGPT</div></th>"
let claude_th: String = "<th style=\"text-align:center;padding:0.75rem 1rem;font-weight:400;color:var(--t3);font-size:0.8rem;width:13.5%\">" +
"<div style=\"display:flex;flex-direction:column;align-items:center;gap:0.35rem\">" +
el_img("/assets/brand/anthropic.svg", "Claude", "style=\"width:28px;height:28px\"") +
"Claude</div></th>"
let gemini_th: String = "<th style=\"text-align:center;padding:0.75rem 1rem;font-weight:400;color:var(--t3);font-size:0.8rem;width:13.5%\">" +
"<div style=\"display:flex;flex-direction:column;align-items:center;gap:0.35rem\">" +
el_img("/assets/brand/gemini.svg", "Gemini", "style=\"width:28px;height:28px\"") +
"Gemini</div></th>"
let copilot_th: String = "<th style=\"text-align:center;padding:0.75rem 1rem;font-weight:400;color:var(--t3);font-size:0.8rem;width:13.5%\">" +
"<div style=\"display:flex;flex-direction:column;align-items:center;gap:0.35rem\">" +
el_img("/assets/brand/copilot.svg", "Copilot", "style=\"width:28px;height:28px\"") +
"Copilot</div></th>"
"<thead><tr style=\"border-bottom:2px solid rgba(0,82,160,.20)\">" +
"<th style=\"text-align:left;padding:1rem 1.5rem 1rem 0;font-weight:500;letter-spacing:0.08em;color:var(--t3);font-size:0.75rem;text-transform:uppercase;width:28%\">Feature</th>" +
neuron_th + chatgpt_th + claude_th + gemini_th + copilot_th +
"</tr></thead>"
}
fn comparison_rows() -> String {
let row1: String = "<tr style=\"border-bottom:1px solid rgba(0,0,0,.06)\">" +
"<td style=\"padding:1rem 1.5rem 1rem 0;color:var(--t1);font-weight:500\">Persistent memory</td>" +
"<td style=\"text-align:center;padding:1rem\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span><br><span style=\"font-size:0.7rem;color:var(--t3);font-weight:400\">Permanent, structured</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">Limited memory</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span><br><span style=\"font-size:0.7rem\">Resets each session</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span><br><span style=\"font-size:0.7rem\">Resets each session</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span><br><span style=\"font-size:0.7rem\">Resets each session</span></td>" +
"</tr>"
let row2: String = "<tr style=\"border-bottom:1px solid rgba(0,0,0,.06);background:rgba(0,82,160,.02)\">" +
"<td style=\"padding:1rem 1.5rem 1rem 0;color:var(--t1);font-weight:500\">Your data stays local</td>" +
"<td style=\"text-align:center;padding:1rem\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span><br><span style=\"font-size:0.7rem;color:var(--t3);font-weight:400\">Runs on your device</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span><br><span style=\"font-size:0.7rem\">Cloud only</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span><br><span style=\"font-size:0.7rem\">Cloud only</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span><br><span style=\"font-size:0.7rem\">Cloud only</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span><br><span style=\"font-size:0.7rem\">Cloud only</span></td>" +
"</tr>"
let row3: String = "<tr style=\"border-bottom:1px solid rgba(0,0,0,.06)\">" +
"<td style=\"padding:1rem 1.5rem 1rem 0;color:var(--t1);font-weight:500\">No training on your data</td>" +
"<td style=\"text-align:center;padding:1rem\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span><br><span style=\"font-size:0.7rem;color:var(--t3);font-weight:400\">Architecturally impossible</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">Opt-out required</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">Policy-based</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">Policy-based</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">Policy-based</span></td>" +
"</tr>"
let row4: String = "<tr style=\"border-bottom:1px solid rgba(0,0,0,.06);background:rgba(0,82,160,.02)\">" +
"<td style=\"padding:1rem 1.5rem 1rem 0;color:var(--t1);font-weight:500\">Works offline</td>" +
"<td style=\"text-align:center;padding:1rem\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem;color:var(--t3);font-weight:400\">Coming soon</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"</tr>"
let row5: String = "<tr style=\"border-bottom:1px solid rgba(0,0,0,.06)\">" +
"<td style=\"padding:1rem 1.5rem 1rem 0;color:var(--t1);font-weight:500\">Bring your own API keys</td>" +
"<td style=\"text-align:center;padding:1rem\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span><br><span style=\"font-size:0.7rem;color:var(--t3);font-weight:400\">OpenAI, Anthropic, Grok...</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"</tr>"
let row6: String = "<tr style=\"border-bottom:1px solid rgba(0,0,0,.06);background:rgba(0,82,160,.02)\">" +
"<td style=\"padding:1rem 1.5rem 1rem 0;color:var(--t1);font-weight:500\">Structured knowledge graph</td>" +
"<td style=\"text-align:center;padding:1rem\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span><br><span style=\"font-size:0.7rem;color:var(--t3);font-weight:400\">Your memories, organized</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#C44\">&#10005;</span></td>" +
"</tr>"
let row7: String = "<tr style=\"border-bottom:1px solid rgba(0,0,0,.06)\">" +
"<td style=\"padding:1rem 1.5rem 1rem 0;color:var(--t1);font-weight:500\">Images &amp; video generation</td>" +
"<td style=\"text-align:center;padding:1rem\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem;color:var(--t3);font-weight:400\">Coming soon</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span></td>" +
"</tr>"
let row8: String = "<tr style=\"border-bottom:1px solid rgba(0,0,0,.06)\">" +
"<td style=\"padding:1rem 1.5rem 1rem 0;color:var(--t1);font-weight:500\">You own your outputs</td>" +
"<td style=\"text-align:center;padding:1rem\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span><br><span style=\"font-size:0.7rem;color:var(--t3);font-weight:400\">No platform claim, ever</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">ToS-dependent</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">ToS-dependent</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">ToS-dependent</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">ToS-dependent</span></td>" +
"</tr>"
let row9: String = "<tr style=\"border-bottom:1px solid rgba(0,0,0,.06);background:rgba(0,82,160,.02)\">" +
"<td style=\"padding:1rem 1.5rem 1rem 0;color:var(--t1);font-weight:500\">Price (with inference)</td>" +
"<td style=\"text-align:center;padding:1rem\"><span style=\"color:#008040;font-weight:700;font-size:1rem\">$19/mo</span><br><span style=\"font-size:0.7rem;color:var(--t3);font-weight:400\">or $199 founding (first 1,000)</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"font-weight:500;color:var(--t2)\">$20/mo</span><br><span style=\"font-size:0.7rem\">forgets you</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"font-weight:500;color:var(--t2)\">$20/mo</span><br><span style=\"font-size:0.7rem\">no memory</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"font-weight:500;color:var(--t2)\">Free&#8211;$20</span><br><span style=\"font-size:0.7rem\">no memory</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"font-weight:500;color:var(--t2)\">$30/mo</span><br><span style=\"font-size:0.7rem\">Microsoft 365</span></td>" +
"</tr>"
let row10: String = "<tr>" +
"<td style=\"padding:1rem 1.5rem 1rem 0;color:var(--t1);font-weight:500\">Free tier</td>" +
"<td style=\"text-align:center;padding:1rem\"><span style=\"color:#008040;font-weight:700;font-size:1.1rem\">&#10003;</span><br><span style=\"font-size:0.7rem;color:var(--t3);font-weight:400\">Full app, forever</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">GPT-3.5 only</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">Limited</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">Limited</span></td>" +
"<td style=\"text-align:center;padding:1rem;color:var(--t3)\"><span style=\"color:#D4A017\">&#9679;</span><br><span style=\"font-size:0.7rem\">Microsoft 365 required</span></td>" +
"</tr>"
"<tbody>" + row1 + row2 + row3 + row4 + row5 + row6 + row7 + row8 + row9 + row10 + "</tbody>"
}
fn comparison() -> String {
let table: String = el_div(
"class=\"comparison-table reveal\" style=\"transition-delay:200ms;overflow-x:auto;-webkit-overflow-scrolling:touch\"",
"<table style=\"width:100%;min-width:560px;border-collapse:collapse;font-family:var(--body);font-size:0.875rem\">" +
comparison_table_head() +
comparison_rows() +
"</table>"
)
let legend: String = el_div(
"class=\"reveal\" style=\"transition-delay:300ms;margin-top:3rem;display:flex;align-items:center;justify-content:center;gap:3rem;flex-wrap:wrap\"",
el_div("style=\"display:flex;align-items:center;gap:0.5rem;font-family:var(--body);font-size:0.75rem;color:var(--t3)\"",
"<span style=\"color:#008040;font-weight:700\">&#10003;</span> Yes / Supported"
) +
el_div("style=\"display:flex;align-items:center;gap:0.5rem;font-family:var(--body);font-size:0.75rem;color:var(--t3)\"",
"<span style=\"color:#D4A017\">&#9679;</span> Partial / Limited"
) +
el_div("style=\"display:flex;align-items:center;gap:0.5rem;font-family:var(--body);font-size:0.75rem;color:var(--t3)\"",
"<span style=\"color:#C44\">&#10005;</span> No / Not supported"
)
)
let closing: String = el_div(
"class=\"reveal\" style=\"transition-delay:400ms;margin-top:4rem;padding:clamp(1.5rem,4vw,2.5rem) clamp(1.25rem,4vw,3rem);background:var(--card);border:1px solid rgba(0,82,160,.12);border-left:3px solid var(--navy)\"",
el_p("style=\"font-family:var(--body);font-weight:300;font-size:1rem;color:var(--t2);line-height:1.8;margin-bottom:1rem\"",
"The others are impressive. Some of them are extraordinary at what they do. But they are all built on the same assumption: " +
el_em("your context lives in their cloud, session to session, at their discretion.")
) +
el_p("style=\"font-family:var(--body);font-weight:300;font-size:1rem;color:var(--t2);line-height:1.8\"",
"Neuron starts from a different premise. Your memory is yours. It lives on your machine. It compounds over time, not over sessions. The AI that knows you isn&#39;t an AI you borrowed from someone else&#39;s cloud - it&#39;s one that has been building with you, on your terms, since day one."
)
)
el_section(
"id=\"comparison\" aria-label=\"Comparison\" style=\"padding:8rem 2.5rem;background:var(--bg2)\"",
el_div("class=\"container\"", comparison_header() + table + legend + closing)
)
}