# TASK 59 — The properties panel is a hierarchy (titles own their content) **Status:** ✅ Done — shipped 2026-10-21. ## What it is The creator's ruling (2026-10-21), on the Live scene → Layers → webcam → Properties: > Mirror Rect: needs a title "Shape" above it and **Rect should be selected as a default > if none exists** … also, the "drag to move" help text needs to be **indented under > "Mirror Rect" to show parentage** … same with **Geometry, Border Color, Border > Thickness**. Background → Remove: Remove should be indented under Background as should > Blur. Blur → Strength: Strength should be indented under Blur. One rule covers all of it: **a title owns its content, and the content is indented one level (10px) under it.** Two levels deep when a title is itself nested (Strength under Blur under Background). ## The panel now reads ``` Shape ← NEW title [Mirror] [Rect] [Circle] ← the shape is a CHOICE, Rect selected by default Drag to move · drag the corner dot to resize Geometry ← title (already there), fields indented X [ ] Y [ ] W [ ] H [ ] Border Color ← promoted to a title, the field indented [#2c3a5c] [..] Border Thickness ← promoted to a title, the slider indented [slider] 3 Background ← title, its rows indented Remove [pill] Blur [pill] Strength [slider] 50% ← one level deeper, under Blur ``` ## The shape: a choice, not a toggle Before: one button whose content was `ShapeButtonText` — the **next** action ("Round" when the camera was a rectangle). The creator could not tell what the camera *was*, only what it would become. Now: two `SegmentToggle` options — **Rect** and **Circle** — bound to two new settable bools on `SceneElement`: - `IsRectShape` — true when the clip is the plain rectangle, which is what a camera is when no shape was ever picked (**the creator's "Rect is selected by default if none exists"**). - `IsRoundShape` — true when the clip is a circle. Each setter flips the shape through `ToggleClipShape()` (so the pre-round rect is still stored/restored) and **always re-raises** — a refused write (the vertical Chat layout is rect-only, TASK 57) makes the UI snap back to the truth instead of sticking. `ShapeButtonText` is gone (dead code after this change). ### Why the mutual exclusion lives in the model Not in a WPF `RadioButton` group: a RadioButton group unchecks its siblings by setting `IsChecked` **in code**, which makes WPF drop the binding ("Losing the binding for radio button after I set the property manually in code", stackoverflow 7376373) — the panel would silently stop reflecting the model. Two bool properties with model-side setters keep the binding alive (stackoverflow 50980687 / 57275046 describe the same trap). ## The circle option is still not offered where it must not be The Circle option's `Visibility` binds to `CanToggleClipShape` — false in the vertical tier's Chat layout (TASK 57) — so the option is not even shown there, and the model refuses the write anyway. ## Tests `ytLive.Tests/PropertiesHierarchyTests.cs` — the ONE test for this change: - the model: Rect is selected by default → picking Circle makes the clip Round → picking Rect again restores it → the vertical Chat lock still refuses the circle; - the panel: the `Shape` title owns both options, the Circle option is the one gated by `CanToggleClipShape`, the drag hint is indented and follows the shape row, every titled block's content is indented 10px, and Strength sits at 20px (under Blur). 432/432 green at ship time.