Fix all remaining dark-theme colour bugs across the templates
Follow-up to the player-modal / maintenance-page fix: the same root cause --
colours hard-coded for the light theme -- affected the whole app, in two
places.
1) Inline style attributes (inline outranks the theme rules, so the light
value survives dark mode and the inherited text colour turns
light-on-light). base.html now carries a single, property-scoped
dark-mode override layer that maps every light literal found in the
templates to the theme variables: light backgrounds/whites -> dark
surfaces, semantic pastels -> dark equivalents, dark text -> light text,
light borders -> dark borders, plus .back-link. Scoped to
body.dark-mode, so the light theme is untouched. This covers all
templates, including ones not edited here and any added later.
2) Page-level <style> blocks with no dark support:
* admin/https_config.html hard-coded a light-only palette (blue-tint
panels, dark labels) -- added a body.dark-mode block for it.
* dashboard.html / help.html / manage_player.html coloured text links
with --primary-color (#7c3aed in dark = too dim). Introduced a
dedicated --link-color (#667eea light / #a78bfa dark) and used it for
text links, leaving --primary-color for button/background use.
Verified with an automated luminance scan of all 18 pages in both themes:
dark mode has 0 light backgrounds and 0 dark-on-dark text (the only
remaining light surfaces are the intentional white buttons on the admin
gradient cards), and light mode is unchanged.
This commit is contained in:
@@ -577,6 +577,92 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
Dark theme
|
||||||
|
------------------------------------------------------------------
|
||||||
|
This page predates the shared dark-mode variables and hard-coded its
|
||||||
|
own light palette (light panel/blue-tint backgrounds with dark text).
|
||||||
|
The rules below re-map those to dark equivalents so the page matches
|
||||||
|
the rest of the app when the dark theme is active.
|
||||||
|
------------------------------------------------------------------ */
|
||||||
|
body.dark-mode .back-link { color: #90cdf4; }
|
||||||
|
|
||||||
|
body.dark-mode .status-detection {
|
||||||
|
background: #1e3a5f;
|
||||||
|
border-left-color: #90cdf4;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-mode .badge-success { background: #1a4d2e; color: #86efac; }
|
||||||
|
body.dark-mode .badge-warning { background: #4a3800; color: #fbbf24; }
|
||||||
|
|
||||||
|
body.dark-mode .status-card { border-left-color: #4a5568; }
|
||||||
|
body.dark-mode .status-enabled {
|
||||||
|
background: linear-gradient(135deg, #1a4d2e 0%, #22543d 100%);
|
||||||
|
}
|
||||||
|
body.dark-mode .status-disabled {
|
||||||
|
background: linear-gradient(135deg, #4a3800 0%, #5a4a1e 100%);
|
||||||
|
}
|
||||||
|
body.dark-mode .status-badge { background: #276749; color: #e2e8f0; }
|
||||||
|
body.dark-mode .status-badge-inactive { background: #b45309; color: #fff; }
|
||||||
|
body.dark-mode .status-details code { background: rgba(255, 255, 255, 0.12); }
|
||||||
|
|
||||||
|
body.dark-mode .info-text {
|
||||||
|
background: #1e3a5f;
|
||||||
|
border-left-color: #90cdf4;
|
||||||
|
color: #cbd5e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-mode .form-group label { color: var(--text-color); }
|
||||||
|
body.dark-mode .form-input {
|
||||||
|
background: var(--card-bg);
|
||||||
|
color: var(--text-color);
|
||||||
|
border-color: var(--border-color);
|
||||||
|
}
|
||||||
|
body.dark-mode .form-input:focus { border-color: #90cdf4; }
|
||||||
|
body.dark-mode .form-hint { color: var(--text-secondary); }
|
||||||
|
body.dark-mode .required { color: #fca5a5; }
|
||||||
|
|
||||||
|
body.dark-mode .toggle-slider { background: #4a5568; }
|
||||||
|
body.dark-mode .toggle-slider::after { background: #e2e8f0; }
|
||||||
|
body.dark-mode .toggle-input:checked + .toggle-slider { background: #276749; }
|
||||||
|
body.dark-mode .toggle-text { color: var(--text-color); }
|
||||||
|
|
||||||
|
body.dark-mode .preview-section {
|
||||||
|
background: var(--bg-color);
|
||||||
|
border-color: #90cdf4;
|
||||||
|
}
|
||||||
|
body.dark-mode .preview-section h3 { color: #90cdf4; }
|
||||||
|
|
||||||
|
body.dark-mode .access-points li {
|
||||||
|
background: var(--card-bg);
|
||||||
|
border-left-color: #90cdf4;
|
||||||
|
}
|
||||||
|
body.dark-mode .access-points code { background: #1e3a5f; color: #90cdf4; }
|
||||||
|
|
||||||
|
body.dark-mode .form-actions { border-top-color: var(--border-color); }
|
||||||
|
|
||||||
|
body.dark-mode .info-card {
|
||||||
|
background: linear-gradient(135deg, #1e3a5f 0%, #162032 100%);
|
||||||
|
}
|
||||||
|
body.dark-mode .info-card h2 { color: #90cdf4; }
|
||||||
|
body.dark-mode .info-card li { color: var(--text-secondary); }
|
||||||
|
|
||||||
|
body.dark-mode .nginx-status-card {
|
||||||
|
background: linear-gradient(135deg, #162032 0%, #1e3a5f 100%);
|
||||||
|
border-left-color: #90cdf4;
|
||||||
|
}
|
||||||
|
body.dark-mode .nginx-status-card h2 { color: #90cdf4; }
|
||||||
|
|
||||||
|
body.dark-mode .status-item {
|
||||||
|
background: var(--card-bg);
|
||||||
|
border-left-color: #90cdf4;
|
||||||
|
}
|
||||||
|
body.dark-mode .status-item strong { color: var(--text-color); }
|
||||||
|
body.dark-mode .status-item code { background: #1e3a5f; color: #90cdf4; }
|
||||||
|
|
||||||
|
body.dark-mode .info-section h3 { color: #90cdf4; }
|
||||||
|
body.dark-mode .info-section li { color: var(--text-secondary); }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -18,6 +18,10 @@
|
|||||||
--primary-color: #667eea;
|
--primary-color: #667eea;
|
||||||
--primary-dark: #5568d3;
|
--primary-dark: #5568d3;
|
||||||
--secondary-color: #764ba2;
|
--secondary-color: #764ba2;
|
||||||
|
/* Colour for text links. Kept separate from --primary-color so the
|
||||||
|
primary colour can stay dark enough for button backgrounds while
|
||||||
|
links remain legible on the matching background. */
|
||||||
|
--link-color: #667eea;
|
||||||
--bg-color: #f5f7fa;
|
--bg-color: #f5f7fa;
|
||||||
--card-bg: #ffffff;
|
--card-bg: #ffffff;
|
||||||
--text-color: #2d3748;
|
--text-color: #2d3748;
|
||||||
@@ -34,6 +38,9 @@
|
|||||||
--primary-color: #7c3aed;
|
--primary-color: #7c3aed;
|
||||||
--primary-dark: #6d28d9;
|
--primary-dark: #6d28d9;
|
||||||
--secondary-color: #8b5cf6;
|
--secondary-color: #8b5cf6;
|
||||||
|
/* Dark background needs a lighter link colour (#7c3aed is too dim
|
||||||
|
on a dark surface). */
|
||||||
|
--link-color: #a78bfa;
|
||||||
--bg-color: #1a202c;
|
--bg-color: #1a202c;
|
||||||
--card-bg: #2d3748;
|
--card-bg: #2d3748;
|
||||||
--text-color: #e2e8f0;
|
--text-color: #e2e8f0;
|
||||||
@@ -369,6 +376,165 @@
|
|||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================================================================
|
||||||
|
Dark-mode fixes for INLINE colours
|
||||||
|
----------------------------------------------------------------
|
||||||
|
A recurring pattern across the templates is to set colours with
|
||||||
|
inline style="..." attributes (a few JS blocks build nodes the
|
||||||
|
same way). An inline declaration outranks every normal rule --
|
||||||
|
including the body.dark-mode rules above -- so those literals keep
|
||||||
|
their LIGHT value in dark mode. The text, which inherits the (now
|
||||||
|
light) --text-color, then ends up light-on-light: unreadable.
|
||||||
|
|
||||||
|
Inline styles can only be beaten with !important, so the light
|
||||||
|
literals are mapped to the theme variables here, centrally, with
|
||||||
|
the property scoped so a colour used for two things (e.g. #1a202c
|
||||||
|
is both a dark surface and dark text) is only changed where it is
|
||||||
|
wrong. This fixes every template at once -- including any future
|
||||||
|
page that repeats the pattern -- instead of patching each file.
|
||||||
|
|
||||||
|
Everything is scoped to body.dark-mode, so the LIGHT theme is
|
||||||
|
completely untouched.
|
||||||
|
|
||||||
|
Ordering matters: selectors have equal specificity, so later rules
|
||||||
|
win. The bare "#fff" rule is therefore placed BEFORE the "#fff3cd"
|
||||||
|
/"#fff8e1" ones, because "#fff" is a string prefix of them.
|
||||||
|
================================================================ */
|
||||||
|
|
||||||
|
/* --- White / near-white surfaces -> dark card --------------------- */
|
||||||
|
body.dark-mode [style*="background: white"], body.dark-mode [style*="background-color: white"],
|
||||||
|
body.dark-mode [style*="background: #fff"], body.dark-mode [style*="background-color: #fff"],
|
||||||
|
body.dark-mode [style*="background: #ffffff"], body.dark-mode [style*="background-color: #ffffff"],
|
||||||
|
body.dark-mode [style*="background: #fefefe"], body.dark-mode [style*="background-color: #fefefe"],
|
||||||
|
body.dark-mode [style*="background: #f5f7fa"], body.dark-mode [style*="background-color: #f5f7fa"],
|
||||||
|
body.dark-mode [style*="background: #e9ecef"], body.dark-mode [style*="background-color: #e9ecef"],
|
||||||
|
body.dark-mode [style*="background: #e0e0e0"], body.dark-mode [style*="background-color: #e0e0e0"],
|
||||||
|
body.dark-mode [style*="background: #f0f2ff"], body.dark-mode [style*="background-color: #f0f2ff"],
|
||||||
|
body.dark-mode [style*="background: #e8ebff"], body.dark-mode [style*="background-color: #e8ebff"],
|
||||||
|
body.dark-mode [style*="background: #e7e9ff"], body.dark-mode [style*="background-color: #e7e9ff"],
|
||||||
|
body.dark-mode [style*="background: #ede9fe"], body.dark-mode [style*="background-color: #ede9fe"] {
|
||||||
|
background: var(--card-bg) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Light grey panels -> dark page background -------------------- */
|
||||||
|
body.dark-mode [style*="background: #f8f9fa"], body.dark-mode [style*="background-color: #f8f9fa"],
|
||||||
|
body.dark-mode [style*="background: #f0f0f0"], body.dark-mode [style*="background-color: #f0f0f0"],
|
||||||
|
body.dark-mode [style*="background: #f5f5f5"], body.dark-mode [style*="background-color: #f5f5f5"],
|
||||||
|
body.dark-mode [style*="background: #f4f4f4"], body.dark-mode [style*="background-color: #f4f4f4"],
|
||||||
|
body.dark-mode [style*="background: #f8fafc"], body.dark-mode [style*="background-color: #f8fafc"] {
|
||||||
|
background: var(--bg-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Semantic pastel backgrounds -> dark equivalents -------------- */
|
||||||
|
/* info / blue */
|
||||||
|
body.dark-mode [style*="background: #d1ecf1"], body.dark-mode [style*="background-color: #d1ecf1"],
|
||||||
|
body.dark-mode [style*="background: #cce5ff"], body.dark-mode [style*="background-color: #cce5ff"],
|
||||||
|
body.dark-mode [style*="background: #e7f3ff"], body.dark-mode [style*="background-color: #e7f3ff"],
|
||||||
|
body.dark-mode [style*="background: #f0f7ff"], body.dark-mode [style*="background-color: #f0f7ff"] {
|
||||||
|
background: #1e3a5f !important;
|
||||||
|
}
|
||||||
|
/* success / green */
|
||||||
|
body.dark-mode [style*="background: #d4edda"], body.dark-mode [style*="background-color: #d4edda"],
|
||||||
|
body.dark-mode [style*="background: #d1f0e0"], body.dark-mode [style*="background-color: #d1f0e0"],
|
||||||
|
body.dark-mode [style*="background: #c6f6d5"], body.dark-mode [style*="background-color: #c6f6d5"] {
|
||||||
|
background: #1a4d2e !important;
|
||||||
|
}
|
||||||
|
/* warning / amber (must stay AFTER the "#fff" rule above) */
|
||||||
|
body.dark-mode [style*="background: #fff3cd"], body.dark-mode [style*="background-color: #fff3cd"],
|
||||||
|
body.dark-mode [style*="background: #fff8e1"], body.dark-mode [style*="background-color: #fff8e1"],
|
||||||
|
body.dark-mode [style*="background: #ffeaa7"], body.dark-mode [style*="background-color: #ffeaa7"],
|
||||||
|
body.dark-mode [style*="background: #fef3c7"], body.dark-mode [style*="background-color: #fef3c7"],
|
||||||
|
body.dark-mode [style*="background: #feebc8"], body.dark-mode [style*="background-color: #feebc8"] {
|
||||||
|
background: #4a3800 !important;
|
||||||
|
}
|
||||||
|
/* danger / red */
|
||||||
|
body.dark-mode [style*="background: #f8d7da"], body.dark-mode [style*="background-color: #f8d7da"],
|
||||||
|
body.dark-mode [style*="background: #fed7d7"], body.dark-mode [style*="background-color: #fed7d7"] {
|
||||||
|
background: #4a1a1a !important;
|
||||||
|
}
|
||||||
|
/* mid-grey chips / knobs */
|
||||||
|
body.dark-mode [style*="background: #ccc"], body.dark-mode [style*="background-color: #ccc"],
|
||||||
|
body.dark-mode [style*="background: #6c757d"], body.dark-mode [style*="background-color: #6c757d"] {
|
||||||
|
background: #4a5568 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Dark text -> light text -------------------------------------- */
|
||||||
|
body.dark-mode [style*="color: black"] {
|
||||||
|
color: var(--text-color) !important;
|
||||||
|
}
|
||||||
|
body.dark-mode [style*="color: #6c757d"], body.dark-mode [style*="color:#6c757d"],
|
||||||
|
body.dark-mode [style*="color: #666"], body.dark-mode [style*="color: #888"],
|
||||||
|
body.dark-mode [style*="color: #999"], body.dark-mode [style*="color: #aaa"],
|
||||||
|
body.dark-mode [style*="color: #495057"], body.dark-mode [style*="color: #718096"],
|
||||||
|
body.dark-mode [style*="color: #7f8c8d"], body.dark-mode [style*="color: #5a6a78"],
|
||||||
|
body.dark-mode [style*="color: #4a5568"] {
|
||||||
|
color: var(--text-secondary) !important;
|
||||||
|
}
|
||||||
|
body.dark-mode [style*="color: #555"], body.dark-mode [style*="color: #475569"],
|
||||||
|
body.dark-mode [style*="color: #64748b"] {
|
||||||
|
color: #cbd5e1 !important;
|
||||||
|
}
|
||||||
|
body.dark-mode [style*="color: #333"], body.dark-mode [style*="color: #2c3e50"],
|
||||||
|
body.dark-mode [style*="color: #000"], body.dark-mode [style*="color: #1a202c"],
|
||||||
|
body.dark-mode [style*="color: #2d3748"] {
|
||||||
|
color: var(--text-color) !important;
|
||||||
|
}
|
||||||
|
/* links / info blue */
|
||||||
|
body.dark-mode [style*="color: #0066cc"], body.dark-mode [style*="color: #007bff"],
|
||||||
|
body.dark-mode [style*="color: #0056b3"], body.dark-mode [style*="color: #0c5460"],
|
||||||
|
body.dark-mode [style*="color: #004085"], body.dark-mode [style*="color: #3498db"] {
|
||||||
|
color: #90cdf4 !important;
|
||||||
|
}
|
||||||
|
/* success text */
|
||||||
|
body.dark-mode [style*="color: #155724"], body.dark-mode [style*="color: #156b2e"],
|
||||||
|
body.dark-mode [style*="color: #28a745"], body.dark-mode [style*="color: #27ae60"],
|
||||||
|
body.dark-mode [style*="color: #2f855a"] {
|
||||||
|
color: #86efac !important;
|
||||||
|
}
|
||||||
|
/* warning text */
|
||||||
|
body.dark-mode [style*="color: #856404"], body.dark-mode [style*="color: #92400e"],
|
||||||
|
body.dark-mode [style*="color: #c05621"], body.dark-mode [style*="color: #e67e22"] {
|
||||||
|
color: #fbbf24 !important;
|
||||||
|
}
|
||||||
|
/* danger text */
|
||||||
|
body.dark-mode [style*="color: #721c24"], body.dark-mode [style*="color: #dc3545"],
|
||||||
|
body.dark-mode [style*="color: #e74c3c"], body.dark-mode [style*="color: #e53e3e"],
|
||||||
|
body.dark-mode [style*="color:#e53e3e"], body.dark-mode [style*="color: #c53030"],
|
||||||
|
body.dark-mode [style*="color: #b91c1c"] {
|
||||||
|
color: #fca5a5 !important;
|
||||||
|
}
|
||||||
|
/* purple accents */
|
||||||
|
body.dark-mode [style*="color: #5b21b6"] {
|
||||||
|
color: #a78bfa !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Light borders -> dark borders ------------------------------- */
|
||||||
|
body.dark-mode [style*="border-top-color: white"] {
|
||||||
|
border-top-color: var(--border-color) !important;
|
||||||
|
}
|
||||||
|
body.dark-mode [style*="#e2e8f0"], body.dark-mode [style*="#dee2e6"],
|
||||||
|
body.dark-mode [style*="#ddd"], body.dark-mode [style*="#ccc"],
|
||||||
|
body.dark-mode [style*="#ced4da"], body.dark-mode [style*="#e0e0e0"],
|
||||||
|
body.dark-mode [style*="#eee"], body.dark-mode [style*="#e9ecef"],
|
||||||
|
body.dark-mode [style*="#f0f0f0"], body.dark-mode [style*="#f0f2ff"],
|
||||||
|
body.dark-mode [style*="#888"], body.dark-mode [style*="#999"] {
|
||||||
|
border-color: #4a5568 !important;
|
||||||
|
}
|
||||||
|
body.dark-mode [style*="#c3e6cb"], body.dark-mode [style*="#d1f0e0"] {
|
||||||
|
border-color: #2f855a !important;
|
||||||
|
}
|
||||||
|
body.dark-mode [style*="#f5c6cb"] {
|
||||||
|
border-color: #c53030 !important;
|
||||||
|
}
|
||||||
|
body.dark-mode [style*="#bee5eb"], body.dark-mode [style*="#cce5ff"] {
|
||||||
|
border-color: #2c5282 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- "Back" links (class used across the admin pages) ------------- */
|
||||||
|
body.dark-mode .back-link {
|
||||||
|
color: #90cdf4 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
{% block extra_css %}{% endblock %}
|
{% block extra_css %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ body.dark-mode .compact-btn:not(.btn-success) .compact-btn-icon {
|
|||||||
.playlist-name {
|
.playlist-name {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: var(--primary-color);
|
color: var(--link-color);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
@@ -374,7 +374,7 @@ body.dark-mode .player-chip.is-offline .status-dot { background: #718096; }
|
|||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
.unassigned-note a {
|
.unassigned-note a {
|
||||||
color: var(--primary-color);
|
color: var(--link-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sidebar collapses below the main column when space runs out. */
|
/* Sidebar collapses below the main column when space runs out. */
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
}
|
}
|
||||||
.help-toc a:hover {
|
.help-toc a:hover {
|
||||||
background: var(--bg-color);
|
background: var(--bg-color);
|
||||||
color: var(--primary-color);
|
color: var(--link-color);
|
||||||
}
|
}
|
||||||
.help-toc a.active {
|
.help-toc a.active {
|
||||||
background: var(--primary-color);
|
background: var(--primary-color);
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
margin: 2.25rem 0 0.85rem;
|
margin: 2.25rem 0 0.85rem;
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
color: var(--primary-color);
|
color: var(--link-color);
|
||||||
scroll-margin-top: 20px;
|
scroll-margin-top: 20px;
|
||||||
}
|
}
|
||||||
.help-content h3 {
|
.help-content h3 {
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
border-top: 1px solid var(--border-color);
|
border-top: 1px solid var(--border-color);
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
.help-content a { color: var(--primary-color); }
|
.help-content a { color: var(--link-color); }
|
||||||
.help-content code {
|
.help-content code {
|
||||||
background: var(--bg-color);
|
background: var(--bg-color);
|
||||||
padding: 0.15rem 0.4rem;
|
padding: 0.15rem 0.4rem;
|
||||||
|
|||||||
@@ -363,11 +363,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-player {
|
.modal-player {
|
||||||
color: var(--primary-color);
|
color: var(--link-color);
|
||||||
}
|
|
||||||
|
|
||||||
body.dark-mode .modal-player {
|
|
||||||
color: #a78bfa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-warning {
|
.modal-warning {
|
||||||
|
|||||||
Reference in New Issue
Block a user