<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Context Engineering: Sessions & Memory</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
<style>
body { font-family: 'Inter', sans-serif; background-color: #f8fafc; color: #1e293b; }
h1, h2, h3 { letter-spacing: -0.025em; }
.mono { font-family: 'JetBrains Mono', monospace; }
/* Chart Container Styling - MANDATORY */
.chart-container {
position: relative;
width: 100%;
max-width: 800px; /* Max width to prevent stretching */
height: 350px; /* Base height */
max-height: 450px;
margin-left: auto;
margin-right: auto;
}
<span class="mention-invalid">@media</span> (max-width: 640px) {
.chart-container { height: 280px; }
}
/* Custom Scrollbar */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: #f1f5f9; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
/* Interactive Element Transitions */
.interactive-card { transition: all 0.3s ease; border-left: 4px solid transparent; }
.interactive-card:hover { transform: translateY(-2px); box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); }
.interactive-card.active { border-left-color: #4f46e5; background-color: #eef2ff; }
.pipeline-step { transition: all 0.3s ease; }
.pipeline-step:hover { background-color: #f0fdf4; border-color: #10b981; }
</style>
</head>
<body class="flex flex-col min-h-screen">
<!-- Navigation -->
<nav class="bg-white border-b border-slate-200 sticky top-0 z-50 shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<span class="text-2xl mr-2">🧠</span>
<span class="font-bold text-slate-800 text-lg tracking-tight">Context<span class="text-indigo-600">Engineering</span></span>
</div>
<div class="hidden sm:flex items-center space-x-8">
<button onclick="scrollToSection('hero')" class="text-slate-500 hover:text-indigo-600 font-medium">Overview</button>
<button onclick="scrollToSection('sessions')" class="text-slate-500 hover:text-indigo-600 font-medium">Sessions</button>
<button onclick="scrollToSection('memory')" class="text-slate-500 hover:text-indigo-600 font-medium">Memory</button>
<button onclick="scrollToSection('pipeline')" class="text-slate-500 hover:text-indigo-600 font-medium">Pipeline</button>
</div>
<!-- Mobile Menu Button (simplified functionality for SPA) -->
<div class="flex items-center sm:hidden">
<button class="text-slate-500 hover:text-indigo-600">☰</button>
</div>
</div>
</div>
</nav>
<!-- Main Content -->
<main class="flex-grow">
<!-- Hero Section -->
<section id="hero" class="bg-white py-16 sm:py-24 border-b border-slate-200">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<div class="inline-block bg-indigo-50 text-indigo-700 px-4 py-1.5 rounded-full text-sm font-semibold mb-6">Based on "Context Engineering: Sessions, Memory" (Nov 2025)</div>
<h1 class="text-4xl sm:text-6xl font-extrabold text-slate-900 mb-6">
Architecting the <span class="text-indigo-600">Agent Mind</span>
</h1>
<p class="text-xl text-slate-600 max-w-3xl mx-auto mb-10 leading-relaxed">
Explore the engineering principles behind GenAI context management. Navigate the trade-offs between ephemeral <strong>Sessions</strong> and persistent <strong>Memory</strong> to build robust, hallucination-resistant agents.
</p>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6 max-w-2xl mx-auto">
<div class="p-6 bg-slate-50 rounded-xl border border-slate-200 hover:border-indigo-300 transition-colors cursor-pointer" onclick="scrollToSection('sessions')">
<div class="text-3xl mb-3">⚡</div>
<h3 class="font-bold text-slate-900">Sessions</h3>
<p class="text-slate-500 text-sm mt-2">Short-term interaction history. Fast, expensive, and limited by context windows.</p>
</div>
<div class="p-6 bg-slate-50 rounded-xl border border-slate-200 hover:border-emerald-300 transition-colors cursor-pointer" onclick="scrollToSection('memory')">
<div class="text-3xl mb-3">💾</div>
<h3 class="font-bold text-slate-900">Memory</h3>
<p class="text-slate-500 text-sm mt-2">Long-term storage. Structured, scalable, and essential for personalization.</p>
</div>
</div>
</div>
</section>
<!-- Module A: Sessions -->
<section id="sessions" class="py-16 bg-slate-50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="mb-12">
<h2 class="text-3xl font-bold text-slate-900 mb-4 flex items-center">
<span class="bg-indigo-100 text-indigo-600 p-2 rounded-lg mr-4 text-xl">⚡</span>
Sessions & Context Windows
</h2>
<p class="text-lg text-slate-600 max-w-3xl">
Sessions capture the immediate "Short-term Memory" of an agent. The critical engineering challenge here is managing the <strong>Context Window</strong>. As conversations grow, full history becomes prohibitively expensive and prone to "Lost in the Middle" phenomena.
<br><br>
<strong>Interact below</strong> to compare strategies for handling long context conversations.
</p>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-start">
<!-- Control Panel -->
<div class="bg-white p-6 rounded-2xl shadow-sm border border-slate-200 lg:col-span-1">
<h3 class="font-bold text-slate-800 mb-4 border-b pb-2">Context Strategy</h3>
<div class="space-y-4">
<button onclick="updateChart('full')" id="btn-full" class="strategy-btn w-full text-left p-4 rounded-xl border-2 border-indigo-600 bg-indigo-50 transition-all">
<div class="font-bold text-indigo-900">Full History</div>
<div class="text-xs text-indigo-700 mt-1">Keep everything. High cost, perfect recall (until overflow).</div>
</button>
<button onclick="updateChart('window')" id="btn-window" class="strategy-btn w-full text-left p-4 rounded-xl border-2 border-transparent hover:bg-slate-50 transition-all">
<div class="font-bold text-slate-800">Sliding Window</div>
<div class="text-xs text-slate-500 mt-1">Keep last N turns. Low cost, forgets early details.</div>
</button>
<button onclick="updateChart('summary')" id="btn-summary" class="strategy-btn w-full text-left p-4 rounded-xl border-2 border-transparent hover:bg-slate-50 transition-all">
<div class="font-bold text-slate-800">Summarization</div>
<div class="text-xs text-slate-500 mt-1">Compress history periodically. Balanced cost/recall.</div>
</button>
</div>
<div class="mt-6 bg-yellow-50 p-4 rounded-lg border border-yellow-200">
<h4 class="font-bold text-yellow-800 text-sm mb-1">Engineering Note</h4>
<p id="strategy-desc" class="text-xs text-yellow-800 leading-relaxed">
Full History leads to exponential token costs. Optimization is mandatory for production systems.
</p>
</div>
</div>
<!-- Chart Display -->
<div class="bg-white p-6 rounded-2xl shadow-sm border border-slate-200 lg:col-span-2">
<div class="flex justify-between items-center mb-6">
<h3 class="font-bold text-slate-800">Token Usage vs. Conversation Turns</h3>
<div class="flex space-x-2 text-sm">
<span class="flex items-center"><span class="w-3 h-3 bg-indigo-500 rounded-full mr-2"></span>Token Cost</span>
<span class="flex items-center"><span class="w-3 h-3 bg-emerald-400 rounded-full mr-2"></span>Context Quality</span>
</div>
</div>
<!-- Responsive Chart Container -->
<div class="chart-container">
<canvas id="sessionChart"></canvas>
</div>
</div>
</div>
</div>
</section>
<!-- Module B: Memory -->
<section id="memory" class="py-16 bg-white border-t border-slate-200">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="mb-12">
<h2 class="text-3xl font-bold text-slate-900 mb-4 flex items-center">
<span class="bg-emerald-100 text-emerald-600 p-2 rounded-lg mr-4 text-xl">💾</span>
The Memory Bank
</h2>
<p class="text-lg text-slate-600 max-w-3xl">
To move beyond transient sessions, agents require <strong>Memory</strong>. The report identifies several distinct types of memory modeled after human cognition. Each requires a specific storage architecture.
<br><br>
<strong>Select a memory type</strong> to reveal its architectural requirements.
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-12 gap-8">
<!-- Memory Taxonomy (Left) -->
<div class="md:col-span-4 space-y-3">
<div onclick="selectMemory('episodic')" id="tab-episodic" class="interactive-card active cursor-pointer p-4 rounded-lg bg-slate-50 border border-slate-100">
<div class="flex items-center justify-between">
<h4 class="font-bold text-slate-800">Episodic Memory</h4>
<span class="text-xl">🕰️</span>
</div>
<p class="text-xs text-slate-500 mt-1">Past experiences and events.</p>
</div>
<div onclick="selectMemory('semantic')" id="tab-semantic" class="interactive-card cursor-pointer p-4 rounded-lg bg-white border border-slate-100 hover:bg-slate-50">
<div class="flex items-center justify-between">
<h4 class="font-bold text-slate-800">Semantic Memory</h4>
<span class="text-xl">📚</span>
</div>
<p class="text-xs text-slate-500 mt-1">Facts, concepts, and world knowledge.</p>
</div>
<div onclick="selectMemory('procedural')" id="tab-procedural" class="interactive-card cursor-pointer p-4 rounded-lg bg-white border border-slate-100 hover:bg-slate-50">
<div class="flex items-center justify-between">
<h4 class="font-bold text-slate-800">Procedural Memory</h4>
<span class="text-xl">🛠️</span>
</div>
<p class="text-xs text-slate-500 mt-1">Implicit knowledge on "how to do" things.</p>
</div>
</div>
<!-- Detail View (Right) -->
<div class="md:col-span-8">
<div id="memory-detail-panel" class="bg-slate-900 text-white rounded-2xl p-8 h-full shadow-xl relative overflow-hidden">
<!-- Background Decoration -->
<div class="absolute top-0 right-0 -mr-16 -mt-16 w-64 h-64 bg-indigo-500 rounded-full opacity-10 blur-3xl"></div>
<div class="relative z-10">
<div class="flex items-center mb-6">
<span id="mem-icon" class="text-4xl mr-4">🕰️</span>
<div>
<h3 id="mem-title" class="text-2xl font-bold">Episodic Memory</h3>
<span id="mem-tag" class="inline-block bg-indigo-600 text-xs px-2 py-1 rounded mt-1">Experience Based</span>
</div>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6 mb-6">
<div class="bg-slate-800 bg-opacity-50 p-4 rounded-xl border border-slate-700">
<h5 class="text-slate-400 text-xs uppercase tracking-wider font-bold mb-2">Definition</h5>
<p id="mem-def" class="text-sm leading-relaxed text-slate-200">
Stores sequences of events and interactions. It allows the agent to recall what happened in previous turns or sessions, providing continuity.
</p>
</div>
<div class="bg-slate-800 bg-opacity-50 p-4 rounded-xl border border-slate-700">
<h5 class="text-slate-400 text-xs uppercase tracking-wider font-bold mb-2">Storage Architecture</h5>
<p id="mem-storage" class="text-sm leading-relaxed text-emerald-300 font-mono">
Vector Database + Time-Decay Weighting
</p>
<p class="text-xs text-slate-500 mt-2">Often retrieved via semantic similarity search biased by recency.</p>
</div>
</div>
<div class="bg-slate-800 p-4 rounded-xl border-l-4 border-indigo-500">
<h5 class="text-slate-400 text-xs uppercase tracking-wider font-bold mb-1">Example in Action</h5>
<p id="mem-example" class="text-sm italic text-slate-300">
"User: 'Remember when we discussed Python decorators?' <br>Agent: 'Yes, in our session last Tuesday, we covered the <span class="mention-invalid">@property</span> decorator...'"
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Module C: Pipeline -->
<section id="pipeline" class="py-16 bg-slate-50 border-t border-slate-200">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="mb-10 text-center">
<h2 class="text-3xl font-bold text-slate-900 mb-4">Memory Generation Pipeline</h2>
<p class="text-slate-600 max-w-2xl mx-auto">
Memories don't just appear; they must be manufactured. The report outlines a pipeline to transform raw unstructured text into structured, queryable data.
</p>
</div>
<!-- Process Flow Visualization -->
<div class="relative max-w-5xl mx-auto">
<!-- Connecting Line -->
<div class="absolute top-1/2 left-0 w-full h-1 bg-slate-200 -translate-y-1/2 hidden md:block z-0"></div>
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 relative z-10">
<!-- Step 1 -->
<div class="pipeline-step bg-white p-6 rounded-xl shadow-sm border border-slate-200 text-center cursor-pointer group" onclick="showPipelineDetail('raw')">
<div class="w-12 h-12 bg-slate-100 rounded-full flex items-center justify-center mx-auto mb-4 text-xl group-hover:bg-indigo-100 group-hover:text-indigo-600 transition-colors">📄</div>
<h4 class="font-bold text-slate-800 mb-2">1. Raw Input</h4>
<p class="text-xs text-slate-500">User prompts & conversation history.</p>
</div>
<!-- Step 2 -->
<div class="pipeline-step bg-white p-6 rounded-xl shadow-sm border border-slate-200 text-center cursor-pointer group" onclick="showPipelineDetail('extract')">
<div class="w-12 h-12 bg-slate-100 rounded-full flex items-center justify-center mx-auto mb-4 text-xl group-hover:bg-indigo-100 group-hover:text-indigo-600 transition-colors">⛏️</div>
<h4 class="font-bold text-slate-800 mb-2">2. Extraction</h4>
<p class="text-xs text-slate-500">Identify entities, intent, and facts.</p>
</div>
<!-- Step 3 -->
<div class="pipeline-step bg-white p-6 rounded-xl shadow-sm border border-slate-200 text-center cursor-pointer group" onclick="showPipelineDetail('consolidate')">
<div class="w-12 h-12 bg-slate-100 rounded-full flex items-center justify-center mx-auto mb-4 text-xl group-hover:bg-indigo-100 group-hover:text-indigo-600 transition-colors">🔄</div>
<h4 class="font-bold text-slate-800 mb-2">3. Consolidation</h4>
<p class="text-xs text-slate-500">De-duplicate & merge with existing graphs.</p>
</div>
<!-- Step 4 -->
<div class="pipeline-step bg-white p-6 rounded-xl shadow-sm border border-slate-200 text-center cursor-pointer group" onclick="showPipelineDetail('store')">
<div class="w-12 h-12 bg-slate-100 rounded-full flex items-center justify-center mx-auto mb-4 text-xl group-hover:bg-indigo-100 group-hover:text-indigo-600 transition-colors">🗄️</div>
<h4 class="font-bold text-slate-800 mb-2">4. Storage</h4>
<p class="text-xs text-slate-500">Vector Embeddings & Knowledge Graphs.</p>
</div>
</div>
<!-- Dynamic Detail Box -->
<div id="pipeline-detail" class="mt-8 bg-indigo-50 border border-indigo-100 rounded-xl p-6 text-center transition-all duration-300">
<h4 id="pipe-title" class="text-indigo-900 font-bold text-lg mb-2">Select a stage above</h4>
<p id="pipe-desc" class="text-indigo-800 text-sm">Click on any step in the pipeline to understand the specific engineering tasks involved.</p>
</div>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="bg-slate-900 text-slate-400 py-12">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 grid grid-cols-1 md:grid-cols-2 gap-8">
<div>
<h5 class="text-white font-bold text-lg mb-4">Context Engineering</h5>
<p class="text-sm leading-relaxed mb-4">
An interactive synthesis of the paper "Context Engineering: Sessions, Memory" by Kimberly Milam and Antonio Gulli (Google, Nov 2025). This application demonstrates the architectural patterns for building stateful GenAI agents.
</p>
<div class="flex space-x-4">
<span class="bg-slate-800 px-3 py-1 rounded text-xs">Sessions</span>
<span class="bg-slate-800 px-3 py-1 rounded text-xs">Memory</span>
<span class="bg-slate-800 px-3 py-1 rounded text-xs">Cognitive Architecture</span>
</div>
</div>
<div class="md:text-right">
<h5 class="text-white font-bold text-lg mb-4">Key References</h5>
<ul class="text-sm space-y-2">
<li>Google Vertex AI Documentation</li>
<li>LangChain / LangGraph Memory Concepts</li>
<li>Generative AI Agent Architecture</li>
</ul>
</div>
</div>
</footer>
<!-- JavaScript Logic -->
<script>
// --- DATA & STATE ---
// Session Chart Configuration
const chartConfig = {
full: {
data: [1000, 2500, 5000, 8500, 13000, 18500, 25000],
quality: [100, 100, 100, 95, 90, 85, 80], // Quality drops due to "lost in middle"
title: "Full History Strategy",
desc: "Retains every interaction. Token usage (blue) grows linearly/exponentially, quickly hitting cost and latency limits. Context quality (green) is perfect initially but degrades as models struggle with massive prompts."
},
window: {
data: [1000, 2500, 4000, 4000, 4000, 4000, 4000],
quality: [100, 100, 90, 70, 50, 40, 30], // Quality drops significantly as old info is cut
title: "Sliding Window Strategy",
desc: "Keeps only the last N turns. Token usage caps efficiently (flat line), but Context Quality drops rapidly as key details from the start of the conversation are completely lost."
},
summary: {
data: [1000, 2500, 4500, 5000, 5500, 6000, 6500],
quality: [100, 100, 95, 92, 88, 85, 82], // Balanced approach
title: "Summarization Strategy",
desc: "Periodically summarizes older turns. Token usage grows slowly (controlled). Context quality remains high because key insights are preserved in the summary, even if verbatim text is lost."
}
};
// Memory Taxonomy Data
const memoryData = {
episodic: {
title: "Episodic Memory",
icon: "🕰️",
tag: "Experience Based",
def: "Stores sequences of events and interactions. It allows the agent to recall specific past interactions, providing a sense of continuity and time.",
storage: "Vector Database + Timestamp",
example: "\"User: 'Remember when we discussed Python decorators?' <br>Agent: 'Yes, in our session last Tuesday, we covered the <span class="mention-invalid">@property</span> decorator...'\""
},
semantic: {
title: "Semantic Memory",
icon: "📚",
tag: "Knowledge Based",
def: "Stores general world knowledge, facts, and concepts derived from interactions. It is depersonalized and represents the agent's 'understanding' of the world.",
storage: "Knowledge Graph / Vector DB",
example: "\"User: 'I am a vegetarian.' <br>Agent stores: [User] --is--> [Vegetarian]. Future food recommendations will now automatically exclude meat.\""
},
procedural: {
title: "Procedural Memory",
icon: "🛠️",
tag: "Skill Based",
def: "Implicit knowledge about how to perform tasks. In agents, this often maps to 'Few-Shot Examples' or stored tool definitions loaded into context.",
storage: "Prompt Templates / Function Libraries",
example: "\"User: 'Generate a SQL query.' <br>Agent retrieves: Standard procedures and templates for safe SQL generation tailored to the specific database schema.\""
}
};
// Pipeline Data
const pipelineData = {
raw: {
title: "Raw Input Stream",
desc: "The pipeline begins with the user's latest prompt and the immediate conversation history. This data is unstructured and noisy."
},
extract: {
title: "Information Extraction",
desc: "An LLM analyzes the raw text to identify key entities (People, Dates, Preferences) and user intents. It filters out 'chitchat' to focus on valuable signals."
},
consolidate: {
title: "Consolidation & Refinement",
desc: "New facts are compared against existing memory. Contradictions are resolved (e.g., 'My favorite color is Blue' overwrites 'Red'), and duplicate information is merged."
},
store: {
title: "Structured Storage",
desc: "The refined data is written to the database. Embeddings are generated for Vector Search, and semantic triples are added to Knowledge Graphs for logical retrieval."
}
};
// --- CHART INITIALIZATION ---
let sessionChart;
function initChart() {
const ctx = document.getElementById('sessionChart').getContext('2d');
sessionChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Turn 1', 'Turn 5', 'Turn 10', 'Turn 20', 'Turn 50', 'Turn 75', 'Turn 100'],
datasets: [
{
label: 'Token Cost',
data: chartConfig.full.data,
borderColor: '#4f46e5', // Indigo
backgroundColor: 'rgba(79, 70, 229, 0.1)',
yAxisID: 'y',
tension: 0.4,
fill: true
},
{
label: 'Context Quality (%)',
data: chartConfig.full.quality,
borderColor: '#10b981', // Emerald
borderDash: [5, 5],
yAxisID: 'y1',
tension: 0.4
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
interaction: {
mode: 'index',
intersect: false,
},
plugins: {
tooltip: {
backgroundColor: 'rgba(30, 41, 59, 0.9)',
padding: 12,
titleFont: { size: 14 },
bodyFont: { size: 13 }
},
legend: {
position: 'bottom'
}
},
scales: {
y: {
type: 'linear',
display: true,
position: 'left',
title: { display: true, text: 'Token Count' }
},
y1: {
type: 'linear',
display: true,
position: 'right',
min: 0,
max: 100,
grid: {
drawOnChartArea: false,
},
title: { display: true, text: 'Quality Score' }
},
x: {
grid: { display: false }
}
}
}
});
}
// --- INTERACTION FUNCTIONS ---
function updateChart(strategy) {
// Update UI Buttons
document.querySelectorAll('.strategy-btn').forEach(btn => {
btn.classList.remove('border-indigo-600', 'bg-indigo-50');
btn.classList.add('border-transparent');
btn.querySelector('div').classList.remove('text-indigo-900');
btn.querySelector('div').classList.add('text-slate-800');
});
const activeBtn = document.getElementById(`btn-${strategy}`);
activeBtn.classList.remove('border-transparent');
activeBtn.classList.add('border-indigo-600', 'bg-indigo-50');
activeBtn.querySelector('div').classList.remove('text-slate-800');
activeBtn.querySelector('div').classList.add('text-indigo-900');
// Update Text Description
document.getElementById('strategy-desc').innerText = chartConfig[strategy].desc;
// Update Chart Data
sessionChart.data.datasets[0].data = chartConfig[strategy].data;
sessionChart.data.datasets[1].data = chartConfig[strategy].quality;
sessionChart.update();
}
function selectMemory(type) {
const data = memoryData[type];
// Update UI Tabs
document.querySelectorAll('.interactive-card').forEach(card => {
card.classList.remove('active', 'bg-eef2ff');
card.classList.add('bg-white');
});
const activeCard = document.getElementById(`tab-${type}`);
activeCard.classList.add('active');
activeCard.classList.remove('bg-white');
// Update Detail Content with Animation
const panel = document.getElementById('memory-detail-panel');
panel.classList.add('opacity-50');
setTimeout(() => {
document.getElementById('mem-icon').innerText = data.icon;
document.getElementById('mem-title').innerText = data.title;
document.getElementById('mem-tag').innerText = data.tag;
document.getElementById('mem-def').innerText = data.def;
document.getElementById('mem-storage').innerText = data.storage;
document.getElementById('mem-example').innerHTML = data.example;
panel.classList.remove('opacity-50');
}, 200);
}
function showPipelineDetail(stage) {
const data = pipelineData[stage];
const detailBox = document.getElementById('pipeline-detail');
detailBox.innerHTML = `
<h4 class="text-indigo-900 font-bold text-lg mb-2">${data.title}</h4>
<p class="text-indigo-800 text-sm leading-relaxed">${data.desc}</p>
`;
// Subtle highlight logic for steps could go here
}
function scrollToSection(id) {
document.getElementById(id).scrollIntoView({ behavior: 'smooth' });
}
// --- INITIALIZATION ---
window.addEventListener('load', () => {
initChart();
});
</script>
</body>
</html>
登录后可参与表态
讨论回复
1 条回复
✨步子哥 (steper)
#1
12-31 08:23
登录后可参与表态