hub: fix .data-table btn contrast + customer page hash tabs (v0.47.0 part 1-2)

- style.css: .data-table td a -> :not(.btn) so <a class=btn> keeps the .btn
  palette (View/Download buttons were blue-on-blue invisible)
- customer_unified.html: 8 client-side hash tabs (#tab=...) + sticky summary
  strip; all sections preserved in DOM, hiding is a JS-added body class only
  (no-JS = everything visible); Events tab gets a red error-count badge
- new render tests: TestTemplates_CustomerTabs (+_NoReports)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vvz1NCu22p8dGkRCpeX9re
This commit is contained in:
2026-07-11 21:13:23 +02:00
parent 8e1a3f0d82
commit 9f29bf34c0
3 changed files with 556 additions and 263 deletions
+63 -2
View File
@@ -864,12 +864,14 @@ code {
font-family: var(--font-data);
font-size: 0.875rem;
}
.data-table td a {
/* Plain links only — :not(.btn) keeps <a class="btn"> buttons on the .btn palette
(blue-bright link text on a blue-bright button background is invisible). */
.data-table td a:not(.btn) {
color: var(--blue-bright);
text-decoration: none;
font-family: var(--font-sans, sans-serif);
}
.data-table td a:hover { text-decoration: underline; }
.data-table td a:not(.btn):hover { text-decoration: underline; }
.data-table th a {
color: var(--text-2);
text-decoration: none;
@@ -908,6 +910,65 @@ header h1 span { color: var(--blue-bright); }
:focus-visible { outline: 2px solid var(--blue-bright); outline-offset: 1px; }
/* ── Customer page tabs (v0.47.0) ──────────────────────────────────────────
Hash-based client-side tabs. Graceful degradation is load-bearing: panels
are hidden ONLY under body.js-tabs (added by JS on DOMContentLoaded) — with
JS off every panel stays visible and the page reads top-to-bottom. */
.summary-strip {
position: sticky;
top: 0;
z-index: 40;
display: flex;
align-items: center;
gap: 1rem;
flex-wrap: wrap;
padding: 0.5rem 0.75rem;
margin: 0.75rem 0 0;
background: var(--bg-0);
border: 1px solid var(--line);
border-radius: var(--radius);
font-size: 0.85rem;
}
.summary-strip .strip-name { font-weight: 600; color: var(--text-1); }
.summary-strip .strip-item { color: var(--text-2); white-space: nowrap; }
.summary-strip .strip-item code { font-size: 0.85em; }
.tab-nav {
display: flex;
gap: 0.25rem;
margin: 0.75rem 0 1rem;
border-bottom: 1px solid var(--line);
overflow-x: auto;
white-space: nowrap;
}
.tab-nav a {
color: var(--text-2);
text-decoration: none;
font-size: 0.9rem;
padding: 0.45rem 0.75rem;
border-bottom: 2px solid transparent;
flex-shrink: 0;
}
.tab-nav a:hover { color: var(--text-1); }
.tab-nav a.active {
color: var(--blue-bright);
border-bottom-color: var(--blue-bright);
font-weight: 600;
}
.tab-badge {
display: inline-block;
min-width: 1.2em;
margin-left: 0.35em;
padding: 0 0.35em;
background: var(--crit);
color: #fff;
border-radius: var(--radius);
font-size: 0.75em;
font-weight: 600;
text-align: center;
}
body.js-tabs .tab-panel:not(.tab-panel-active) { display: none; }
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation: none !important; transition: none !important; }
}