diff --git a/src/app/bugreport/page.tsx b/src/app/bugreport/page.tsx
index 21dce49c4..c9c920058 100644
--- a/src/app/bugreport/page.tsx
+++ b/src/app/bugreport/page.tsx
@@ -227,9 +227,22 @@ export default function BugReportPage() {
)}
-
diff --git a/src/app/medications/page.tsx b/src/app/medications/page.tsx
index 690c103c7..6e52ebbbc 100644
--- a/src/app/medications/page.tsx
+++ b/src/app/medications/page.tsx
@@ -505,9 +505,21 @@ function IntakeImportDialog({
- {importing && }
-
+ {/*
+ v1.4.33 IW9 — icon swap (not append) on `importing`
+ to keep the button width stable through the
+ in-flight request. Pre-v1.4.33 both icons painted
+ during loading and the button grew by ~24 px, which
+ showed up as a CLS hit on the medications import
+ dialog.
+ */}
+ {importing ? (
+
+ ) : (
+
+ )}
{t("common.import")}
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx
index 642a7a72f..0e3df88f6 100644
--- a/src/components/ui/button.tsx
+++ b/src/components/ui/button.tsx
@@ -4,6 +4,31 @@ import { Slot } from "radix-ui";
import { cn } from "@/lib/utils";
+/**
+ * v1.4.33 IW9 — loading-state convention.
+ *
+ * Callers driving a transient loading state on a button must SWAP the
+ * leading icon for `` rather than APPENDING the spinner
+ * next to the existing icon. The legacy `{loading && }`
+ * pattern grew the button by ~24 px during the request, which produced
+ * the 0.186 CLS hit flagged on the v1.4.33 Lighthouse run. The
+ * spinner and the icon are both 16 px (`h-4 w-4`); swapping keeps the
+ * intrinsic button width stable.
+ *
+ * ```tsx
+ *
+ * {loading ? (
+ *
+ * ) : (
+ *
+ * )}
+ * {label}
+ *
+ * ```
+ *
+ * Also: pass `aria-busy={loading || undefined}` so screen readers
+ * announce the in-flight state.
+ */
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
{