diff --git a/src/base.css b/src/base.css
index 284460c..c4d48cb 100644
--- a/src/base.css
+++ b/src/base.css
@@ -94,6 +94,24 @@ details.spec .spec-body { padding:2px 16px 16px; }
.progbox-msg.ok { color:#5fd08a; } .progbox-msg.bad { color:#ff8a7a; }
[data-embed] .progbox { display:none !important; }
+/* ---- shared dimensioned schematic views (front + top/side with inch dims) ---- */
+.dview { width:100%; max-width:540px; margin:16px auto 0; }
+.dview .cap { text-align:center; font-size:11px; color:var(--muted,#7f8b9a); margin:0 0 8px; }
+.drow { display:flex; align-items:stretch; gap:6px; }
+.dvy { flex:0 0 15px; writing-mode:vertical-rl; transform:rotate(180deg); display:flex; align-items:center; justify-content:center;
+ font-size:9px; color:var(--muted,#7f8b9a); letter-spacing:.03em; white-space:nowrap; border-right:1px solid var(--panel-bd,#2a313c); }
+.dvx { text-align:center; font-size:9px; color:var(--muted,#7f8b9a); letter-spacing:.03em;
+ border-top:1px solid var(--panel-bd,#2a313c); padding-top:3px; margin:3px 0 0 17px; }
+.dschem { flex:1; min-width:0; position:relative; border:1px solid #33363c; border-radius:8px;
+ background:radial-gradient(rgba(255,255,255,.02) .5px, transparent .6px) 0 0/3px 3px, linear-gradient(160deg,#26282d,#15161a);
+ box-shadow:inset 0 1px 0 rgba(255,255,255,.05), 0 6px 16px rgba(0,0,0,.4); overflow:hidden; }
+.dschem .scap { position:absolute; left:7px; top:5px; font-size:8px; color:var(--silk,#aab2bc); letter-spacing:.08em; text-transform:uppercase; opacity:.7; }
+.dschem .ctl { position:absolute; border-radius:50%; background:radial-gradient(circle at 38% 32%,#cfd6dd,#6c7480 60%,#3b424c); box-shadow:0 1px 3px rgba(0,0,0,.5); }
+.dschem .scr { position:absolute; border-radius:4px; background:#06080c; box-shadow:inset 0 0 8px rgba(0,0,0,.7); }
+.dschem .jk { position:absolute; width:12px; height:12px; border-radius:50%; border:2px solid #5b6470; background:radial-gradient(circle at 40% 34%,#333a44,#07090c 72%); }
+.dschem .jk.u { width:14px; height:6px; border-radius:3px; }
+.dschem .jl { position:absolute; font-size:7px; color:var(--silk,#aab2bc); letter-spacing:.03em; text-transform:uppercase; opacity:.85; text-align:center; line-height:1.1; }
+
/* ---- "Show info" toggle + technical section ---- */
.info-toggle { display:flex; align-items:center; justify-content:center; gap:8px; margin:18px auto 0; max-width:620px;
font-size:13px; color:var(--muted,#7f8b9a); cursor:pointer; }
diff --git a/src/progbox.js b/src/progbox.js
index 84c8bbf..4343e4a 100644
--- a/src/progbox.js
+++ b/src/progbox.js
@@ -2,11 +2,11 @@
Uses the engine codec (patchToSetup / setupToPatch / codeToSetlist) for decode + lint.
Host page provides: window.currentProgramString() and window.loadProgramString(plain).
Exposes window.progRefresh() — call it after the device's program changes. When the
- page is embedded it posts {type:'varasys-prog'} to the parent instead of touching the box. */
+ page is embedded it posts {type:'varasys-prog'} to the parent instead of touching the box.
+ Defers to DOM-ready so the box/toggle/techinfo are found wherever they sit on the page. */
(function () {
- var box = document.getElementById("dProg");
- var msg = document.getElementById("dProgMsg");
var embedded = document.documentElement.dataset.embed === "1";
+ var box, msg, editing = false;
function setMsg(t, ok) { if (!msg) return; msg.textContent = t || ""; msg.classList.toggle("ok", !!ok && !!t); msg.classList.toggle("bad", !ok && !!t); }
function lint(text) {
text = (text || "").trim(); if (!text) return { ok: false, msg: "empty" };
@@ -22,7 +22,12 @@
return { ok: true, plain: setupToPatch(s), msg: s.lanes.length + " lane" + (s.lanes.length > 1 ? "s" : "") + " · " + s.bpm + " BPM" };
} catch (e) { return { ok: false, msg: "✗ " + e.message }; }
}
- var editing = false;
+ function doLoad() {
+ var r = lint(box.value);
+ if (!r.ok) { box.classList.add("err"); setMsg(r.msg, false); return; }
+ box.classList.remove("err"); box.value = r.plain; setMsg("✓ " + r.msg, true);
+ try { if (window.loadProgramString) window.loadProgramString(r.plain); } catch (e) { setMsg("✗ " + e.message, false); }
+ }
// report the current program: to the parent when embedded, else into the box.
// No-op on pages without a program hook (e.g. panel-based Teacher/Player).
window.progRefresh = function () {
@@ -31,30 +36,28 @@
if (embedded) { try { parent.postMessage({ type: "varasys-prog", patch: p }, "*"); } catch (e) {} return; }
if (box && !editing) { box.value = p; setMsg("", true); }
};
- if (box) {
- box.addEventListener("focus", function () { editing = true; });
- box.addEventListener("blur", function () { editing = false; });
- box.addEventListener("input", function () { box.classList.remove("err"); });
- box.addEventListener("keydown", function (e) { if (e.key === "Enter") { e.preventDefault(); doLoad(); } });
- var loadBtn = document.getElementById("dProgLoad"); if (loadBtn) loadBtn.addEventListener("click", doLoad);
- var copyBtn = document.getElementById("dProgCopy"); if (copyBtn) copyBtn.addEventListener("click", function () {
- try { navigator.clipboard.writeText(box.value); copyBtn.textContent = "Copied!"; setTimeout(function () { copyBtn.textContent = "Copy"; }, 1200); } catch (e) { box.select(); }
- });
+ function init() {
+ box = document.getElementById("dProg"); msg = document.getElementById("dProgMsg");
+ if (box) {
+ box.addEventListener("focus", function () { editing = true; });
+ box.addEventListener("blur", function () { editing = false; });
+ box.addEventListener("input", function () { box.classList.remove("err"); });
+ box.addEventListener("keydown", function (e) { if (e.key === "Enter") { e.preventDefault(); doLoad(); } });
+ var loadBtn = document.getElementById("dProgLoad"); if (loadBtn) loadBtn.addEventListener("click", doLoad);
+ var copyBtn = document.getElementById("dProgCopy"); if (copyBtn) copyBtn.addEventListener("click", function () {
+ try { navigator.clipboard.writeText(box.value); copyBtn.textContent = "Copied!"; setTimeout(function () { copyBtn.textContent = "Copy"; }, 1200); } catch (e) { box.select(); }
+ });
+ }
+ // "Show info" toggle — reveals the technical section (#techinfo + any .tech); ?info=1 opens it checked
+ var tog = document.getElementById("infoToggle"), tech = document.getElementById("techinfo");
+ if (tog) {
+ var extra = document.querySelectorAll(".tech");
+ var apply = function (on) { if (tech) tech.hidden = !on; for (var i = 0; i < extra.length; i++) extra[i].hidden = !on; };
+ var open = /[?&]info=1/.test(location.search);
+ tog.checked = open; apply(open);
+ tog.addEventListener("change", function () { apply(tog.checked); });
+ }
+ window.progRefresh();
}
- function doLoad() {
- var r = lint(box.value);
- if (!r.ok) { box.classList.add("err"); setMsg(r.msg, false); return; }
- box.classList.remove("err"); box.value = r.plain; setMsg("✓ " + r.msg, true);
- try { if (window.loadProgramString) window.loadProgramString(r.plain); } catch (e) { setMsg("✗ " + e.message, false); }
- }
- // "Show info" toggle — reveals the technical section; ?info=1 opens it checked
- var tog = document.getElementById("infoToggle"), tech = document.getElementById("techinfo");
- if (tog) {
- var extra = document.querySelectorAll(".tech"); // e.g. dimensioned views outside #techinfo
- var apply = function (on) { if (tech) tech.hidden = !on; for (var i = 0; i < extra.length; i++) extra[i].hidden = !on; };
- var open = /[?&]info=1/.test(location.search);
- tog.checked = open; apply(open);
- tog.addEventListener("change", function () { apply(tog.checked); });
- }
- window.progRefresh();
+ if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", init); else init();
})();
diff --git a/stage.html b/stage.html
index ba5daed..f4861d5 100644
--- a/stage.html
+++ b/stage.html
@@ -322,6 +322,33 @@ window.loadProgramString = function(plain){ var s=patchToSetup(plain); tracks=[{
daisy‑chain off one charger or power bank.
+
+
Dimensions & layout — ≈ 4.7 × 3.7 × 1.5 in (120 × 93 × 38 mm), a 1590BB‑style stompbox
+
+
↕ 3.7 in (93 mm)
+
+
Front
+
+
+
+
+
angled TFT · RGB beat light · Tap + Next footswitches
+
+
+
↔ 4.7 in (120 mm) wide
+
+
↕ 1.5 in (38 mm)
+
+
Top edge — I/O
+
+
+
+
Trig · Inst In · Out TRS · Exp · USB‑C · USB‑C thru
+
+
+
↔ 4.7 in (120 mm)
+
+
Spec & bill of materials