diff --git a/web/app.js b/web/app.js
index e2be24d..da0cb11 100644
--- a/web/app.js
+++ b/web/app.js
@@ -320,6 +320,14 @@ function currentStepWaterMass() {
return sudWaterMass;
}
+function currentStepGrainMass() {
+ if (sudStepIndex !== null && sudStepIndex >= 0 && sudStepIndex < sudSchedule.length) {
+ const step = sudSchedule[sudStepIndex];
+ if ('grain_mass' in step) return step.grain_mass;
+ }
+ return sudGrainMass;
+}
+
function updatePotVisualization() {
// Thermometer mercury column (0°C = y=174, 100°C = y=28, tube length = 146)
const tubeBottom = 174;
@@ -338,9 +346,14 @@ function updatePotVisualization() {
const potInnerBottom = 172;
const potInnerH = potInnerBottom - potInnerTop; // 142
+ const particlesEl = document.getElementById('grain-particles');
+ const waterClipRect = document.getElementById('water-clip-rect');
+
if (sudEmpty || sudVolumen <= 0) {
waterFillEl.setAttribute('height', '0');
waterWaveEl.setAttribute('d', '');
+ if (waterClipRect) waterClipRect.setAttribute('height', '0');
+ if (particlesEl) particlesEl.style.opacity = '0';
return;
}
@@ -350,6 +363,14 @@ function updatePotVisualization() {
waterFillEl.setAttribute('y', waterTop.toFixed(1));
waterFillEl.setAttribute('height', waterH.toFixed(1));
waterWaveEl.setAttribute('d', wavePathD(63, 177, waterTop, 3, 28));
+
+ if (waterClipRect) {
+ waterClipRect.setAttribute('y', waterTop.toFixed(1));
+ waterClipRect.setAttribute('height', waterH.toFixed(1));
+ }
+ if (particlesEl) {
+ particlesEl.style.opacity = currentStepGrainMass() > 0 ? '1' : '0';
+ }
}
// --- Status line - mirrors update_status_step_label(). ---
diff --git a/web/index.html b/web/index.html
index b87f72f..ebcbfcf 100644
--- a/web/index.html
+++ b/web/index.html
@@ -55,6 +55,9 @@
+
+
+
@@ -93,6 +96,45 @@
fill="none" stroke="#4a9ed8" stroke-width="2"
clip-path="url(#pot-clip)"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/style.css b/web/style.css
index 0e20be6..845235b 100644
--- a/web/style.css
+++ b/web/style.css
@@ -153,6 +153,19 @@ header#connection-bar {
display: block;
}
+/* Grain particle animation */
+@keyframes float-p {
+ 0%, 100% { transform: translate(0px, 0px); }
+ 25% { transform: translate(1.5px, -3px); }
+ 50% { transform: translate(-1px, 2px); }
+ 75% { transform: translate(2px, -1.5px); }
+}
+.grain-p {
+ fill: #c8a060;
+ animation: float-p var(--fp-dur, 3s) ease-in-out infinite var(--fp-del, 0s);
+}
+#grain-particles { transition: opacity 0.5s; }
+
/* Stirrer animation */
@keyframes stir-rotate {
to { transform: rotate(360deg); }