diff --git a/apps/web/src/setup/steps/InstallingStep.tsx b/apps/web/src/setup/steps/InstallingStep.tsx
index 6f0a2e74..2e5ce0d5 100644
--- a/apps/web/src/setup/steps/InstallingStep.tsx
+++ b/apps/web/src/setup/steps/InstallingStep.tsx
@@ -204,9 +204,9 @@ export function InstallingStep({ flow, mode }: InstallingStepProps) {
conversations different and preview the actual scenarios the player is
minutes away from, so the first conversation is the real model. */}
{mode === 'wizard' && (
+ // Plain div, not a named region: the eyebrow and heading below are the
+ // section's own visible text, so a region label would repeat them.
{t('setup.installing.missionsHeading')}
+ {/* The visible h3 above labels this list; no aria-label needed. */}
{previews.map((s) => (
diff --git a/apps/web/src/setup/steps/WelcomeStep.tsx b/apps/web/src/setup/steps/WelcomeStep.tsx
index 74958012..fb8ba4b2 100644
--- a/apps/web/src/setup/steps/WelcomeStep.tsx
+++ b/apps/web/src/setup/steps/WelcomeStep.tsx
@@ -27,10 +27,11 @@ export function WelcomeStep({ flow }: { flow: UseSetupFlowReturn }) {
{t('setup.welcome.subheadline')}
- {/* The promise — why this is not a chatbot (issue #473) */}
+ {/* The promise — why this is not a chatbot (issue #473). No aria-label:
+ the heading below is the note's visible content, so labelling the
+ note with the same text would double-announce it to screen readers. */}