Two visit steps join the getting-started path: "Browse categories and
keywords" (5th) and "Browse the reports" (8th). Nothing in the database
counts them: they are done by "Got it" on their card, stored as
onboarding_acknowledged_<key> in user_preferences (no migration).
- computeChecklist: eight rows; the visit rows are locked until the
profile's visit steps are initialized, so a finished path does not
flash a "Next step" before they are marked done.
- initializeVisitSteps: once per profile, after the first successful
load with the Budget entitlement known; acknowledges both steps when
every other step is done or skipped, then sets the flag. No
transaction (D16): idempotent writes, the flag last.
- Reducer: ACKNOWLEDGE wins over an older snapshot like SKIP but keeps
the card latch, so the card says "Done." and offers the next step.
- StepCard: "Got it" before "Skip this step" when onAcknowledge is
given; OnboardingStepCard passes it for a visit step.
- Banner counter, card rank and end of path wait for
budgetReady && visitStepsInitialized; the list shows the visit rows
"pending" until then.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the page of the step in progress, a card takes the place of the
banner. `StepCard` is driven by props: an h2 title that takes the focus
("Step n of N", then the step), the page's sentence, a status region
always rendered that receives "Done.", "Skip this step" until the step is
done, then "Next step" or the end of the path. `OnboardingStepCard` is
the only piece that reads the path: it renders on the latched card page
only, so the card survives its own success, focuses its title once per
arrival by "Next step" and consumes the navigation state.
The control to use carries `data-onboarding-highlight`, drawn in
styles.css as a 3px accent outline with a pulse bounded to three cycles
and none under prefers-reduced-motion; a test reads the stylesheet and
checks 3:1 against the background and the cards in both themes. The
target is passed by props to EmptyState's primary action, the first
SourceList card and WizardNavigation's next button, never queried.
`importCardModel` reads the wizard and the checklist in order: importing
before the counters, a report that added nothing as a failure, and the
"steps 3 and 4 checked" row at rest, where it can apply. CARD_PAGES gets
/import; the Import page builds the input, renders the card first and
highlights the model's target only while the card shows, and its empty
state waits for the folder to be read.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>