feat: add Mine Map v1

This commit is contained in:
lussierj committed 2026-08-10 19:55:20 +00:00
1 parent 548051899e
commit 60a831950c
16 files changed
+2027 -163

No files matched your search

+368
View File
@@ -753,3 +753,371 @@ tbody tr:last-child td {
padding: 14px;
}
}
/* Mine Map v1 */
.map-context {
padding: 15px;
border: 1px solid var(--line);
background: var(--surface);
}
.map-context-head,
.map-status-band,
.inspector-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.map-context h2,
.map-inspector-v1 h2,
.unplaced-section h2 {
margin: 0;
font-size: 17px;
}
.map-control-grid {
display: grid;
grid-template-columns: minmax(150px, .8fr) minmax(150px, .8fr)
minmax(170px, .9fr) minmax(220px, 1.4fr);
gap: 10px;
margin-top: 14px;
}
.map-filters {
margin-top: 12px;
border-top: 1px solid #e3e8ed;
padding-top: 10px;
}
.map-filters summary {
min-height: 36px;
cursor: pointer;
color: #334252;
font-size: 13px;
font-weight: 750;
}
.map-filter-grid {
display: grid;
grid-template-columns: repeat(4, minmax(135px, 1fr)) auto;
align-items: end;
gap: 10px;
}
.map-filter-grid .quiet-button,
.icon-button {
color: var(--ink);
border-color: #8e9ba8;
background: #fff;
}
.map-status-band {
align-items: flex-start;
margin: 12px 0;
}
.map-summary,
.map-legend {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
}
.summary-fact {
display: inline-flex;
align-items: baseline;
gap: 5px;
padding-right: 9px;
border-right: 1px solid var(--line);
color: var(--muted);
font-size: 12px;
}
.summary-fact strong {
color: var(--ink);
font-size: 15px;
}
.mine-map-workspace {
display: grid;
grid-template-columns: minmax(0, 1fr) 320px;
border: 1px solid var(--line);
background: var(--surface);
}
.mine-map-workspace[hidden],
.map-inspector-v1[hidden],
.unplaced-section[hidden],
.map-notice[hidden] {
display: none;
}
.map-main-column {
min-width: 0;
}
.map-legend {
min-height: 50px;
padding: 10px 14px;
border-bottom: 1px solid var(--line);
background: #f7f8fa;
font-size: 12px;
}
.legend-item {
display: inline-flex;
align-items: center;
gap: 5px;
}
.legend-marker,
.status-marker {
display: inline-grid;
place-items: center;
width: 24px;
height: 24px;
border: 1px solid #758493;
border-radius: 4px;
color: #263442;
background: #eef1f4;
font-size: 10px;
font-weight: 850;
}
.map-notice {
margin: 14px;
padding: 13px;
border-left: 4px solid var(--warn);
background: #fff8e8;
color: #694100;
font-size: 13px;
}
.map-viewport-v1 {
display: grid;
gap: 14px;
min-height: 380px;
max-height: calc(100vh - 330px);
overflow: auto;
padding: 14px;
background: #e9edf0;
}
.map-rack {
min-width: 0;
border: 1px solid #aeb8c2;
background: #fff;
}
.rack-title {
margin: 0;
padding: 9px 12px;
color: #fff;
background: #263442;
font-size: 14px;
}
.map-shelf {
display: grid;
grid-template-columns: 112px minmax(0, 1fr);
border-top: 1px solid var(--line);
}
.map-shelf:first-of-type {
border-top: 0;
}
.shelf-title {
margin: 0;
padding: 12px;
color: #40505f;
background: #f3f5f7;
font-size: 12px;
}
.position-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(142px, 1fr));
gap: 7px;
padding: 8px;
}
.map-position {
display: grid;
grid-template-rows: auto auto auto auto;
gap: 5px;
min-width: 0;
min-height: 118px;
padding: 9px;
border: 1px solid #8e9ba8;
border-left: 5px solid #758493;
border-radius: 4px;
color: var(--ink);
background: #fff;
text-align: left;
}
button.map-position {
cursor: pointer;
}
button.map-position:hover {
border-color: #40505f;
background: #f8fafb;
}
.map-position[data-selected="true"] {
box-shadow: 0 0 0 3px var(--focus);
}
.map-position[data-filtered="true"] {
opacity: .34;
filter: grayscale(1);
}
.map-position[data-status="online"] { border-left-color: #177245; }
.map-position[data-status="offline"] { border-left-color: #b42318; background: #fff5f4; }
.map-position[data-status="unstable"] { border-left-color: #9a5b00; background: #fff9ed; }
.map-position[data-status="repair"] { border-left-color: #6b4ca5; background: #f7f3fc; }
.map-position[data-status="spare"] { border-left-color: #1677b8; background: #f1f8fc; }
.map-position[data-status="retired"] { border-left-color: #4d5660; background: #eef0f2; }
.map-position[data-status="empty"] { border-style: dashed; border-left-color: #8e9ba8; background: #f8fafb; }
.map-position[data-status="expected"] { border-left-color: #996600; background: #fff9e8; }
.map-position[data-status="conflict"] { border-left-color: #b42318; background: #fff0ee; }
.map-position[data-status="blocked"] { border-left-color: #4d5660; background: #e5e8eb; }
.map-position[data-status="switch"] { border-left-color: #28706d; background: #eff8f7; }
.map-position[data-status="restricted"] { border-left-color: #596675; background: #f3f5f7; }
.position-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 6px;
}
.position-label,
.position-miner,
.position-value,
.position-freshness {
overflow-wrap: anywhere;
}
.position-label { font-size: 12px; }
.position-miner { font-size: 13px; font-weight: 750; }
.position-value { color: #334252; font-size: 12px; }
.position-freshness { color: var(--muted); font-size: 10px; }
.map-inspector-v1 {
position: sticky;
top: 12px;
align-self: start;
min-width: 0;
max-height: calc(100vh - 90px);
overflow-y: auto;
padding: 16px;
border-left: 1px solid var(--line);
background: #fff;
}
.icon-button {
width: 42px;
height: 42px;
border-radius: 4px;
cursor: pointer;
font-weight: 800;
}
.status-callout {
padding: 10px;
border-left: 4px solid #758493;
background: #f3f5f7;
font-size: 13px;
font-weight: 750;
}
.status-callout[data-status="online"] { border-color: var(--good); }
.status-callout[data-status="offline"] { border-color: var(--danger); }
.status-callout[data-status="repair"] { border-color: #6b4ca5; }
.inspector-details {
grid-template-columns: minmax(92px, auto) minmax(0, 1fr);
margin-bottom: 18px;
}
.inspector-details dd {
overflow-wrap: anywhere;
}
.command-link {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 42px;
padding: 8px 15px;
border: 1px solid #1b5f89;
border-radius: 5px;
color: #fff;
background: #176b9a;
text-decoration: none;
font-weight: 750;
}
.unplaced-section {
padding: 14px;
border-top: 1px solid var(--line);
}
#mapUnplaced,
.legacy-position-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
gap: 8px;
}
.legacy-position-entry {
display: grid;
gap: 7px;
padding: 10px;
border: 1px solid var(--line);
background: #fff;
}
.legacy-position-path {
color: var(--muted);
font-size: 11px;
}
.unplaced-miner {
display: grid;
gap: 4px;
padding: 10px;
border-left: 4px solid #758493;
background: #f3f5f7;
font-size: 12px;
}
@media (max-width: 1180px) {
.map-control-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.map-filter-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.mine-map-workspace { grid-template-columns: 1fr; }
.map-inspector-v1 { position: static; max-height: none; border-top: 1px solid var(--line); border-left: 0; }
}
@media (max-width: 680px) {
.map-context-head,
.map-status-band { align-items: flex-start; flex-direction: column; }
.map-control-grid,
.map-filter-grid { grid-template-columns: 1fr; }
.map-viewport-v1 { max-height: none; padding: 9px; }
.map-shelf { grid-template-columns: 1fr; }
.shelf-title { position: sticky; left: 0; z-index: 1; }
.position-grid { grid-template-columns: repeat(2, minmax(130px, 1fr)); overflow-x: auto; }
.map-inspector-v1 { position: fixed; inset: 0; z-index: 80; max-height: none; overflow-y: auto; }
}
@media (max-width: 420px) {
.position-grid { grid-template-columns: minmax(150px, 1fr); }
}