Floating (BlurFloat) modals draw no card, so in a light theme the light content
sits on a light frosted backdrop with almost no separation (washed out — the
Manage-portfolio modal being the clearest case). Add a faint elevated sheet
(translucent Surface) + a defining edge (OnSurface) behind floating content in
LIGHT themes only, gated on a new IsLightTheme() (background luminance) helper.
Dark themes are unchanged (they already read fine). Kept translucent to preserve
the airy floating feel; respects "no dark backdrop in light theme".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The PIN/passphrase input uses default ImGui framing, which is subtle on the glass
card — when focused there was no clear indication the field is active. Draw an
accent (Primary) ring around the input while it's focused/being edited so it's
obvious the field is ready for typing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Regression from the full-window lock overlay: the full-window ##LockInputBlocker
InvisibleButton (drawn first) shadowed the lock card's widgets (PIN/passphrase
input, Unlock button, mode toggle) that overlap it, so clicks never reached them
(dead) and the app's global "hand cursor on clickable hover" fired for the whole
screen. Mark the blocker SetNextItemAllowOverlap() so the later widgets take
hit-test priority — the exact use case in ImGui's docs (invisible button covering
an area where subsequent items are added). The portfolio avoids this by putting
its content in a child window; the lock screen draws direct, so it needs the flag.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address two GUI-review points:
1. Light themes no longer get a dark modal backdrop: DrawFullWindowBlurBackdrop
now tints toward the theme app background (WithAlpha(Background(), ...)) for
both the opaque base and the frost, so a light theme gets a light frosted
backdrop and a dark theme a dark one. Fixes all blur overlays, not just the
lock screen.
2. The lock screen now blurs the WHOLE window (sidebar included), not just the
content area: renderLockScreen opens a full-viewport borderless overlay window
(##LockOverlay, same pattern as the modal overlays / portfolio, opened from
within ##ContentArea) with an input blocker, instead of drawing in the content
child. Removed the theme-independent dark scrim (contradicted point 1).
Auth logic untouched. Needs GUI re-verify of all auth paths + that the whole
screen (incl. sidebar) obscures on lock and unlock returns cleanly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GUI review (light theme) showed the blurred backdrop is light there, washing out
the (now glass) card. Add a theme-independent dark scrim over the blur so the lock
screen reads as a clearly-dimmed "locked" state and the card stands out in both
light and dark themes — standard lock-screen dimming. Alpha tunable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GUI review showed the lock card was a flat light SurfaceVariant panel that stood
out against the dark glass cards of the other modals. Draw it with the same
GlassPanelSpec (rounding 16, fill 35, border 50) that BeginOverlayDialog uses, so
it renders as the same opaque-dark glass card on the blur backdrop. Visual only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The lock screen no longer reads screens.lock-screen.backdrop-alpha (replaced by
the live-blur backdrop in c7f89e5). Remove the now-dead schema key.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The security DIALOGS (encrypt/decrypt/change-passphrase/remove-encryption, PIN
set/change/remove) already adopted the blur backdrop via the Phase 2 flip (they
use BeginOverlayDialog). This finishes Phase 4 by giving the bespoke lock screen
the same live-blur backdrop over the wallet content — restyle only, auth logic
(PIN/passphrase input, attempt counting, lockout timer) untouched.
The lock screen previously defaulted to backdrop-alpha=0 (wallet fully visible
behind the card); the blur now obscures it — a privacy improvement as well as a
consistency one. Capture-once on lock-open + resize (frame-gap detected via the
shared BlurCaptureStateFor), MarkBlurOverlayDrawn drives the theme-effect
suppression + acrylic re-capture on unlock. The opaque base in
DrawFullWindowBlurBackdrop guarantees the wallet is obscured even if blur is
unavailable (low-spec / acrylic-off / capture failure) — no content leak. UV
mapping is screen-space, so the content-area sub-rect blurs the correct region.
Needs GUI verification of every auth path (PIN/passphrase unlock, lockout).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The two Phase 3 "bespoke overlays" aren't content modals: the send-error is an
in-tab glass banner (already consistent — left as-is), and the shutdown screen is
a teardown screen where a blur backdrop would be semantically wrong (should read
as "closing") + risky on the teardown path. Per that finding, apply minor
consistency polish to the shutdown screen only:
- Share the overlay-scrim tone via a new material::OverlayScrimColor(opacity),
used by both the dialog scrim and the shutdown scrim (was a slightly different
hardcoded 0.06/0.06/0.08 → now the 0.04/0.04/0.06 dialog base).
- "Shutting Down" title → theme Warning() amber (was hardcoded gold).
- Force-Quit confirm destructive button → theme Error() (alpha-varied) instead of
hardcoded reds.
No behavior change; the shutdown scrim stays opaque (no blur).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per the user's selection, convert the large multi-section dialogs to the BlurFloat
style (floating content on the blur, plain heading, no glass card), each KEEPING
its authored width so width-coupled content is untouched:
- Export all keys, Console RPC reference, Explorer block detail
- Updater dialogs: daemon update, xmrig update, bootstrap download (multi-state)
Settings and Address book intentionally kept as cards (the modal Settings *window*
is dead code — show_settings_ is never set; the live Settings surface is the nav
page, not a modal; Address book has a nested edit that reads better contained).
All other confirm/input dialogs stay card-on-blur ("card for small"). Updater
dialogs are multi-state — GUI-check each state (confirm/progress/done/failed).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Convert two clean detail-view dialogs to the BlurFloat style (floating content on
the blur, plain h6 heading, no glass card) — the "float for large" half of the
plan, applied conservatively: keep each dialog's authored card width so its
width-coupled content (absolute SameLine positions, GetWindowWidth math) is
unchanged, and rely on the footer Close + outside-click for dismissal (the plain
heading drops the title-bar close X, matching the portfolio modal). Auto-height
preserved. A representative pair to GUI-review before rolling the treatment out to
the other large dialogs (or reverting if the card-on-blur reads better).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Grep-verified dead, zero live callers (the live paths all go through
BeginOverlayDialog and already got the blur backdrop):
- App::renderAboutDialog (app.cpp/app.h) — dispatch uses ui::RenderAboutDialog.
- src/ui/windows/import_key_dialog.{h,cpp} (ImportKeyDialog class) — live path is
App::renderImportKeyDialog.
- src/ui/windows/backup_wallet_dialog.{h,cpp} (BackupWalletDialog class) — live
path is App::renderBackupDialog.
Drop the two dead files from CMakeLists. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Flip the positional BeginOverlayDialog overload's default to blurBackdrop=true, so
every app dialog (~43 call sites) now renders its card on the live-blur backdrop
instead of the opaque scrim — matching the Manage-Portfolio look. Cards stay
auto-height (small dialogs stay small = "card for small") and render opaque via
the existing sole-consumer fallback (a translucent glass card would thrash the
single-slot blur cache against the radius-64 backdrop). Nested dialogs (address
book edit) already pass a distinct idSuffix, so their blur windows/capture keys
don't collide. A dialog that wants the old scrim can pass a spec with
blurBackdrop=false. Big visual change — needs a GUI sweep; trivially reverted.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The adversarial review found the ModalRenderGuard lagged the old
PortfolioEditorActive() signal by one extra frame on CLOSE (a possible 1-frame
"opaque panels" flash). Latch the overlay's open flag (already available via
spec.p_open) — "drew this frame AND still open after Esc/Close/outside handling" —
instead of just "drew last frame", so the guard drops and the acrylic re-capture
fire on the same frame the overlay closes, matching the old inline behavior on
both edges.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dogfood the Phase 0 framework: RenderPortfolioEditor now opens via
material::BeginOverlayDialog(BlurFloat) + EndOverlayDialog instead of its own
inline overlay scaffold, and uses the promoted material:: SegmentedControl /
RightAlignX / BeginFadeScrollChild helpers (overlay_scroll.h). Delete the
portfolio's inline backdrop/capture-once state machine + its PfEditState capture
statics + the four local helper copies. App::render's ModalRenderGuard is now
driven by the modal-agnostic AnyBlurOverlayActiveLastFrame() (timing-equivalent),
and LatchBlurOverlayActive() at frame end handles the acrylic re-capture on close.
Framework tweak: floating cards pop the card WindowPadding after BeginChild (so
nested children don't inherit it) and center button labels, keeping the net
style-var count at 2 so EndOverlayDialog is unchanged and GlassCard stays
byte-identical. RenderPortfolioEditor: 357 -> 282 lines. Needs GUI verification
that the portfolio modal is visually/behaviourally unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Refactor BeginOverlayDialog to run through an OverlayDialogSpec + OverlayStyle
(GlassCard vs BlurFloat) with orthogonal flags (blurBackdrop / floatingContent /
plainHeading, fixed vs auto card height). The classic look is now GlassCard with
all flags off; the existing positional overload forwards to it → all ~43 current
dialogs are byte-identical (verified line-by-line). The BlurFloat path — live-blur
backdrop with per-overlay capture-once (frame-gap arming), floating content, plain
h6 heading — is implemented but unused until Phase 1 dogfoods it on the portfolio.
Also replace the unusable open-refcount with a per-frame drawn flag + last-frame
latch that invalidates the acrylic capture on the overlay's close transition.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First step toward unifying all app modals on the Manage-Portfolio visual style.
Add, as shared material:: helpers (additive — no caller yet, no visible change):
- blur-overlay open refcount + 1-frame latch (Push/Pop/AnyBlurOverlayActive[LastFrame],
LatchBlurOverlayActive) so App::render's effect guard can be modal-agnostic;
- capture-frame query (IsCapturingBlurBackdrop) for scroll-fade suppression;
- RightAlignX and SegmentedControl (promoted verbatim from market_tab);
- BeginFadeScrollChild/EndFadeScrollChild in a dedicated overlay_scroll.h (kept
out of the widely-included draw_helpers.h because effects::ScrollFadeShader's GL
headers clash with SDL's in some TUs).
Also fix IsCurrentWindowOverlayDialog to prefix-match "##OverlayScrim" so suffixed
overlay windows are recognized by the modal-aware hover check.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add market_iv_1h/1d/1w/1m and market_updated ("· Updated %s") keys and use them
in the chart interval strip (previously hardcoded "1H"/"1D"/"1W"/"1M") and the
pair-selector attribution line (previously a literal "· Updated %s"). Closes the
audit's i18n gaps in the market tab.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the balance summary (fiat/DRGX/BTC + shielded ratio bar) and the
draggable/resizable custom-group card grid (drag/resize gestures, dot grid,
click-to-edit) out of RenderMarketTab into mktDrawPortfolio(MktCtx); the local
x-coord `cx` renamed `cx0` (ctx param is `cx`). Drop the now-unused
gap/dl/glassSpec/buf locals. RenderMarketTab is now ~150 lines (from 962) — a
thin orchestrator: precompute -> build MktCtx -> hero/chart/pair/portfolio.
Verbatim bodies. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the ~250-line chart block (interval strip + 24h stats + refresh, plotted
curve with grid/area-fill/hi-lo+time labels/hover crosshair+tooltip, empty
state) out of RenderMarketTab into mktDrawPriceChart(MktCtx), recomputing cheap
locals and reading the precomputed series via the ctx. Drop the now-unused
hs/pad locals. Verbatim body. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Introduce a MktCtx struct holding RenderMarketTab's precomputed geometry/series,
built once after the precompute, and extract the combined hero card (glass panel
spanning header + chart, price/ticker/period-badge/trade button) into
mktDrawPriceHero(MktCtx). Cheap locals (dl/fonts/dp/market) recomputed in the
helper; the hero's local x-coord `cx` renamed `cx0` (the ctx param is `cx`).
Verbatim body. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the exchange/pair chip grid (wrapping flat chips + click-to-switch +
attribution line) out of RenderMarketTab into mktDrawPairSelector(app, registry,
availWidth), recomputing its own schema/fonts/market. Drop the now-unused ovFont
local. Verbatim body. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lift the ~90-line [&]-capturing drawCard closure out of RenderMarketTab's grid
code into a file-static mktDrawCard(MktCardCtx, min, max, entry, hov). The
captured locals (dl/state/market/mktDp/pfInset/pfCardPad/sub1/capFont) are
bundled into a MktCardCtx bound once per frame. Verbatim body. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pull the ~30-line row-major cell placement (honor stored placement else
auto-place) out of RenderMarketTab into a pure, deterministic helper taking
(entries, cols, minW, minH). Also bump the grid resize-readout buffer 16->32 to
silence a worst-case -Wformat-truncation the extraction surfaced. No behavior
change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pull the three detail-pane section blocks out of RenderPortfolioEditor into
pfDrawAppearanceSection / pfDrawPriceSection / pfDrawAddressSection (each
recomputes its own dp/fonts/state; the section dispatch is a 3-line switch).
Verbatim move — same widgets, IDs and drawing. RenderPortfolioEditor drops from
~760 to ~357 lines. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Convert the four [&]-capturing lambdas (persist / buildWorking / workingMatches /
commitIfNeeded) into file-static pfPersist / pfBuildWorking / pfWorkingMatches /
pfCommitIfNeeded that operate on the s_pfEdit struct + take Settings*. Removes
the per-frame closure setup and lets the upcoming section helpers reuse them.
No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the loose market_tab.cpp statics into MarketViewState (s_mkt),
PfEditState (s_pfEdit) and PfGridDrag (s_grid). Pure mechanical rename
(compile-verified, no behavior change) that shrinks the global surface and gives
the upcoming function decompositions a single state handle per concern instead
of ~35 free names.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the no-I/O, no-ImGui series helpers (resampleHistory, bucketBySeconds,
sparklineSeries, chartSeries) out of market_tab.cpp into an inline header under
data/ (mirroring data/portfolio.h) and cover them with a testMarketSeries()
group in test_phase4.cpp (resample block averaging + partial blocks, window
bucketing + guards, sparkline fallback, chart time-window filtering + live
timestamp synthesis). market_tab now calls data::sparklineSeries/chartSeries.
No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the two identical equal-width segmented controls (the detail section
switcher Appearance/Price/Addresses and the address type filter
All/Shielded/Transparent) into one pfSegmentedControl(dl, origin, w, h, labels,
count, selected, font, idBase, dp) that returns the clicked index. Same track /
active-pill / centered-label drawing and per-cell hit-test as before; the
variable-width chart-interval strip is left as-is. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dedup the identical min/max→rect projection shared by pfDrawSparkline and
pfDrawSparklineFilled into pfProjectSeries, and the repeated right-align cursor
math (footer Close, detail Revert/Save, summary Manage button) into
pfRightAlignX. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Audit cleanup of market_tab.cpp:
- Remove the write-only statics s_history_initialized and s_last_refresh_time
(assigned in several places, never read) and their now-dead assignments.
- Align the portfolio grid card's BTC value to %.8f to match the editor preview
(pfBuildDisplay) and the summary rows; it was the lone %.6f, so the same
balance rendered with different precision in the preview vs the card.
- Fix the stale s_pf_sel comment (no "-2 = unsaved draft" state exists).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merge the two address-section rows into one: the All/Shielded/Transparent
segmented type filter sits on the left and Select all / Clear / Funded are
right-aligned on the same line, both vertically centered. Select-all is deferred
to a flag applied after the filtered set is built, so it still targets the
current filter (and stays idempotent via PortfolioEntryAdd's dedup).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Complete the explicit-save model: leaving the Manage-portfolio modal via Esc or
an outside-click now discards the current group's uncommitted edits (matching
the discard-on-switch behavior), while the Close button still commits. Only the
Save and Close buttons persist; every other exit path is a cancel.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switching to another group in the Manage-portfolio list (or adding/deleting a
group) now discards the current group's uncommitted working edits instead of
auto-saving them — only the Save button (and closing the modal) persists. This
matches the explicit-save model signalled by the Revert/Save buttons and the
unsaved-changes dot: navigating between drafts is ephemeral until saved.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Move the group-scoped Revert/Save buttons into the detail container (sized to
the Add-entry height) so they read as lower-hierarchy than the modal-level
Close, which now stands alone in the footer. The detail body is wrapped in a
child that reserves the bottom row.
- Add an amber "unsaved changes" dot on the selected group row while its working
copy differs from the stored entry; also gate the detail Revert/Save on that
dirty state.
- Addresses: narrow the All/Shielded/Transparent segmented control (360px) and
right-align Select all / Clear / Funded on one line; give the Select all /
Clear pills more text padding.
- Appearance: shrink the icon search field and right-align it on the heading
line, with a "Search icons…" hint.
- Price: move the sparkline toggle onto the 24h line; the interval radios stay
below, enabled only when the sparkline is shown.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rework the Manage-portfolio detail pane's Appearance and Addresses sections:
- Icon picker: search field inline with the "Icon" heading (filters by name,
hides the "None" slot while searching); grid now always fits 12 icons per
row, scaling cell size to width and centering the block.
- Both the icon grid and the address list scroll via a shared helper
(pfBeginScrollChild/pfEndScrollChild): smooth scrolling + the Settings-tab
edge-fade shader + a thicker, rounded scrollbar inset from the container edge
(bordered outer frame wrapping an inner scrolling child). Smaller container
radius. Fade gates off in low-spec and while the acrylic backdrop is being
captured — latched per-frame so the last capture frame no longer clashes with
the render-state reset.
- Addresses: All/Shielded/Transparent segmented control moved to its own row,
capped at 580px; Select all / Clear pills moved left of the Funded checkbox
on one left-aligned row (Funded vertically centered against the pills).
- Custom colour "+" swatch inset a few px so its selection outline no longer
clips at the modal's right edge.
- Remove the divider above the footer Revert/Save/Close buttons.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Appearance: icon-picker cells doubled (56px, iconXL glyphs); color swatches back to a
single row that hides overflow but always keeps the custom "+" cell visible at the right.
- Price: basis radios are now horizontal, matching the sparkline-interval radios.
- Addresses: All/Shielded/Transparent segmented control shrinks to sit on one line with
the Funded toggle to its right; Select all / Clear are rounded (pill) buttons with
padding, right-aligned on their own row.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Price: the basis and sparkline-interval dropdowns become radio groups (all options
visible), now that the segmented layout gives the section full height.
- Addresses: the All/Shielded/Transparent chips become a rounded segmented control
matching the top switcher. "Select shown" renamed to "Select all"; Select all + Clear
moved onto the Funded row, right-aligned. Address list gets inner WindowPadding.
- Appearance: 17 more preset colors (25 total), and the swatches now wrap into a grid
(with the custom-color cell) instead of a single overflowing row.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Swap the collapsible Appearance/Price/Addresses dropdown sections for a single
segmented pill control (one section shown at a time) — no dropdown headers. The
active section now owns the full detail height, so the icon grid and address list
fill the available space instead of fixed heights. State: s_pf_section (0/1/2)
replaces the three accordion open-flags.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Raising the backdrop radius alone would thrash the shared radius-keyed blur cache (the
glass panels blur at ~30). Instead, while a full-window blur overlay is active, glass
panels use their opaque fallback (IsFullWindowBlurOverlayActive) — they're covered by the
backdrop anyway — so the backdrop is the SOLE applyBlur caller and can use a strong custom
radius (64) with the cache staying coherent and frozen. The flag is toggled alongside the
theme-effect suppression by a RAII guard in App::render().
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch the live-blur behind the modal from a per-frame capture (which flickered from
per-frame re-blur non-determinism) to capture-once-on-open, re-captured only on resize.
- Insert the acrylic live-capture callback into the overlay draw list ONLY for a few
frames on open and whenever the viewport size changes; other frames reuse the frozen
blurred snapshot (blurCacheValid_), so there's no per-frame capture/re-blur cost. State:
s_pf_was_open (reset on close), s_pf_capture_frames, s_pf_capture_w/h.
Two fixes from an adversarial review of the timing/pipeline interaction:
- Do NOT override the backdrop blurRadius to 40. applyBlur caches one blurred buffer
keyed on radius, shared with every glass panel (market cards + the modal preview card,
radius ~30). A different radius thrashed that cache every frame and made the backdrop
sample the wrong blur, defeating the frozen-blur guarantee. Using the theme card's
radius keeps one blur serving all surfaces, frozen.
- Skip the blur on the overlay's first frame (allowBlur=false) — the live content isn't
captured until that frame's render, so blurring then would show stale/background pixels
for one frame; draw the plain opaque scrim instead.
Compiles on OpenGL (Linux) + DX11 (Windows). Needs on-device visual verification.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Fix the ImGui error on hovering a group row: the per-row delete was an
overlapping InvisibleButton + SetCursorScreenPos over the row Selectable. Replace
it with a manual IsMouseHoveringRect / IsMouseClicked hit-test (no overlapping
ImGui item, no cursor manipulation).
- Delete icon is larger (iconMed) and inset from the row edge (spacingMd).
- Footer no longer clipped: reserve 56px for the 40px buttons + separator.
- Manage-portfolio heading is now plain text (h6) with no title-bar background or
divider — content floats on the backdrop.
- Sidebar theme-effect borders no longer bleed through the overlay: suppress panel
theme-effects frame-wide (RAII guard in App::render via ui::PortfolioEditorActive)
while the modal is open, instead of only during the market render.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The acrylic system only blurred a frozen snapshot of the static app background. Add
an overlay-time re-capture so the Manage-portfolio modal blurs the LIVE tab content
behind it.
- AcrylicMaterial::captureLiveFramebuffer() (GL blit of FB 0 / DX11 CopyResource of the
backbuffer + no-backend stub) mirrors captureBackgroundDirect but bypasses the
dirtyFrames_ gate so it refreshes every frame the overlay is open, forcing a re-blur.
- ImGuiAcrylic::GetLiveCaptureCallback() returns a draw callback for it.
- market_tab: the modal inserts that callback (+ ImDrawCallback_ResetRenderState) at the
START of its overlay draw list, before the backdrop, so the capture holds the app UI
drawn below and the backdrop blurs it. On close, InvalidateCapture() re-captures the
background so other glass panels don't keep blurring the stale live capture.
- Panel theme-effects are suppressed during the market render while the modal is open
(their foreground-draw-list borders draw above all windows and would otherwise bleed
over the overlay). Market tab body is rendered again (no longer skipped).
- Backdrop draws the acrylic at full strength (fallbackColor.w=1) over an opaque base so
the blurred content reads clearly; lighter dim.
Design mapped via an Explore investigation of the capture/blur pipeline; compiles on
both OpenGL (Linux) and DX11 (Windows cross-build). Needs on-device visual verification.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- The per-row delete icon's SetCursorScreenPos left the ImGui cursor at the icon,
so the next group row started too high and rows overlapped. Capture the row's
end cursor after the Selectable and restore it after drawing the delete icon.
- Force centered button-label alignment for the modal (ButtonTextAlign 0.5,0.5)
so the footer/Add buttons read consistently.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Delete moved from the footer to a per-row trash icon on each group (shown on
hover/selected), with deferred deletion + selection fix-up.
- Removed the title-bar X; the footer is now right-aligned Revert / Save / Close
(larger buttons), Close commits + dismisses. Esc and outside-click still close.
- Add entry now immediately creates a persisted "Untitled" group and selects it
(no more invisible draft state); the -2 draft path is gone.
- Backdrop bleed-through fixed: when the modal is open the Market tab body is not
rendered, so its content and foreground theme-effect borders no longer show over
the overlay — the modal floats on the app's blurred/opaque backdrop.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add button can no longer be cut off: it's now a normal widget below the group
list (in a group with the scroll child) instead of nested inside the list child.
- Stop the modal's 28x20 WindowPadding from cascading into the nested master/detail/
list children (pop it right after the card child begins) — that double-padding
was squeezing the master column and the Add button.
- Right pane navigability: collapsed accordion sections now show a compact summary
on the right (Appearance -> icon, Price -> basis, Addresses -> N selected), so a
group's state is readable without expanding. Section titles are consistent
title-case ("Appearance"/"Price"/"Addresses").
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove the centered glass card behind the Manage-portfolio content so it floats
directly on the blurred/opaque full-window backdrop. The little live-preview card
keeps its panel (it previews the actual group card).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop ImGuiWindowFlags_NoBringToFrontOnFocus on the overlay window — it stopped
the per-frame SetNextWindowFocus() from raising the modal, so it rendered behind
the market chart/cards. Now matches the proven BeginOverlayDialog behavior.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Combine the old list/edit modes into one master-detail view rendered as a
full-window overlay instead of a floating dialog.
- Backdrop: new material::DrawFullWindowBlurBackdrop draws an opaque base first
(so the sheet is opaque regardless of the UI-opacity slider — the acrylic path
multiplies its alpha by GetUIOpacity), then a strong full-window blur of the
backdrop, gated exactly like DrawGlassPanel so low-performance mode skips the
blur entirely (just the opaque scrim).
- Frame: bespoke full-window overlay (not BeginOverlayDialog) that mirrors the
scrim plumbing and preserves both overlay popup gotchas verbatim (no focus-steal
and no outside-click dismiss while a combo / color picker is open). Title-bar X,
Esc, and outside-click all dismiss.
- Left (master): selectable group list with accent bar + icon + name + value line,
and a pinned "Add group" button.
- Right (detail): live preview + label header, then a single-open accordion
(Appearance = color + outline opacity + icon; Price; Addresses) so only one
control group shows at a time — far less cluttered than the old two-column form.
- Footer: Delete / Revert / Save. Editing auto-commits named groups on navigation
and on close (preserving grid geometry); unnamed drafts are dropped.
- s_pf_editing tri-state replaced by s_pf_sel (+ accordion open-state); the Manage
button and grid-card click open with a valid selection.
Design + adversarial review done via multi-agent workflows (understand/design, then
a 3-lens ImGui-lifecycle / state-safety / backdrop review; zero confirmed defects).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>