All ManualWindow instances share the show state, so one check covers the
welcome screen and the view; the old copies were button-only and gated on
a construction-time config snapshot.
The built-in tooltip border is rendered at frame end in the global
ImGuiCol_Border, so it cannot react to hover; suppress it via
PopupBorderSize and stroke the same rect manually.
The manual rendering was a View method bound to View members. Move it
into a ManualWindow class that owns the active chunk, scroll-reset and
shown state and holds a reference to the shared manual data.
The manual data is invariant — derived only from the embedded manual — so
each View re-parsed it needlessly. It's now computed once and shared by all
Views and the LLM.
The intro and global-settings achievements recorded state even while
achievements were disabled, so the intro toast could be consumed before the
user ever enabled the feature — and then never appear when they later opted
in. The intro now fires at the enable points, so it shows the first time the
feature is enabled.
Achieve() now propagates a category unlock to the category's remaining
items, matching the constructor's load-time behavior. This lets an
achievement complete in the session where its category first unlocks.
The differences against the previous renderer are deliberate: the
drawn state is canonical from event 0, HasBlockingLock clears when the
blockers drain, same-state neighbors merge, a waiting thread shows as
holding only on its true acquire, a shared holder waiting for exclusive
draws as blocking, the Blocked and Sharing lists contain only genuinely
blocked roles, and the tooltip holder count follows the cursor position
in the holder-change log.
Opening and parsing on the browser main thread froze the tab for the
whole load; the file selector path already loads in a worker thread,
so boot now uses the same thread, progress modal, and error dialogs.