diff --git a/assets/views/admin/catalog/_price_preview.html b/assets/views/admin/catalog/_price_preview.html
new file mode 100644
index 0000000..766af27
--- /dev/null
+++ b/assets/views/admin/catalog/_price_preview.html
@@ -0,0 +1,8 @@
+{# OOB fragment: effective-price cells recomputed from the unsaved profile
+ selection on the products page. Each span replaces the matching #eff-
+ span in the table via htmx out-of-band swap. Rendered by
+ admin_products::profiles_preview. #}
+{% import "macros/ui.html" as ui %}
+{% for product in products %}
+{{ ui::eff_price(p=product, preview=true) }}
+{% endfor %}
diff --git a/assets/views/admin/catalog/products.html b/assets/views/admin/catalog/products.html
index 63943c1..51cf00e 100644
--- a/assets/views/admin/catalog/products.html
+++ b/assets/views/admin/catalog/products.html
@@ -40,6 +40,9 @@
{% if profiles | length > 0 %}