git.lucas.co / cce-designer
graphic design tool
git clone https://git.lucas.co/cce-designer.git

commitb84345b954ca5b199024d62ac6ae3dee124e7110
parent78a0cbcec9
authorLucas Galante <[email protected]>
date2026-07-29 12:23
feat: viewport focus tints its rim; playbar wears the live params fill

The viewport's Boss rim now carries the focused-pane specular tint
(plate_focus_tint, via the new boss_edges_tinted) exactly like the plated
panes, and the flat focus ring defers to it under control_relief — same
contract as the params pane. The playbar's plate drops its hand-rolled
PARAM_BG copy for param_plate_fill(), so a Style-section retint / opacity /
blur toggle reaches it live like every other pane.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/playbar.rs | 14 ++++++--------
 src/render.rs  | 24 +++++++++++++++---------
 2 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/src/playbar.rs b/src/playbar.rs
index ae9a445..c59d5d0 100644
--- a/src/playbar.rs
+++ b/src/playbar.rs
@@ -81,15 +81,13 @@ impl Paint for Playbar {
         true
     }
 
-    /// The pane IS its own plate, exactly the ParametersBg contract: PARAM_BG
-    /// scaled by the global plate opacity, alpha negated as the blur marker.
+    /// The pane IS its own plate, exactly the ParametersBg contract: the
+    /// parameter plate's fill — tint, opacity, and blur-behind marker
+    /// (`param_plate_fill`) — so it tracks a live retint / opacity / blur
+    /// toggle with the other panes (the old hand-rolled PARAM_BG copy froze
+    /// the Style section's "Plate Color" out of this pane).
     fn color(&self) -> [f32; 4] {
-        let mut c = colors::PARAM_BG;
-        c[3] *= cce_ui::layout::plate_opacity();
-        if colors::plate_blur() {
-            c[3] = -c[3].abs();
-        }
-        c
+        colors::param_plate_fill()
     }
 
     fn solid_border(&self) -> Option<([f32; 4], f32)> {
diff --git a/src/render.rs b/src/render.rs
index 8107710..31bc8a9 100644
--- a/src/render.rs
+++ b/src/render.rs
@@ -218,12 +218,16 @@ impl State {
                 let (px, py, pw, ph) = self.positions[VIEWPORT_IDX];
                 if pw > 0.0 && ph > 0.0 {
                     let r = colors::backplate_corner_radius() * cce_ui::layout::corner_span_factor();
-                    pc.boss_edges(
-                        rect(px, py, pw, ph),
-                        (r, r, r, r),
-                        cce_ui::colors::plate_bevel_width(),
-                        (true, true, true, true),
-                    );
+                    let vp_rect = rect(px, py, pw, ph);
+                    let radii = (r, r, r, r);
+                    let depth = cce_ui::colors::plate_bevel_width();
+                    // Focus marks through the rim's specular tint, exactly the
+                    // plated panes' treatment (plate_focus_tint).
+                    if let Some(tint) = self.plate_focus_tint(idx) {
+                        pc.boss_edges_tinted(vp_rect, radii, depth, (true, true, true, true), tint);
+                    } else {
+                        pc.boss_edges(vp_rect, radii, depth, (true, true, true, true));
+                    }
                 }
             }
             for (qx, qy, qw, qh, qc) in w.extra_quads() {
@@ -463,8 +467,9 @@ impl State {
     /// only visual indicator of `focused_pane`.
     /// The focused pane's plate carries the highlight as its bevel's specular
     /// tint under `control_relief` — the ring in `append_context_border` is the
-    /// flat-style treatment. The viewport (rim-only Boss overlay, which carries
-    /// no tint) and the circular pane (arc ring) keep the ring in both styles.
+    /// flat-style treatment (the viewport's rim-only Boss overlay tints the
+    /// same way). Only the circular pane (arc ring) keeps the ring in both
+    /// styles.
     fn plate_focus_tint(&self, idx: usize) -> Option<[f32; 3]> {
         if !cce_ui::layout::control_relief() {
             return None;
@@ -473,6 +478,7 @@ impl State {
             NETWORK_PANEL_IDX | CONTENT_IDX => {
                 self.focused_pane == LEFT_MENUBAR_IDX && !self.circular_network_pane
             }
+            VIEWPORT_IDX => self.focused_pane == RIGHT_MENUBAR_IDX,
             PARAM_IDX => self.focused_pane == PARAM_MENUBAR_IDX,
             SPREADSHEET_IDX => self.focused_pane == SPREADSHEET_MENUBAR_IDX,
             _ => false,
@@ -520,7 +526,7 @@ impl State {
                 self.positions[NETWORK_PANEL_IDX]
             }
             RIGHT_MENUBAR_IDX => {
-                if !self.show_viewport {
+                if !self.show_viewport || relief {
                     return;
                 }
                 self.positions[VIEWPORT_IDX]