Move remaining static inline styles into dashboard.css, bump Now Playing text size

Three inline style="..." attributes were pure styling with no per-request
data behind them (a hero-block spacing tweak, a trailing note's margin, a
gap between two stacked rows) — moved each into dashboard.css as a scoped
structural selector so future adjustments happen in one place instead of
being split between the template and the stylesheet.

Also bumped .stream-title/.stream-user/.stream-icon in the Now Playing
card one step up the existing --fs-* scale (13px->15px, 12px->13px,
15px->18px) rather than introducing a one-off size.

Documented the "styles belong in CSS, not inline" rule in CLAUDE.md,
with the actual exception: per-request computed values (a meter's width,
a threshold colour) and JS-toggled initial visibility still can't live
in a static stylesheet and are fine to stay inline.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Barely Removable 2026-08-27 06:27:43 -07:00
parent 1cc5a247cf
commit 326ab6cee5
3 changed files with 26 additions and 6 deletions

View file

@ -42,6 +42,17 @@ the user's Unraid home server. Server-side project directory is still named
`SCRIPT_NAME` subpath. Server-rendered config (timezone, script root)
reaches JS through `<body data-*>`, never string-interpolated into a
script block.
- **No `style="..."` attributes for anything static.** A one-off tweak
(button height, a margin, a font size) belongs in the matching
`static/css/*.css` file, scoped with a structural selector (an
adjacent-sibling or `:last-child` rule tied to the surrounding markup)
or a small modifier class — not inline on the element. The only
legitimate inline `style=` left in `dashboard.html` are per-request
computed values Jinja has to interpolate (a meter's `width: {{ pct
}}%`, a colour chosen by threshold) and JS-toggled initial visibility
(`display:none` on something `dashboard.js` reveals) — those can't
live in a static stylesheet. Everything else should read as a class
name, not a value.
- **`static/css/base.css`** — the single source of truth for the design
tokens, shared by all three templates: surfaces, a 6-step `--fs-*` type
scale, semantic colours, and `--tap: 44px` for minimum touch targets.

View file

@ -131,6 +131,9 @@ main {
}
.row.cols-3 { grid-template-columns: repeat(3, 1fr); }
.row.cols-2 { grid-template-columns: repeat(2, 1fr); }
/* A section with two stacked rows (Watch insights) needs the same gap
between them as the grid uses between columns. */
.row + .row { margin-top: var(--gap); }
/* ── Card ───────────────────────────────────────────── */
.card {
@ -193,13 +196,13 @@ main {
border-top: 1px solid var(--border);
}
.stream:first-child { border-top: none; padding-top: 0; }
.stream-icon { font-size: var(--fs-base); flex-shrink: 0; }
.stream-icon { font-size: var(--fs-lg); flex-shrink: 0; }
.stream-info { min-width: 0; flex: 1; }
.stream-title {
font-size: var(--fs-sm); font-weight: 600;
font-size: var(--fs-base); font-weight: 600;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.stream-user { font-size: var(--fs-xs); color: var(--text-3); }
.stream-user { font-size: var(--fs-sm); color: var(--text-3); }
.live-dot {
width: 7px; height: 7px; border-radius: 50%;
background: var(--ok); flex-shrink: 0;
@ -242,6 +245,10 @@ dl.stats {
margin: 0;
grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
}
/* Only the Downloads card stacks stats below the hero figure/sub block —
give that pairing breathing room without affecting stats blocks that
open a card (Sonarr/Radarr put dl.stats right after the search bar). */
.card-body > [aria-live="polite"] + dl.stats { margin-top: 0.9rem; }
dl.stats > div {
background: var(--surface-2);
border: 1px solid var(--border);
@ -595,6 +602,8 @@ dd.is-accent { color: var(--accent); }
}
.empty { color: var(--text-3); font-size: var(--fs-sm); }
/* Storage card's usage note trails the meter with no room to spare below it. */
.meter-legend + .empty { margin-bottom: 0; }
/* ── Errors ─────────────────────────────────────────── */
.error {

View file

@ -130,7 +130,7 @@
<span id="sab-timeleft-row" style="display:none;"> · ETA <span id="sab-timeleft"></span></span>
</div>
</div>
<dl class="stats" style="margin-top:0.9rem;">
<dl class="stats">
<div><dt>Avg speed (7d)</dt><dd>{{ sabnzbd.avg_speed }}</dd></div>
<div><dt>Grabbed (7d)</dt><dd>{{ sabnzbd.completed_7d }}</dd></div>
<div><dt>Volume (7d)</dt><dd>{{ sabnzbd.week_size }}</dd></div>
@ -168,7 +168,7 @@
{% if unraid.disk_count %}<span>{{ unraid.disk_count }} disk{{ 's' if unraid.disk_count != 1 }}</span>{% endif %}
</div>
{% if unraid.source == "local" %}
<p class="empty" style="margin-bottom:0;">Container disk usage ({{ unraid.mount }}). Set <code>UNRAID_API_KEY</code> for full array stats.</p>
<p class="empty">Container disk usage ({{ unraid.mount }}). Set <code>UNRAID_API_KEY</code> for full array stats.</p>
{% endif %}
{% if unraid.disks or unraid.caches %}
@ -520,7 +520,7 @@
</div>
{% if tautulli.top_tv_list or tautulli.top_movie_list %}
<div class="row cols-2" style="margin-top: var(--gap);">
<div class="row cols-2">
<div class="card">
<div class="card-header"><h3>Top TV</h3></div>
<div class="card-body">