Skip to content

Instantly share code, notes, and snippets.

@christianalfoni
Created February 27, 2026 08:58
Show Gist options
  • Select an option

  • Save christianalfoni/ab39ad7536822956ab70ac4d549dd97e to your computer and use it in GitHub Desktop.

Select an option

Save christianalfoni/ab39ad7536822956ab70ac4d549dd97e to your computer and use it in GitHub Desktop.
LLMs and the future
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>How We Actually Interact With LLMs</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Syne:wght@400;600;800&display=swap" rel="stylesheet">
<style>
:root {
--bg: #080c10;
--surface: #0d1520;
--surface2: #111d2e;
--border: rgba(80,160,255,0.15);
--accent: #3b9eff;
--accent2: #00e5c0;
--accent3: #ff6b35;
--text: #c8dff5;
--text-dim: #5a7a9a;
--text-bright: #eaf4ff;
--mono: 'Space Mono', monospace;
--sans: 'Syne', sans-serif;
--glow: 0 0 20px rgba(59,158,255,0.3);
--glow2: 0 0 20px rgba(0,229,192,0.3);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
background: var(--bg);
color: var(--text);
font-family: var(--sans);
overflow-x: hidden;
}
/* Grid background */
body::before {
content: '';
position: fixed;
inset: 0;
background-image:
linear-gradient(rgba(59,158,255,0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(59,158,255,0.03) 1px, transparent 1px);
background-size: 40px 40px;
pointer-events: none;
z-index: 0;
}
/* HERO */
.hero {
position: relative;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 80px 40px;
z-index: 1;
}
.hero::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 600px;
height: 600px;
background: radial-gradient(circle, rgba(59,158,255,0.08) 0%, transparent 70%);
pointer-events: none;
}
.eyebrow {
font-family: var(--mono);
font-size: 11px;
letter-spacing: 4px;
color: var(--accent);
text-transform: uppercase;
margin-bottom: 24px;
opacity: 0;
animation: fadeUp 0.8s ease 0.2s forwards;
}
.hero h1 {
font-family: var(--sans);
font-weight: 800;
font-size: clamp(36px, 6vw, 80px);
line-height: 1.05;
color: var(--text-bright);
max-width: 900px;
opacity: 0;
animation: fadeUp 0.8s ease 0.4s forwards;
}
.hero h1 span { color: var(--accent); }
.hero h1 em { color: var(--accent2); font-style: normal; }
.hero-sub {
margin-top: 28px;
font-size: 18px;
color: var(--text-dim);
max-width: 560px;
line-height: 1.7;
opacity: 0;
animation: fadeUp 0.8s ease 0.6s forwards;
}
.scroll-hint {
position: absolute;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
font-family: var(--mono);
font-size: 10px;
letter-spacing: 3px;
color: var(--text-dim);
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
opacity: 0;
animation: fadeUp 0.8s ease 1s forwards;
}
.scroll-hint::after {
content: '';
width: 1px;
height: 40px;
background: linear-gradient(to bottom, var(--accent), transparent);
animation: pulse 2s ease infinite;
}
/* NAV DOTS */
.nav-dots {
position: fixed;
right: 30px;
top: 50%;
transform: translateY(-50%);
z-index: 100;
display: flex;
flex-direction: column;
gap: 14px;
}
.nav-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--border);
border: 1px solid var(--text-dim);
cursor: pointer;
transition: all 0.3s ease;
position: relative;
}
.nav-dot.active {
background: var(--accent);
border-color: var(--accent);
box-shadow: var(--glow);
}
.nav-dot::after {
content: attr(data-label);
position: absolute;
right: 18px;
top: 50%;
transform: translateY(-50%);
font-family: var(--mono);
font-size: 10px;
white-space: nowrap;
color: var(--text-dim);
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
}
.nav-dot:hover::after { opacity: 1; }
/* SECTIONS */
section {
position: relative;
z-index: 1;
padding: 120px 40px;
max-width: 1100px;
margin: 0 auto;
}
.section-label {
font-family: var(--mono);
font-size: 10px;
letter-spacing: 4px;
color: var(--accent);
text-transform: uppercase;
margin-bottom: 16px;
display: flex;
align-items: center;
gap: 12px;
}
.section-label::before {
content: '';
display: block;
width: 24px;
height: 1px;
background: var(--accent);
}
section h2 {
font-size: clamp(28px, 4vw, 52px);
font-weight: 800;
color: var(--text-bright);
line-height: 1.1;
max-width: 700px;
margin-bottom: 20px;
}
section h2 span { color: var(--accent); }
section h2 em { color: var(--accent2); font-style: normal; }
.section-intro {
font-size: 17px;
line-height: 1.8;
color: var(--text-dim);
max-width: 620px;
margin-bottom: 64px;
}
/* DIVIDER */
.divider {
width: 100%;
max-width: 1100px;
margin: 0 auto;
height: 1px;
background: linear-gradient(to right, transparent, var(--border), transparent);
position: relative;
z-index: 1;
}
/* ======== SECTION 1: CONTEXT WINDOW ======== */
.context-demo {
display: flex;
flex-direction: column;
gap: 0;
position: relative;
}
.turn-group {
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 0;
align-items: center;
}
.message-bubble {
padding: 14px 20px;
border-radius: 8px;
font-family: var(--mono);
font-size: 12px;
line-height: 1.6;
position: relative;
transition: all 0.3s ease;
}
.msg-user {
background: rgba(59,158,255,0.08);
border: 1px solid rgba(59,158,255,0.25);
color: var(--accent);
margin-left: auto;
max-width: 340px;
width: 100%;
}
.msg-llm {
background: rgba(0,229,192,0.06);
border: 1px solid rgba(0,229,192,0.2);
color: var(--accent2);
margin-right: auto;
max-width: 340px;
width: 100%;
}
.msg-label {
font-size: 9px;
letter-spacing: 2px;
opacity: 0.6;
margin-bottom: 4px;
text-transform: uppercase;
}
.context-window-visual {
margin: 0 24px;
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
min-width: 80px;
}
.ctx-bar {
height: 20px;
border-radius: 3px;
transition: width 0.5s ease, opacity 0.5s ease;
opacity: 0.5;
}
.ctx-bar.user-bar { background: var(--accent); }
.ctx-bar.llm-bar { background: var(--accent2); }
.ctx-label {
font-family: var(--mono);
font-size: 9px;
color: var(--text-dim);
letter-spacing: 2px;
text-transform: uppercase;
margin-bottom: 4px;
text-align: center;
}
.ctx-total {
font-family: var(--mono);
font-size: 9px;
color: var(--text-dim);
margin-top: 4px;
text-align: center;
}
.connector-line {
width: 1px;
background: linear-gradient(to bottom, var(--border), var(--border));
align-self: stretch;
margin: 0 auto;
position: relative;
}
.connector-line::after {
content: '↓';
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
color: var(--text-dim);
font-size: 12px;
}
.send-arrow {
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
color: var(--text-dim);
padding: 8px;
}
#playConversation {
margin-top: 48px;
padding: 12px 32px;
background: transparent;
border: 1px solid var(--accent);
color: var(--accent);
font-family: var(--mono);
font-size: 12px;
letter-spacing: 2px;
cursor: pointer;
border-radius: 4px;
transition: all 0.2s ease;
text-transform: uppercase;
}
#playConversation:hover {
background: rgba(59,158,255,0.1);
box-shadow: var(--glow);
}
.insight-box {
margin-top: 40px;
padding: 24px 28px;
border-left: 2px solid var(--accent3);
background: rgba(255,107,53,0.05);
border-radius: 0 8px 8px 0;
}
.insight-box p {
font-size: 15px;
line-height: 1.7;
color: var(--text);
}
.insight-box strong {
color: var(--accent3);
font-family: var(--mono);
font-size: 13px;
letter-spacing: 1px;
}
/* ======== SECTION 2: INFERENCE LOOP ======== */
.loop-container {
position: relative;
width: 100%;
}
/* Timeline bar at top */
.era-timeline {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 2px;
margin-bottom: 48px;
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
}
.era {
padding: 16px 20px;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
}
.era:hover { background: rgba(59,158,255,0.05); }
.era.active { background: rgba(59,158,255,0.1); }
.era-num {
font-family: var(--mono);
font-size: 10px;
color: var(--text-dim);
letter-spacing: 2px;
margin-bottom: 6px;
}
.era-title {
font-weight: 600;
font-size: 14px;
color: var(--text-bright);
}
.era-pct {
font-family: var(--mono);
font-size: 12px;
margin-top: 8px;
}
/* Visual loop diagram */
.loop-diagram {
display: flex;
flex-direction: column;
align-items: center;
gap: 0;
position: relative;
}
.loop-row {
display: flex;
align-items: center;
gap: 0;
width: 100%;
justify-content: center;
}
.loop-node {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px 28px;
border-radius: 10px;
font-family: var(--mono);
font-size: 13px;
font-weight: 700;
letter-spacing: 1px;
transition: all 0.4s ease;
min-width: 160px;
text-align: center;
position: relative;
}
.node-llm {
background: rgba(59,158,255,0.1);
border: 1.5px solid var(--accent);
color: var(--accent);
}
.node-reason {
background: rgba(139,92,246,0.1);
border: 1.5px solid rgba(139,92,246,0.7);
color: rgba(167,139,250,1);
}
.node-human {
background: rgba(255,107,53,0.08);
border: 1.5px solid var(--accent3);
color: var(--accent3);
}
.node-tool {
background: rgba(0,229,192,0.08);
border: 1.5px solid var(--accent2);
color: var(--accent2);
}
.node-sub {
font-size: 9px;
letter-spacing: 2px;
opacity: 0.7;
margin-top: 4px;
text-transform: uppercase;
}
.loop-arrow {
display: flex;
align-items: center;
padding: 0 12px;
color: var(--text-dim);
font-size: 18px;
position: relative;
min-width: 60px;
justify-content: center;
}
.loop-arrow-label {
position: absolute;
top: -18px;
left: 50%;
transform: translateX(-50%);
font-family: var(--mono);
font-size: 9px;
color: var(--text-dim);
white-space: nowrap;
letter-spacing: 1px;
}
.loop-vertical {
display: flex;
flex-direction: column;
align-items: center;
gap: 0;
padding: 8px 0;
}
.v-arrow {
width: 1px;
height: 30px;
background: var(--border);
position: relative;
}
.v-arrow.down::after {
content: '↓';
position: absolute;
bottom: -12px;
left: 50%;
transform: translateX(-50%);
color: var(--text-dim);
font-size: 14px;
}
.v-arrow.up::after {
content: '↑';
position: absolute;
top: -12px;
left: 50%;
transform: translateX(-50%);
color: var(--text-dim);
font-size: 14px;
}
/* Proportion bar */
.proportion-vis {
width: 100%;
margin-top: 48px;
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
padding: 24px;
background: var(--surface);
}
.prop-label {
font-family: var(--mono);
font-size: 10px;
letter-spacing: 3px;
color: var(--text-dim);
text-transform: uppercase;
margin-bottom: 20px;
}
.prop-bar-container {
margin-bottom: 16px;
}
.prop-name {
font-family: var(--mono);
font-size: 11px;
color: var(--text);
margin-bottom: 6px;
display: flex;
justify-content: space-between;
}
.prop-bar {
height: 24px;
border-radius: 3px;
display: flex;
overflow: hidden;
background: rgba(255,255,255,0.03);
gap: 2px;
}
.prop-seg {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-family: var(--mono);
font-size: 9px;
letter-spacing: 1px;
transition: width 0.8s cubic-bezier(0.4, 0, 0.2, 1);
overflow: hidden;
white-space: nowrap;
}
.seg-prompt { background: rgba(255,107,53,0.6); color: rgba(255,255,255,0.8); }
.seg-reason { background: rgba(139,92,246,0.55); color: rgba(255,255,255,0.85); }
.seg-tool { background: rgba(0,229,192,0.5); color: rgba(0,0,0,0.8); }
.seg-state { background: rgba(255,210,60,0.5); color: rgba(0,0,0,0.8); }
/* Era dots */
.era-tabs {
display: flex;
gap: 8px;
margin-bottom: 32px;
}
.era-tab {
padding: 8px 18px;
border-radius: 4px;
border: 1px solid var(--border);
font-family: var(--mono);
font-size: 10px;
letter-spacing: 2px;
cursor: pointer;
color: var(--text-dim);
text-transform: uppercase;
transition: all 0.2s ease;
background: transparent;
}
.era-tab:hover { border-color: var(--accent); color: var(--accent); }
.era-tab.active { border-color: var(--accent); color: var(--accent); background: rgba(59,158,255,0.08); }
/* ======== SECTION 3: LOCAL vs REMOTE ======== */
.toggle-wrap {
display: flex;
gap: 0;
margin-bottom: 48px;
border: 1px solid var(--border);
border-radius: 10px;
overflow: hidden;
width: fit-content;
}
.toggle-option {
padding: 16px 36px;
background: transparent;
border: none;
cursor: pointer;
font-family: var(--mono);
font-size: 13px;
font-weight: 700;
letter-spacing: 1px;
color: var(--text-dim);
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 4px;
transition: all 0.25s ease;
}
.toggle-option:first-child {
border-right: 1px solid var(--border);
}
.toggle-option:hover {
color: var(--text);
background: rgba(255,255,255,0.03);
}
.toggle-option.active.local-opt {
background: rgba(59,158,255,0.08);
color: var(--accent);
box-shadow: inset 0 -2px 0 var(--accent);
}
.toggle-option.active.remote-opt {
background: rgba(0,229,192,0.08);
color: var(--accent2);
box-shadow: inset 0 -2px 0 var(--accent2);
}
.toggle-sub {
font-size: 10px;
letter-spacing: 2px;
text-transform: uppercase;
opacity: 0.55;
font-weight: 400;
}
.spectrum-display {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
margin-top: 40px;
}
.spectrum-panel {
padding: 24px;
border-radius: 10px;
border: 1px solid var(--border);
background: var(--surface);
transition: all 0.4s ease;
}
.spectrum-panel.active-panel {
border-color: var(--accent);
background: var(--surface2);
}
.sp-title {
font-family: var(--mono);
font-size: 11px;
letter-spacing: 3px;
text-transform: uppercase;
color: var(--accent);
margin-bottom: 20px;
}
.arch-diagram {
display: flex;
flex-direction: column;
gap: 8px;
}
.arch-row {
display: flex;
align-items: center;
gap: 10px;
font-size: 13px;
font-family: var(--mono);
}
.arch-box {
padding: 8px 14px;
border-radius: 6px;
font-size: 11px;
letter-spacing: 1px;
text-align: center;
flex-shrink: 0;
transition: all 0.4s ease;
}
.arch-arrow {
color: var(--text-dim);
font-size: 14px;
}
.arch-latency {
font-size: 10px;
font-family: var(--mono);
padding: 3px 8px;
border-radius: 3px;
margin-left: auto;
}
.latency-high { color: var(--accent3); background: rgba(255,107,53,0.1); }
.latency-low { color: var(--accent2); background: rgba(0,229,192,0.1); }
/* Properties list */
.prop-list {
margin-top: 20px;
display: flex;
flex-direction: column;
gap: 10px;
}
.prop-item {
display: flex;
align-items: flex-start;
gap: 10px;
font-size: 13px;
line-height: 1.5;
}
.prop-icon {
font-size: 14px;
margin-top: 1px;
flex-shrink: 0;
}
.prop-text { color: var(--text); }
/* Speed indicator */
.speed-meter {
width: 100%;
margin: 20px 0;
}
.speed-bar {
height: 6px;
border-radius: 3px;
background: linear-gradient(to right, var(--accent2), var(--accent));
transition: width 0.5s ease;
}
.speed-label {
font-family: var(--mono);
font-size: 10px;
color: var(--text-dim);
display: flex;
justify-content: space-between;
margin-bottom: 6px;
}
/* ======== SECTION 4: THE FUTURE ======== */
.future-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
margin-bottom: 48px;
}
.future-card {
padding: 28px;
border-radius: 12px;
border: 1px solid var(--border);
background: var(--surface);
position: relative;
overflow: hidden;
transition: all 0.3s ease;
}
.future-card:hover {
border-color: var(--accent);
transform: translateY(-2px);
}
.future-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
opacity: 0;
transition: opacity 0.3s ease;
}
.future-card:hover::before {
opacity: 1;
background: linear-gradient(to right, var(--accent), var(--accent2));
}
.card-icon {
font-size: 28px;
margin-bottom: 16px;
}
.card-title {
font-weight: 700;
font-size: 16px;
color: var(--text-bright);
margin-bottom: 10px;
}
.card-body {
font-size: 14px;
line-height: 1.7;
color: var(--text-dim);
}
.future-timeline {
padding: 32px;
border: 1px solid var(--border);
border-radius: 12px;
background: var(--surface);
position: relative;
overflow: hidden;
}
.ft-title {
font-family: var(--mono);
font-size: 10px;
letter-spacing: 3px;
color: var(--text-dim);
text-transform: uppercase;
margin-bottom: 32px;
}
.timeline-item {
display: flex;
gap: 24px;
align-items: flex-start;
margin-bottom: 28px;
position: relative;
}
.timeline-item:last-child { margin-bottom: 0; }
.tl-left {
display: flex;
flex-direction: column;
align-items: center;
gap: 0;
min-width: 80px;
text-align: center;
}
.tl-dot {
width: 12px;
height: 12px;
border-radius: 50%;
border: 2px solid var(--text-dim);
flex-shrink: 0;
}
.tl-dot.past { background: var(--text-dim); border-color: var(--text-dim); }
.tl-dot.present { background: var(--accent); border-color: var(--accent); box-shadow: 0 0 12px rgba(59,158,255,0.5); }
.tl-dot.future-dot { background: transparent; border-color: var(--accent2); border-style: dashed; }
.tl-connector {
width: 1px;
flex: 1;
background: var(--border);
min-height: 28px;
margin-top: 4px;
}
.tl-era {
font-family: var(--mono);
font-size: 9px;
letter-spacing: 2px;
text-transform: uppercase;
margin-top: 6px;
color: var(--text-dim);
}
.tl-right { flex: 1; }
.tl-heading {
font-weight: 700;
font-size: 15px;
color: var(--text-bright);
margin-bottom: 6px;
}
.tl-desc {
font-size: 13px;
line-height: 1.6;
color: var(--text-dim);
}
.tl-tag {
display: inline-block;
margin-top: 8px;
padding: 3px 10px;
border-radius: 3px;
font-family: var(--mono);
font-size: 9px;
letter-spacing: 2px;
text-transform: uppercase;
}
.tag-past { background: rgba(90,122,154,0.2); color: var(--text-dim); }
.tag-now { background: rgba(59,158,255,0.15); color: var(--accent); }
.tag-soon { background: rgba(0,229,192,0.1); color: var(--accent2); }
.tag-future { background: rgba(255,107,53,0.1); color: var(--accent3); }
/* CLOSING */
.closing {
text-align: center;
padding: 120px 40px;
position: relative;
z-index: 1;
}
.closing h2 {
font-size: clamp(32px, 5vw, 64px);
font-weight: 800;
color: var(--text-bright);
max-width: 800px;
margin: 0 auto 24px;
line-height: 1.1;
}
.closing p {
font-size: 18px;
color: var(--text-dim);
max-width: 540px;
margin: 0 auto;
line-height: 1.7;
}
.closing::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 800px;
height: 400px;
background: radial-gradient(ellipse, rgba(0,229,192,0.05) 0%, transparent 70%);
pointer-events: none;
}
/* ANIMATIONS */
@keyframes fadeUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
0%, 100% { opacity: 0.3; }
50% { opacity: 1; }
}
@keyframes flowPulse {
0% { opacity: 0.3; transform: scaleX(0.97); }
50% { opacity: 1; transform: scaleX(1); }
100% { opacity: 0.3; transform: scaleX(0.97); }
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.typing-dot {
display: inline-block;
width: 6px; height: 6px;
border-radius: 50%;
background: currentColor;
margin: 0 2px;
animation: blink 1.2s ease infinite;
}
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
/* Highlight new messages */
@keyframes msgIn {
from { opacity: 0; transform: translateX(20px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes msgInLeft {
from { opacity: 0; transform: translateX(-20px); }
to { opacity: 1; transform: translateX(0); }
}
.msg-new-right { animation: msgIn 0.4s ease forwards; }
.msg-new-left { animation: msgInLeft 0.4s ease forwards; }
/* Reveal animation for sections */
.reveal {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.7s ease, transform 0.7s ease;
}
.reveal.visible {
opacity: 1;
transform: translateY(0);
}
/* Context window with bracket animation */
.ctx-bracket {
border: 1px solid var(--border);
border-radius: 4px;
padding: 8px 12px;
margin: 0 auto;
width: 68px;
transition: all 0.5s ease;
display: flex;
flex-direction: column;
gap: 2px;
align-items: center;
}
.ctx-mini {
width: 44px;
height: 6px;
border-radius: 2px;
opacity: 0.7;
transition: all 0.4s ease;
}
/* The inference loop animated */
.loop-animated {
position: relative;
width: 500px;
margin: 0 auto;
}
.loop-box {
position: relative;
padding: 40px;
border: 1px solid var(--border);
border-radius: 12px;
background: var(--surface);
}
/* Pulse ring on LLM node when active */
@keyframes ringPulse {
0% { transform: scale(1); opacity: 0.8; }
100% { transform: scale(1.4); opacity: 0; }
}
.node-pulse {
position: absolute;
inset: -4px;
border-radius: 12px;
border: 2px solid var(--accent);
animation: ringPulse 1.2s ease infinite;
pointer-events: none;
}
/* Loop connector paths */
.loop-svg {
position: absolute;
inset: 0;
pointer-events: none;
}
.flow-path {
fill: none;
stroke-dasharray: 6 4;
stroke-dashoffset: 0;
animation: dashFlow 1.5s linear infinite;
}
@keyframes dashFlow {
to { stroke-dashoffset: -20; }
}
</style>
</head>
<body>
<!-- Nav dots -->
<div class="nav-dots">
<div class="nav-dot active" data-label="Overview" onclick="scrollToSection(0)"></div>
<div class="nav-dot" data-label="The Conversation" onclick="scrollToSection(1)"></div>
<div class="nav-dot" data-label="The Inference Loop" onclick="scrollToSection(2)"></div>
<div class="nav-dot" data-label="Local vs Remote" onclick="scrollToSection(3)"></div>
<div class="nav-dot" data-label="The Future" onclick="scrollToSection(4)"></div>
</div>
<!-- HERO -->
<div class="hero" id="s0">
<div class="eyebrow">A mental model</div>
<h1>How we actually interact<br>with <span>language models</span></h1>
<p class="hero-sub">From single messages to autonomous agents — a visual exploration of how our relationship with LLMs is fundamentally changing.</p>
<div class="scroll-hint">SCROLL</div>
</div>
<div class="divider"></div>
<!-- SECTION 1: THE CONVERSATION -->
<section id="s1" class="reveal">
<div class="section-label">Part 01</div>
<h2>There is no<br><span>memory.</span> Only context.</h2>
<p class="section-intro">Every interaction with an LLM is stateless. It doesn't remember you. What feels like a "conversation" is really just you repeatedly sending a longer and longer document — the whole history — and the model predicting what comes next.</p>
<div style="display: flex; gap: 48px; align-items: flex-start; flex-wrap: wrap;">
<div style="flex: 1; min-width: 300px;">
<div style="margin-bottom: 20px; font-family: var(--mono); font-size: 10px; letter-spacing: 3px; color: var(--text-dim); text-transform: uppercase;">Interactive demo — watch the context grow</div>
<div class="context-demo" id="convDemo">
<!-- Populated by JS -->
</div>
<button id="playConversation" onclick="stepConversation()">▶ Next exchange</button>
</div>
<div style="flex: 0 0 220px;">
<div style="font-family: var(--mono); font-size: 10px; letter-spacing: 3px; color: var(--text-dim); text-transform: uppercase; margin-bottom: 16px;">Context window</div>
<div id="contextViz" style="display: flex; flex-direction: column; gap: 3px; padding: 16px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); min-height: 240px; justify-content: flex-end;">
<!-- Bars added dynamically -->
</div>
<div style="font-family: var(--mono); font-size: 10px; color: var(--text-dim); margin-top: 8px; display: flex; justify-content: space-between;">
<span>🟦 You</span>
<span>🟩 LLM</span>
<span id="ctxCount">0 turns</span>
</div>
<div style="margin-top: 20px; padding: 14px; background: var(--surface2); border-radius: 6px; border: 1px solid var(--border);">
<div style="font-family: var(--mono); font-size: 9px; letter-spacing: 2px; color: var(--text-dim); text-transform: uppercase; margin-bottom: 8px;">KEY INSIGHT</div>
<p style="font-size: 13px; line-height: 1.6; color: var(--text);">The LLM is <em style="color: var(--accent); font-style: normal;">not</em> tracking your conversation. You're feeding it the entire history each time and it predicts the next completion.</p>
</div>
</div>
</div>
<div class="insight-box" style="margin-top: 48px;">
<p><strong>→ THE ILLUSION</strong> — The model generates one response, then you append your reply and send it all back. The model has no awareness of "having said" anything — it just sees tokens and predicts more tokens. The sense of continuity is entirely constructed by the application layer.</p>
</div>
</section>
<div class="divider"></div>
<!-- SECTION 2: INFERENCE LOOP -->
<section id="s2" class="reveal">
<div class="section-label">Part 02</div>
<h2>The rise of the<br><em>inference loop</em></h2>
<p class="section-intro">We started by chatting with LLMs. Then we gave them tools. Now the tools have taken over — the majority of what an LLM does in agentic workflows is call tools, not talk to you.</p>
<!-- Era selector -->
<div class="era-tabs" id="eraTabs">
<button class="era-tab active" onclick="setEra(0, this)">Early days</button>
<button class="era-tab" onclick="setEra(1, this)">With tools</button>
<button class="era-tab" onclick="setEra(2, this)">With reasoning</button>
<button class="era-tab" onclick="setEra(3, this)">Agentic now</button>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: start; flex-wrap: wrap;">
<div>
<!-- Loop diagram -->
<div id="loopDiagram" style="padding: 32px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); position: relative;">
<!-- Populated by JS -->
</div>
</div>
<div>
<div style="font-family: var(--mono); font-size: 10px; letter-spacing: 3px; color: var(--text-dim); text-transform: uppercase; margin-bottom: 20px;">Work distribution</div>
<div id="propViz">
<!-- Populated by JS -->
</div>
<div id="eraDescription" style="margin-top: 24px; padding: 20px; background: var(--surface2); border-radius: 8px; border: 1px solid var(--border); font-size: 14px; line-height: 1.7; color: var(--text-dim);">
<!-- Populated by JS -->
</div>
</div>
</div>
<div class="insight-box" style="margin-top: 48px; border-left-color: var(--accent2);">
<p><strong style="color: var(--accent2);">→ THE SHIFT</strong> — The human is no longer the primary driver of the loop. The LLM calls a tool, gets a result, reasons about it, calls another tool. You set it in motion — then it runs. Your messages are the spark, not the fuel.</p>
</div>
</section>
<div class="divider"></div>
<!-- SECTION 3: LOCAL vs REMOTE -->
<section id="s3" class="reveal">
<div class="section-label">Part 03</div>
<h2>Local tools vs<br><span>remote intelligence</span></h2>
<p class="section-intro">Where do the tools live? Right now most run locally — on your machine or close to you. Flip to "remote" and something fundamental shifts: tools move next to the model, latency collapses, and the system becomes truly autonomous.</p>
<div class="toggle-wrap">
<button class="toggle-option local-opt active" onclick="setMode('local', this)">
← Local
<span class="toggle-sub">Inference loop runs on your machine</span>
</button>
<button class="toggle-option remote-opt" onclick="setMode('remote', this)">
Remote →
<span class="toggle-sub">Inference loop co-located with the model</span>
</button>
</div>
<div class="spectrum-display">
<!-- Left panel: architecture -->
<div class="spectrum-panel" id="archPanel">
<div class="sp-title">Architecture</div>
<div class="arch-diagram" id="archDiagram">
<!-- Populated by JS -->
</div>
</div>
<!-- Right panel: properties -->
<div class="spectrum-panel">
<div class="sp-title">Characteristics</div>
<div class="prop-list" id="propList">
<!-- Populated by JS -->
</div>
</div>
</div>
<div class="insight-box" style="margin-top: 48px; border-left-color: var(--accent3);">
<p><strong style="color: var(--accent3);">→ THE TRAJECTORY</strong> — As compute moves closer to the model and tools become co-located, the round-trip cost of agentic work approaches zero. The LLM doesn't wait for your machine to respond — it runs its own environment.</p>
</div>
</section>
<div class="divider"></div>
<!-- SECTION 4: THE FUTURE -->
<section id="s4" class="reveal">
<div class="section-label">Part 04</div>
<h2>The prompt<br>disappears</h2>
<p class="section-intro">The next step is removing the last thing we control: the initial message. The LLM doesn't wait for you — it wakes up on its own, triggered by an event, and runs until the job is done.</p>
<div class="future-grid">
<div class="future-card">
<div class="card-icon">⚡</div>
<div class="card-title">Event-triggered inference</div>
<div class="card-body">An email arrives, a sensor fires, a deadline passes. The system detects it and kicks off an inference loop — no human needed to start the chain.</div>
</div>
<div class="future-card">
<div class="card-icon">🔄</div>
<div class="card-title">Self-sustaining loops</div>
<div class="card-body">Once running, the LLM calls tools, evaluates results, and decides its own next step. The loop runs until a goal is met or an edge case surfaces for human review.</div>
</div>
<div class="future-card">
<div class="card-icon">🏗️</div>
<div class="card-title">Own environment</div>
<div class="card-body">The model needs compute, files, code execution, APIs — all colocated. The "AI system" becomes less a chatbot and more infrastructure that thinks.</div>
</div>
<div class="future-card">
<div class="card-icon">👤</div>
<div class="card-title">Human as exception handler</div>
<div class="card-body">We don't disappear — we become reviewers, approvers, and edge-case handlers. The human prompt goes from input to interrupt signal.</div>
</div>
</div>
<div class="future-timeline">
<div class="ft-title">Evolution of the interaction model</div>
<div class="timeline-item">
<div class="tl-left">
<div class="tl-dot past"></div>
<div class="tl-connector"></div>
<div class="tl-era">Early</div>
</div>
<div class="tl-right">
<div class="tl-heading">One message in, one message out</div>
<div class="tl-desc">Human sends a prompt, model returns a completion. Fully synchronous, fully human-driven. The interaction is a transaction.</div>
<span class="tl-tag tag-past">Chat completions</span>
</div>
</div>
<div class="timeline-item">
<div class="tl-left">
<div class="tl-dot past"></div>
<div class="tl-connector"></div>
<div class="tl-era">Recent</div>
</div>
<div class="tl-right">
<div class="tl-heading">Tools appear; loops emerge</div>
<div class="tl-desc">The model can call functions. A single user message triggers multiple inference + tool call cycles before responding. The loop is born.</div>
<span class="tl-tag tag-past">Function calling</span>
</div>
</div>
<div class="timeline-item">
<div class="tl-left">
<div class="tl-dot present"></div>
<div class="tl-connector"></div>
<div class="tl-era">Now</div>
</div>
<div class="tl-right">
<div class="tl-heading">Agentic systems — you set goals, not steps</div>
<div class="tl-desc">You describe an outcome. The model breaks it down, executes tool calls autonomously, and reports back. The human is upstream, not inline.</div>
<span class="tl-tag tag-now">Agent SDK / MCP</span>
</div>
</div>
<div class="timeline-item">
<div class="tl-left">
<div class="tl-dot future-dot"></div>
<div class="tl-connector"></div>
<div class="tl-era">Soon</div>
</div>
<div class="tl-right">
<div class="tl-heading">Event-triggered; prompt is optional</div>
<div class="tl-desc">The trigger is an event in a system, not a human message. The model runs, does the work, logs results. You review, not initiate.</div>
<span class="tl-tag tag-soon">Autonomous agents</span>
</div>
</div>
<div class="timeline-item">
<div class="tl-left">
<div class="tl-dot future-dot"></div>
<div class="tl-era">Future</div>
</div>
<div class="tl-right">
<div class="tl-heading">LLMs as infrastructure</div>
<div class="tl-desc">The distinction between "AI" and "software system" collapses. Inference loops run continuously, calling each other, managing state, acting on the world.</div>
<span class="tl-tag tag-future">LLM OS</span>
</div>
</div>
</div>
</section>
<!-- CLOSING -->
<div class="closing">
<h2>We're not chatting.<br>We're <span style="color: var(--accent2);">orchestrating.</span></h2>
<p>The mental model of "sending a message and getting one back" is already obsolete. What we're really doing is defining goals, configuring loops, and stepping back.</p>
</div>
<script>
// ─── SCROLL REVEAL ───────────────────────────────────────────────
const observer = new IntersectionObserver((entries) => {
entries.forEach(e => {
if (e.isIntersecting) e.target.classList.add('visible');
});
}, { threshold: 0.12 });
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
// ─── NAV DOTS ────────────────────────────────────────────────────
const sections = ['s0','s1','s2','s3','s4'];
function scrollToSection(i) {
document.getElementById(sections[i]).scrollIntoView({ behavior: 'smooth' });
}
window.addEventListener('scroll', () => {
sections.forEach((id, i) => {
const el = document.getElementById(id);
if (!el) return;
const rect = el.getBoundingClientRect();
const dots = document.querySelectorAll('.nav-dot');
if (rect.top <= window.innerHeight / 2 && rect.bottom >= window.innerHeight / 2) {
dots.forEach(d => d.classList.remove('active'));
dots[i].classList.add('active');
}
});
});
// ─── SECTION 1: CONVERSATION DEMO ────────────────────────────────
const conversations = [
{ user: "What's the capital of France?", llm: "Paris is the capital of France." },
{ user: "And what language do they speak there?", llm: "They speak French — it's the official language." },
{ user: "Any famous landmarks I should know about?", llm: "The Eiffel Tower, the Louvre, and Notre-Dame are iconic." },
{ user: "How long would a good visit take?", llm: "A solid visit would need at least 3–4 days to see the highlights." },
];
let convStep = 0;
const demo = document.getElementById('convDemo');
const ctxViz = document.getElementById('contextViz');
const ctxCount = document.getElementById('ctxCount');
function stepConversation() {
if (convStep >= conversations.length) {
convStep = 0;
demo.innerHTML = '';
ctxViz.innerHTML = '';
ctxCount.textContent = '0 turns';
return;
}
const { user, llm } = conversations[convStep];
// User bubble
const uWrap = document.createElement('div');
uWrap.style.cssText = 'display:flex; justify-content:flex-end; margin-bottom:6px;';
uWrap.innerHTML = `<div class="message-bubble msg-user msg-new-right">
<div class="msg-label">You</div>${user}
</div>`;
demo.appendChild(uWrap);
// Typing indicator
const typingWrap = document.createElement('div');
typingWrap.style.cssText = 'display:flex; justify-content:flex-start; margin-bottom:6px;';
typingWrap.innerHTML = `<div class="message-bubble msg-llm" style="padding:12px 20px;">
<div class="msg-label">LLM</div>
<span class="typing-dot"></span><span class="typing-dot"></span><span class="typing-dot"></span>
</div>`;
demo.appendChild(typingWrap);
demo.scrollTop = demo.scrollHeight;
setTimeout(() => {
typingWrap.remove();
const llmWrap = document.createElement('div');
llmWrap.style.cssText = 'display:flex; justify-content:flex-start; margin-bottom:6px;';
llmWrap.innerHTML = `<div class="message-bubble msg-llm msg-new-left">
<div class="msg-label">LLM</div>${llm}
</div>`;
demo.appendChild(llmWrap);
// Context viz
const uBar = document.createElement('div');
uBar.style.cssText = `height: 14px; border-radius: 2px; background: rgba(59,158,255,0.5); width: ${55 + convStep * 10}%; margin-bottom: 2px; animation: msgIn 0.3s ease;`;
const lBar = document.createElement('div');
lBar.style.cssText = `height: 14px; border-radius: 2px; background: rgba(0,229,192,0.4); width: ${40 + convStep * 8}%; margin-bottom: 2px; animation: msgIn 0.3s ease;`;
ctxViz.appendChild(uBar);
ctxViz.appendChild(lBar);
ctxCount.textContent = `${convStep + 1} turn${convStep ? 's' : ''} · ${(convStep + 1) * 2} messages sent`;
convStep++;
if (convStep >= conversations.length) {
document.getElementById('playConversation').textContent = '↩ Reset';
}
}, 900);
}
// ─── SECTION 2: INFERENCE LOOP ───────────────────────────────────
const eras = [
{
name: 'Early days',
promptPct: 99,
reasonPct: 0,
toolPct: 0,
statePct: 1,
desc: 'Text in, text out. No tools, no explicit reasoning steps — the model generates a response directly from your prompt in a single pass. A better search engine / writing assistant.',
diagram: 'chat',
},
{
name: 'With tools',
promptPct: 57,
reasonPct: 0,
toolPct: 40,
statePct: 3,
desc: 'Function calling arrives. The model calls a few tools per message before responding — but reasoning is still minimal and implicit. The loop has emerged.',
diagram: 'tools',
},
{
name: 'With reasoning',
promptPct: 24,
reasonPct: 48,
toolPct: 24,
statePct: 4,
desc: 'Extended thinking models arrive. Now the model explicitly reasons before acting — planning, reflecting, reconsidering. Reasoning tokens come to dominate the interaction.',
diagram: 'tools_reason',
},
{
name: 'Agentic now',
promptPct: 5,
reasonPct: 40,
toolPct: 45,
statePct: 10,
desc: 'For every one human message, the model cycles through reasoning and tool calls dozens to hundreds of times. The human prompt is just the starting gun — reasoning and tools are the work.',
diagram: 'agent',
},
];
function renderLoopDiagram(type) {
const el = document.getElementById('loopDiagram');
const diagrams = {
chat: `
<div style="display:flex; flex-direction:column; align-items:center; gap:8px;">
<div style="padding: 8px 0; font-family: var(--mono); font-size: 9px; color: var(--text-dim); letter-spacing: 2px; text-transform: uppercase;">You send a message</div>
<div class="loop-node node-human" style="width:160px;">👤 Human<div class="node-sub">Prompt</div></div>
<div style="display:flex; flex-direction:column; align-items:center;">
<div style="width:1px; height:20px; background: linear-gradient(var(--accent3), var(--accent)); animation: flowPulse 1.5s ease infinite;"></div>
<div style="font-family:var(--mono); font-size:9px; color: var(--text-dim); letter-spacing:1px;">sends full context</div>
<div style="width:1px; height:20px; background: linear-gradient(var(--accent), var(--accent3));"></div>
</div>
<div class="loop-node node-llm" style="width:160px; position:relative;">🧠 LLM<div class="node-sub">Generates response</div><div class="node-pulse"></div></div>
<div style="display:flex; flex-direction:column; align-items:center;">
<div style="width:1px; height:20px; background: linear-gradient(var(--accent2), transparent);"></div>
<div style="font-family:var(--mono); font-size:9px; color: var(--text-dim);">appends reply</div>
<div style="width:1px; height:20px;"></div>
</div>
<div class="loop-node node-human" style="width:160px;">👤 Human<div class="node-sub">Reads · Replies</div></div>
</div>
`,
tools: `
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;">
<div class="loop-node node-human" style="width:160px;">👤 Human<div class="node-sub">Sends goal</div></div>
<div style="width:1px; height:14px; background: var(--border);"></div>
<div class="loop-node node-llm" style="width:160px; position:relative;">🧠 LLM<div class="node-sub">Decides · Acts</div><div class="node-pulse"></div></div>
<div style="display:flex; align-items:center; gap:10px;">
<div style="width:1px; height:24px; background: linear-gradient(var(--accent), var(--accent2));"></div>
<div style="font-family:var(--mono); font-size:9px; color:var(--accent2);">tool call</div>
</div>
<div class="loop-node node-tool" style="width:160px;">🔧 Tool<div class="node-sub">Executes · Returns</div></div>
<div style="display:flex; align-items:center; gap:10px;">
<div style="width:1px; height:24px; background: linear-gradient(var(--accent2), var(--accent));"></div>
<div style="font-family:var(--mono); font-size:9px; color:var(--text-dim);">result back to LLM</div>
</div>
<div style="font-family:var(--mono); font-size:9px; color:var(--text-dim); padding: 4px 12px; border: 1px solid var(--border); border-radius:4px;">↩ LLM + tool loop (1–3×)</div>
<div style="width:1px; height:12px; background: var(--border);"></div>
<div class="loop-node node-human" style="width:160px;">👤 Human<div class="node-sub">Gets answer</div></div>
</div>
`,
tools_reason: `
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;">
<div class="loop-node node-human" style="width:160px;">👤 Human<div class="node-sub">Sends goal</div></div>
<div style="width:1px; height:14px; background: var(--border);"></div>
<div class="loop-node node-reason" style="width:160px; position:relative;">💭 Reasoning<div class="node-sub">Understand · Plan</div></div>
<div style="display:flex; align-items:center; gap:10px;">
<div style="width:1px; height:24px; background: linear-gradient(rgba(139,92,246,0.6), var(--accent2));"></div>
<div style="font-family:var(--mono); font-size:9px; color:var(--accent2);">tool call</div>
</div>
<div class="loop-node node-tool" style="width:160px;">🔧 Tool<div class="node-sub">Executes · Returns</div></div>
<div style="display:flex; align-items:center; gap:10px;">
<div style="width:1px; height:24px; background: linear-gradient(var(--accent2), rgba(139,92,246,0.6));"></div>
<div style="font-family:var(--mono); font-size:9px; color:var(--text-dim);">result → reason again</div>
</div>
<div style="font-family:var(--mono); font-size:9px; color:var(--text-dim); padding: 4px 12px; border: 1px solid var(--border); border-radius:4px;">↩ reasoning + tool loop (1–3×)</div>
<div style="width:1px; height:12px; background: var(--border);"></div>
<div class="loop-node node-llm" style="width:160px; position:relative;">🧠 LLM<div class="node-sub">Responds to human</div><div class="node-pulse"></div></div>
<div style="width:1px; height:12px; background: var(--border);"></div>
<div class="loop-node node-human" style="width:160px;">👤 Human<div class="node-sub">Gets answer</div></div>
</div>
`,
agent: `
<div style="display:flex; flex-direction:column; align-items:center; gap:4px;">
<div class="loop-node node-human" style="width:200px; opacity: 0.6;">👤 Human<div class="node-sub">Sets goal (once)</div></div>
<div style="width:1px; height:12px; background: var(--border);"></div>
<div style="border: 1px dashed rgba(59,158,255,0.3); border-radius: 10px; padding: 20px; width: 100%; background: rgba(59,158,255,0.03);">
<div style="font-family:var(--mono); font-size:9px; color:var(--accent); letter-spacing:2px; text-transform:uppercase; text-align:center; margin-bottom:16px;">Orchestrator loop</div>
<div style="display:flex; flex-direction:column; align-items:center; gap:6px;">
<div class="loop-node node-reason" style="width:200px;">💭 Reasoning<div class="node-sub">Plan · Reflect · Decide</div></div>
<div style="display:flex; width:100%; gap:8px; justify-content:center; margin: 4px 0;">
<div style="display:flex; flex-direction:column; align-items:center; gap:4px; flex:1;">
<div style="width:1px; height:16px; background: linear-gradient(rgba(139,92,246,0.6), var(--accent2));"></div>
<div class="loop-node node-tool" style="width:100%; font-size:11px;">🔧 Tools<div class="node-sub">Code · Files · APIs</div></div>
<div style="font-family:var(--mono); font-size:9px; color:var(--text-dim); text-align:center;">result</div>
</div>
<div style="display:flex; flex-direction:column; align-items:center; gap:4px; flex:1;">
<div style="width:1px; height:16px; background: linear-gradient(rgba(139,92,246,0.6), rgba(255,193,7,0.7));"></div>
<div class="loop-node" style="width:100%; font-size:11px; background:rgba(255,193,7,0.07); border:1.5px solid rgba(255,193,7,0.5); color:rgba(255,210,60,0.95);">📋 State<div class="node-sub">Todos · Tasks · Scratchpad</div></div>
<div style="font-family:var(--mono); font-size:9px; color:var(--text-dim); text-align:center;">state</div>
</div>
</div>
<div style="font-family:var(--mono); font-size:10px; color: rgba(139,92,246,0.8); letter-spacing:1px;">↑↓ ×10–100 iterations</div>
</div>
<div style="margin-top:16px; border-top: 1px solid rgba(59,158,255,0.15); padding-top:14px;">
<div style="font-family:var(--mono); font-size:9px; color:rgba(59,158,255,0.6); letter-spacing:2px; text-transform:uppercase; text-align:center; margin-bottom:10px;">Spawns sub-agents</div>
<div style="display:flex; gap:8px; justify-content:center;">
<div style="padding:10px 12px; border-radius:8px; border:1px dashed rgba(59,158,255,0.25); background:rgba(59,158,255,0.04); flex:1; text-align:center;">
<div style="font-family:var(--mono); font-size:10px; color:var(--accent);">🤖 Sub-agent</div>
<div style="font-family:var(--mono); font-size:8px; color:var(--text-dim); margin-top:3px; letter-spacing:1px;">Own loop · Own tools</div>
</div>
<div style="padding:10px 12px; border-radius:8px; border:1px dashed rgba(59,158,255,0.25); background:rgba(59,158,255,0.04); flex:1; text-align:center;">
<div style="font-family:var(--mono); font-size:10px; color:var(--accent);">🤖 Sub-agent</div>
<div style="font-family:var(--mono); font-size:8px; color:var(--text-dim); margin-top:3px; letter-spacing:1px;">Own loop · Own tools</div>
</div>
<div style="padding:10px 12px; border-radius:8px; border:1px dashed rgba(59,158,255,0.15); background:rgba(59,158,255,0.02); flex:1; text-align:center;">
<div style="font-family:var(--mono); font-size:10px; color:var(--text-dim);">🤖 ···</div>
<div style="font-family:var(--mono); font-size:8px; color:var(--text-dim); margin-top:3px; letter-spacing:1px;">Parallel</div>
</div>
</div>
</div>
</div>
<div style="width:1px; height:12px; background: var(--border);"></div>
<div class="loop-node node-human" style="width:200px; opacity: 0.6;">👤 Human<div class="node-sub">Reviews result</div></div>
</div>
`,
};
el.innerHTML = diagrams[type] || '';
}
function renderPropViz(promptPct, reasonPct, toolPct, statePct) {
const el = document.getElementById('propViz');
el.innerHTML = `
<div class="prop-bar-container">
<div class="prop-bar" style="height:28px; gap:2px;">
${promptPct > 0 ? `<div class="prop-seg seg-prompt" style="width:${promptPct}%">${promptPct > 12 ? 'Human' : ''}</div>` : ''}
${reasonPct > 0 ? `<div class="prop-seg seg-reason" style="width:${reasonPct}%">${reasonPct > 12 ? 'Reasoning' : ''}</div>` : ''}
${toolPct > 0 ? `<div class="prop-seg seg-tool" style="width:${toolPct}%">${toolPct > 12 ? 'Tools' : ''}</div>` : ''}
${statePct > 0 ? `<div class="prop-seg seg-state" style="width:${statePct}%">${statePct > 8 ? 'State' : ''}</div>` : ''}
</div>
<div style="display:flex; justify-content:space-between; margin-top: 10px; flex-wrap:wrap; gap:6px;">
<span style="font-family:var(--mono); font-size:10px; color:rgba(255,107,53,0.8);">🟧 Human ${promptPct}%</span>
<span style="font-family:var(--mono); font-size:10px; color:rgba(139,92,246,0.9);">🟪 Reasoning ${reasonPct}%</span>
<span style="font-family:var(--mono); font-size:10px; color:var(--accent2);">🟩 Tools ${toolPct}%</span>
${statePct > 0 ? `<span style="font-family:var(--mono); font-size:10px; color:rgba(255,210,60,0.9);">🟨 State ${statePct}%</span>` : ''}
</div>
</div>
<div style="margin-top:16px; font-family:var(--mono); font-size:10px; color: var(--text-dim);">
Approximate share of total inference compute per interaction
</div>
`;
}
let currentEra = 0;
function setEra(i, btn) {
currentEra = i;
document.querySelectorAll('.era-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
const era = eras[i];
renderLoopDiagram(era.diagram);
renderPropViz(era.promptPct, era.reasonPct, era.toolPct, era.statePct);
document.getElementById('eraDescription').textContent = era.desc;
}
// Init section 2
renderLoopDiagram('chat');
renderPropViz(99, 0, 0, 1);
document.getElementById('eraDescription').textContent = eras[0].desc;
// --- SECTION 3: LOCAL / REMOTE TOGGLE ---
const modes = {
local: {
speedWidth: '15%',
speedLabel: 'Slow — inference loop crosses the network each iteration',
archHtml: `
<div style="display:flex; align-items:stretch; margin: 12px 0; align-items:center;">
<div style="display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; border: 1px dashed rgba(255,107,53,0.35); border-radius:8px; padding: 12px 14px; background: rgba(255,107,53,0.04); min-width: 130px; flex-shrink:0;">
<div style="font-family:var(--mono); font-size:9px; color:rgba(255,107,53,0.7); letter-spacing:1px; text-transform:uppercase; margin-bottom:2px;">Inference loop</div>
<div style="font-family:var(--mono); font-size:10px; color:var(--text);">🔧 Tools</div>
<div style="font-family:var(--mono); font-size:10px; color:var(--text);">💭 Reasoning</div>
<div style="font-family:var(--mono); font-size:10px; color:var(--text);">📋 State</div>
<div style="font-family:var(--mono); font-size:9px; color:var(--text-dim); letter-spacing:1px; margin-top:2px;">YOUR MACHINE</div>
</div>
<div style="flex:1; display:flex; align-items:center; justify-content:center; position:relative;">
<div style="position:absolute; left:0; right:0; height:1px; background: linear-gradient(to right, rgba(255,107,53,0.4), rgba(255,107,53,0.15));"></div>
<div style="position:relative; background: var(--surface); padding: 4px 10px; border: 1px solid rgba(255,107,53,0.3); border-radius:4px; font-family:var(--mono); font-size:9px; color:var(--accent3); letter-spacing:2px; text-transform:uppercase;">slow</div>
</div>
<div style="display:flex; flex-direction:column; align-items:center; justify-content:center; padding: 12px 16px; background: rgba(59,158,255,0.07); border: 1px solid var(--accent); border-radius:8px; min-width: 110px; flex-shrink:0;">
<div style="font-family:var(--mono); font-size:13px; color:var(--accent);">🧠 LLM</div>
<div style="font-family:var(--mono); font-size:9px; color:var(--text-dim); letter-spacing:1px; margin-top:4px;">REMOTE API</div>
</div>
</div>
<div style="margin-top: 8px; padding: 10px 14px; background: rgba(255,107,53,0.05); border: 1px solid rgba(255,107,53,0.2); border-radius: 6px; font-family:var(--mono); font-size:10px; color: var(--accent3); letter-spacing: 1px;">
⚠ Intelligence depends on you for every permission<br>⚠ Secrets must live on your machine — a fragile trust boundary<br>⚠ Machine must stay on for the entire run
</div>
`,
props: [
{ icon: '🔑', text: 'The intelligence relies on you for access — API keys, credentials, and secrets must be stored and managed locally, creating a fragile and insecure boundary' },
{ icon: '🚪', text: 'Every tool call requires a permission you granted — the agent can only do what you explicitly unlocked: file access, code execution, network calls, and so on' },
{ icon: '⚠️', text: 'Inherently insecure environment — secrets on disk, broad local permissions, and code execution mean the blast radius of any mistake is your entire machine' },
{ icon: '⏳', text: 'High latency — each inference loop iteration crosses the network, making long agentic runs slow and fragile' },
{ icon: '💻', text: 'Your machine must stay on and available throughout — no sleeping, no closing the lid' },
]
},
remote: {
speedWidth: '92%',
speedLabel: 'Near-instant — inference loop runs co-located with the model',
archHtml: `
<div style="display:flex; align-items:center; margin: 12px 0;">
<div style="flex:1;"></div>
<div style="display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; border: 1px dashed rgba(0,229,192,0.35); border-radius:8px; padding: 12px 14px; background: rgba(0,229,192,0.04); min-width: 130px; flex-shrink:0;">
<div style="font-family:var(--mono); font-size:9px; color:rgba(0,229,192,0.7); letter-spacing:1px; text-transform:uppercase; margin-bottom:2px;">Inference loop</div>
<div style="font-family:var(--mono); font-size:10px; color:var(--text);">🔧 Tools</div>
<div style="font-family:var(--mono); font-size:10px; color:var(--text);">💭 Reasoning</div>
<div style="font-family:var(--mono); font-size:10px; color:var(--text);">📋 State</div>
<div style="font-family:var(--mono); font-size:9px; color:var(--text-dim); letter-spacing:1px; margin-top:2px;">SAME INFRA</div>
</div>
<div style="display:flex; align-items:center; justify-content:center; position:relative; width:60px; flex-shrink:0;">
<div style="position:absolute; left:0; right:0; height:1px; background: rgba(0,229,192,0.3);"></div>
<div style="position:relative; background: var(--surface); padding: 4px 8px; border: 1px solid rgba(0,229,192,0.35); border-radius:4px; font-family:var(--mono); font-size:9px; color:var(--accent2); letter-spacing:2px; text-transform:uppercase;">fast</div>
</div>
<div style="display:flex; flex-direction:column; align-items:center; justify-content:center; padding: 12px 16px; background: rgba(59,158,255,0.07); border: 1px solid var(--accent); border-radius:8px; min-width: 110px; flex-shrink:0;">
<div style="font-family:var(--mono); font-size:13px; color:var(--accent);">🧠 LLM</div>
<div style="font-family:var(--mono); font-size:9px; color:var(--text-dim); letter-spacing:1px; margin-top:4px;">SAME INFRA</div>
</div>
<div style="flex:1;"></div>
</div>
<div style="margin-top: 8px; padding: 10px 14px; background: rgba(0,229,192,0.06); border: 1px solid rgba(0,229,192,0.2); border-radius: 6px; font-family:var(--mono); font-size:10px; color: var(--accent2); letter-spacing: 1px;">
✓ Self-contained — runs without you<br>✓ Event-triggered — no prompt needed<br>✓ Loop runs indefinitely and independently
</div>
`,
props: [
{ icon: '⚡', text: 'Near-zero loop latency — inference, tools, and compute share the same infrastructure' },
{ icon: '🤖', text: 'Fully autonomous — no human needed to advance the loop once triggered' },
{ icon: '🔔', text: 'Event-triggered — a webhook, schedule, or system event starts the run, not a human message' },
{ icon: '☁️', text: 'Your machine can be off — the system runs in the cloud independently' },
{ icon: '💻', text: 'Code execution as a tool — the model writes and runs code inline, collapsing multi-step reasoning into a single loop iteration' },
{ icon: '🗂️', text: 'Filesystem as scratchpad — intermediate results are offloaded to files rather than bloating the context window, keeping each inference step lean' },
{ icon: '👤', text: 'Human becomes an exception handler — you review outputs and approve edge cases, not individual steps' },
]
}
};
let currentMode = 'local';
function setMode(mode, btn) {
currentMode = mode;
document.querySelectorAll('.toggle-option').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
applyMode(mode);
}
function applyMode(mode) {
const m = modes[mode];
document.getElementById('archDiagram').innerHTML = m.archHtml;
document.getElementById('propList').innerHTML = m.props.map(p => `
<div class="prop-item">
<span class="prop-icon">${p.icon}</span>
<span class="prop-text" style="font-size:12px;">${p.text}</span>
</div>
`).join('');
}
applyMode('local');
// ─── INITIAL STATE ────────────────────────────────────────────────
// Start first turn
stepConversation();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment