← back to Abrams
public/chat.html
89 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Abrams — Chat</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/panel.css" />
<style>
.container { max-width: 760px; margin: 0 auto; padding: 100px 24px 60px; }
.chat-window { background: var(--bg-2); border: 1px solid var(--hairline); padding: 24px; min-height: 420px; max-height: 60vh; overflow-y: auto; margin-bottom: 16px; }
.msg { padding: 8px 14px; margin: 4px 0; border-radius: 14px; max-width: 80%; font-size: 14px; line-height: 1.5; }
.msg.user { background: var(--accent); color: #111; margin-left: auto; }
.msg.bot { background: var(--bg-3); color: var(--fg); }
.composer { display: flex; gap: 8px; }
.composer input { flex: 1; background: var(--bg-2); border: 1px solid var(--hairline); color: var(--fg); padding: 12px 16px; font-family: var(--sans); font-size: 14px; }
.composer button { background: var(--accent); color: #111; border: none; padding: 12px 28px; font-family: var(--mono); font-size: 11px; letter-spacing: .2em; font-weight: 600; cursor: pointer; }
.hint { color: var(--fg-3); font-family: var(--mono); font-size: 11px; letter-spacing: .15em; text-transform: uppercase; margin-bottom: 14px; }
</style>
</head>
<body>
<div class="chrome">
<a class="logo" href="/">ABRAMS<span class="dot">.</span></a>
<div class="nav-burger" role="button" aria-label="open menu">
<span class="bars"><span></span><span></span><span></span></span>
<span class="label">MENU</span>
</div>
</div>
<div class="container">
<h1 style="font-family:var(--serif);font-size:42px;font-weight:400;margin:0 0 6px;">Talk to Abrams</h1>
<p class="hint">Ask anything · projects, ideas, trademark, leads</p>
<div class="chat-window" id="window">
<div class="msg bot"><strong>Abrams:</strong> Hi. I'm the umbrella over Steve Abrams's whole stack. Ask me about any project — Abrams Report, AbramsOS, Butlr, the lawyer directory, mp3.agentabrams. Or ask "what's new", "show me revenue ideas", "how do I get on the panel", or "what's the trademark plan".</div>
</div>
<div class="composer">
<input id="input" placeholder="Type a message…" />
<button onclick="send()">SEND</button>
</div>
</div>
<footer>© 2026 Steven Abrams</footer>
<script src="/static/js/corner-nav.js"></script>
<script src="/static/js/gamify.js"></script>
<script>
function esc(s){ return String(s||'').replace(/[&<>"']/g, m=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[m])); }
const win = document.getElementById('window');
const input = document.getElementById('input');
input.addEventListener('keydown', e => { if (e.key === 'Enter') send(); });
async function send() {
const txt = input.value.trim(); if (!txt) return;
win.innerHTML += `<div class="msg user">${esc(txt)}</div>`;
input.value = '';
win.scrollTop = win.scrollHeight;
const reply = await localReply(txt);
win.innerHTML += `<div class="msg bot"><strong>Abrams:</strong> ${esc(reply)}</div>`;
win.scrollTop = win.scrollHeight;
}
// Local intent-routed reply — no LLM call yet; future: wire to /api/chat → George / Big Red.
async function localReply(q) {
const Q = q.toLowerCase();
if (/trademark|tm|file|class/.test(Q)) return 'Trademark hub is at /trademark — direct USPTO links, the 5 classes you actually need (35 + 42 first, then 9 + 41 + 16), DIY at $1,250 or attorney at $4,750.';
if (/swot|ideas|revenue|moat/.test(Q)) {
const r = await fetch('/api/ideas').then(x=>x.json()).catch(()=>({}));
return `${(r.ideas||[]).length} SWOTs in the ledger. Top one: ${(r.ideas||[])[0]?.name||'pending'}. Full ledger at /ideas.`;
}
if (/project|inventory|empire|live|status/.test(Q)) {
const r = await fetch('/api/projects').then(x=>x.json()).catch(()=>({}));
const live = (r.projects||[]).filter(p=>p.status==='live');
return `${(r.projects||[]).length} projects tracked. ${live.length} live: ${live.slice(0,5).map(p=>p.name).join(', ')}. Full grid on the home panel.`;
}
if (/lead|partner|panel|join/.test(Q)) return 'Drop a line at the lead form on the home panel — or DM info@designerwallcoverings.com. Lead routing is built into the panel; every submission becomes an event on the build log.';
if (/butlr|call|dial/.test(Q)) return 'Butlr — AI dialer that holds for you. Live at butlr.agentabrams.com. Type /butlr in the terminal to place a call.';
if (/abramsos|os|warranty|recall/.test(Q)) return 'AbramsOS = household rights operating system. Tracks receipts (Gmail), warranties, recalls, class actions. Running locally on port 9931.';
if (/report|news|drudge/.test(Q)) return 'Abrams Report = Drudge-style design-industry news aggregator. Curation-driven. Live at report.agentabrams.com (DNS TBD).';
if (/mp3|audio|music/.test(Q)) return 'mp3.agentabrams.com indexes every MP3 ever made on Steve\'s machine — 358 tracks at first scan.';
if (/lawyer|attorney|bar|directory/.test(Q)) return 'lawyers.agentabrams.com — full California bar directory, claim-flow planned at $49/mo per listing.';
if (/hello|hi|hey|sup/.test(Q)) return 'Hi. Ask me about projects, ideas, trademark, leads, or any specific Abrams asset.';
return `I'm a local intent-router for now (no LLM call yet). Try asking about "trademark", "projects", "SWOT", "leads", "Butlr", "AbramsOS", "Report", "lawyers", or "mp3".`;
}
</script>
</body>
</html>