The number was capped at 6rem, so a readout given half a wall stopped growing at the size it reached in a small tile. Removing the cap was not enough on its own. Sizing text off container units means choosing a coefficient for some assumed number of characters, and the value here is not a fixed width: the coefficient that fills a tile nicely for "-45.9" pushes "-100.5" nine percent out through the side. Measured it rather than guessed — the tile now sets a trial size, reads the width the actual text wants, and scales to fit. That runs only when the tile size or the length of the reading changes, not on every frame. It now fills about 98% of the width wherever width is the limit and 92% of the height wherever height is, at every tile size from 180x70 up to 1400x700, with no overflow on either axis. The CSS keeps a conservative size for the first paint before the measurement has run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
149 lines
4.4 KiB
CSS
149 lines
4.4 KiB
CSS
/* SPL Meter — every colour comes from the shell's variables so themes and
|
|
per-tile tints reach in. Nothing here is hardcoded except the canvas
|
|
heat ramp, which client.js owns because it has to interpolate. */
|
|
|
|
[data-module="spl-meter"] .spl {
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
}
|
|
|
|
/* ── readout ──────────────────────────────────────────────────────── */
|
|
|
|
[data-module="spl-meter"] .spl-readout {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 0.25em;
|
|
min-height: 0;
|
|
padding: 0.25rem;
|
|
}
|
|
|
|
[data-module="spl-meter"] .spl-value {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 0.2em;
|
|
line-height: 1;
|
|
color: var(--text);
|
|
}
|
|
|
|
/* A first-paint size only. client.js measures the text and sets the real
|
|
one inline, because CSS has to assume a digit count and gets it wrong the
|
|
moment the reading needs a sixth character: the coefficient that fills a
|
|
tile for "-45.9" pushes "-100.5" straight out through the side. */
|
|
[data-module="spl-meter"] .spl-num {
|
|
font-size: clamp(1.25rem, min(26cqw, 60cqh), 100rem);
|
|
font-variant-numeric: tabular-nums;
|
|
font-weight: 600;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
[data-module="spl-meter"] .spl-unit {
|
|
font-size: clamp(0.65rem, min(7cqw, 15cqh), 26rem);
|
|
color: var(--muted);
|
|
}
|
|
|
|
[data-module="spl-meter"] .spl-sub {
|
|
font-size: 0.7rem;
|
|
color: var(--muted);
|
|
text-align: center;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
[data-module="spl-meter"] .spl-readout[data-level="warn"] .spl-num { color: var(--warn); }
|
|
[data-module="spl-meter"] .spl-readout[data-level="alarm"] .spl-num { color: var(--danger); }
|
|
[data-module="spl-meter"] .spl-readout[data-level="idle"] .spl-num { color: var(--muted); }
|
|
|
|
/* ── level bars ───────────────────────────────────────────────────── */
|
|
|
|
[data-module="spl-meter"] .spl-bars {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
gap: 0.35rem;
|
|
padding: 0.4rem;
|
|
min-height: 0;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
[data-module="spl-meter"] .spl-bar {
|
|
display: grid;
|
|
grid-template-columns: 1.4em 1fr 3.4em;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
[data-module="spl-meter"] .spl-bar-label { color: var(--muted); text-align: right; }
|
|
|
|
[data-module="spl-meter"] .spl-bar-track {
|
|
position: relative;
|
|
height: 0.65rem;
|
|
border-radius: 0.35rem;
|
|
background: color-mix(in srgb, var(--border) 60%, transparent);
|
|
overflow: hidden;
|
|
}
|
|
|
|
[data-module="spl-meter"] .spl-bar-fill {
|
|
position: absolute;
|
|
inset: 0 auto 0 0;
|
|
width: 0;
|
|
border-radius: inherit;
|
|
background: var(--accent);
|
|
transition: width 60ms linear;
|
|
}
|
|
|
|
[data-module="spl-meter"] .spl-bar[data-level="warn"] .spl-bar-fill { background: var(--warn); }
|
|
[data-module="spl-meter"] .spl-bar[data-level="alarm"] .spl-bar-fill { background: var(--danger); }
|
|
[data-module="spl-meter"] .spl-bar[data-level="idle"] .spl-bar-fill { background: var(--muted); }
|
|
|
|
/* Peak hold sits on the track rather than inside the fill, so it stays
|
|
visible when the bar falls away underneath it. */
|
|
[data-module="spl-meter"] .spl-bar-peak {
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 2px;
|
|
background: var(--text);
|
|
opacity: 0.75;
|
|
}
|
|
|
|
[data-module="spl-meter"] .spl-bar-value {
|
|
font-variant-numeric: tabular-nums;
|
|
text-align: right;
|
|
color: var(--text);
|
|
}
|
|
|
|
[data-module="spl-meter"] .spl-bar.clip .spl-bar-value { color: var(--danger); }
|
|
|
|
/* ── canvas tiles ─────────────────────────────────────────────────── */
|
|
|
|
[data-module="spl-meter"] .spl-canvas {
|
|
flex: 1;
|
|
display: block;
|
|
width: 100%;
|
|
min-height: 0;
|
|
border-radius: 0.25rem;
|
|
}
|
|
|
|
/* The readout scales off both of the tile's dimensions, so the container
|
|
has to be sized on both axes — inline-size alone leaves cqh undefined. */
|
|
[data-module="spl-meter"] .spl { container-type: size; }
|
|
|
|
/* The sub-line is the first thing to go when the tile gets short: the
|
|
number is the point, and a clipped caption under it is worse than none. */
|
|
[data-module="spl-meter"] .spl-sub {
|
|
max-width: 100%;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
@container (max-height: 90px) {
|
|
[data-module="spl-meter"] .spl-sub { display: none; }
|
|
}
|