diff --git a/plugins/host_agent/templates/_host_charts.html b/plugins/host_agent/templates/_host_charts.html
index 96bc142..72899ee 100644
--- a/plugins/host_agent/templates/_host_charts.html
+++ b/plugins/host_agent/templates/_host_charts.html
@@ -1,70 +1,6 @@
-{# History-charts fragment for the full-metrics page — lazy-loaded via HTMX so
- the date_bin history query never blocks the page shell, and refreshed on a
- slow cadence / range change. #}
-
-
-
Utilization % — last {{ range_key }}
-
-
-
-
Throughput (B/s) — last {{ range_key }}
-
-
-
-
Load & pressure — last {{ range_key }}
-
-
-
-
+{# History data-only fragment. Swapped into the hidden #hm-charts-data poller;
+ the script runs and feeds the persistent charts created by host_detail.html,
+ updating them in place (no canvas swap → no flicker / no re-animation). #}
diff --git a/plugins/host_agent/templates/host_detail.html b/plugins/host_agent/templates/host_detail.html
index 44b4bb2..359b1fc 100644
--- a/plugins/host_agent/templates/host_detail.html
+++ b/plugins/host_agent/templates/host_detail.html
@@ -3,15 +3,17 @@
{% block title %}{{ host.name }} — Metrics — Steward{% endblock %}
{% block breadcrumb %}{{ crumbs([("Hosts", "/hosts/"), (host.name, "/hosts/" ~ host.id), ("Metrics", "")]) }}{% endblock %}
{% block content %}
-{# Shell only: the current-state and history-chart sections stream in via HTMX
- below, so the heavy history query never blocks first paint and the data
- refreshes live (≈ the agent's push cadence) without a full reload. #}
+{# Shell only: current-state + history data stream in via HTMX so the heavy
+ history query never blocks first paint and the data refreshes live (≈ the
+ agent's push cadence). The chart CANVASES live here permanently — only their
+ data is polled and applied in place, so refreshes never re-create/flicker. #}
{{ host.name }}
{% include "_time_range.html" %}
-{# Current state — lazy + polled live (latest snapshot the server holds). #}
+{# Current state — lazy + polled live. Atomic innerHTML swap of fixed-height
+ cards, so values update without a layout jump. #}
Loading metrics…
-{# History charts — lazy (never blocks paint), refreshed on a slow cadence and
- on range change; range comes from the shared #time-range input. #}
-
+
+
Utilization % — last {{ current_range }}
+
+
+
+
Throughput (B/s) — last {{ current_range }}
+
+
+
+
Load & pressure — last {{ current_range }}
+
+
+
+{# Hidden poller: fetches the history series and applies it to the charts above
+ (no visible swap). Lazy on load → never blocks paint; refreshed slowly + on
+ range change. #}
+
+ hx-swap="innerHTML">
+
+
{% endblock %}