// components/account.el - Account dashboard page.
// Client-rendered: El serves the HTML shell, JS handles auth + data.
from founding_badge import { founding_badge, founding_badge_css }
extern fn el_html_doc(lang: String, head: String, body: String) -> String
extern fn el_meta_charset(charset: String) -> String
extern fn el_meta(attrs: String) -> String
extern fn el_title(text: String) -> String
extern fn el_link_stylesheet(href: String) -> String
extern fn el_script_src(src: String, defer_load: Bool) -> String
extern fn el_script_inline(code: String) -> String
extern fn el_nav(attrs: String, children: String) -> String
extern fn el_div(attrs: String, children: String) -> String
extern fn el_a(href: String, attrs: String, children: String) -> String
extern fn el_img(attrs: String) -> String
extern fn el_p(attrs: String, children: String) -> String
extern fn el_h1(attrs: String, text: String) -> String
extern fn el_button(attrs: String, label: String) -> String
extern fn el_span(attrs: String, children: String) -> String
extern fn el_input(type_attr: String, attrs: String) -> String
extern fn el_label(for_id: String, attrs: String, children: String) -> String
extern fn el_ul(attrs: String, children: String) -> String
extern fn el_li(attrs: String, children: String) -> String
fn account_css() -> String {
let css: String = "*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #FAFAF8;
--bg2: #F0F0EC;
--card: #FFFFFF;
--navy: #0052A0;
--navy-d: rgba(0,82,160,.06);
--navy-m: rgba(0,82,160,.12);
--navy-b: rgba(0,82,160,.20);
--navy-65: rgba(0,82,160,.65);
--navy-85: rgba(0,82,160,.85);
--t1: #0D0D14;
--t2: #3A3A4A;
--t3: #6B6B7E;
--t4: rgba(13,13,20,.35);
--border: rgba(0,0,0,.07);
--border2: rgba(0,0,0,.13);
--head: 'Playfair Display', Georgia, serif;
--body: 'IBM Plex Sans', system-ui, sans-serif;
}
html { scroll-behavior: smooth; }
html, body {
background: var(--bg);
color: var(--t1);
font-family: var(--body);
font-weight: 400;
-webkit-font-smoothing: antialiased;
min-height: 100vh;
}
body::before {
content: '';
position: fixed;
inset: 0;
pointer-events: none;
z-index: 0;
background-image:
linear-gradient(rgba(0,0,0,.022) 1px, transparent 1px),
linear-gradient(90deg, rgba(0,0,0,.022) 1px, transparent 1px);
background-size: 48px 48px;
}
#nav {
position: fixed;
top: 0; left: 0; right: 0;
z-index: 100;
background: rgba(250,250,248,.95);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border-bottom: 1px solid var(--border);
}
.nav-inner {
max-width: 1280px;
margin: 0 auto;
padding: 0 2rem;
height: 4rem;
display: flex;
align-items: center;
justify-content: space-between;
}
.nav-logo img { height: 2rem; width: auto; display: block; }
.nav-back {
font-family: var(--body);
font-size: 0.675rem;
font-weight: 400;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--t3);
text-decoration: none;
transition: color 200ms;
}
.nav-back:hover { color: var(--t1); }
.page-shell {
position: relative;
z-index: 1;
min-height: 100vh;
padding: 6rem 2rem 4rem;
}
.page-inner {
max-width: 680px;
margin: 0 auto;
}
.page-heading { margin-bottom: 2.5rem; }
.page-eyebrow {
font-family: var(--body);
font-size: 0.7rem;
font-weight: 500;
letter-spacing: 0.22em;
text-transform: uppercase;
color: var(--navy-65);
margin-bottom: 0.75rem;
}
.page-title {
font-family: 'Playfair Display', Georgia, serif;
font-size: clamp(1.75rem, 4vw, 2.5rem);
font-weight: 600;
line-height: 1.1;
letter-spacing: -0.02em;
color: var(--t1);
}
.account-section {
display: flex;
flex-direction: column;
gap: 1.25rem;
}
.card-dark {
background: var(--card);
border: 1px solid rgba(0,0,0,.07);
box-shadow: 0 2px 12px rgba(13,13,20,.04);
padding: 2rem;
}
.card-label {
font-family: var(--body);
font-size: 0.65rem;
font-weight: 600;
letter-spacing: 0.22em;
text-transform: uppercase;
color: var(--navy-65);
margin-bottom: 1.25rem;
}
.plan-row {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 1.5rem;
flex-wrap: wrap;
}
.plan-name {
font-family: 'Playfair Display', Georgia, serif;
font-size: 1.5rem;
font-weight: 600;
color: var(--t1);
margin-bottom: 0.375rem;
}
.plan-status {
display: inline-flex;
align-items: center;
gap: 0.4rem;
font-size: 0.65rem;
font-weight: 600;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--navy);
background: rgba(0,82,160,.07);
border: 1px solid rgba(0,82,160,.18);
padding: 0.3rem 0.75rem;
}
.plan-status-dot {
width: 5px;
height: 5px;
border-radius: 50%;
background: var(--navy);
flex-shrink: 0;
}
.plan-meta {
margin-top: 1.25rem;
display: flex;
gap: 2rem;
flex-wrap: wrap;
}
.plan-meta-item {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.plan-meta-label {
font-size: 0.6rem;
font-weight: 600;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--t3);
}
.plan-meta-value {
font-size: 0.875rem;
font-weight: 400;
color: var(--t1);
}
.timeline {
display: flex;
flex-direction: column;
gap: 0;
}
.timeline-item {
display: flex;
gap: 1.25rem;
padding-bottom: 1.5rem;
position: relative;
}
.timeline-item:last-child { padding-bottom: 0; }
.timeline-left {
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
width: 1.5rem;
}
.timeline-dot {
width: 10px;
height: 10px;
border-radius: 50%;
border: 2px solid var(--navy);
background: var(--bg);
flex-shrink: 0;
margin-top: 3px;
}
.timeline-dot.filled { background: var(--navy); }
.timeline-line {
flex: 1;
width: 1px;
background: rgba(0,82,160,.15);
margin-top: 4px;
}
.timeline-content {
flex: 1;
padding-bottom: 0.25rem;
}
.timeline-date {
font-size: 0.65rem;
font-weight: 600;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--navy-65);
margin-bottom: 0.375rem;
}
.timeline-text {
font-family: var(--body);
font-weight: 400;
font-size: 0.9rem;
color: var(--t1);
line-height: 1.6;
}
.timeline-sub {
font-family: var(--body);
font-weight: 300;
font-size: 0.8125rem;
color: var(--t2);
line-height: 1.6;
margin-top: 0.25rem;
}
.devices-row {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.device-icon {
width: 2.5rem;
height: 2.5rem;
border: 1px solid rgba(0,82,160,.18);
background: rgba(0,82,160,.04);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.devices-count {
font-family: 'Playfair Display', Georgia, serif;
font-size: 1.25rem;
font-weight: 600;
color: var(--t1);
}
.devices-sub { font-size: 0.8125rem; color: var(--t2); }
.devices-note {
font-family: var(--body);
font-weight: 300;
font-size: 0.8125rem;
color: var(--t3);
line-height: 1.65;
border-top: 1px solid var(--border);
padding-top: 1rem;
margin-top: 0.5rem;
}
.badge-wrap {
display: flex;
flex-direction: column;
align-items: center;
padding: 2rem;
}
.badge-caption {
margin-top: 1.25rem;
font-size: 0.75rem;
font-weight: 400;
letter-spacing: 0.04em;
color: var(--t3);
text-align: center;
}
.signin-wrap {
min-height: 60vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 3rem 1rem;
}
.signin-icon {
width: 4rem;
height: 4rem;
border: 1px solid rgba(0,82,160,.20);
background: rgba(0,82,160,.04);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 1.5rem;
}
.signin-title {
font-family: 'Playfair Display', Georgia, serif;
font-size: clamp(1.5rem, 3vw, 2rem);
font-weight: 600;
color: var(--t1);
margin-bottom: 0.75rem;
}
.signin-sub {
font-family: var(--body);
font-weight: 300;
font-size: 0.9375rem;
color: var(--t2);
max-width: 24rem;
margin: 0 auto 2rem;
line-height: 1.65;
}
.signin-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
width: 100%;
box-sizing: border-box;
font-family: var(--body);
font-size: 0.8125rem;
font-weight: 500;
letter-spacing: 0.04em;
color: var(--t1);
background: var(--card);
border: 1px solid var(--border2);
padding: 0.875rem 1.5rem;
cursor: pointer;
transition: border-color 200ms, background 200ms, box-shadow 200ms;
text-decoration: none;
}
.signin-btn:hover {
border-color: rgba(0,82,160,.35);
background: rgba(0,82,160,.03);
box-shadow: 0 2px 8px rgba(0,82,160,.08);
}
.btn-primary {
display: inline-flex;
align-items: center;
gap: 0.75rem;
font-family: var(--body);
font-size: 0.75rem;
font-weight: 500;
letter-spacing: 0.15em;
text-transform: uppercase;
text-decoration: none;
color: #fff;
background: var(--navy);
padding: 1rem 2rem;
border: none;
cursor: pointer;
transition: background 300ms, box-shadow 300ms;
box-shadow: 0 2px 16px rgba(0,82,160,.20);
}
.btn-primary:hover { background: #0078D4; }
.btn-ghost {
display: inline-flex;
align-items: center;
gap: 0.75rem;
font-family: var(--body);
font-size: 0.75rem;
font-weight: 400;
letter-spacing: 0.15em;
text-transform: uppercase;
text-decoration: none;
color: var(--t2);
background: transparent;
padding: 0.875rem 1.75rem;
border: 1px solid var(--border2);
cursor: pointer;
transition: border-color 300ms, color 300ms;
}
.btn-ghost:hover { border-color: rgba(0,82,160,.35); color: var(--t1); }
.action-row {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 1rem;
}
.action-row-right {
display: flex;
align-items: center;
gap: 0.75rem;
}
.user-chip { display: flex; align-items: center; gap: 0.625rem; }
.user-avatar {
width: 2rem;
height: 2rem;
border-radius: 50%;
background: rgba(0,82,160,.12);
border: 1px solid rgba(0,82,160,.20);
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
font-weight: 600;
color: var(--navy);
overflow: hidden;
flex-shrink: 0;
}
.user-avatar img { width: 100%; height: 100%; object-fit: cover; }
.user-email { font-size: 0.8125rem; color: var(--t2); }
.skeleton {
background: linear-gradient(90deg, rgba(0,0,0,.05) 25%, rgba(0,0,0,.08) 50%, rgba(0,0,0,.05) 75%);
background-size: 200% 100%;
animation: skeleton-shimmer 1.4s infinite;
border-radius: 3px;
}
@keyframes skeleton-shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.navy-line {
height: 1px;
background: linear-gradient(90deg, rgba(0,82,160,.30) 0%, rgba(0,82,160,.08) 100%);
}
.acct-section-header { margin-bottom: 1.25rem; }
.acct-input {
display: block;
width: 100%;
font-family: var(--body);
font-size: 0.875rem;
font-weight: 400;
color: var(--t1);
background: var(--bg);
border: 1px solid var(--border2);
padding: 0.75rem 1rem;
margin-bottom: 0.625rem;
outline: none;
transition: border-color 200ms;
}
.acct-input:focus { border-color: rgba(0,82,160,.45); }
.acct-input::placeholder { color: var(--t4); }
@media (max-width: 600px) {
.plan-row { flex-direction: column; }
.card-dark { padding: 1.5rem; }
.page-shell { padding: 5.5rem 1.25rem 3rem; }
}
::-webkit-scrollbar { width: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--navy); border-radius: 2px; }
::-webkit-scrollbar-thumb:hover { background: #0078D4; }
.acct-email { font-family: var(--body); font-size: .875rem; color: var(--t2); font-weight: 300; }
.acct-header-row { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 2rem; }
.status-badge-preorder { display: inline-flex; align-items: center; gap: .375rem; font-size: .65rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: #92600A; background: rgba(146,96,10,.08); border: 1px solid rgba(146,96,10,.2); padding: .3rem .75rem; }
.download-btn-disabled { display: inline-flex; align-items: center; gap: .75rem; font-family: var(--body); font-size: .75rem; font-weight: 500; letter-spacing: .15em; text-transform: uppercase; color: var(--t3); background: var(--bg2); padding: 1rem 2rem; border: 1px solid var(--border2); cursor: not-allowed; }
.plan-billing-note { font-family: var(--body); font-size: .8125rem; font-weight: 300; color: var(--t2); margin-top: 1rem; line-height: 1.6; }
.plan-billing-link { color: var(--navy-65); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; background: none; border: none; font-family: var(--body); font-size: .8125rem; font-weight: 300; padding: 0; }
.plan-billing-link:hover { color: var(--navy); }
.download-status { font-size: .65rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; color: var(--t3); margin-bottom: .75rem; }
.download-title { font-family: 'Playfair Display', Georgia, serif; font-size: 1.25rem; font-weight: 600; color: var(--t1); margin-bottom: .5rem; }
.download-body { font-family: var(--body); font-weight: 300; font-size: .875rem; color: var(--t2); line-height: 1.7; margin-bottom: 1.5rem; }
.roadmap-list { display: flex; flex-direction: column; gap: 0; }
.roadmap-phase { padding: 1.25rem 0; border-bottom: 1px solid var(--border); }
.roadmap-phase-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: .875rem; }
.roadmap-phase-label { font-family: var(--body); font-size: .7rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--navy); }
.roadmap-phase-date { font-family: var(--body); font-size: .7rem; font-weight: 400; color: var(--t3); letter-spacing: .06em; }
.roadmap-items { list-style: none; display: flex; flex-direction: column; gap: .5rem; }
.roadmap-items li { font-family: var(--body); font-size: .875rem; font-weight: 300; color: var(--t2); line-height: 1.6; padding-left: 1rem; position: relative; }
.roadmap-items li::before { content: \"-\"; position: absolute; left: 0; color: var(--navy-65); }
.signout-section { padding-top: 1rem; display: flex; justify-content: flex-end; }"
""
}
fn account_nav() -> String {
let logo_img: String = el_img("src=\"/assets/brand/neuron-wordmark-on-light.png\" srcset=\"/assets/brand/neuron-wordmark-on-light@2x.png 2x\" alt=\"Neuron\" height=\"28\"")
el_nav(
"id=\"nav\"",
el_div(
"class=\"nav-inner\"",
el_a("/", "class=\"nav-logo\" aria-label=\"Neuron home\"", logo_img) +
el_a("/", "class=\"nav-back\"", "← Home")
)
)
}
fn account_signin_svg_user() -> String {
""
}
fn account_signin_svg_google() -> String {
""
}
fn account_signin_svg_github() -> String {
""
}
fn account_signin_svg_download() -> String {
""
}
fn account_signin_svg_device() -> String {
""
}
fn account_signin_section() -> String {
let or_divider: String = el_div(
"style=\"display:flex;align-items:center;gap:1rem;margin:.125rem 0\"",
el_div("style=\"flex:1;height:1px;background:var(--border2)\"", "") +
el_span("style=\"font-family:var(--body);font-size:.75rem;color:var(--t3);letter-spacing:.06em\"", "or") +
el_div("style=\"flex:1;height:1px;background:var(--border2)\"", "")
)
let email_input: String = ""
let email_btn: String = ""
let email_msg: String = el_p("id=\"acct-email-msg\" style=\"display:none;font-size:.8rem;text-align:center;margin-top:.25rem\"", "")
let options_wrap: String = el_div(
"style=\"width:100%;max-width:20rem;margin:0 auto;display:flex;flex-direction:column;gap:.75rem\"",
el_button("type=\"button\" class=\"signin-btn\" id=\"btn-google\" onclick=\"signInWith('google')\"", account_signin_svg_google() + " Continue with Google") +
el_button("type=\"button\" class=\"signin-btn\" id=\"btn-github\" onclick=\"signInWith('github')\"", account_signin_svg_github() + " Continue with GitHub") +
or_divider +
email_input +
email_btn +
email_msg
)
el_div(
"id=\"signin-section\"",
el_div(
"class=\"signin-wrap\"",
el_div("class=\"signin-icon\"", account_signin_svg_user()) +
el_h1("class=\"signin-title\"", "Sign in to your account") +
el_p("class=\"signin-sub\"", "Enter your email to receive a sign-in link, or continue with a social account.") +
options_wrap
)
)
}
fn account_plan_card() -> String {
el_div(
"class=\"card-dark\" id=\"plan-card\"",
el_p("class=\"card-label\"", "Your Plan") +
el_div(
"class=\"plan-row\"",
el_div(
"",
el_p("class=\"plan-name\" id=\"plan-name-el\"", "Loading...") +
el_div("id=\"plan-status-el\"", "") +
el_div("id=\"plan-billing-note-el\"", "")
)
) +
el_div("class=\"plan-meta\" id=\"plan-meta-el\"", "")
)
}
fn account_roadmap_phase1() -> String {
el_div(
"class=\"roadmap-phase\"",
el_div(
"class=\"roadmap-phase-header\"",
el_span("class=\"roadmap-phase-label\"", "Now shipping") +
el_span("class=\"roadmap-phase-date\"", "Q3 2026")
) +
el_ul(
"class=\"roadmap-items\"",
el_li("", "macOS and Windows clients") +
el_li("", "Persistent memory — local, encrypted") +
el_li("", "Bring your own API keys (OpenAI, Anthropic, Grok)") +
el_li("", "Neuron Inference — priced below the major APIs") +
el_li("", "Gmail, Slack, Google Calendar connectors") +
el_li("", "VS Code extension") +
el_li("", "Founding member badge in-app")
)
)
}
fn account_roadmap_phase2() -> String {
el_div(
"class=\"roadmap-phase\"",
el_div(
"class=\"roadmap-phase-header\"",
el_span("class=\"roadmap-phase-label\"", "Following launch") +
el_span("class=\"roadmap-phase-date\"", "Q4 2026")
) +
el_ul(
"class=\"roadmap-items\"",
el_li("", "Process and knowledge packets") +
el_li("", "Local inference via Ollama") +
el_li("", "Additional connectors — GitHub, Notion, Linear, more") +
el_li("", "Mobile companion app") +
el_li("", "Family accounts")
)
)
}
fn account_roadmap_phase3() -> String {
el_div(
"class=\"roadmap-phase\" style=\"border-bottom:none\"",
el_div(
"class=\"roadmap-phase-header\"",
el_span("class=\"roadmap-phase-label\"", "2027") +
el_span("class=\"roadmap-phase-date\"", "H1 2027")
) +
el_ul(
"class=\"roadmap-items\"",
el_li("", "Imprints — starting with C-suite (CEO, CTO, CFO, CMO, COO)") +
el_li("", "Enterprise accounts") +
el_li("", "Plugin marketplace (open to developers)") +
el_li("", "API access for power users")
)
)
}
fn account_roadmap_section() -> String {
el_div(
"id=\"roadmap-section\" style=\"display:none\"",
el_div(
"class=\"card-dark\"",
el_p("class=\"card-label\"", "Product Roadmap") +
el_p("style=\"font-family:var(--body);font-weight:300;font-size:.875rem;color:var(--t2);line-height:1.7;margin-bottom:1.5rem\"",
"As a Founding Member, you have visibility into what we're building. This is the real roadmap — not marketing."
) +
el_div("class=\"roadmap-list\"", account_roadmap_phase1() + account_roadmap_phase2() + account_roadmap_phase3()) +
el_p("style=\"font-family:var(--body);font-weight:300;font-size:.75rem;color:var(--t3);margin-top:1.5rem;line-height:1.7\"",
"This roadmap is directional, not a commitment. Founding Members shape what gets built and when through their feedback and votes. Your input has real weight."
)
)
)
}
fn account_family_section() -> String {
let child_attest: String = ""
el_div(
"id=\"family-section\" style=\"display:none\"",
el_div(
"class=\"card-dark\"",
el_div(
"class=\"acct-section-header\"",
el_p("class=\"card-label\"", "Family members") +
el_p("style=\"font-size:.8125rem;font-weight:300;color:var(--t2);line-height:1.65\"", "Add up to 5 children to your Founding Member plan. $10/month per child.")
) +
el_div("id=\"family-list\"", "") +
el_div(
"id=\"add-child-form\"",
el_input("email", "id=\"child-email\" placeholder=\"Child's email\" class=\"acct-input\"") +
el_input("number", "id=\"child-dob-year\" placeholder=\"Birth year (e.g. 2012)\" min=\"1990\" max=\"2007\" class=\"acct-input\"") +
child_attest +
el_button("class=\"btn-primary\" onclick=\"addFamilyMember()\" style=\"padding:.75rem 1.5rem\"", "Add family member") +
el_p("id=\"family-msg\" style=\"display:none;font-size:.8rem;margin-top:.5rem\"", "")
)
)
)
}
fn account_badge_section() -> String {
el_div(
"id=\"badge-section\" style=\"display:none\"",
el_div(
"class=\"card-dark\" style=\"padding:2.5rem 2rem;text-align:center;border-top:3px solid var(--navy);background:linear-gradient(135deg,rgba(0,82,160,.03) 0%,rgba(0,82,160,.06) 100%)\"",
el_p("class=\"card-label\" style=\"margin-bottom:1.5rem;letter-spacing:.25em\"", "Your Founding Member Badge") +
el_div("id=\"badge-html-container\" style=\"display:flex;justify-content:center;margin-bottom:1.5rem\"", "") +
el_p("style=\"font-family:var(--body);font-weight:300;font-size:.8125rem;color:var(--t3);line-height:1.7;max-width:24rem;margin:0 auto\"",
"This badge will appear in the Neuron app at launch. Your number is permanent."
)
)
)
}
fn account_timeline_item1() -> String {
el_div(
"class=\"timeline-item\"",
el_div(
"class=\"timeline-left\"",
el_div("class=\"timeline-dot filled\"", "") +
el_div("class=\"timeline-line\"", "")
) +
el_div(
"class=\"timeline-content\"",
el_p("class=\"timeline-date\"", "Now") +
el_p("class=\"timeline-text\"", "Your preorder is confirmed.") +
el_p("class=\"timeline-sub\"", "A confirmation email has been sent to your address. Thank you for being here early.")
)
)
}
fn account_timeline_item2() -> String {
el_div(
"class=\"timeline-item\"",
el_div(
"class=\"timeline-left\"",
el_div("class=\"timeline-dot filled\" style=\"background:rgba(0,82,160,.4);border-color:rgba(0,82,160,.4)\"", "") +
el_div("class=\"timeline-line\"", "")
) +
el_div(
"class=\"timeline-content\"",
el_p("class=\"timeline-date\" style=\"color:var(--navy);font-weight:600\"", "Within 30 days") +
el_p("class=\"timeline-text\"", "Neuron for Mac & Windows ships.") +
el_p("class=\"timeline-sub\"", "You'll receive an email with your download link and license key. macOS and Windows simultaneously.")
)
)
}
fn account_timeline_item3() -> String {
el_div(
"class=\"timeline-item\"",
el_div(
"class=\"timeline-left\"",
el_div("class=\"timeline-dot\"", "")
) +
el_div(
"class=\"timeline-content\"",
el_p("class=\"timeline-date\"", "Q3 2026") +
el_p("class=\"timeline-text\"", "Neuron Inference launches.") +
el_p("class=\"timeline-sub\"", "Our own inference layer, priced below the major APIs. No setup required - it activates automatically for your plan.")
)
)
}
fn account_timeline_card() -> String {
el_div(
"class=\"card-dark\" id=\"timeline-card\"",
el_p("class=\"card-label\"", "What happens next") +
el_div(
"class=\"timeline\"",
account_timeline_item1() +
account_timeline_item2() +
account_timeline_item3()
)
)
}
fn account_download_card() -> String {
el_div(
"class=\"card-dark\" style=\"border-top:3px solid var(--navy)\"",
el_p("class=\"card-label\"", "Download") +
el_p("class=\"download-status\" style=\"color:var(--navy)\"", "Shipping within 30 days") +
el_p("class=\"download-title\"", "Neuron for Mac & Windows") +
el_p("class=\"download-body\"", "macOS and Windows simultaneously. You'll receive a download link and license key by email the moment it ships. Nothing to do right now.") +
el_button("type=\"button\" class=\"download-btn-disabled\" disabled aria-disabled=\"true\"",
account_signin_svg_download() + " Download arriving soon"
)
)
}
fn account_devices_card() -> String {
el_div(
"class=\"card-dark\"",
el_p("class=\"card-label\"", "Devices") +
el_div(
"class=\"devices-row\"",
el_div("class=\"device-icon\"", account_signin_svg_device()) +
el_div(
"",
el_p("class=\"devices-count\"", "2 devices included with your plan") +
el_p("class=\"devices-sub\"", "Currently: Setup at launch")
)
) +
el_p("class=\"devices-note\"", "Device activation happens when you install. Your license key will be in your launch email.")
)
}
fn account_dashboard_section() -> String {
let header_row: String = el_div(
"class=\"acct-header-row\"",
el_div(
"",
el_p("class=\"page-eyebrow\" style=\"margin-bottom:.375rem\"", "Account") +
el_h1("class=\"page-title\" style=\"margin-bottom:.5rem\"", "Your Account") +
el_p("class=\"acct-email\" id=\"acct-header-email\"", "")
) +
el_div(
"style=\"padding-top:.25rem\"",
el_button("type=\"button\" class=\"btn-ghost\" id=\"signout-btn-top\" onclick=\"signOut()\"", "Sign out")
)
)
let signout_row: String = el_div(
"class=\"signout-section\"",
el_button("type=\"button\" class=\"btn-ghost\" id=\"signout-btn\" onclick=\"signOut()\"", "Sign out")
)
el_div(
"id=\"dashboard-section\" style=\"display:none\"",
header_row +
el_div(
"class=\"account-section\"",
account_plan_card() +
account_roadmap_section() +
account_family_section() +
account_badge_section() +
account_timeline_card() +
account_download_card() +
account_devices_card() +
signout_row
)
)
}
fn account_page(supabase_url: String, supabase_anon_key: String) -> String {
let head: String =
el_meta_charset("UTF-8") +
el_meta("name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"") +
el_title("My Account - Neuron") +
el_meta("name=\"description\" content=\"Manage your Neuron account, view your plan, and access your founding member details.\"") +
"" +
"" +
"" +
"" +
el_link_stylesheet("https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,500;0,600;1,400;1,500&family=IBM+Plex+Sans:wght@300;400;500;600&display=swap") +
account_css()
let body: String =
account_nav() +
el_div(
"class=\"page-shell\"",
el_div(
"class=\"page-inner\"",
account_signin_section() +
account_dashboard_section()
)
) +
el_script_src("https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2/dist/umd/supabase.min.js", false) +
el_script_inline("window.NEURON_CFG=window.NEURON_CFG||{};window.NEURON_CFG.supabase_url=\"" + supabase_url + "\";window.NEURON_CFG.supabase_anon_key=\"" + supabase_anon_key + "\";") +
el_script_src("/js/account-auth.js", true) +
el_script_src("/js/account-dashboard.js", true)
el_html_doc("lang=\"en\"", head, body)
}