[eric] onboarding: Claude-styled interactive flow mock (discovery cards/name/consent/connect -> personalized payoff) + payoff mock

This commit is contained in:
ciregenz
2026-06-30 19:24:57 -07:00
parent f4c090ce9f
commit a54e4ba571
2 changed files with 245 additions and 0 deletions
@@ -0,0 +1,146 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>OpenSwarm onboarding flow (Claude-styled mock)</title>
<!--
Interactive click-through mock of the onboarding flow, styled to match Claude.ai onboarding
(spark + wordmark top-center, serif headings, line icons, white CTA, flat warm near-black,
content vertically centered). One thing per screen: cards -> name -> personalize -> connect ->
payoff. Real fonts are Copernicus/Styrene; this falls back to Georgia + system sans.
-->
<style>
:root{--bg:#1C1B19;--surface:#252420;--surface2:#2b2a25;--white:#F3F1EA;--muted:#8F8D86;
--ghost:#6f6e68;--coral:#D97757;--border:rgba(243,241,234,0.08);--border2:rgba(243,241,234,0.14);
--serif:"Copernicus","Tiempos Headline",Georgia,"Times New Roman",serif;
--sans:"Styrene B","Anthropic Sans",-apple-system,"SF Pro Text",system-ui,sans-serif;}
*{margin:0;padding:0;box-sizing:border-box}
html,body{height:100%}
body{background:var(--bg);font-family:var(--sans);-webkit-font-smoothing:antialiased;color:var(--white);overflow:hidden}
.brand{position:fixed;top:34px;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:9px;z-index:5}
.brand .wm{font-family:var(--serif);font-size:25px;font-weight:500;letter-spacing:.2px}
.brand .spark{line-height:0}
.screen{position:fixed;inset:0;display:none;flex-direction:column;align-items:center;justify-content:center}
.screen.on{display:flex;animation:fade .5s ease}
@keyframes fade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.wrap{width:min(720px,88vw);display:flex;flex-direction:column;align-items:center;text-align:center}
h1{font-family:var(--serif);font-weight:500;font-size:33px;line-height:1.15;letter-spacing:-0.005em;color:var(--white)}
.sub{margin-top:12px;font-size:15px;color:var(--muted)}
.cards{margin-top:52px;display:flex;gap:18px;justify-content:center;width:100%}
.card{flex:1;min-height:250px;padding:34px 22px;border-radius:16px;background:var(--surface);border:1px solid var(--border);
cursor:pointer;display:flex;flex-direction:column;align-items:center;transition:all .18s ease}
.card:hover{background:var(--surface2);border-color:var(--border2);transform:translateY(-2px)}
.card .ic{color:var(--white);margin-top:10px;margin-bottom:auto;opacity:.92}
.card .t{font-family:var(--serif);font-size:21px;font-weight:500;margin-top:28px}
.card .d{margin-top:8px;font-size:13px;color:var(--muted);line-height:1.4;max-width:170px}
.field{margin-top:46px;width:100%;max-width:430px}
.input{width:100%;background:var(--surface);border:1px solid var(--border2);border-radius:12px;padding:15px 18px;color:var(--white);font-size:16px;font-family:var(--sans);text-align:left;outline:none}
.input::placeholder{color:var(--ghost)}
.input:focus{border-color:var(--coral)}
.pill{margin-top:24px;width:100%;max-width:430px;background:var(--white);color:#1a1917;border:none;border-radius:11px;padding:14px;font:inherit;font-size:15px;font-weight:600;cursor:pointer;transition:filter .15s}
.pill:hover{filter:brightness(.94)}
.ghost{margin-top:26px;color:var(--muted);font-size:14px;cursor:pointer}.ghost:hover{color:var(--white)}
.stream{font-family:var(--serif);font-weight:500;font-size:29px;line-height:1.4;max-width:620px;min-height:4.4em;color:var(--white)}
.caret{display:inline-block;width:2px;height:1.02em;background:var(--coral);margin-left:3px;vertical-align:-3px;animation:blink 1s steps(1) infinite}
@keyframes blink{50%{opacity:0}}
.btns{margin-top:14px;display:flex;flex-direction:column;align-items:center;gap:16px}
.connlist{margin-top:44px;width:100%;max-width:440px;display:flex;flex-direction:column;gap:11px}
.conn{display:flex;align-items:center;gap:14px;background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:16px 18px;text-align:left}
.conn .cn{font-size:15px;font-weight:500}.conn .cd{font-size:12.5px;color:var(--muted);margin-top:2px}
.conn .cbtn{margin-left:auto;font-size:13px;color:var(--white);background:var(--surface2);border:1px solid var(--border2);border-radius:999px;padding:6px 15px;cursor:pointer}
.conn .cbtn.done{color:var(--muted);background:transparent}
.remark{margin-top:10px;font-size:15px;color:var(--muted);font-style:italic}
.insight{margin-top:20px;font-size:16px;color:var(--muted);line-height:1.5;max-width:540px}
.prompt{margin-top:26px;width:100%;max-width:600px;background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:20px 22px;text-align:left}
.prompt .p{font-size:15.5px;line-height:1.55;color:var(--white)}
.composer{margin-top:16px;display:flex;align-items:center;gap:12px;color:var(--muted);font-size:13px;border-top:1px solid var(--border);padding-top:14px}
.composer .run{margin-left:auto;background:var(--white);color:#1a1917;border-radius:9px;padding:7px 15px;font-weight:600;cursor:pointer}
.ideas{margin-top:24px;width:100%;max-width:600px;text-align:left}.ideas .lbl{font-size:13px;color:var(--muted);margin-bottom:8px}
.idea{display:flex;align-items:center;gap:13px;padding:10px 10px;font-size:15.5px;cursor:pointer;border-radius:9px;transition:background .15s}.idea:hover{background:var(--surface)}
.idea .ii{color:var(--muted);width:22px;display:flex;justify-content:center}
.dots{position:fixed;bottom:40px;left:50%;transform:translateX(-50%);display:flex;gap:9px}
.dot{width:6px;height:6px;border-radius:50%;background:rgba(243,241,234,0.16)}.dot.on{background:var(--coral)}
.restart{position:fixed;bottom:34px;right:30px;font-size:12px;color:var(--ghost);cursor:pointer}
@media(prefers-reduced-motion:reduce){*{animation:none!important}.caret{animation:none!important}}
</style></head><body>
<div class="brand"><span class="spark"></span><span class="wm">OpenSwarm</span></div>
<div class="screen" id="s1"><div class="wrap">
<h1>Where do you want help first?</h1>
<div class="cards">
<div class="card" onclick="show(2)"><span class="ic" data-i="work"></span><div class="t">My work</div><div class="d">clients, admin, the busywork</div></div>
<div class="card" onclick="show(2)"><span class="ic" data-i="home"></span><div class="t">My personal life</div><div class="d">errands, plans, life admin</div></div>
<div class="card" onclick="show(2)"><span class="ic" data-i="build"></span><div class="t">Building things</div><div class="d">tools, sites, ideas</div></div>
</div>
<div class="ghost" onclick="show(5)">just show me</div>
</div></div>
<div class="screen" id="s2"><div class="wrap">
<h1>What should I call you?</h1>
<div class="sub">so this feels like yours, not a demo</div>
<div class="field"><input class="input" placeholder="Your name" value=""></div>
<button class="pill" onclick="show(3)">Continue</button>
<div class="ghost" onclick="show(3)">skip</div>
</div></div>
<div class="screen" id="s3"><div class="wrap">
<div class="stream"><span id="streamtxt"></span><span class="caret"></span></div>
<div class="btns" id="d3btns" style="opacity:0"><button class="pill" onclick="show(4)">Yes, get to know me</button><span class="ghost" style="margin-top:2px" onclick="show(5)">not now</span></div>
</div></div>
<div class="screen" id="s4"><div class="wrap">
<h1>Connect what I can work with</h1>
<div class="sub">optional, and I&#39;ll only ever read it to understand you</div>
<div class="connlist">
<div class="conn"><span class="ci" data-i="mail"></span><div><div class="cn">Google</div><div class="cd">Gmail, Calendar, Drive</div></div><span class="cbtn" onclick="this.textContent='Connected';this.classList.add('done')">Connect</span></div>
<div class="conn"><span class="ci" data-i="doc"></span><div><div class="cn">Notion</div><div class="cd">notes, docs, tasks</div></div><span class="cbtn" onclick="this.textContent='Connected';this.classList.add('done')">Connect</span></div>
<div class="conn"><span class="ci" data-i="chat"></span><div><div class="cn">Slack</div><div class="cd">messages, channels</div></div><span class="cbtn" onclick="this.textContent='Connected';this.classList.add('done')">Connect</span></div>
</div>
<button class="pill" style="max-width:200px" onclick="show(5)">Continue</button>
<div class="ghost" onclick="show(5)">skip for now</div>
</div></div>
<div class="screen" id="s5"><div class="wrap">
<h1>Good evening, Eric.</h1>
<div class="remark">(someone&#39;s been busy, huh)</div>
<div class="insight">I see you&#39;re juggling client work and a launch. Here&#39;s one I can do right now, plus a few I lined up for you.</div>
<div class="prompt"><div class="p">Send me a morning briefing: today&#39;s calendar, anything urgent in my email, and what my competitors shipped. Show me a sample before it goes live.</div>
<div class="composer"><span>+</span><span>Cowork</span><span style="margin-left:8px">Opus 4.8</span><span class="run">Run</span></div></div>
<div class="ideas"><div class="lbl">Ideas for you</div>
<div class="idea"><span class="ii" data-i="sun"></span> Send me a morning briefing</div>
<div class="idea"><span class="ii" data-i="tray"></span> Clean up + chase my overdue invoices</div>
<div class="idea"><span class="ii" data-i="build"></span> Build me a lightweight client tracker</div>
<div class="idea"><span class="ii" data-i="globe"></span> Watch my 3 competitors, ping me on changes</div>
</div>
</div></div>
<div class="dots" id="dots"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="dot"></span></div>
<div class="restart" onclick="show(1)">start over</div>
<script>
function spark(sz,c){var r='';for(var i=0;i<12;i++){var a=i*30*Math.PI/180;var x1=12+3.1*Math.cos(a),y1=12+3.1*Math.sin(a),x2=12+9.3*Math.cos(a),y2=12+9.3*Math.sin(a);r+='<line x1="'+x1.toFixed(2)+'" y1="'+y1.toFixed(2)+'" x2="'+x2.toFixed(2)+'" y2="'+y2.toFixed(2)+'"/>';}return '<svg width="'+sz+'" height="'+sz+'" viewBox="0 0 24 24" stroke="'+c+'" stroke-width="1.7" stroke-linecap="round">'+r+'</svg>';}
var ICON={
work:'<rect x="3" y="7.5" width="18" height="12" rx="2"/><path d="M8 7.5V6a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1.5"/><path d="M3 13h18"/>',
home:'<path d="M4 10.5 12 4l8 6.5"/><path d="M6 9.5V20h12V9.5"/><path d="M10 20v-5h4v5"/>',
build:'<path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/>',
mail:'<rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 6 9-6"/>',
doc:'<path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"/><path d="M14 3v5h5"/>',
chat:'<path d="M21 15a2 2 0 0 1-2 2H8l-4 4V5a2 2 0 0 1 2-2h13a2 2 0 0 1 2 2z"/>',
sun:'<circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/>',
tray:'<path d="M3 12h4l2 3h6l2-3h4"/><path d="M5 6h14l2 6v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-6z"/>',
globe:'<circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3a15 15 0 0 1 0 18a15 15 0 0 1 0-18"/>'};
function ico(name,sz,sw){return '<svg width="'+sz+'" height="'+sz+'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="'+(sw||1.5)+'" stroke-linecap="round" stroke-linejoin="round">'+ICON[name]+'</svg>';}
document.querySelectorAll('.spark').forEach(function(s){s.innerHTML=spark(20,'#D97757');});
document.querySelectorAll('.card .ic').forEach(function(e){e.innerHTML=ico(e.dataset.i,46,1.3);});
document.querySelectorAll('.conn .ci').forEach(function(e){e.innerHTML=ico(e.dataset.i,20);});
document.querySelectorAll('.idea .ii').forEach(function(e){e.innerHTML=ico(e.dataset.i,17);});
window.typeS3=function(){var el=document.getElementById('streamtxt');var btns=document.getElementById('d3btns');
var full="Want me to actually get you? Say yes and I'll take a quick look at whatever you connect, so everything I show is aimed at your world, not a generic demo.";
el.textContent='';btns.style.opacity=0;var i=0;clearInterval(window.__tw);
window.__tw=setInterval(function(){el.textContent=full.slice(0,++i);if(i>=full.length){clearInterval(window.__tw);btns.style.transition='opacity .6s';btns.style.opacity=1;}},16);};
window.show=function(n){document.querySelectorAll('.screen').forEach(function(s){s.classList.remove('on')});
document.getElementById('s'+n).classList.add('on');
document.getElementById('dots').style.display=(n<=4?'flex':'none');
document.querySelectorAll('.dot').forEach(function(d,idx){d.classList.toggle('on',idx===(n-1))});
if(n===3)window.typeS3();};
window.show(1);
</script>
</body></html>
@@ -0,0 +1,99 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>OpenSwarm value payoff (beat 2 mock)</title>
<!--
Static mock of BEAT 2: after the one-tap personalize, the value lands immediately.
A real agent is already DOING their task (live browser), captioned as the differentiator,
with more tailored valuable outcomes to pick + a type-your-own. This is the "wow from real
value" beat, not a screen they read. Premium warm skin, same tokens as welcomeScreen.
-->
<style>
:root {
--bg:#1A1918; --surface:rgba(250,249,245,0.045); --border:rgba(250,249,245,0.09);
--border-hover:rgba(196,99,58,0.55); --white:#FAF9F5; --muted:#9C9A92;
--ghost:rgba(156,154,146,0.6); --accent:#C4633A; --accent-soft:rgba(196,99,58,0.12);
--ok:#7AB948; --frame:#0F0D0B;
--serif:"Tiempos Headline","Anthropic Serif",Georgia,serif;
--sans:"Anthropic Sans",-apple-system,"SF Pro Text",system-ui,sans-serif;
--ease:cubic-bezier(0.16,1,0.3,1);
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{height:100%}
body{
background:var(--bg);
background-image:radial-gradient(55% 45% at 50% 0%, rgba(196,99,58,0.09) 0%, transparent 70%);
font-family:var(--sans); -webkit-font-smoothing:antialiased; color:var(--white);
display:flex; align-items:center; justify-content:center; overflow:hidden;
}
.wrap{ width:min(720px,90vw); }
.ctx{ display:flex; align-items:center; gap:8px; color:var(--muted); font-size:14px; margin-bottom:22px; }
.ctx .chip{ background:var(--surface); border:1px solid var(--border); border-radius:999px; padding:5px 12px; }
h1{ font-family:var(--serif); font-weight:500; font-size:30px; letter-spacing:-0.01em; margin-bottom:20px; }
/* Hero: the agent already DOING it, live */
.hero{ background:var(--surface); border:1px solid var(--border); border-radius:18px; padding:16px; margin-bottom:14px; }
.browser{ background:var(--frame); border:1px solid rgba(250,249,245,0.07); border-radius:12px; overflow:hidden; }
.bar{ display:flex; align-items:center; gap:7px; padding:9px 12px; border-bottom:1px solid rgba(250,249,245,0.06); }
.dot{ width:10px; height:10px; border-radius:50%; }
.dot.r{ background:#E06B5A } .dot.y{ background:#E0A94C } .dot.g{ background:#7AB948 }
.addr{ margin-left:8px; flex:1; background:rgba(250,249,245,0.05); border-radius:6px; font-size:12px; color:var(--muted); padding:4px 10px; }
.work{ padding:16px 16px 18px; }
.step{ display:flex; align-items:center; gap:10px; font-size:14px; color:var(--white); padding:6px 0; }
.step .m{ width:16px; text-align:center; }
.step.done{ color:var(--muted); }
.step.now .m{ color:var(--accent); animation:spin 1s linear infinite; display:inline-block; }
.caption{ display:flex; align-items:center; gap:8px; margin-top:14px; padding-top:12px; border-top:1px solid rgba(250,249,245,0.06); font-size:13px; color:var(--accent); }
.pulse{ width:7px; height:7px; border-radius:50%; background:var(--accent); box-shadow:0 0 0 0 rgba(196,99,58,0.6); animation:ping 1.6s var(--ease) infinite; }
.more-label{ font-size:13px; color:var(--muted); margin:20px 2px 10px; }
.grid{ display:grid; grid-template-columns:1fr 1fr; gap:12px; }
.opt{ text-align:left; padding:16px 18px; border-radius:14px; background:var(--surface); border:1px solid var(--border);
cursor:pointer; transition:background 180ms var(--ease), border-color 180ms var(--ease), transform 180ms var(--ease); }
.opt:hover{ background:var(--accent-soft); border-color:var(--border-hover); transform:translateY(-2px); }
.opt .t{ font-size:15px; font-weight:550; }
.opt .d{ margin-top:4px; font-size:13px; color:var(--muted); }
.own{ margin-top:16px; display:flex; align-items:center; gap:10px; background:var(--surface); border:1px solid var(--border);
border-radius:12px; padding:13px 16px; color:var(--ghost); font-size:14px; }
.own .send{ margin-left:auto; color:var(--muted); }
@keyframes spin{ to{ transform:rotate(360deg) } }
@keyframes ping{ 0%{ box-shadow:0 0 0 0 rgba(196,99,58,0.55) } 70%{ box-shadow:0 0 0 9px rgba(196,99,58,0) } 100%{ box-shadow:0 0 0 0 rgba(196,99,58,0) } }
</style>
</head>
<body>
<div class="wrap">
<div class="ctx"><span class="chip">🌐 Online</span> <span>you picked this a second ago</span></div>
<h1>On it. Watch, this is real:</h1>
<div class="hero">
<div class="browser">
<div class="bar">
<span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
<span class="addr">bestbuy.com headphones sony-wh-1000xm5</span>
</div>
<div class="work">
<div class="step done"><span class="m"></span> opened 4 retailers</div>
<div class="step done"><span class="m"></span> read the live prices + stock</div>
<div class="step now"><span class="m"></span> building you a side-by-side with the cheapest in stock</div>
<div class="caption"><span class="pulse"></span> a real browser, going and doing it. not a search summary.</div>
</div>
</div>
</div>
<div class="more-label">or point me at one of these instead</div>
<div class="grid">
<div class="opt"><div class="t">⏰ Watch a price, ping me when it drops</div><div class="d">Name a product, I'll keep checking and text you.</div></div>
<div class="opt"><div class="t">🪑 Find the best-rated one under my budget</div><div class="d">I read the reviews so you don't have to.</div></div>
</div>
<div class="own">✎ ...or just tell me exactly what to do <span class="send"></span></div>
</div>
</body>
</html>