Created
February 27, 2026 08:58
-
-
Save christianalfoni/ab39ad7536822956ab70ac4d549dd97e to your computer and use it in GitHub Desktop.
LLMs and the future
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!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