···
65
+
.timeline-container {
66
+
background: rgba(17, 17, 27, 0.9);
67
+
border: 1px solid #313244;
76
+
margin-bottom: 10px;
78
+
justify-content: space-between;
79
+
align-items: center;
91
+
transform: translateX(-50%);
92
+
white-space: nowrap;
94
+
.timeline-marker.start {
96
+
transform: translateX(0);
98
+
.timeline-marker.end {
100
+
transform: translateX(0);
103
+
.timeline-marker.highlight {
108
+
width: 100% !important;
109
+
-webkit-appearance: none;
112
+
background: linear-gradient(to right, #313244 0%, #313244 100%);
114
+
border-radius: 6px;
116
+
position: relative;
118
+
.timeline-slider::-webkit-slider-thumb {
119
+
-webkit-appearance: none;
123
+
background: #a6e3a1;
125
+
border-radius: 50%;
126
+
border: 3px solid #11111b;
127
+
box-shadow: 0 2px 8px rgba(166, 227, 161, 0.4);
128
+
transition: all 0.2s ease;
130
+
.timeline-slider::-moz-range-thumb {
133
+
background: #a6e3a1;
135
+
border-radius: 50%;
136
+
border: 3px solid #11111b;
137
+
box-shadow: 0 2px 8px rgba(166, 227, 161, 0.4);
138
+
transition: all 0.2s ease;
140
+
.timeline-slider::-webkit-slider-thumb:hover {
141
+
background: #b4e7b9;
142
+
transform: scale(1.1);
143
+
box-shadow: 0 4px 12px rgba(166, 227, 161, 0.6);
145
+
.timeline-slider::-moz-range-thumb:hover {
146
+
background: #b4e7b9;
147
+
transform: scale(1.1);
148
+
box-shadow: 0 4px 12px rgba(166, 227, 161, 0.6);
150
+
.timeline-slider:active::-webkit-slider-thumb {
152
+
transform: scale(0.95);
154
+
.timeline-slider:active::-moz-range-thumb {
156
+
transform: scale(0.95);
69
-
margin-bottom: 10px;
162
+
margin-bottom: -1rem;
···
203
+
transform: translateX(-50%);
···
<button id="next">Next →</button>
<button id="reset">↺ Reset</button>
184
-
<div class="control-row">
185
-
<label for="speed">Speed:</label>
186
-
<input type="range" id="speed" min="0" max="1000" value="900" step="5">
187
-
<span class="info" id="stepInfo">Step: 0 / 7845</span>
282
+
<div class="timeline-label">
283
+
<span>Timeline</span>
284
+
<span id="timelineStep">Step 0 of 7845</span>
286
+
<input type="range" id="timeline" class="timeline-slider" min="0" max="7845" value="0" step="1">
287
+
<div class="timeline-markers">
288
+
<div class="timeline-marker start">Start<br>0</div>
289
+
<div class="timeline-marker highlight" style="left: 12.746972594008923%;">Part 1<br>1000</div>
290
+
<div class="timeline-marker highlight end">Part 2<br>7845</div>
<div class="legend-item"><div class="legend-box junction"></div> Isolated Junction (small)</div>
···
const prevBtn = document.getElementById('prev');
const nextBtn = document.getElementById('next');
const resetBtn = document.getElementById('reset');
550
-
const speedSlider = document.getElementById('speed');
551
-
const stepInfo = document.getElementById('stepInfo');
653
+
const timelineSlider = document.getElementById('timeline');
654
+
const timelineStep = document.getElementById('timelineStep');
const statsInfo = document.getElementById('statsInfo');
const stage = stages[currentStage];
556
-
stepInfo.textContent = `Step: ${currentStage} / ${stages.length - 1}`;
659
+
timelineStep.textContent = `Step ${currentStage} of ${stages.length - 1}`;
const part1Result = stages[Math.min(1000, stages.length - 1)].product;
const part2Result = stage.part2Product || 0;
···
prevBtn.disabled = currentStage === 0;
nextBtn.disabled = currentStage === stages.length - 1;
669
+
// Update timeline slider and gradient
670
+
timelineSlider.value = currentStage;
671
+
const percent = (currentStage / (stages.length - 1)) * 100;
672
+
timelineSlider.style.background = `linear-gradient(to right, #a6e3a1 0%, #a6e3a1 ${percent}%, #313244 ${percent}%, #313244 100%)`;
updateConnections(stage);
···
prevBtn.addEventListener('click', () => goToStage(currentStage - 1));
nextBtn.addEventListener('click', () => goToStage(currentStage + 1));
resetBtn.addEventListener('click', () => goToStage(0));
686
+
// Timeline slider scrubbing
687
+
timelineSlider.addEventListener('input', (e) => {
688
+
goToStage(parseInt(e.target.value));
playBtn.addEventListener('click', () => {
···
requestAnimationFrame(animate);
606
-
// Auto-advance if playing
719
+
// Auto-advance if playing (zero delay - advance every frame)
608
-
const speed = 1000 - parseInt(speedSlider.value);
609
-
if (time - lastTime > speed) {
610
-
if (currentStage < stages.length - 1) {
611
-
goToStage(currentStage + 1);
614
-
playBtn.textContent = '▶ Play';
721
+
if (currentStage < stages.length - 1) {
722
+
goToStage(currentStage + 1);
725
+
playBtn.textContent = '▶ Play';