Loading files
:root {
--cream: #f4efe6;
--cream-2: #ede7db;
--ink: #141414;
--muted: #6b655a;
--faint: #a69f90;
--rule: #d9d1c0;
--led: #e8552e;
--ok: #267a43;
--bad: #b43b2d;
--field: #fbf7ef;
}
* {
box-sizing: border-box;
}
body {
width: 460px;
max-height: 620px;
margin: 0;
padding: 16px;
overflow-y: auto;
background: var(--cream);
color: var(--ink);
font: 12px/1.45 Inter, ui-sans-serif, system-ui, sans-serif;
}
header,
.section-head,
.band-head,
.band-actions {
display: flex;
align-items: center;
}
header {
justify-content: space-between;
gap: 12px;
padding-bottom: 12px;
border-bottom: 1px solid var(--ink);
margin-bottom: 10px;
}
.brand {
display: flex;
align-items: center;
min-width: 0;
gap: 8px;
}
.brand img {
width: 24px;
height: 24px;
flex: 0 0 auto;
}
h1 {
margin: 0;
font-size: 13px;
font-weight: 600;
text-transform: uppercase;
}
section {
margin: 0;
padding: 12px 0;
border-bottom: 1px solid var(--rule);
background: transparent;
}
.status {
min-width: 82px;
padding: 5px 8px 4px;
border: 1px solid var(--ink);
background: var(--field);
font-size: 10px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
letter-spacing: .12em;
text-align: center;
text-transform: uppercase;
}
.ok { color: var(--ok); }
.bad { color: var(--bad); }
.label {
display: block;
margin-bottom: 6px;
color: var(--muted);
font-size: 10px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
letter-spacing: .14em;
text-transform: uppercase;
}
.device {
display: grid;
grid-template-columns: 1fr 74px;
gap: 7px;
}
input,
select,
button {
font: inherit;
}
input[type="text"],
select {
width: 100%;
border: 1px solid var(--rule);
background: var(--field);
color: var(--ink);
}
input[type="text"] {
padding: 8px 9px;
}
select {
padding: 3px 6px;
}
button {
min-height: 32px;
border: 1px solid var(--ink);
background: var(--ink);
color: var(--cream);
cursor: pointer;
font-size: 10px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
letter-spacing: .1em;
text-transform: uppercase;
}
button:hover {
background: var(--cream);
color: var(--ink);
}
.small-button,
.remove-band {
min-height: 26px;
padding: 5px 8px;
}
.remove-band {
border-color: var(--rule);
background: transparent;
color: var(--muted);
}
.actions {
display: grid;
/* Two, since WS Test moved into the diagnostics fold. */
grid-template-columns: 1fr 1fr;
gap: 7px;
margin-top: 8px;
}
.actions button {
padding: 8px;
}
.detail {
min-height: 18px;
margin-top: 7px;
color: var(--muted);
font-size: 11px;
}
.section-head {
justify-content: space-between;
gap: 8px;
}
.spectrum-wrap {
position: relative;
height: 132px;
border: 1px solid var(--ink);
background: var(--field);
}
#spectrum {
display: block;
width: 100%;
height: 100%;
}
.spectrum-bands {
position: absolute;
inset: 0;
pointer-events: none;
}
.spectrum-band {
position: absolute;
top: 0;
bottom: 0;
border-left: 1px solid var(--led);
border-right: 1px solid var(--led);
background: rgba(232, 85, 46, .16);
}
.spectrum-band span {
position: absolute;
left: 5px;
top: 5px;
color: var(--ink);
font-size: 10px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.spectrum-scale {
display: grid;
grid-template-columns: repeat(5, 1fr);
margin-top: 5px;
color: var(--muted);
font-size: 10px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.spectrum-scale span:last-child {
text-align: right;
}
.global {
display: grid;
grid-template-columns: 1fr 42px;
align-items: center;
gap: 8px;
}
.global label,
.manual-grid label {
display: grid;
align-items: center;
gap: 8px;
color: var(--muted);
font-size: 11px;
}
.global label {
grid-template-columns: 74px 1fr;
}
.manual-grid {
display: grid;
gap: 8px;
}
.manual-grid label {
grid-template-columns: 28px 1fr 40px;
}
.value,
output {
color: var(--ink);
text-align: right;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-variant-numeric: tabular-nums;
}
.band {
margin: 0;
padding-top: 12px;
}
.band-head {
justify-content: space-between;
gap: 8px;
margin-bottom: 8px;
}
.band-title {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
}
.band-actions {
gap: 7px;
}
.target {
display: grid;
grid-template-columns: auto 48px;
align-items: center;
gap: 5px;
color: var(--muted);
font-size: 11px;
}
.band-strip,
.map-row {
display: grid;
align-items: center;
gap: 8px;
margin: 8px 0;
}
.band-strip {
grid-template-columns: 1fr 1fr 92px;
}
.map-row {
grid-template-columns: 48px 1fr 92px;
}
.map-row > span,
.row span {
color: var(--muted);
font-size: 10px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
text-transform: uppercase;
}
.band-readout {
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 4px;
align-items: center;
color: var(--muted);
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 10px;
}
.map-sliders {
display: grid;
gap: 4px;
}
.row {
display: grid;
grid-template-columns: 54px 1fr 48px;
align-items: center;
gap: 8px;
margin: 6px 0;
}
details.advanced {
margin-top: 8px;
}
details.advanced summary {
color: var(--muted);
cursor: pointer;
font-size: 10px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
letter-spacing: .08em;
text-transform: uppercase;
}
input[type="range"] {
width: 100%;
accent-color: var(--ink);
}
.meter {
height: 6px;
margin-top: 8px;
overflow: hidden;
background: var(--cream-2);
border: 1px solid var(--rule);
}
.meter.out {
height: 3px;
margin-top: 3px;
}
.meter div {
width: 0;
height: 100%;
background: var(--led);
transition: width .08s linear;
}
.meter.out div {
background: var(--ink);
}
/* ── Named frequency ranges, per band ────────────────────────────────────
The sliders are log-scaled now, so a range is reachable by hand — but
nobody should have to drag for "bass" when the name is the thing they
mean. Same six ranges the device's own audio page offers. */
.hz-presets {
display: flex;
flex-wrap: wrap;
gap: 4px;
margin-top: 6px;
}
.hz-presets button {
min-height: 0;
padding: 3px 7px;
font-size: 10px;
letter-spacing: 0.04em;
border-color: var(--rule);
background: transparent;
color: var(--muted);
}
.hz-presets button:hover {
color: var(--ink);
border-color: var(--ink);
}
/* ── Diagnostics, folded ─────────────────────────────────────────────────
Connecting with no audio and pushing the knobs by hand is how you tell a
dead panel from a dead capture. Worth having, not worth the space. */
.diagnostics > summary {
cursor: pointer;
color: var(--muted);
font-size: 11px;
letter-spacing: 0.06em;
text-transform: uppercase;
padding: 4px 0;
}
.diagnostics > summary:hover {
color: var(--ink);
}
.diagnostics #manualConnect {
margin: 6px 0 10px;
width: 100%;
}
/* ── Band selector ───────────────────────────────────────────────────────
Four bands, one editor on screen. These say which one you are on, which
knob it drives, and whether it is muted — the three things worth knowing
before you switch. */
.band-tabs {
display: grid;
/* Four bands and All. */
grid-template-columns: repeat(4, 1fr) 1.2fr;
gap: 6px;
margin-top: 10px;
}
.band-tab {
display: flex;
flex-direction: column;
align-items: center;
gap: 1px;
padding: 6px 0 5px;
min-height: 0;
border-color: var(--rule);
background: transparent;
color: var(--muted);
}
.band-tab strong { font-size: 13px; font-weight: 600; }
.band-tab span { font-size: 9px; letter-spacing: 0.08em; }
.band-tab:hover { color: var(--ink); border-color: var(--ink); }
.band-tab.active {
background: var(--ink);
border-color: var(--ink);
color: var(--cream);
}
/* A muted band stays in place and stays reachable — it just is not driving
anything, and should not look like it is. */
.band-tab.muted { opacity: 0.45; }
.band-tab.muted strong { text-decoration: line-through; }
.spectrum-band { cursor: pointer; }
.spectrum-band.muted { opacity: 0.35; }
.mute-band {
min-height: 26px;
padding: 5px 8px;
border-color: var(--rule);
background: transparent;
color: var(--muted);
}
.mute-band.on {
border-color: var(--led);
color: var(--led);
}
.hint {
font-size: 10px;
letter-spacing: 0.04em;
color: var(--faint);
}
/* `hidden` loses to any explicit display, and .band sets one. Say it again. */
.band[hidden] { display: none; }
.band-tab.all strong { font-size: 11px; letter-spacing: 0.06em; }
/* ── The response graph ──────────────────────────────────────────────────
Six sliders became one picture. Left to right is how loud the band is,
bottom to top is where the knob lands, and the line between them is every
number at once — which is the thing the sliders could not show. */
.band-row {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 10px;
margin-bottom: 6px;
}
.band-key {
color: var(--muted);
font-size: 10px;
letter-spacing: 0.14em;
text-transform: uppercase;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
white-space: nowrap;
}
.band-note { color: var(--faint); font-size: 10px; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.plot-wrap { display: flex; gap: 10px; }
.plot-axis {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-end;
width: 26px;
height: 180px;
padding: 2px 0;
color: var(--faint);
font-size: 9px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.plot-col { flex: 1; min-width: 0; }
.plot {
position: relative;
height: 180px;
border: 1px solid var(--ink);
background: var(--field);
overflow: hidden;
cursor: grab;
/* The handles are dragged; the popup must not pan or select instead. */
touch-action: none;
user-select: none;
color: var(--ink);
}
.plot:active { cursor: grabbing; }
/* the stretch of knob the music is allowed to use */
.plot-out { position: absolute; left: 0; right: 0; background: #f0e6d6; }
/* the levels this band responds to at all */
.plot-in {
position: absolute; top: 0; bottom: 0;
border-left: 1px dashed var(--faint);
border-right: 1px dashed var(--faint);
}
.plot-curve { position: absolute; inset: 0; width: 100%; height: 100%; }
.plot-vline { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--led); opacity: .55; }
.plot-hline { position: absolute; left: 0; right: 0; height: 1px; background: var(--led); opacity: .55; }
.plot-dot {
position: absolute;
width: 9px; height: 9px;
margin: -5px 0 0 -5px;
border-radius: 50%;
background: var(--led);
box-shadow: 0 0 0 2px var(--field);
}
/* Handles: triangles pointing at the edge they move. Input on the floor,
output on the right wall — so which axis a handle belongs to is visible
before it is dragged. */
.h { position: absolute; width: 14px; height: 14px; background: var(--ink); }
.h-in-min, .h-in-max { bottom: 0; margin-left: -7px; clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.h-out-min, .h-out-max { right: 0; margin-top: -7px; clip-path: polygon(0 50%, 100% 0, 100% 100%); }
.h.on { background: var(--led); }
.plot-scale {
display: flex;
justify-content: space-between;
margin-top: 3px;
color: var(--faint);
font-size: 9px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
/* The same four numbers as words, for anyone who wants to read rather than
aim — and so a value can be checked without hovering a handle. */
.readout {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 7px 14px;
margin-top: 12px;
padding: 10px 11px;
background: var(--field);
border: 1px solid var(--rule);
}
.readout > div {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 8px;
}
.readout span { color: var(--muted); font-size: 11px; }
.readout output { font-size: 11px; }
/* Boost bends the line rather than moving its ends, so it is not something
to drag on the plot. Seven steps, and the hint says what the shape means. */
.boost-row { display: flex; align-items: center; gap: 12px; margin-top: 13px; }
.boost-steps { flex: 1; display: flex; gap: 3px; }
.boost-steps button {
flex: 1;
min-height: 0;
height: 22px;
padding: 0;
border-color: var(--rule);
background: var(--field);
}
.boost-steps button.soft { background: var(--cream-2); }
.boost-steps button.on { background: var(--ink); border-color: var(--ink); }
.boost-steps button:hover { border-color: var(--ink); }
.boost-row .gainOut { width: 34px; text-align: right; font-size: 11px; }
.boost-hint { margin-top: 6px; color: var(--muted); font-size: 11px; }
/* The meters said nothing about which was which. */
.meter-row { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.meter-row .meter { flex: 1; margin-top: 0; }
.meter-key {
width: 26px;
color: var(--faint);
font-size: 9px;
letter-spacing: 0.1em;
text-transform: uppercase;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
/* How much of its knob this band actually uses. The number that names a
band which is technically working and doing nothing. */
.travelOut { width: 42px; text-align: right; font-size: 10px; color: var(--muted); }
.travelOut.weak { color: var(--led); }
/* The one road to the mapping editor — mapping no longer lives in the popup. */
.editor-cta {
width: 100%;
font: inherit;
font-weight: 600;
cursor: pointer;
border: 1px solid var(--ink);
border-radius: 2px;
background: var(--ink);
color: var(--cream);
padding: 9px 12px;
}
.editor-cta:hover { background: var(--led); border-color: var(--led); }
ea39f3ad2This file is pinned to the selected release. Download the original to open it in your design tool.