Fixes from a review of the mobile-UI branch.
- Guard the inspector size clamps so min<=max (f32::clamp panics otherwise) and set a
window min_inner_size; prevents a crash / degenerate layout at small sizes. Same
small-size guards for the piano-roll landscape toggle bar and the intent grid.
- Landscape 2->1 edge reveal: snap to fullscreen at frac>=0.5 (the preview's phase
boundary) instead of COLLAPSE_HI, so releasing mid-drag no longer jumps backward.
Both edges.
- Gate the double-tap-drag marquee to mobile so it can't hijack a desktop Brush/Draw
drag.
- Timeline mobile long-press: request a repaint while counting down so it fires even
when the finger is held perfectly still.
- Landscape folded top bar: lay the filename+search+overflow cluster out within a
reserved center span (gutters for the pane's own label/buttons) and elide the
filename, so it can't overlap or overflow the header.
- Node editor connect/disconnect: assert + document the top-level-graph assumption.
- Palette search field focuses only when unfocused (no per-frame focus stomp); reset
the inspector tap-anchor on orientation change; remove stale main.rs.backup.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the phone shell orientation-aware (portrait vs landscape). Orientation is
aspect-based (rotation = a resize the shell re-lays-out each frame); LB_MOBILE_UI=2
opens a landscape dev window. `SharedPaneState.is_portrait` is published to panes.
- Stack caps at 2 panes in landscape (max_panes through the R1–R6 drag ops), with a
per-frame clamp so rotating while 3 are open drops to 2.
- Edge drags are a continuous full-height reveal instead of stalling at the capped
trigger: 1-pane → split → next-pane-fullscreen, and (landscape 2-pane) a two-phase
slide-then-collapse to 1 pane. Both top and bottom edges, mirrored. Release snaps to
stay / split / fullscreen. Dividers resize and collapse-to-1 at the extremes.
- Inspector becomes a right-side vertical column in landscape (inspector_width_frac,
left-edge horizontal resize); portrait keeps the bottom sheet.
- Piano roll: vertical "Synthesia" view in portrait; landscape shows a Keys/Notes
segmented toggle over the conventional horizontal roll / full keyboard.
- Start screen reflows to 2 rows × 3 with the recent list beside it in landscape.
- Landscape headers are shorter (52→34px) and the top bar folds into the middle of the
top pane header (no separate band), reclaiming vertical space.
All gated to mobile; desktop unchanged (is_portrait defaults true).
Add Theme::var(name, ctx) (CSS custom-property getter) and Theme::apply_to_egui(ctx)
which maps the palette onto egui's global Visuals so standard widgets share the
theme colors. Add a mobile::palette::Palette built from the theme each frame and
replace the duplicated per-file C_* color constants across all mobile modules
(omni, topbar, stack, inspector, transport, intent, shell) with it. Add --scrim
and --accent-* category vars to styles.css. Apply the theme visuals every frame in
update(). Mobile and the main UI now share one CSS-variable-driven palette that
responds to light/dark/user themes.
Reserve a slim top bar in the mobile shell showing the project filename (or
"Lightningbeam" when unsaved) on the left, and ⌕/⋯ on the right. ⋯ opens a
curated overflow sheet (Save/Save As/Open/New/Import/Export/Undo/Redo/
Preferences); ⌕ opens a command palette that searches the whole menu tree
(flattened from MenuItemDef::menu_structure()). Both dispatch MenuActions.
Completes the P4 omnibutton + global menu.
Per design feedback, drop the top-tabs + single-ribbon model. The mobile UI
is now one vertical stack of all panes in a fixed order (Outliner, Asset
Library, Stage, Timeline, Piano Roll, Virtual Piano, Node/Instrument, Script
editor) with a window of 2-3 consecutive panes visible at a time.
Dragging the dividers between panes and the top/bottom screen edges grows,
shrinks, or slides the window via a small state machine (R1-R6 in stack.rs),
with continuous interpolation during the drag and snap-on-release. The
Node/Instrument band toggles between the node editor and the preset browser.
The transport stays pinned as the bottom floor.
Each visible band reuses PaneInstance::render_content full-bleed (surface.rs).
Removes topbar.rs and ribbon.rs; rewrites mod.rs state (window_top,
window_count, show_instruments, drag); adds stack.rs.
New src/mobile/ module renders a phone-style shell: top surface tabs
(Stage/Time/Nodes/Mixer/Tree), a single full-bleed hero pane reusing the
existing PaneInstance renderers, a resizable timeline ribbon (peek/half/full
snap tiers riding above the floor), and a fixed transport bar wired to the
audio controller (play/pause, timecode, project scrub).
Gated entirely on the LB_MOBILE_UI env var: when set, main() opens a
phone-aspect window and update() routes the central panel through
render_mobile_shell instead of render_layout_node, sharing the same
build_frame context and post-render drain. Desktop is unchanged when unset.
Tabs mirror the pane list; per the wireframe the Toolbar and Infopanel do
not become tabs (they become the omnibutton and inspector in later phases),
and the Nodes surface is a placeholder pending the focus/patch rework.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>