Apply sleek black theme and table format for chord panels

This commit is contained in:
Michael Winter 2026-03-31 19:17:37 +02:00
parent 00cfac2e5c
commit e0bacce10a

View file

@ -135,8 +135,8 @@
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 20px;
background: #1a1a2e;
color: #eee;
background: #000000;
color: #cccccc;
}
.container {
@ -147,6 +147,9 @@
h1 {
text-align: center;
margin-bottom: 10px;
font-weight: 300;
letter-spacing: 2px;
color: #ffffff;
}
.controls {
@ -158,35 +161,39 @@
}
.controls button {
padding: 10px 20px;
font-size: 16px;
padding: 8px 16px;
font-size: 14px;
cursor: pointer;
background: #16213e;
color: #eee;
border: 1px solid #0f3460;
border-radius: 5px;
background: #0a0a0a;
color: #888888;
border: 1px solid #222222;
border-radius: 4px;
transition: all 0.2s ease;
}
.controls button:hover {
background: #0f3460;
background: #151515;
color: #ffffff;
border-color: #444444;
}
.controls button:disabled {
opacity: 0.5;
opacity: 0.3;
cursor: not-allowed;
}
.index-display {
font-size: 18px;
font-weight: bold;
font-size: 14px;
color: #666666;
letter-spacing: 1px;
}
#graph-container {
width: 100%;
height: 450px;
border: 1px solid #0f3460;
border-radius: 8px;
background: #16213e;
border: 1px solid #1a1a1a;
border-radius: 4px;
background: #050505;
position: relative;
}
@ -197,33 +204,44 @@
}
.chord-panel {
background: #16213e;
background: #0a0a0a;
padding: 15px;
border-radius: 8px;
min-width: 250px;
border-radius: 4px;
min-width: 200px;
border: 1px solid #1a1a1a;
}
.chord-panel h3 {
margin-top: 0;
color: #e94560;
color: #666666;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 500;
}
.chord-panel.current {
border: 2px solid #e94560;
border: 1px solid #333333;
}
.chord-panel.current h3 {
color: #00d4ff;
}
.chord-panel.prev, .chord-panel.next {
opacity: 0.7;
opacity: 0.6;
}
.pitch-list {
list-style: none;
padding: 0;
font-size: 12px;
}
.pitch-list li {
padding: 5px 0;
font-family: monospace;
padding: 4px 0;
color: #888888;
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;
}
.file-input {
@ -232,44 +250,20 @@
}
.file-input input {
padding: 10px;
background: #16213e;
color: #eee;
border: 1px solid #0f3460;
border-radius: 5px;
padding: 8px;
background: #0a0a0a;
color: #888888;
border: 1px solid #222222;
border-radius: 4px;
}
svg {
width: 100%;
height: 100%;
}
.node circle {
stroke: #fff;
stroke-width: 2px;
}
.node.current circle {
stroke: #e94560;
stroke-width: 3px;
}
.link {
stroke: #4a5568;
stroke-width: 2px;
}
.link-label {
fill: #a0aec0;
font-size: 12px;
font-family: monospace;
}
.node-label {
fill: #eee;
font-size: 11px;
font-family: monospace;
text-anchor: middle;
.file-select {
padding: 8px;
background: #0a0a0a;
color: #888888;
border: 1px solid #222222;
border-radius: 4px;
margin-left: 10px;
}
</style>
</head>
@ -326,7 +320,7 @@
const graphHeight = 450;
// Voice colors - sleek pastel scheme
const voiceColors = ['#5EAFD6', '#CE8E94', '#8FCEA4', '#E5C686'];
const voiceColors = ['#7eb5a6', '#c5a3ff', '#ffb3b3', '#ffd700'];
// Create Cytoscape instance
function initCytoscape() {
@ -337,40 +331,41 @@
selector: 'node',
style: {
'background-color': 'data(color)',
'width': 36,
'height': 36,
'width': 32,
'height': 32,
'label': 'data(cents)',
'text-valign': 'center',
'text-halign': 'center',
'color': '#eee',
'font-size': '9px',
'text-outline-width': 2,
'text-outline-color': 'data(color)',
'color': '#000000',
'font-size': '10px',
'font-family': 'monospace',
'font-weight': 'bold',
'text-outline-width': 0,
'border-width': 0,
}
},
{
selector: 'edge',
style: {
'width': 2,
'line-color': '#556',
'width': 1.5,
'line-color': '#555555',
'curve-style': 'straight',
'target-arrow-shape': 'none',
'label': 'data(ratio)',
'font-size': '10px',
'color': '#aaa',
'font-size': '12px',
'color': '#ffffff',
'text-rotation': 'autorotate',
'text-margin-y': -12,
'text-background-color': '#16213e',
'text-margin-y': -10,
'text-background-color': '#000000',
'text-background-opacity': 0.8,
'text-background-padding': '3px',
'text-background-padding': '2px',
}
},
{
selector: ':selected',
style: {
'border-width': 3,
'border-color': '#fff',
'border-width': 2,
'border-color': '#00d4ff',
}
}
],
@ -598,24 +593,70 @@
}
function updateChordPanel(elementId, data) {
const ul = document.getElementById(elementId);
ul.innerHTML = "";
const container = document.getElementById(elementId);
container.innerHTML = "";
if (!data || (Array.isArray(data) && data.length === 0)) {
ul.innerHTML = "<li>(none)</li>";
container.innerHTML = "<div>(none)</div>";
return;
}
// Handle both formats: raw chord array or nodes array from graph API
const items = Array.isArray(data) ? data : (data.nodes || []);
items.forEach(item => {
const li = document.createElement("li");
const fraction = item.fraction || item.fraction;
const hs_array = item.hs_array || [];
li.textContent = `${fraction} (${hs_array.join(", ")})`;
ul.appendChild(li);
if (items.length === 0) return;
// Determine number of columns from first node's hs_array
const cols = items[0].hs_array ? items[0].hs_array.length : 0;
if (cols === 0) return;
// Create table - let it size based on content
const table = document.createElement("table");
table.style.fontFamily = "monospace";
table.style.fontSize = "10px";
table.style.borderCollapse = "collapse";
table.style.tableLayout = "auto";
table.style.lineHeight = "1.2";
table.style.margin = "0 auto";
// Header row - split into separate cells to match row structure
const headerRow = document.createElement("tr");
const headerParts = ["2", "3", "5", "7"];
headerParts.forEach((part, idx) => {
const th = document.createElement("th");
th.textContent = part;
th.style.padding = "0px 4px";
th.style.textAlign = idx === 0 ? "left" : "right";
th.style.borderBottom = "1px solid #444";
th.style.paddingBottom = "1px";
th.style.fontWeight = "normal";
th.style.color = "#666";
th.style.whiteSpace = "nowrap";
headerRow.appendChild(th);
});
table.appendChild(headerRow);
// Data rows (all nodes)
items.forEach((item) => {
const row = document.createElement("tr");
const hs = item.hs_array || [];
hs.forEach((val, j) => {
const td = document.createElement("td");
td.textContent = val;
td.style.padding = "0px 4px";
td.style.textAlign = "right";
td.style.color = "#888";
td.style.whiteSpace = "nowrap";
if (j === 0) {
td.style.textAlign = "left";
}
row.appendChild(td);
});
table.appendChild(row);
});
container.appendChild(table);
}
// Update display - now handled by loadFromAPI