Fix low-contrast links, inline code, and warning badges on dark surfaces

Two independent contrast bugs, both from a token being used somewhere
it was never validated as a text color:

- Links/inline code used --accent as their text color against dark
  card surfaces, measuring 2.8-3.6:1 (below the 4.5:1 AA threshold for
  normal text) depending on the surface. Worst case: the sender's own
  DM chat bubble uses --accent as its *background*, so a link inside
  your own message was the exact same color as the bubble - 1.0:1,
  functionally invisible. Added --link/--link-hover (same hue/
  saturation as --accent, lightened until they clear 4.5:1 against the
  darkest realistic surface) and repointed the sitewide `a`/`a:hover`
  default, `.rendered-content a`/`code`, `.docs-chat-bubble a`, and
  `.ds-chat-citations a`. The DM chat bubble additionally needed
  bubble-scoped overrides (link, AI-adjusted note, attachment-pending
  placeholder, failed-send outline/retry-hint) since its background
  *is* --accent, which --link alone doesn't fix.
- `background: var(--warning); color: var(--white)` (chat's connection
  banner, a container badge, a service-status badge, and docs' PUT/4xx
  badges) measured ~1.7:1 - yellow needs dark text. Added --on-warning
  mirroring the existing --on-accent pattern and repointed just the
  warning-backed variants, leaving sibling info/success/danger badges
  untouched (they have the same underlying issue but are out of scope
  for this pass).

