Give Storage its own row and rebuild the disk list as a table
All checks were successful
Deploy / deploy (push) Successful in 23s

Ten disks stacked at --row-h each turned one third of the "Right now"
strip into a ~950px tower. The row is a grid, so Now playing and
Downloads stretched to match and held roughly 1500px of empty card
between them.

The information needed width, not a shorter list. "Right now" drops to
two columns and Storage moves to a full-width row beneath it, where the
same ten disks are a six-column table — disk, used, size, free, usage
bar, temp — at ~270px total. Nothing is hidden and nothing scrolls
except the table itself, which gets its own overflow container below
720px rather than wrapping the sizes into mush.

Also: the array total moves to a bar above the table and the summary
into the card header, so the hero figure isn't repeating what every row
already says. The header summary is a sentence rather than a badge, so
it needs .card-meta-wrap to opt out of the global nowrap — without it
that one string pushed the whole page sideways on a phone.

Local-fallback (no per-disk data) and error states keep the previous
hero-figure treatment. CLAUDE.md now carries the dead-space rule this
came from.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Barely Removable 2026-08-27 06:52:34 -07:00
parent 326ab6cee5
commit 08c71ba68d
3 changed files with 176 additions and 74 deletions

View file

@ -539,32 +539,68 @@ dd.is-accent { color: var(--accent); }
}
.req-sub { font-size: var(--fs-xs); color: var(--text-3); }
/* ── Storage — per-disk breakdown ──────────────────────── */
/* Same row anatomy as indexer/request rows: name/sub on the left, a status
badge on the right. Data + cache disks get a usage meter; parity disks
(no filesystem) are rendered compact — name and temp only. */
.disk-list { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.85rem; }
.disk-item {
display: flex;
align-items: center;
gap: 0.7rem;
min-height: var(--row-h);
padding: 0.6rem 0.7rem;
background: var(--surface-2);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
min-width: 0;
/* ── Storage — per-disk table ──────────────────────────── */
/* Storage owns a full-width row of its own, so the per-disk breakdown is a
real table rather than a stack of cards: columns line up, digits are
tabular, and a new metric is a new column instead of a redesign. Stacking
these as rows in a third-of-a-page column is what hollowed out the two
cards beside it — see the dead-space rule in CLAUDE.md. */
/* Storage's header meta is a sentence, not a badge. .card-meta is nowrap so
short status words never break; this one has to wrap or it pushes the whole
page sideways on a phone. */
.card-meta.card-meta-wrap { white-space: normal; text-align: right; }
.array-meter.meter { margin-top: 0; margin-bottom: 1.1rem; }
.table-scroll { overflow-x: auto; }
.disk-table {
width: 100%;
border-collapse: collapse;
font-variant-numeric: tabular-nums;
}
.disk-info { min-width: 0; flex: 1; }
.disk-name {
font-size: var(--fs-sm); font-weight: 600;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
.disk-table th, .disk-table td { padding: 0.45rem 0.6rem; text-align: left; }
.disk-table th:first-child, .disk-table td:first-child { padding-left: 0; }
.disk-table th:last-child, .disk-table td:last-child { padding-right: 0; }
.disk-table thead th {
font-size: var(--fs-xs);
font-weight: 500;
color: var(--text-3);
white-space: nowrap;
padding-bottom: 0.5rem;
border-bottom: 1px solid var(--border);
}
.disk-table tbody th {
font-size: var(--fs-sm);
font-weight: 600;
color: var(--text);
white-space: nowrap;
}
.disk-table tbody td {
font-size: var(--fs-sm);
color: var(--text-2);
border-bottom: 1px solid var(--border);
}
.disk-table tbody th { border-bottom: 1px solid var(--border); }
.disk-table tbody tr:last-child th,
.disk-table tbody tr:last-child td { border-bottom: none; }
.disk-table .num { text-align: right; white-space: nowrap; }
/* The bar and its percentage share one cell, so the bar flexes with the
table while the number stays a fixed, right-aligned column of digits. */
.disk-table .usage { width: 32%; min-width: 140px; }
.usage-cell { display: flex; align-items: center; gap: 0.6rem; }
.usage-cell .meter { margin-top: 0; flex: 1; height: 5px; }
.usage-pct {
font-size: var(--fs-xs);
color: var(--text-3);
width: 2.6em;
text-align: right;
flex-shrink: 0;
}
.disk-null { color: var(--text-3); }
.disk-table tr.is-parity th { color: var(--text-2); }
@media (max-width: 720px) {
/* Below this the six columns stop fitting; the table scrolls in its own
container rather than squeezing the sizes into unreadable wraps. */
.table-scroll .disk-table { min-width: 540px; }
}
.disk-sub { font-size: var(--fs-xs); color: var(--text-3); }
.disk-meter.meter { margin-top: 0.4rem; height: 4px; }
.disk-list-compact { margin-top: 0.5rem; }
.disk-item-compact { justify-content: space-between; padding: 0.5rem 0.7rem; min-height: auto; }
.disk-item-compact .disk-name { flex: 1; }
.badge.temp-ok { background: var(--ok-dim); color: var(--ok); }
.badge.temp-warn { background: var(--warn-dim); color: var(--warn); }
.badge.temp-danger { background: var(--danger-dim); color: var(--danger); }