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 @@ -
- Segment Range -
- - -
- End - -
-
-
-
Effect
@@ -199,10 +181,6 @@
-
- -
- @@ -517,6 +495,35 @@ + +
+ +
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);