Declare the Monitor board in one place, so a card's width and position stop living in eighteen inline styles and four media queries

This commit is contained in:
Gmer4Lfe
2026-08-23 00:44:30 -04:00
parent bd13bdc6e1
commit fd1ab58598
4 changed files with 444 additions and 65 deletions
+79 -34
View File
@@ -190,7 +190,32 @@ body.vv-fullscreen #displaybox { padding-left: 1rem !important; padding-top: .5r
.vv-nb-settings { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
padding: 5px 10px; background: #101010; border-bottom: 1px solid #1a1a1a; }
/* ── Monitor: locked row height + scrollable cards ────────────────────────── */
/* ── Monitor: the board ───────────────────────────────────────────────────────
Only the half of the layout that is the same at every width lives here. Which cards exist,
how wide each one is, what order they sit in, how many columns the board has at this width
and how tall a row may be are all generated by include/monitor_board.php and arrive as
--vv-cols, --vv-sp and --vv-rowdiv. Do not put a column count or a breakpoint in this file;
they are arithmetic over the card floor, and that arithmetic has one home.
minmax(0, 1fr), not 1fr: bare 1fr means minmax(auto, 1fr), and that auto floor resolves to the
larger of min-content and min-width — one card holding an unbreakable string would push its
column past its share and drag the grid out of the container. The row axis carried this guard
for years; the column axis never did.
min-width: 0 on the cards for the same reason, overriding the 200px .vv-card floor the flex
layouts on other pages need. On this board the ladder is what guarantees a card's width, so a
card defending its own floor can only overflow the track the ladder just sized for it. */
#vv-monitor {
display: grid;
grid-template-columns: repeat(var(--vv-cols, 8), minmax(0, 1fr));
gap: 12px;
width: 100%;
box-sizing: border-box;
}
#vv-monitor > .vv-card {
grid-column: span var(--vv-sp, 1);
min-width: 0;
}
/* Cards on the monitor grid are flex columns — h3 pins, body scrolls */
#vv-monitor .vv-card {
@@ -213,29 +238,38 @@ body.vv-fullscreen #displaybox { padding-left: 1rem !important; padding-top: .5r
/* Dynamic row heights capped per screen tier — rows size to content, never exceed the cap.
minmax(0, Xpx): track is content-driven but capped; align-items:stretch makes all cards
in a row fill the track, so short cards (Pools, Watchdog) match tall ones (Array).
Breakpoints are viewport height (after browser chrome), not screen height. */
Breakpoints are viewport height (after browser chrome), not screen height.
The divisor is --vv-rowdiv, not a literal 4. It used to be 4 because the board happened to be
four rows at eight columns, so the two numbers were the same by accident and only one of them
moved when the column count changed. monitor_board.php derives it as min(rows at this rung,
VV_MON_ROWS_PER_SCREEN): the cap means "no card taller than this fraction of the screen", and a
board short enough to fit divides by its own row count and fills the screen instead. */
/* ~720p (viewport ≤ 700px) */
@media (min-width: 481px) and (max-height: 700px) {
#vv-monitor { grid-auto-rows: minmax(0, calc((100vh - 160px) / 4)); }
}
/* ~1080p (viewport 7011100px) */
@media (min-width: 481px) and (min-height: 701px) and (max-height: 1100px) {
#vv-monitor { grid-auto-rows: minmax(0, calc((100vh - 240px) / 4)); }
@media (min-height: 701px) and (max-height: 1100px) {
#vv-monitor { grid-auto-rows: minmax(0, calc((100vh - 240px) / var(--vv-rowdiv, 4))); }
}
/* ~1440p (viewport 11011450px) — calibrated on 15" 1440p display */
@media (min-width: 481px) and (min-height: 1101px) and (max-height: 1450px) {
#vv-monitor { grid-auto-rows: minmax(0, calc((100vh - 335px) / 4)); }
@media (min-height: 1101px) and (max-height: 1450px) {
#vv-monitor { grid-auto-rows: minmax(0, calc((100vh - 335px) / var(--vv-rowdiv, 4))); }
}
/* ~4K (viewport > 1450px) */
@media (min-width: 481px) and (min-height: 1451px) {
#vv-monitor { grid-auto-rows: minmax(0, calc((100vh - 500px) / 4)); }
@media (min-height: 1451px) {
#vv-monitor { grid-auto-rows: minmax(0, calc((100vh - 500px) / var(--vv-rowdiv, 4))); }
}
/* Mobile: natural heights, let page scroll */
@media (max-width: 480px) {
#vv-monitor { grid-auto-rows: auto !important; }
#vv-monitor .vv-card { overflow: visible !important; }
/* Natural heights, page scrolls. Height is what makes a phone in landscape unusable, not width:
this hatch was keyed to max-width:480 alone, so portrait (393px wide) got content-sized rows and
worked, while landscape (851x393) missed it and inherited the four-row cap — 58px cards with
overflow:hidden and scrollbars disabled. Nothing was visible and nothing said so.
The width half is the two-column rung from monitor_board.php (below 696px). It is written as a
literal here because a media query cannot read a custom property; if VV_MON_CARD_FLOOR changes,
this number and the AI row's two below are the only three places that have to follow it. */
@media (max-width: 695px), (max-height: 700px) {
#vv-monitor { grid-auto-rows: auto; }
#vv-monitor .vv-card { overflow: visible; }
#vv-monitor .vv-card > div { overflow-y: visible; min-height: auto; }
}
@@ -251,13 +285,17 @@ body.vv-fullscreen #displaybox { padding-left: 1rem !important; padding-top: .5r
default stays start so a card added later has to say so. */
#vv-monitor-ai {
display: grid;
grid-template-columns: repeat(8, 1fr);
grid-template-columns: repeat(8, minmax(0, 1fr));
gap: 12px;
margin-top: 12px;
width: 100%;
box-sizing: border-box;
align-items: start;
}
/* Same reason as the board above: the ladder guarantees the width, so a card defending the 200px
.vv-card floor can only overflow the track it was given. At the four-column rung's own minimum
(696px) a column is 160px, and that floor would have pushed this row out of the page. */
#vv-monitor-ai > .vv-card { min-width: 0; }
/* Explicit placement, two rows. The left column carries AI over Tokens; Conversations and the
Assistant span both rows, so the Assistant sets the height and the two stacked cards divide
@@ -354,8 +392,14 @@ body.vv-fullscreen #displaybox { padding-left: 1rem !important; padding-top: .5r
#vv-ai-tokens-card .vv-ai-tok-head:first-child { margin-top: 0; }
/* Medium width — 4 columns, mirroring #vv-monitor's own breakpoint. The 1/2/5 spans do not
survive the narrower grid: 5 of 4 would silently overflow the track. */
@media (max-width: 1024px) {
survive the narrower grid: 5 of 4 would silently overflow the track.
1383 and 695 below are the four- and two-column rungs from include/monitor_board.php, minus
one. This row keeps its own placement — the 1/2/5 split is not a power of two and does not want
to be — but it cannot keep its own breakpoints: at any width where these two disagree the board
above is four columns while this row is still eight, and the page visibly stops being one
board. If VV_MON_CARD_FLOOR moves, these move with it. */
@media (max-width: 1383px) {
#vv-monitor-ai { grid-template-columns: repeat(4, 1fr) !important; }
#vv-ai-stats-card { grid-column: 1 / span 1 !important; grid-row: 1 !important; }
#vv-ai-tokens-card { grid-column: 1 / span 1 !important; grid-row: 2 !important; }
@@ -365,10 +409,14 @@ body.vv-fullscreen #displaybox { padding-left: 1rem !important; padding-top: .5r
#vv-ai-assistant-card { grid-column: 1 / span 4 !important; grid-row: 3 !important; }
}
/* Phone — single column, natural heights, page scrolls. Matching heights is meaningless once
/* Narrow — single column, natural heights, page scrolls. Matching heights is meaningless once
the cards are stacked, and the inner scroll has to go with it: on a page that already scrolls,
a scroll region inside it is a trap for a thumb. */
@media (max-width: 480px) {
a scroll region inside it is a trap for a thumb.
695, where the board above drops to two columns, rather than the 480 this used to use. There is
no two-column layout for this row and there should not be: its 1/1/3/4 split at four columns is
already the narrowest arrangement in which the Assistant transcript is readable. */
@media (max-width: 695px) {
#vv-monitor-ai { grid-template-columns: 1fr !important; }
/* grid-row has to be released along with grid-column. The explicit rows above are the whole
reason Tokens sits under AI, and left in place on a single-column grid they would stack
@@ -389,14 +437,14 @@ body.vv-fullscreen #displaybox { padding-left: 1rem !important; padding-top: .5r
.vv-cpu-core { min-width: 7px !important; }
}
@media (max-width: 1024px) {
#vv-monitor { grid-template-columns: repeat(4, 1fr) !important; }
#vv-docker { grid-column: span 4 !important; }
/* Reset explicit placements so cards reflow in the 4-col grid */
#vv-docker-folders { grid-column: span 4 !important; }
#vv-parity-card { grid-column: auto !important; }
#vv-storage-card { grid-column: auto !important; }
#vv-array-card { grid-column: auto !important; }
/* The four-column rung. Nothing about placement is here any more: the column count and every
span come from the generated ladder, and the six !important overrides this block used to carry
existed only to out-shout the inline styles the cards no longer have. Two of them
(#vv-storage-card, #vv-array-card) were resetting hand-placed column indexes — 3/span 2 and
5/span 4 — which is the pair that made the grid invent implicit columns at any count but eight.
What is left is the one thing that genuinely belongs to width: at this rung the Streams card is
half the board rather than a quarter, and its right-hand chips no longer fit. */
@media (max-width: 1383px) {
/* Streams header: hide right chip group entirely, keep server badges + media type */
.vv-stream-right { display: none; }
}
@@ -441,10 +489,7 @@ body.vv-fullscreen #displaybox { padding-left: 1rem !important; padding-top: .5r
.vv-cpu-cores { gap: 2px !important; }
.vv-cpu-core { min-width: 6px !important; }
/* Monitor single-column — explicit placement cards need override too */
#vv-monitor { grid-template-columns: 1fr !important; }
#vv-monitor > .vv-card { grid-column: 1 / -1 !important; }
#vv-docker-folders { grid-column: 1 / -1 !important; }
/* The single-column rung is generated — see include/monitor_board.php. */
}
/* Shared footer (Save Schedule left, info right) — same min-height so log card ends level with script cards */