diff --git a/openless-all/app/src/components/Onboarding.tsx b/openless-all/app/src/components/Onboarding.tsx
index 249f1ba6..90ee702a 100644
--- a/openless-all/app/src/components/Onboarding.tsx
+++ b/openless-all/app/src/components/Onboarding.tsx
@@ -293,7 +293,12 @@ function DesktopOnboarding({
]);
setAccessibility(a);
setMicrophone(m);
- const aOk = !requiresAccessibility || a === 'granted' || a === 'notApplicable';
+ // Gate on the real permission status — macOS returns granted/denied, other
+ // platforms return notApplicable. This must NOT depend on the hotkey
+ // capability flag: it is null while it loads, so trusting it let mic-only
+ // onboarding finish before we knew macOS needs Accessibility, dropping users
+ // into the app with a dead hotkey. Mirrors the gate in App.tsx.
+ const aOk = a === 'granted' || a === 'notApplicable';
const mOk = m === 'granted' || m === 'notApplicable';
if (aOk && mOk) {
onComplete();
@@ -362,7 +367,7 @@ function DesktopOnboarding({
>
- {requiresAccessibility && (
+ {(requiresAccessibility || accessibility === 'denied') && (
)}