# Speech style toolbar live-edit refinement Status: **Approved; implementation complete, editor verification pending** (2026-09-29). This follow-up extends `specs/speech_style_toolbar_refinements.md` with immediate style application, a short non-blocking token effect demo, a dismissible styling toolbar, persistent hover selection feedback, and a lighter token-selection highlight. ## 1. Goals - Let children try style choices without confirming every chooser. - Preview an effect on its selected token, or all tokens in the selected bubble when no token is selected, without replaying the whole speech or blocking input. - Keep **Done styling** distinct from **Save speech**. - Preserve the selected choice outline while hovering it. - Keep selected word colors easy to see while making the word target obvious. ## 2. Immediate chooser editing - Remove **Cancel** and **Done** from the Frame, Letters, and Effects choosers. - Apply each selected choice immediately to the composer draft. Frame affects the selected bubble. Font, size, and color affect the selected token when one is targeted, otherwise the bubble defaults; a bubble-default choice clears that property from per-word overrides so the new default reaches every word. Effects affect the selected token when targeted, otherwise all text in the selected non-empty bubble. - Switching to another category or clicking outside the chooser closes the current chooser and keeps all choices already made. Escape dismisses the chooser and keeps those choices too. Opening a different category opens its chooser without rolling back the previous selection. - Stage clicks retain their existing selection behavior: clicking a token selects it; clicking elsewhere in the usable stage clears the token target while retaining the bubble selection. Those clicks also dismiss the open chooser without undoing choices. - Every choice updates the composer draft and its recoverable local draft. It does **not** commit the action to the scene queue or rule. **Save speech** remains the scene commit point; the composer's existing **Cancel** still discards the speech edit session. - Remove chooser transaction state that exists only to support Cancel/Done rollback. Keep choice selected-state feedback and the existing saved payload format. ## 3. Scoped effect demonstration - Selecting Shake, Wave, Bounce, or No effect applies it immediately to the current token, or to the selected bubble's default effect when no token is targeted. - For Shake, Wave, or Bounce, show a one-second preview on the same scope as the choice: the selected token or all tokens in the selected bubble. Other bubbles remain still. **No effect** stops the active preview immediately. - The preview accepts input throughout. It does not enter the full-speech PLAYING or blank-hold states, disable the toolbar, change action duration, or block stage bubble/token selection. - Keep the bubble frame, stack placement, and stage toolbar anchor stable throughout the one-second sample and when it ends. Refresh the animated token in place while retaining the current measured layout; typography, text, or placement edits may rebuild the layout immediately. - If another effect is selected before the current preview ends, stop the current animation and start the new effect from time zero on the same scope. Changing the selected token or closing the composer stops the current preview. Switching chooser categories alone does not cancel the remaining preview time. - When the one-second demonstration ends, the text returns to its static editor appearance; its chosen effect remains saved in the draft and plays during **Preview speech** as part of the full sequence. - Keep full-sequence **Preview speech** behavior unchanged, including configured transitions and the one-second blank hold. ### Ownership `SpeechComposer` remains the source of truth for draft style choices, Message editing, and recovery data. The Message panel is a non-dimming, toolbar-anchored chooser with a highlighted Message button. It remains open while editing; clicking Message again, choosing another category, or pressing Escape closes it. The text field stays fixed as the emoji grid opens and the panel expands downward. The composer owns its text and per-token style-span maintenance. Keep the one-second effect demo in a separate transient editor-preview state, independent of the full-sequence replay clock and serialized payload. `SpeechBubble` renders that transient motion only for the selected token or selected bubble scope while remaining in static-editor interaction mode. `SandboxStage` continues to own toolbar visibility, event routing, and preview updates. ## 4. Done styling and re-entry - Add a prominent **✓ Done styling** button to the main Speech Style toolbar, at least 56 px high. - It closes the style chooser and hides the Speech Style toolbar only. It does not save speech to the scene, cancel the composer, or unlock unrelated stage editing. The message editor and **Save speech** / **Cancel** controls remain available. - Clicking a speech bubble or its text while the composer remains open reopens the Speech Style toolbar and selects that bubble/token. Empty-stage clicks continue to clear the token target without reopening the toolbar. - Keep the current selected bubble and token highlight state when the toolbar is hidden. A later bubble click updates that state as usual. ## 5. Choice hover and token highlight - A selected Frame, Font, Size, Color, or Effect choice keeps its bright selection border in normal, hover, pressed, and focus states. Hover may lighten/darken the fill but must not replace or reduce the selected border. - Replace the strong filled word marker with a subtle rounded target: a low-opacity fill (about 15–20%) behind the token plus a clear bright outline and a thin dark contrast edge. The text glyphs and their chosen colors stay fully visible. - Keep the marker input-transparent and aligned with the rendered token, including wrapped tokens and punctuation. Selection and hit-testing semantics remain unchanged. - Center the text horizontally and vertically within each speech frame so font and size changes do not leave the text stranded against an edge. ## 6. Integration scope 1. `scripts/speech_composer.gd`: apply selected choices directly to `_draft`, update recovery data, and manage an interruptible one-second token-effect timer separate from replay. 2. `scripts/stickman_speech_bubble.gd` and `scripts/speech_word_effect.gd`: render the transient selected-token effect without disabling static-editor hit testing; draw the translucent rounded token marker. 3. `scripts/speech_style_toolbar.gd`: remove chooser Cancel/Done, preserve selected borders across hover states, and add Done styling. 4. `scripts/sandbox_stage.gd`: dismiss chooser without rollback, hide/reopen the toolbar as specified, and route transient effect-preview updates without blocking stage input. 5. Reuse/add local `sandbox_theme.json` values as needed. Do not change global theme, speech payload schema, action IDs, queue/rule serialization, or full-sequence replay semantics. ## 7. Acceptance checks - A chosen frame/font/size/color/effect remains applied when switching categories, dismissing the chooser, or reopening it. - Draft recovery includes each immediate style choice; only **Save speech** commits it to the scene, and composer **Cancel** still discards the edit session. - An effect choice previews only its targeted token, or all tokens in the selected bubble with no target, for about one second while text editing, category changes, and stage selection remain responsive. - The effect sample does not make the bubble or its styling toolbar jump as the animated glyph moves or when the sample ends. - With no token selected, changing a bubble's font, size, or color updates all its text, including tokens that previously had a per-word override for that property. - Text remains centered after changing font or size on a token or bubble. - Choosing another effect during that second visibly replaces the active demo without overlapping or replaying the whole speech. **No effect**, target change, and composer close stop the transient demo. - Full-sequence **Preview speech** still runs once with its blank hold. - Done styling hides the stage toolbar but leaves the composer open and stage interaction locked to speech composition. Clicking a speech bubble/token reopens the toolbar; clicking empty stage does not. - Hovering a selected choice never hides its selection border. - Selected token text remains legible in all 16 colors under a rounded, translucent marker; punctuation and wrapped tokens remain selectable. - Saved scene data uses the existing speech payload and reloads with selected styles intact. - The Message panel contains the emoji picker, blocks stage/object input while open, and leaves stage token selection as the only way to choose a styling target. It does not dim the stage or move the text field when the emoji grid opens. - Timing is selected from the stage toolbar but keeps the existing action-wide `duration_mode` IDs and Normal/Slow/Slower behavior; Show arrangement, Reveal, and Entrance remain in the inspector. ## 8. Risks and boundaries The most important distinction is between saving a choice into the recoverable composer draft and committing the complete speech action into the scene. The one-second effect sample must remain independent from full speech replay, and the renderer must keep editor hit-testing enabled while a sample animates. Verify the marker with bright, dark, and similarly colored text, plus punctuation and wrapped words, in the Godot editor.