diff --git a/ui-concepts/console-euclid-live/app.js b/ui-concepts/console-euclid-live/app.js
index 5efe113..a9c4159 100644
--- a/ui-concepts/console-euclid-live/app.js
+++ b/ui-concepts/console-euclid-live/app.js
@@ -264,11 +264,21 @@ function renderTabs() {
tab.className = "strip-tab" + (seg.id === engine.state.selectedId ? " active" : "");
tab.type = "button";
tab.innerHTML = `
-
CH ${seg.id + 1}${seg.length}px
+
+ CH ${seg.id + 1} · ${seg.length}px
+
+
+
+
${eff ? eff.name : seg.effect}
`;
tab.addEventListener("click", () => engine.selectSegment(seg.id));
+ tab.querySelector(".tab-cog").addEventListener("click", (e) => {
+ e.stopPropagation();
+ engine.selectSegment(seg.id);
+ openSegPopover(seg.id);
+ });
wrap.appendChild(tab);
});
@@ -329,10 +339,31 @@ function deleteActiveChannel() {
const seg = engine.selectedSegment();
if (!seg) return;
engine.deleteSegment(seg.id);
+ closeSegPopover();
showToast(`CH ${seg.id + 1} removed`);
}
$("#deleteChannelBtn").addEventListener("click", deleteActiveChannel);
+/* Per-channel settings popover — opened by the ⋯ on a tab. Holds the channel's
+ range editor + remove (moved out of the Controls card). The inputs keep their
+ ids, so the range/delete wiring below is unchanged; the popover always targets
+ the selected channel (the ⋯ selects it before opening). */
+function openSegPopover(segId) {
+ const seg = engine.segmentById(segId);
+ if (!seg) return;
+ const eff = engine.effectById(seg.effect);
+ $("#segPopTitle").textContent = "CH " + (seg.id + 1);
+ $("#segPopSub").textContent = eff ? eff.name : String(seg.effect);
+ $("#segPopBackdrop").classList.add("show");
+ $("#segPopover").classList.add("show");
+}
+function closeSegPopover() {
+ $("#segPopBackdrop").classList.remove("show");
+ $("#segPopover").classList.remove("show");
+}
+$("#segPopBackdrop").addEventListener("click", closeSegPopover);
+document.addEventListener("keydown", (e) => { if (e.key === "Escape") closeSegPopover(); });
+
// Editable segment boundaries. Commit on change (blur / Enter); the engine
// clamps to the strip and PUTs {start}/{length}. Enter blurs to commit.
function commitRange(field) {
diff --git a/ui-concepts/console-euclid-live/index.html b/ui-concepts/console-euclid-live/index.html
index 2a42114..07c21f6 100644
--- a/ui-concepts/console-euclid-live/index.html
+++ b/ui-concepts/console-euclid-live/index.html
@@ -172,24 +172,6 @@
-
-
Effect
@@ -199,10 +181,6 @@
-
-
-
-
@@ -517,6 +495,35 @@
+
+
+
+
+ CH 1
+ —
+
+
+
+
+
+
+
diff --git a/ui-concepts/console-euclid-live/styles.css b/ui-concepts/console-euclid-live/styles.css
index c7905bb..620e27d 100644
--- a/ui-concepts/console-euclid-live/styles.css
+++ b/ui-concepts/console-euclid-live/styles.css
@@ -315,6 +315,21 @@ input, button, textarea{ font-family: inherit; color: inherit; }
box-shadow: none;
}
+/* Keep the CONSOLE/SETTINGS toggle on-screen on narrow viewports: the rail is
+ otherwise all flex-shrink:0 and overflows off the right edge. Shed the
+ decorative model number + divider first, then tighten spacing on the
+ smallest screens so the wordmark + toggle always fit. */
+@media (max-width: 620px){
+ .brand-model{ display: none; }
+ .brand-plate{ padding-right: 0; border-right: none; }
+}
+@media (max-width: 440px){
+ .top-rail{ padding: 12px 12px; gap: 8px; }
+ .brand{ gap: 9px; }
+ .brand-plate .mark{ font-size: 18px; letter-spacing: 0.2em; }
+ .nav-toggle button{ padding: 7px 11px; }
+}
+
/* ==========================================================================
Views
========================================================================== */
@@ -1633,6 +1648,69 @@ input, button, textarea{ font-family: inherit; color: inherit; }
transform: scale(1) translateY(0);
pointer-events: auto;
}
+
+/* ── Per-channel ⋯ button + settings popover ───────────────────────────── */
+.tab-cog{
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 20px; height: 16px;
+ margin: -3px -4px -3px 6px;
+ border-radius: 3px;
+ color: var(--c-text-faint);
+ cursor: pointer;
+ transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
+}
+.tab-cog:hover{ color: var(--c-text); background: var(--c-line-soft); }
+.tab-cog svg{ width: 15px; height: 15px; }
+.strip-tab.active .tab-cog{ color: var(--c-text-dim); }
+
+.seg-popover{
+ position: fixed;
+ z-index: 51;
+ left: 50%; top: 50%;
+ transform: translate(-50%, -48%) scale(0.98);
+ width: min(320px, calc(100vw - 32px));
+ background: var(--c-chassis);
+ border: var(--hair) solid var(--c-text);
+ border-radius: var(--radius-panel);
+ padding: 16px;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease);
+}
+.seg-popover.show{
+ opacity: 1;
+ transform: translate(-50%, -50%) scale(1);
+ pointer-events: auto;
+}
+.seg-pop-head{
+ display: flex;
+ align-items: baseline;
+ gap: 8px;
+ margin-bottom: 14px;
+}
+.seg-pop-title{
+ font-family: var(--font-display);
+ font-style: italic;
+ font-size: 16px;
+ color: var(--c-text);
+}
+.seg-pop-sub{
+ font-family: var(--font-mono);
+ font-size: 10px;
+ font-weight: 700;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ color: var(--c-text-faint);
+}
+.seg-pop-actions{
+ margin-top: 16px;
+ padding-top: 14px;
+ border-top: var(--hair) solid var(--c-line-soft);
+}
+.seg-pop-actions .seg-remove{ width: 100%; }
+.seg-remove:hover{ color: var(--c-red); border-color: var(--c-red); }
.cp-preview{
height: 38px;
border-radius: var(--radius-ctl);