diff --git a/frontend/src/components/dashboard/NextStepCard.tsx b/frontend/src/components/dashboard/NextStepCard.tsx
index 5d54a266..9b158d5a 100644
--- a/frontend/src/components/dashboard/NextStepCard.tsx
+++ b/frontend/src/components/dashboard/NextStepCard.tsx
@@ -6,6 +6,7 @@ import type { OnboardingStatus } from '@/api/onboarding'
import { useTrialBanner } from '@/hooks/useTrialBanner'
import type { TrialBannerStage } from '@/hooks/useTrialBanner'
import { useOnboardingStatus } from '@/hooks/useOnboardingStatus'
+import { FOCUS_START_SESSION_EVENT } from '@/components/dashboard/StartSessionInput'
/**
* Next-step card — surfaces the single highest-priority incomplete onboarding
@@ -114,9 +115,10 @@ export function pickNextStep(
export function NextStepCard() {
const status = useOnboardingStatus()
const [locallyDismissed, setLocallyDismissed] = useState(false)
+ const [locallyHidden, setLocallyHidden] = useState(false)
const { stage } = useTrialBanner()
- if (!status || status.dismissed || locallyDismissed) return null
+ if (!status || status.dismissed || locallyDismissed || locallyHidden) return null
const next = pickNextStep(status, stage)
if (!next) return null
@@ -154,14 +156,29 @@ export function NextStepCard() {
-
- {next.ctaLabel}
-
-
+ {next.key === 'ran_session' ? (
+
+ ) : (
+
+ {next.ctaLabel}
+
+
+ )}
)
diff --git a/frontend/src/components/dashboard/SetupChecklist.tsx b/frontend/src/components/dashboard/SetupChecklist.tsx
index 7d8677b2..13ddcb1f 100644
--- a/frontend/src/components/dashboard/SetupChecklist.tsx
+++ b/frontend/src/components/dashboard/SetupChecklist.tsx
@@ -5,6 +5,7 @@ import type { OnboardingStatus } from '@/api/onboarding'
import { useTrialBanner } from '@/hooks/useTrialBanner'
import type { TrialBannerStage } from '@/hooks/useTrialBanner'
import { useOnboardingStatus } from '@/hooks/useOnboardingStatus'
+import { FOCUS_START_SESSION_EVENT } from '@/components/dashboard/StartSessionInput'
/**
* Unified setup checklist — single list (no SOLO/TEAM bifurcation).
@@ -112,6 +113,21 @@ export function SetupChecklist() {
{item.label}
+ ) : item.key === 'ran_session' ? (
+
) : (
([])
const [isDragOver, setIsDragOver] = useState(false)
+ const [nudge, setNudge] = useState(false)
const navigate = useNavigate()
+ const wrapperRef = useRef(null)
const textareaRef = useRef(null)
const fileInputRef = useRef(null)
const dragCounterRef = useRef(0)
useEffect(() => { textareaRef.current?.focus() }, [])
+ // External "focus me" trigger (e.g. NextStepCard "Start a session" CTA on
+ // the same page). Scrolls into view, focuses the textarea, and pulses a
+ // ring so the click feels intentional even when the input was already
+ // partially visible.
+ useEffect(() => {
+ const handler = () => {
+ wrapperRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' })
+ textareaRef.current?.focus({ preventScroll: true })
+ setNudge(true)
+ window.setTimeout(() => setNudge(false), 900)
+ }
+ window.addEventListener(FOCUS_START_SESSION_EVENT, handler)
+ return () => window.removeEventListener(FOCUS_START_SESSION_EVENT, handler)
+ }, [])
+
// Auto-grow textarea
useEffect(() => {
const el = textareaRef.current
@@ -190,7 +209,8 @@ export function StartSessionInput() {
return (
{/* Main input area */}
{/* Drag overlay */}
{isDragOver && (