Files
usmt-dash/web/overview.css
T
Johan Sandoval 76068893ee Overview calendar: mark today in amber so it can't pass for the selected day
Today gets an amber stripe across the top, an amber badge on the date and
an amber edge; the selected day keeps the blue outline and tint.
2026-10-07 21:02:41 +00:00

182 lines
13 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: amber stripe across the top and an amber badge on the date. Blue is kept for the
selected day (outline and tint), so the two never look alike, even when today is selected. */
.ov-day-head { display: flex; align-items: center; gap: 5px; min-width: 0; }
.ov-today::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 4px; background: #f59e0b; border-radius: 6px 6px 0 0; }
.ov-today .ov-day-num { margin-top: 2px; background: #f59e0b; color: #1f2937; font-weight: 800; border-radius: 999px; min-width: 1.7em; padding: 0 0.4em; box-sizing: border-box; text-align: center; line-height: 1.6; }
.ov-day.ov-today:not(.ov-selected):not(:hover) { border-color: rgba(245,158,11,0.6); }
.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; } }