--accent itself is untouched, so every button/badge/nav element using
it as a solid fill is unchanged. Verified with computed WCAG contrast
ratios and Playwright screenshots against a live render of the real
CSS, plus the production homepage to confirm no regression to brand
colors.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vnp7vzE4hvsytMo5YjszJm
This commit is contained in:
2026-09-08 20:48:30 +02:00
co-authored by Claude Sonnet 5
parent eec1b3e3de
commit 82d6628af1
10 changed files with 42 additions and 14 deletions
+2 -2
View File
@@ -377,12 +377,12 @@ body {
} }
a { a {
color: var(--accent); color: var(--link);
text-decoration: none; text-decoration: none;
} }
a:hover { a:hover {
color: var(--accent-hover); color: var(--link-hover);
} }
button { button {
+26 -2
View File
@@ -178,7 +178,7 @@ dp-chat[mode="embed"] {
flex-shrink: 0; flex-shrink: 0;
padding: var(--space-xs) var(--space-lg); padding: var(--space-xs) var(--space-lg);
background: var(--warning); background: var(--warning);
color: var(--white); color: var(--on-warning);
font-size: 0.75rem; font-size: 0.75rem;
font-weight: 600; font-weight: 600;
text-align: center; text-align: center;
@@ -283,6 +283,14 @@ dp-chat[mode="embed"] {
border-bottom-left-radius: 4px; border-bottom-left-radius: 4px;
} }
.message-bubble.mine .rendered-content a {
color: var(--on-accent);
}
.message-bubble.mine .rendered-content a:hover {
opacity: 0.8;
}
.message-bubble.pending { .message-bubble.pending {
opacity: 0.6; opacity: 0.6;
} }
@@ -292,6 +300,10 @@ dp-chat[mode="embed"] {
cursor: pointer; cursor: pointer;
} }
.message-bubble.mine.failed {
outline-color: var(--on-accent);
}
.retry-hint { .retry-hint {
display: block; display: block;
margin-top: 0.25rem; margin-top: 0.25rem;
@@ -299,6 +311,10 @@ dp-chat[mode="embed"] {
color: var(--danger); color: var(--danger);
} }
.message-bubble.mine .retry-hint {
color: var(--on-accent);
}
.message-bubble.mine .content-copy-btn, .message-bubble.mine .content-copy-btn,
.message-bubble.theirs .content-copy-btn { .message-bubble.theirs .content-copy-btn {
opacity: 0; opacity: 0;
@@ -328,7 +344,7 @@ dp-chat[mode="embed"] {
} }
.message-bubble.mine .message-time { .message-bubble.mine .message-time {
color: rgba(255, 255, 255, 0.7); color: rgba(255, 255, 255, 0.85);
} }
.message-receipt { .message-receipt {
@@ -355,6 +371,10 @@ dp-chat[mode="embed"] {
opacity: 0; opacity: 0;
} }
.message-bubble.mine .ai-adjusted-note {
color: rgba(255, 255, 255, 0.85);
}
.attachment-pending { .attachment-pending {
margin-top: 0.35rem; margin-top: 0.35rem;
font-size: 0.8rem; font-size: 0.8rem;
@@ -362,6 +382,10 @@ dp-chat[mode="embed"] {
color: var(--text-secondary); color: var(--text-secondary);
} }
.message-bubble.mine .attachment-pending {
color: rgba(255, 255, 255, 0.85);
}
.date-separator { .date-separator {
position: sticky; position: sticky;
top: 0; top: 0;
+1 -1
View File
@@ -14,7 +14,7 @@
} }
.cm-badge.cm-running { background: var(--success); color: var(--white); } .cm-badge.cm-running { background: var(--success); color: var(--white); }
.cm-badge.cm-crashed { background: var(--danger); color: var(--white); } .cm-badge.cm-crashed { background: var(--danger); color: var(--white); }
.cm-badge.cm-paused { background: var(--warning); color: var(--white); } .cm-badge.cm-paused { background: var(--warning); color: var(--on-warning); }
.cm-badge.cm-stopped { background: var(--text-muted); color: var(--white); } .cm-badge.cm-stopped { background: var(--text-muted); color: var(--white); }
.cm-badge.cm-removed { background: var(--text-muted); color: var(--white); } .cm-badge.cm-removed { background: var(--text-muted); color: var(--white); }
.cm-badge.cm-created, .cm-badge.cm-created,
+1 -1
View File
@@ -592,7 +592,7 @@ dp-deepsearch-chat {
} }
.ds-chat-citations a { .ds-chat-citations a {
color: var(--accent); color: var(--link);
} }
.ds-chat-status { .ds-chat-status {
+1 -1
View File
@@ -91,7 +91,7 @@ dp-docs-chat {
} }
.docs-chat-bubble a { .docs-chat-bubble a {
color: var(--accent); color: var(--link);
text-decoration: none; text-decoration: none;
} }
+2 -2
View File
@@ -171,7 +171,7 @@
.method-get { background: var(--info); } .method-get { background: var(--info); }
.method-post { background: var(--success); } .method-post { background: var(--success); }
.method-delete { background: var(--danger); } .method-delete { background: var(--danger); }
.method-put { background: var(--warning); } .method-put { background: var(--warning); color: var(--on-warning); }
.auth-badge { .auth-badge {
border: 1px solid var(--border-light); border: 1px solid var(--border-light);
@@ -380,7 +380,7 @@ textarea.param-input {
.response-2xx { background: var(--success); } .response-2xx { background: var(--success); }
.response-3xx { background: var(--info); } .response-3xx { background: var(--info); }
.response-4xx { background: var(--warning); } .response-4xx { background: var(--warning); color: var(--on-warning); }
.response-5xx { background: var(--danger); } .response-5xx { background: var(--danger); }
.response-redirect { .response-redirect {
+3 -3
View File
@@ -47,12 +47,12 @@
.rendered-content h4 { font-size: 0.9375rem; } .rendered-content h4 { font-size: 0.9375rem; }
.rendered-content a { .rendered-content a {
color: var(--accent); color: var(--link);
text-decoration: underline; text-decoration: underline;
} }
.rendered-content a:hover { .rendered-content a:hover {
color: var(--accent-hover); color: var(--link-hover);
} }
.rendered-content hr { .rendered-content hr {
@@ -98,7 +98,7 @@
padding: 0.125rem 0.375rem; padding: 0.125rem 0.375rem;
border-radius: 4px; border-radius: 4px;
background: var(--bg-card-hover); background: var(--bg-card-hover);
color: var(--accent); color: var(--link);
} }
.rendered-content pre { .rendered-content pre {
+1 -1
View File
@@ -59,7 +59,7 @@
.service-status.stalled { .service-status.stalled {
background: var(--warning); background: var(--warning);
color: var(--white); color: var(--on-warning);
} }
.service-controls { .service-controls {
+4
View File
@@ -16,6 +16,9 @@
--accent-gradient: linear-gradient(135deg, #b73f1e, #af3050, #8f3b71); --accent-gradient: linear-gradient(135deg, #b73f1e, #af3050, #8f3b71);
--on-accent: #fff; --on-accent: #fff;
--link: #df5f3b;
--link-hover: #d4627e;
--text-primary: #e9e4ff; --text-primary: #e9e4ff;
--text-secondary: #c8c3e5; --text-secondary: #c8c3e5;
--text-muted: #9b93c9; --text-muted: #9b93c9;
@@ -27,6 +30,7 @@
--warning: #fbbf24; --warning: #fbbf24;
--danger: #f87171; --danger: #f87171;
--info: #60a5fa; --info: #60a5fa;
--on-warning: #1c1200;
--radius: 8px; --radius: 8px;
--radius-input: 8px; --radius-input: 8px;
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "devplacepy" name = "devplacepy"
version = "1.0.9" version = "1.0.10"
description = "DevPlace - The Developer Social Network" description = "DevPlace - The Developer Social Network"
requires-python = ">=3.12" requires-python = ">=3.12"
dependencies = [ dependencies = [