Each device now migrates on the day of its date tag instead of on a looping 24-hour clock: earlier days are finished, today's devices go through backup and restore during working hours, later days haven't started. The few that don't finish have a cause the dashboard shows (broken client, broken WMI, low disk, a USMT error, unreachable PC). A simulated team keeps two weeks of working days tagged. During working hours it adds devices, reschedules or drops one, tags stuck PCs with their problem, then fixes them and moves them to a new day; each morning finished days are closed out and a new day is scheduled. Actions print in the worker terminal as [Team] lines. Settings live in Demo.Team. The visitor sandbox now keeps per-tag edits laid over the live roster, so the team's changes keep showing around a visitor's own edits. Overview calendar: today is a filled badge on the date number, so it no longer looks like the selected day (outline plus tint).
179 lines
12 KiB
CSS
179 lines
12 KiB
CSS
/* ---------- Overview page ---------- */
|
|
/* Chart colors: an ordinal blue ramp for migration stage (not started -> in progress ->
|
|
completed) and a sequential blue ramp for counts, each stepped separately for dark mode
|
|
(validated with the dataviz palette checker against the card surfaces). */
|
|
/* Stage colors read as status: not started = red, in progress = amber, completed = green
|
|
(the dashboard's status palette; every colored mark also carries a number or a label) */
|
|
#overview {
|
|
--ov-todo: #d03b3b; --ov-doing: #f0a20c; --ov-done: #0ca30c; --ov-other: #8a8f98;
|
|
--ov-track: rgba(127,127,127,0.12);
|
|
--ov-good: #0ca30c; --ov-serious: #ec835a;
|
|
}
|
|
[data-theme="dark"] #overview { --ov-todo: #e05555; --ov-doing: #e8a317; --ov-done: #2fb344; --ov-other: #6b7280; --ov-track: rgba(255,255,255,0.07); }
|
|
/* Location bands: how much of a location is done, red -> green */
|
|
.ov-h0 { background: #d03b3b; color: #fff; }
|
|
.ov-h1 { background: #ec835a; color: #1f2328; }
|
|
.ov-h2 { background: #fab219; color: #1f2328; }
|
|
.ov-h3 { background: #8fd16a; color: #1f2328; }
|
|
.ov-h4 { background: #0ca30c; color: #fff; }
|
|
.ov-heat-key { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 10px; }
|
|
.ov-heat-key-item { display: inline-flex; align-items: center; gap: 6px; font-size: 0.8em; color: var(--text-muted); }
|
|
.ov-heat-key-item i { width: 14px; height: 10px; border-radius: 3px; }
|
|
|
|
/* What opened the list below: clearly marked */
|
|
.ov-tile.ov-selected { border: 2px solid #3498db !important; background: rgba(52,152,219,0.12); box-shadow: 0 0 0 3px rgba(52,152,219,0.25); transform: none; position: relative; }
|
|
.ov-showing { display: inline-block; margin-top: 6px; font-size: 0.72em; font-weight: 700; color: #fff; background: #3498db; border-radius: 999px; padding: 2px 8px; }
|
|
.ov-bar-row.ov-selected { background: rgba(52,152,219,0.16); box-shadow: inset 3px 0 0 #3498db; }
|
|
.ov-legend-item.ov-selected { color: var(--text-main); box-shadow: inset 0 -2px 0 #3498db; }
|
|
.ov-legend-item.ov-selected .ov-key { box-shadow: none; }
|
|
.ov-heat-cell.ov-selected, .ov-heat-sum.ov-selected { box-shadow: 0 0 0 2px var(--bg-card), 0 0 0 5px #3498db !important; }
|
|
.ov-heat-sum.ov-selected { background: rgba(52,152,219,0.16); }
|
|
|
|
/* The list: same look as the dashboard's tables, header sticks under the nav */
|
|
.ov-drill[hidden] { display: none; }
|
|
.ov-drill { padding: 0 !important; overflow: visible !important; border-radius: 10px; }
|
|
.ov-drill-head { border-left-color: #3498db !important; border-radius: 10px 10px 0 0; }
|
|
.ov-drill-title { font-weight: 700; }
|
|
.ov-drill .ov-head-btns { display: flex; gap: 8px; margin-left: auto; }
|
|
.ov-drill-empty, .ov-drill-note { padding: 12px 16px; margin: 0; }
|
|
|
|
#overview-root { max-width: 1500px; margin: 0 auto; display: flex; flex-direction: column; gap: 18px; }
|
|
.ov-title { margin: 0; color: var(--text-main); }
|
|
.ov-subtitle { margin: 4px 0 0; color: var(--text-muted); }
|
|
.ov-card { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 10px; padding: 18px 20px; min-width: 0; box-sizing: border-box; }
|
|
.ov-card-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
|
|
.ov-card-head h2 { margin: 0; font-size: 1.05em; color: var(--text-main); }
|
|
.ov-card-sub { color: var(--text-muted); font-size: 0.85em; }
|
|
.ov-head-btns { margin-left: auto; display: flex; gap: 8px; }
|
|
.ov-btn { border: 1px solid var(--border-color); background: transparent; color: var(--text-main); border-radius: 6px; padding: 5px 12px; cursor: pointer; font: inherit; font-size: 0.85em; }
|
|
.ov-btn:hover { border-color: #3498db; color: #3498db; }
|
|
.ov-note, .ov-empty-text { color: var(--text-muted); font-size: 0.85em; margin: 10px 0 0; }
|
|
|
|
/* progress */
|
|
.ov-progress { display: grid; grid-template-columns: auto 1fr; gap: 6px 28px; align-items: center; }
|
|
.ov-hero { grid-row: span 2; }
|
|
.ov-hero-num { font-size: 52px; font-weight: 700; line-height: 1; color: var(--text-main); font-variant-numeric: tabular-nums; }
|
|
.ov-hero-label { color: var(--text-muted); margin-top: 6px; font-size: 0.9em; }
|
|
.ov-stack { display: flex; gap: 2px; overflow: hidden; }
|
|
.ov-stack .ov-seg { min-width: 4px; cursor: pointer; }
|
|
.ov-stack .ov-seg:first-child { border-radius: 4px 0 0 4px; }
|
|
.ov-stack .ov-seg:last-child { border-radius: 0 4px 4px 0; }
|
|
.ov-stack .ov-seg:only-child { border-radius: 4px; }
|
|
.ov-stack .ov-seg:hover { filter: brightness(1.12); }
|
|
.ov-meter { height: 18px; }
|
|
.ov-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center; }
|
|
.ov-legend-item { display: inline-flex; align-items: center; gap: 6px; background: none; border: 0; padding: 2px 0; color: var(--text-muted); font: inherit; font-size: 0.88em; cursor: pointer; }
|
|
span.ov-legend-item { cursor: default; }
|
|
.ov-legend-item b { color: var(--text-main); }
|
|
.ov-legend-note { color: var(--text-muted); font-size: 0.82em; }
|
|
.ov-legend-small { margin-left: auto; }
|
|
.ov-key { display: inline-block; width: 12px; height: 12px; border-radius: 3px; flex: 0 0 12px; }
|
|
|
|
/* issue tiles */
|
|
.ov-issues { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
|
|
.ov-tile { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 10px; padding: 12px 14px; cursor: pointer; transition: border-color 0.15s, transform 0.15s; outline: none; }
|
|
.ov-tile:hover, .ov-tile:focus-visible { border-color: #3498db; transform: translateY(-1px); }
|
|
.ov-tile.ov-selected { border-color: #3498db; box-shadow: 0 0 0 2px rgba(52,152,219,0.35); }
|
|
.ov-tile-top { display: flex; align-items: center; gap: 7px; }
|
|
.ov-status-icon { display: inline-flex; width: 16px; height: 16px; flex: 0 0 16px; }
|
|
.ov-status-icon svg { width: 16px; height: 16px; }
|
|
.ov-has .ov-status-icon { color: var(--ov-serious); }
|
|
.ov-zero .ov-status-icon { color: var(--ov-good); }
|
|
.ov-tile-label { font-size: 0.85em; font-weight: 600; color: var(--text-main); line-height: 1.2; }
|
|
.ov-tile-num { font-size: 34px; font-weight: 700; color: var(--text-main); line-height: 1.1; margin-top: 8px; font-variant-numeric: tabular-nums; }
|
|
.ov-zero .ov-tile-num { color: var(--text-muted); }
|
|
.ov-tile-sub { font-size: 0.8em; color: var(--text-muted); margin-top: 2px; }
|
|
|
|
.ov-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: 18px; }
|
|
|
|
/* status bars */
|
|
.ov-bars { display: flex; flex-direction: column; gap: 4px; }
|
|
.ov-bar-row { display: grid; grid-template-columns: 150px 1fr 44px; align-items: center; gap: 10px; padding: 5px 6px; border-radius: 6px; cursor: pointer; outline: none; }
|
|
.ov-bar-row:hover, .ov-bar-row:focus-visible { background: var(--ov-track); }
|
|
.ov-bar-label { font-size: 0.88em; color: var(--text-main); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.ov-bar-track { height: 14px; }
|
|
.ov-bar { display: block; height: 14px; border-radius: 0 4px 4px 0; }
|
|
.ov-bar-value { text-align: right; font-weight: 700; color: var(--text-main); font-variant-numeric: tabular-nums; }
|
|
|
|
/* heatmap */
|
|
.ov-toggle { margin-left: auto; display: inline-flex; border: 1px solid var(--border-color); border-radius: 6px; overflow: hidden; }
|
|
.ov-toggle button { border: 0; background: transparent; color: var(--text-muted); padding: 5px 10px; font: inherit; font-size: 0.82em; cursor: pointer; }
|
|
.ov-toggle button.on { background: #3498db; color: #fff; }
|
|
.ov-heat-wrap { overflow-x: auto; }
|
|
table.ov-heat { border-collapse: separate; border-spacing: 2px; width: 100%; }
|
|
#overview table.ov-heat th { font-size: 0.8em; color: var(--text-muted); font-weight: 600; padding: 4px 6px; text-align: center; white-space: nowrap; background: none !important; position: static !important; border: 0; text-transform: none; }
|
|
#overview table.ov-heat tbody th { text-align: left; color: var(--text-main); font-size: 0.88em; }
|
|
table.ov-heat td { padding: 0; text-align: center; border: 0; background: none; }
|
|
.ov-heat-cell { display: flex; align-items: center; justify-content: center; min-width: 44px; height: 36px; border-radius: 4px; font-weight: 700; font-variant-numeric: tabular-nums; cursor: pointer; outline: none; }
|
|
.ov-heat-cell:hover, .ov-heat-cell:focus-visible { box-shadow: 0 0 0 2px var(--bg-card), 0 0 0 4px #3498db; }
|
|
.ov-heat-none { color: var(--text-muted); opacity: 0.5; }
|
|
.ov-heat-sum { font-weight: 700; color: var(--text-main); cursor: pointer; padding: 6px; border-radius: 4px; }
|
|
.ov-heat-sum:hover { background: var(--ov-track); }
|
|
|
|
/* calendar */
|
|
.ov-months { display: grid; grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); gap: 22px; }
|
|
.ov-month-name { font-weight: 700; color: var(--text-main); margin-bottom: 8px; }
|
|
.ov-cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px; }
|
|
.ov-dow { font-size: 0.72em; color: var(--text-muted); text-align: center; padding-bottom: 2px; }
|
|
.ov-day { position: relative; min-height: 50px; border-radius: 6px; background: var(--ov-track); padding: 4px 5px; box-sizing: border-box; display: flex; flex-direction: column; outline: none; }
|
|
.ov-day.ov-pad { background: none; }
|
|
.ov-day.ov-weekend:not(.ov-has-day) { opacity: 0.45; }
|
|
.ov-day-num { font-size: 0.72em; color: var(--text-muted); }
|
|
.ov-day-count { font-size: 1.05em; font-weight: 700; color: var(--text-main); margin-top: auto; font-variant-numeric: tabular-nums; }
|
|
.ov-day-bar { height: 6px; margin-top: 3px; }
|
|
.ov-has-day { cursor: pointer; background: var(--bg-card); border: 1px solid var(--border-color); }
|
|
.ov-has-day:hover, .ov-has-day:focus-visible, .ov-day.ov-selected { border-color: #3498db; box-shadow: 0 0 0 1px #3498db; }
|
|
/* Today: the date number in a filled badge (like a calendar app), so it can't be mistaken for
|
|
the selected day, which gets the outline and a tint */
|
|
.ov-today .ov-day-num { align-self: flex-start; background: #3498db; color: #fff; font-weight: 700; border-radius: 999px; min-width: 1.6em; padding: 0 0.4em; box-sizing: border-box; text-align: center; line-height: 1.55; }
|
|
.ov-day.ov-selected { background: rgba(52,152,219,0.16); }
|
|
|
|
|
|
/* tooltip */
|
|
.ov-tip { position: fixed; z-index: 4000; display: none; pointer-events: none; background: var(--bg-card); color: var(--text-main); border: 1px solid var(--border-color); border-radius: 8px; padding: 8px 10px; box-shadow: 0 6px 20px rgba(0,0,0,0.25); font-size: 0.85em; max-width: 260px; }
|
|
.ov-tip-value { font-weight: 700; font-size: 1.15em; }
|
|
.ov-tip-label { color: var(--text-muted); margin-bottom: 4px; }
|
|
.ov-tip-row { display: flex; align-items: center; gap: 6px; }
|
|
.ov-tip-row .ov-key { width: 10px; height: 3px; border-radius: 2px; flex-basis: 10px; }
|
|
|
|
@media (max-width: 1100px) {
|
|
.ov-grid { grid-template-columns: minmax(0, 1fr); }
|
|
}
|
|
@media (max-width: 900px) {
|
|
.ov-issues { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
}
|
|
@media (max-width: 700px) {
|
|
.ov-progress { grid-template-columns: 1fr; }
|
|
.ov-hero { grid-row: auto; }
|
|
.ov-hero-num { font-size: 44px; }
|
|
.ov-issues { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
|
|
.ov-tile { padding: 10px; }
|
|
.ov-tile-num { font-size: 28px; }
|
|
.ov-card { padding: 14px; }
|
|
.ov-bar-row { grid-template-columns: 112px 1fr 36px; gap: 6px; }
|
|
.ov-months { grid-template-columns: minmax(0, 1fr); }
|
|
.ov-day { min-height: 44px; padding: 3px; }
|
|
.ov-legend-small { margin-left: 0; }
|
|
.ov-head-btns { margin-left: 0; }
|
|
}
|
|
@media (max-width: 700px) {
|
|
#overview table.ov-heat th { padding: 4px 3px; font-size: 0.72em; }
|
|
#overview table.ov-heat tbody th { font-size: 0.78em; padding-right: 6px; }
|
|
.ov-heat-cell { min-width: 34px; height: 34px; }
|
|
.ov-bar-row { grid-template-columns: 128px 1fr 32px; }
|
|
.ov-bar-label { font-size: 0.82em; }
|
|
}
|
|
|
|
/* Undocumented apps list: room goes to the device names */
|
|
#ov-table td.ov-src-list { white-space: normal; overflow-wrap: anywhere; }
|
|
|
|
/* Loading placeholder (first fraction of a second, before the data arrives) */
|
|
.ov-skel { min-height: 150px; margin-bottom: 18px;
|
|
background: linear-gradient(90deg, var(--bg-card) 25%, rgba(127,127,127,0.10) 50%, var(--bg-card) 75%);
|
|
background-size: 200% 100%; animation: ov-skel 1.2s linear infinite; }
|
|
.ov-skel-hero { min-height: 120px; }
|
|
.ov-skel-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
|
|
@media (max-width: 700px) { .ov-skel-row { grid-template-columns: 1fr; } }
|
|
@keyframes ov-skel { from { background-position: 100% 0; } to { background-position: -100% 0; } }
|
|
@media (prefers-reduced-motion: reduce) { .ov-skel { animation: none; } }
|