diff --git a/public/assets/app.css b/public/assets/app.css
index 0e70e8c..f31aca2 100644
--- a/public/assets/app.css
+++ b/public/assets/app.css
@@ -119,9 +119,8 @@ button, input, select {
.workspace {
display: grid;
- grid-template-columns: minmax(320px, 420px) minmax(420px, 1fr) minmax(320px, 390px);
+ grid-template-columns: 1fr;
gap: 24px;
- align-items: start;
}
.panel {
@@ -140,12 +139,33 @@ button, input, select {
color: var(--muted);
}
-.panel--controls,
-.panel--sidebar {
+.panel--dashboard {
display: grid;
gap: 18px;
}
+.dashboard-grid {
+ display: grid;
+ grid-template-columns: minmax(320px, 1.15fr) minmax(320px, 1fr);
+ gap: 18px;
+}
+
+.dashboard-block {
+ display: grid;
+ gap: 16px;
+}
+
+.dashboard-controls {
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: 14px;
+ align-items: end;
+}
+
+.dashboard-block--library {
+ padding-top: 8px;
+}
+
.field {
display: grid;
gap: 8px;
@@ -184,6 +204,11 @@ button, input, select {
padding-right: 4px;
}
+.library--wide {
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ max-height: 420px;
+}
+
.component-card,
.rack-item,
.subpanel,
@@ -263,20 +288,14 @@ button, input, select {
.rack-stage {
display: grid;
- gap: 18px;
+ gap: 0;
}
-.rack-summary,
.stat-grid {
display: grid;
gap: 12px;
}
-.rack-summary {
- grid-template-columns: repeat(3, minmax(0, 1fr));
-}
-
-.summary-card,
.stat-card {
padding: 16px;
border-radius: var(--radius-md);
@@ -284,7 +303,6 @@ button, input, select {
border: 1px solid rgba(75, 57, 37, 0.12);
}
-.summary-card strong,
.stat-card strong {
display: block;
margin-top: 6px;
@@ -297,7 +315,7 @@ button, input, select {
border: 1px solid rgba(105, 108, 115, 0.14);
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(239, 232, 214, 0.88));
- padding: 16px;
+ padding: 6px;
overflow: hidden;
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.7),
@@ -306,9 +324,9 @@ button, input, select {
.rack-shell {
position: relative;
- width: min(100%, 1180px);
+ width: min(100%, 1380px);
margin: 0 auto;
- aspect-ratio: 3 / 2;
+ aspect-ratio: 3.1 / 2;
border-radius: 28px;
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(0, 0, 0, 0.16)),
@@ -330,34 +348,34 @@ button, input, select {
.rack-shell__frame--top,
.rack-shell__frame--bottom {
- left: 9%;
- right: 9%;
- height: 8%;
- border-radius: 14px;
+ left: 5.1%;
+ right: 5.1%;
+ height: 4.8%;
+ border-radius: 12px;
}
.rack-shell__frame--top {
- top: 6%;
+ top: 3.6%;
}
.rack-shell__frame--bottom {
- bottom: 6%;
+ bottom: 3.6%;
}
.rack-shell__frame--left,
.rack-shell__frame--right {
- top: 8%;
- bottom: 8%;
- width: 6.8%;
- border-radius: 24px;
+ top: 4.7%;
+ bottom: 4.7%;
+ width: 3.2%;
+ border-radius: 18px;
}
.rack-shell__frame--left {
- left: 0.5%;
+ left: 0.6%;
}
.rack-shell__frame--right {
- right: 0.5%;
+ right: 0.6%;
}
.rack-shell__screw {
@@ -395,17 +413,17 @@ button, input, select {
height: 58%;
}
-.rack-shell__screw--tl { top: 7.4%; left: 10.6%; }
-.rack-shell__screw--tr { top: 7.4%; right: 10.6%; }
-.rack-shell__screw--bl { bottom: 7.4%; left: 10.6%; }
-.rack-shell__screw--br { bottom: 7.4%; right: 10.6%; }
+.rack-shell__screw--tl { top: 4.2%; left: 5.8%; }
+.rack-shell__screw--tr { top: 4.2%; right: 5.8%; }
+.rack-shell__screw--bl { bottom: 4.2%; left: 5.8%; }
+.rack-shell__screw--br { bottom: 4.2%; right: 5.8%; }
.rack-core {
position: absolute;
- inset: 15% 12.8% 14% 12.8%;
+ inset: 8.7% 6.2% 8.3% 6.2%;
display: grid;
- grid-template-columns: 10% 1fr 10%;
- gap: 0;
+ grid-template-columns: 5.5% 1fr 5.5%;
+ gap: 0.8%;
z-index: 2;
}
@@ -442,11 +460,11 @@ button, input, select {
}
.rack-rail__label--left {
- left: -2.1rem;
+ left: -1.65rem;
}
.rack-rail__label--right {
- right: -1.6rem;
+ right: -1.35rem;
}
.rack-rail__tick {
@@ -494,6 +512,7 @@ button, input, select {
.rack-bay {
position: relative;
overflow: hidden;
+ border-radius: 4px;
background:
radial-gradient(circle at center, rgba(96, 99, 108, 0.22), transparent 48%),
linear-gradient(180deg, #181a1f, #2a2d34 36%, #22252c 68%, #17191d 100%);
@@ -562,24 +581,24 @@ button, input, select {
.rack-grid__header-badge {
position: absolute;
- top: 1.7%;
+ top: 0.9%;
z-index: 6;
- padding: 14px 18px;
+ padding: 10px 14px;
border-radius: 16px;
background: rgba(17, 19, 24, 0.84);
color: #f6f7f9;
- font-size: 1.05rem;
+ font-size: 0.98rem;
box-shadow:
inset 0 0 0 1px rgba(255, 255, 255, 0.12),
0 10px 20px rgba(20, 22, 28, 0.18);
}
.rack-grid__header-badge--left {
- left: 1.8%;
+ left: 0.9%;
}
.rack-grid__header-badge--right {
- right: 1.8%;
+ right: 0.9%;
}
.rack-items-layer {
@@ -693,12 +712,14 @@ button, input, select {
padding: 0;
user-select: none;
overflow: hidden;
- border-radius: 8px;
- border: 1px solid rgba(32, 36, 42, 0.8);
- background: linear-gradient(180deg, rgba(235, 239, 244, 0.98), rgba(191, 200, 211, 0.98));
+ border-radius: 14px;
+ border: 1px solid rgba(30, 34, 40, 0.84);
+ background:
+ linear-gradient(180deg, rgba(248, 250, 252, 0.98), rgba(209, 215, 224, 0.98) 58%, rgba(187, 194, 204, 0.98));
box-shadow:
- inset 0 1px 0 rgba(255, 255, 255, 0.94),
- 0 8px 14px rgba(5, 6, 7, 0.24);
+ inset 0 1px 0 rgba(255, 255, 255, 0.96),
+ inset 0 -2px 0 rgba(0, 0, 0, 0.14),
+ 0 12px 18px rgba(5, 6, 7, 0.28);
touch-action: none;
cursor: grab;
}
@@ -721,15 +742,16 @@ button, input, select {
display: flex;
flex-direction: column;
justify-content: space-between;
- padding: 6px 10px 6px 10px;
+ padding: 8px 12px 8px 12px;
background:
- linear-gradient(180deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0) 42%),
- linear-gradient(90deg, rgba(255, 255, 255, 0.38), rgba(255, 255, 255, 0.06) 34%, rgba(255, 255, 255, 0.18));
+ linear-gradient(180deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0) 28%),
+ linear-gradient(90deg, rgba(255, 255, 255, 0.26), rgba(255, 255, 255, 0.06) 32%, rgba(255, 255, 255, 0.16));
}
.rack-item__face {
position: absolute;
inset: 0;
+ filter: drop-shadow(0 10px 10px rgba(0, 0, 0, 0.18));
}
.rack-item__meta,
@@ -745,7 +767,7 @@ button, input, select {
}
.rack-item__drag-hint {
- align-self: start;
+ align-self: end;
padding: 5px 8px;
border-radius: 999px;
background: rgba(19, 23, 28, 0.78);
@@ -791,7 +813,7 @@ button, input, select {
}
.stat-grid {
- grid-template-columns: repeat(2, minmax(0, 1fr));
+ grid-template-columns: repeat(3, minmax(0, 1fr));
}
.field-row {
@@ -1114,7 +1136,8 @@ button, input, select {
}
@media (max-width: 1280px) {
- .workspace {
+ .dashboard-grid,
+ .dashboard-controls {
grid-template-columns: 1fr;
}
@@ -1128,15 +1151,14 @@ button, input, select {
padding: 18px;
}
- .rack-summary,
.stat-grid,
- .field-row {
+ .field-row,
+ .dashboard-controls {
grid-template-columns: 1fr;
}
.rack-grid {
- padding-left: 62px;
- padding-right: 26px;
+ padding: 8px;
}
.rack-shell,
diff --git a/public/assets/app.js b/public/assets/app.js
index 29672f3..ea7e97c 100644
--- a/public/assets/app.js
+++ b/public/assets/app.js
@@ -30,7 +30,6 @@ function cacheDom() {
ui.componentFilter = document.getElementById("component-filter");
ui.pluginInput = document.getElementById("plugin-input");
ui.componentLibrary = document.getElementById("component-library");
- ui.rackSummary = document.getElementById("rack-summary");
ui.rackGrid = document.getElementById("rack-grid");
ui.projectStats = document.getElementById("project-stats");
ui.bomOutput = document.getElementById("bom-output");
@@ -51,7 +50,7 @@ function bindEvents() {
ui.projectName.addEventListener("input", () => {
state.projectName = ui.projectName.value.trim() || "Neues Rack-Projekt";
- renderSummary();
+ renderStats();
});
ui.rackColor.addEventListener("input", () => {
state.rackColor = ui.rackColor.value;
@@ -89,7 +88,6 @@ async function loadBootstrap() {
}
function renderAll() {
- renderSummary();
renderLibrary();
renderSelectionInfo();
renderRack();
@@ -112,26 +110,7 @@ function renderTemplateOptions() {
}
function renderSummary() {
- const rack = getCurrentRackTemplate();
- if (!rack) {
- ui.rackSummary.innerHTML = "";
- return;
- }
-
- ui.rackSummary.innerHTML = `
-
- Projekt
- ${escapeHtml(state.projectName)}
-
-
- Rack-Standard
- ${rack.rackStandard === "19_inch" ? "19 inch" : "10 inch"}
-
-
- Kapazitaet
- ${rack.totalU}U / ${rack.usableDepthMm} mm
-
- `;
+ renderStats();
}
function renderLibrary() {
@@ -384,6 +363,18 @@ function renderStats() {
}, 0);
ui.projectStats.innerHTML = `
+
+ Projekt
+ ${escapeHtml(state.projectName)}
+
+
+ Rack
+ ${rack.rackStandard === "19_inch" ? '19"' : '10"'} ยท ${rack.totalU}U
+
+
+ Tiefe
+ ${rack.usableDepthMm} mm
+
Belegte U
${usedU} / ${rack.totalU}
diff --git a/public/index.php b/public/index.php
index ded5764..3061e80 100644
--- a/public/index.php
+++ b/public/index.php
@@ -42,45 +42,100 @@ $apiBase = $publicBase === '' ? '' : $publicBase;
-
-
-
Projekt
-
Rack-Vorlage, Bibliothek und Plugin-Import.
+
+
+
+
+
Projekt
+
Rack-Vorlage, Bibliothek und Plugin-Import.
+
+
+
+
+
+
+
+
Auswertung
+
Stueckliste, Platzreserve und Kabelschaetzung.
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
Einsteckmodus
-
Kein Element ausgewaehlt
+
+
+
Bibliothek
+
Module per Drag-and-Drop direkt aus der Liste ins Rack ziehen.
-
-
-
-
-
-
-
-
+
+
@@ -90,55 +145,9 @@ $apiBase = $publicBase === '' ? '' : $publicBase;
-
-