diff --git a/src/components/admin/backups-section.tsx b/src/components/admin/backups-section.tsx
index 21ef61c6e..6ecd99694 100644
--- a/src/components/admin/backups-section.tsx
+++ b/src/components/admin/backups-section.tsx
@@ -87,6 +87,7 @@ function RestoreRowDialog({
aria-label={t("admin.section.backups.restoreAria", {
username: row.username,
})}
+ className="min-h-11"
>
{pending ? (
@@ -343,6 +344,7 @@ export function BackupsSection() {
size="sm"
disabled={runBackup.isPending}
onClick={() => runBackup.mutate()}
+ className="min-h-11"
>
{runBackup.isPending ? (
@@ -398,6 +400,7 @@ export function BackupsSection() {
variant="outline"
disabled={upload.isPending}
onClick={() => fileInputRef.current?.click()}
+ className="min-h-11"
>
{upload.isPending ? (
@@ -438,6 +441,7 @@ export function BackupsSection() {
size="sm"
disabled={runBackup.isPending}
onClick={() => runBackup.mutate()}
+ className="min-h-11"
>
{runBackup.isPending ? (
@@ -496,6 +500,7 @@ export function BackupsSection() {
aria-label={t("admin.section.backups.downloadAria", {
username: row.username,
})}
+ className="min-h-11"
>
{downloadingId === row.id ? (
diff --git a/src/components/onboarding/tour.tsx b/src/components/onboarding/tour.tsx
index dbe7f6db7..a6459f14a 100644
--- a/src/components/onboarding/tour.tsx
+++ b/src/components/onboarding/tour.tsx
@@ -417,13 +417,19 @@ export function OnboardingTour({
{t(stop.bodyKey)}
+ {/* v1.4.15 H4 design: tour footer buttons reach the WCAG 2.5.5
+ 44 px tap-target floor on mobile. The `size="sm"` default
+ of `h-8` clipped to ~32 px which Marc reported as too small
+ on the iPad / iPhone PWA shell. Bumping to `min-h-11` (44 px)
+ keeps the desktop visual close enough — the buttons grow
+ ~4 px taller — while making mobile usable. */}
{t("onboarding.tour.skip")}
@@ -434,6 +440,7 @@ export function OnboardingTour({
variant="outline"
size="sm"
onClick={handlePrev}
+ className="min-h-11"
>
{t("onboarding.tour.back")}
@@ -444,6 +451,7 @@ export function OnboardingTour({
size="sm"
onClick={handleNext}
data-testid="onboarding-tour-primary"
+ className="min-h-11"
>
{isLast ? t("onboarding.tour.done") : t("onboarding.tour.next")}
diff --git a/src/components/settings/notification-status-card.tsx b/src/components/settings/notification-status-card.tsx
index e1f0d6314..4e567ee31 100644
--- a/src/components/settings/notification-status-card.tsx
+++ b/src/components/settings/notification-status-card.tsx
@@ -256,6 +256,10 @@ function ChannelRow({
+ {/* v1.4.15 H4 design: action buttons hit the WCAG 2.5.5 44 px
+ floor on mobile via `min-h-11`. Settings is the most-touched
+ mobile surface; `size="sm"` here clips to ~32 px which Marc
+ flagged as too small on the iPad/iPhone PWA shell. */}
{channel.state === "auto_disabled" && (
{reEnablePending ? (
@@ -281,6 +286,7 @@ function ChannelRow({
onClick={onTest}
disabled={testPending || channel.state === "auto_disabled"}
data-testid={`send-test-${channel.type}`}
+ className="min-h-11"
>
{testPending ? (