Skip to content

Commit ff2cba3

Browse files
authored
Merge pull request #198 from CultureBotAI/chore/review-cleanup
CommunityMech review cleanup: CVD-safe palette, PaCMAP labels, data-table, de-emoji, footer, discussions/examples dark
2 parents 7933177 + a315e3c commit ff2cba3

279 files changed

Lines changed: 7773 additions & 914 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/discussions/index.html

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1">
66
<title>Knowledge gaps & discussions</title>
77
<style>
8-
:root { --fg:#1a1a1a; --muted:#666; --line:#e2e2e2; --accent:#2a6; --bg:#fff; }
8+
:root { --fg:#1a1a1a; --muted:#666; --line:#e2e2e2; --accent:#2a6; --bg:#fff; --card:#fff; }
99
* { box-sizing: border-box; }
1010
body { font-family: -apple-system, system-ui, sans-serif; color: var(--fg); margin: 0; background: var(--bg); }
1111
header { padding: 1rem 1.25rem; border-bottom: 1px solid var(--line); }
@@ -27,6 +27,20 @@
2727
a { color: var(--accent); text-decoration: none; }
2828
a:hover { text-decoration: underline; }
2929
.empty { color: var(--muted); padding: 2rem; text-align: center; }
30+
/* ---- Dark theme (OS default; superseded by the toggle) ---- */
31+
@media (prefers-color-scheme: dark){
32+
:root:not([data-theme="light"]){--fg:#e8ecf4; --muted:#99a2b5; --line:#2a3142; --accent:#5fbf90; --bg:#101420; --card:#1a1f2e;}
33+
:root:not([data-theme="light"]) .badge{background:#243044; color:#cdd7ff;}
34+
:root:not([data-theme="light"]) .badge.gap{background:#3a2330; color:#f2b8c6;}
35+
:root:not([data-theme="light"]) .rationale{color:#c9d2e3;}
36+
}
37+
:root[data-theme="dark"]{--fg:#e8ecf4; --muted:#99a2b5; --line:#2a3142; --accent:#5fbf90; --bg:#101420; --card:#1a1f2e;}
38+
:root[data-theme="dark"] .badge{background:#243044; color:#cdd7ff;}
39+
:root[data-theme="dark"] .badge.gap{background:#3a2330; color:#f2b8c6;}
40+
:root[data-theme="dark"] .rationale{color:#c9d2e3;}
41+
@media (prefers-reduced-motion: reduce){
42+
*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important;}
43+
}
3044
</style>
3145
</head>
3246
<body>
@@ -123,5 +137,6 @@ <h1 id="title">Knowledge gaps &amp; discussions</h1>
123137
renderFacets(); render();
124138
})();
125139
</script>
140+
<script src="theme-toggle.js"></script>
126141
</body>
127142
</html>

app/discussions/theme-toggle.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* Mech theme toggle — vendored byte-identical across all Mech sites.
2+
* Applies the saved theme to <html data-theme> (falling back to the OS
3+
* preference) before paint, and injects a self-contained fixed toggle button.
4+
* No dependencies; no per-page markup or CSS required beyond loading this file.
5+
* The page's own dark palette is supplied via :root[data-theme="dark"] and the
6+
* prefers-color-scheme media query in that page's stylesheet. */
7+
(function () {
8+
var KEY = 'mech-theme';
9+
var root = document.documentElement;
10+
11+
function osDark() {
12+
return !!(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
13+
}
14+
function current() {
15+
return root.getAttribute('data-theme') || (osDark() ? 'dark' : 'light');
16+
}
17+
18+
// Apply the saved preference as early as possible to avoid a flash.
19+
try {
20+
var saved = localStorage.getItem(KEY);
21+
if (saved === 'dark' || saved === 'light') root.setAttribute('data-theme', saved);
22+
} catch (e) {}
23+
24+
function setIcon(btn) {
25+
var dark = current() === 'dark';
26+
btn.querySelector('.theme-toggle-icon').textContent = dark ? '☀' : '☾'; // sun / moon
27+
btn.setAttribute('aria-pressed', dark ? 'true' : 'false');
28+
}
29+
function toggle(btn) {
30+
var next = current() === 'dark' ? 'light' : 'dark';
31+
root.setAttribute('data-theme', next);
32+
try { localStorage.setItem(KEY, next); } catch (e) {}
33+
setIcon(btn);
34+
}
35+
function mount() {
36+
if (document.querySelector('.theme-toggle')) return;
37+
38+
var css =
39+
'.theme-toggle{position:fixed;bottom:18px;right:18px;z-index:2000;width:40px;height:40px;' +
40+
'border-radius:50%;border:1px solid var(--line,var(--border,rgba(128,128,128,.4)));' +
41+
'background:var(--card,var(--surface,var(--card-bg,#fff)));' +
42+
'color:var(--ink,var(--text,var(--fg,#1a1a1a)));font-size:18px;line-height:1;cursor:pointer;' +
43+
'display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px rgba(0,0,0,.25);' +
44+
'transition:border-color .15s,transform .15s;}' +
45+
'.theme-toggle:hover{border-color:var(--accent,var(--primary,var(--brand-1,#888)));transform:translateY(-1px);}' +
46+
'.theme-toggle:focus-visible{outline:2px solid var(--accent,var(--primary,#888));outline-offset:2px;}' +
47+
'@media (prefers-reduced-motion: reduce){.theme-toggle{transition:none;}}';
48+
var st = document.createElement('style');
49+
st.textContent = css;
50+
document.head.appendChild(st);
51+
52+
var btn = document.createElement('button');
53+
btn.type = 'button';
54+
btn.className = 'theme-toggle';
55+
btn.setAttribute('aria-label', 'Toggle dark mode');
56+
btn.title = 'Toggle light / dark';
57+
btn.innerHTML = '<span class="theme-toggle-icon" aria-hidden="true"></span>';
58+
btn.addEventListener('click', function () { toggle(btn); });
59+
document.body.appendChild(btn);
60+
setIcon(btn);
61+
62+
// If the visitor has no explicit choice, follow live OS-theme changes.
63+
if (window.matchMedia) {
64+
try {
65+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function () {
66+
if (!root.getAttribute('data-theme')) setIcon(btn);
67+
});
68+
} catch (e) {}
69+
}
70+
}
71+
72+
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', mount);
73+
else mount();
74+
})();

docs/browser.html

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,83 @@
413413
color: #64748b;
414414
font-size: 0.875rem;
415415
}
416-
</style>
416+
/* ---- Dark theme (OS default; superseded by the toggle) ---- */
417+
@media (prefers-color-scheme: dark){
418+
:root:not([data-theme="light"]){--card:#1a1f2e; --ink:#e8ecf4; --line:#2a3142; --accent:#6ea6f0;}
419+
:root:not([data-theme="light"]) body{background:#101420;color:#e8ecf4}
420+
:root:not([data-theme="light"]) header{background:linear-gradient(135deg,#1d2740,#101420);border-bottom-color:#2a3142}
421+
:root:not([data-theme="light"]) header .home-link{color:#6ea6f0}
422+
:root:not([data-theme="light"]) h1{color:#e8ecf4}
423+
:root:not([data-theme="light"]) .subtitle{color:#99a2b5}
424+
:root:not([data-theme="light"]) .filter-panel{background:#1a1f2e;border-color:#2a3142}
425+
:root:not([data-theme="light"]) .filter-panel h3{color:#e8ecf4}
426+
:root:not([data-theme="light"]) .search-container input{background:#101420;border-color:#2a3142;color:#e8ecf4}
427+
:root:not([data-theme="light"]) .clear-btn{color:#99a2b5}
428+
:root:not([data-theme="light"]) .clear-btn:hover{color:#e8ecf4}
429+
:root:not([data-theme="light"]) .search-results-count{color:#99a2b5;border-bottom-color:#2a3142}
430+
:root:not([data-theme="light"]) .facet-section{border-bottom-color:#2a3142}
431+
:root:not([data-theme="light"]) .facet-toggle{color:#99a2b5}
432+
:root:not([data-theme="light"]) .facet-actions button{background:#101420;border-color:#2a3142;color:#e8ecf4}
433+
:root:not([data-theme="light"]) .facet-actions button:hover{background:#232a3d}
434+
:root:not([data-theme="light"]) .facet-checkbox:hover{background:rgba(255,255,255,.04)}
435+
:root:not([data-theme="light"]) .facet-count{color:#99a2b5}
436+
:root:not([data-theme="light"]) .active-filters{background:rgba(251,191,36,.12);border-color:#fbbf24}
437+
:root:not([data-theme="light"]) .btn-reset{background:#101420;border-color:#fbbf24;color:#e8ecf4}
438+
:root:not([data-theme="light"]) .btn-reset:hover{background:rgba(251,191,36,.15)}
439+
:root:not([data-theme="light"]) .filter-tag{background:#101420;border-color:#2a3142;color:#e8ecf4}
440+
:root:not([data-theme="light"]) .filter-tag-remove{color:#99a2b5}
441+
:root:not([data-theme="light"]) .filter-tag-remove:hover{color:#f87171}
442+
:root:not([data-theme="light"]) .umap-link{background:#1a1f2e;border-color:#6ea6f0}
443+
:root:not([data-theme="light"]) .umap-link h2{color:#6ea6f0}
444+
:root:not([data-theme="light"]) .umap-link p{color:#99a2b5}
445+
:root:not([data-theme="light"]) .umap-link a{background:#6ea6f0;color:#101420}
446+
:root:not([data-theme="light"]) .umap-link a:hover{background:#8fbcf5}
447+
:root:not([data-theme="light"]) .community-card{background:#1a1f2e;border-color:#2a3142}
448+
:root:not([data-theme="light"]) .community-card h2{color:#6ea6f0}
449+
:root:not([data-theme="light"]) .community-card .description{color:#99a2b5}
450+
:root:not([data-theme="light"]) .badge-category{background:#232a3d;color:#cbd5e1}
451+
:root:not([data-theme="light"]) .badge-member-count{background:#232a3d;color:#cbd5e1}
452+
:root:not([data-theme="light"]) footer{border-top-color:#2a3142;color:#99a2b5}
453+
}
454+
:root[data-theme="dark"]{--card:#1a1f2e; --ink:#e8ecf4; --line:#2a3142; --accent:#6ea6f0;}
455+
:root[data-theme="dark"] body{background:#101420;color:#e8ecf4}
456+
:root[data-theme="dark"] header{background:linear-gradient(135deg,#1d2740,#101420);border-bottom-color:#2a3142}
457+
:root[data-theme="dark"] header .home-link{color:#6ea6f0}
458+
:root[data-theme="dark"] h1{color:#e8ecf4}
459+
:root[data-theme="dark"] .subtitle{color:#99a2b5}
460+
:root[data-theme="dark"] .filter-panel{background:#1a1f2e;border-color:#2a3142}
461+
:root[data-theme="dark"] .filter-panel h3{color:#e8ecf4}
462+
:root[data-theme="dark"] .search-container input{background:#101420;border-color:#2a3142;color:#e8ecf4}
463+
:root[data-theme="dark"] .clear-btn{color:#99a2b5}
464+
:root[data-theme="dark"] .clear-btn:hover{color:#e8ecf4}
465+
:root[data-theme="dark"] .search-results-count{color:#99a2b5;border-bottom-color:#2a3142}
466+
:root[data-theme="dark"] .facet-section{border-bottom-color:#2a3142}
467+
:root[data-theme="dark"] .facet-toggle{color:#99a2b5}
468+
:root[data-theme="dark"] .facet-actions button{background:#101420;border-color:#2a3142;color:#e8ecf4}
469+
:root[data-theme="dark"] .facet-actions button:hover{background:#232a3d}
470+
:root[data-theme="dark"] .facet-checkbox:hover{background:rgba(255,255,255,.04)}
471+
:root[data-theme="dark"] .facet-count{color:#99a2b5}
472+
:root[data-theme="dark"] .active-filters{background:rgba(251,191,36,.12);border-color:#fbbf24}
473+
:root[data-theme="dark"] .btn-reset{background:#101420;border-color:#fbbf24;color:#e8ecf4}
474+
:root[data-theme="dark"] .btn-reset:hover{background:rgba(251,191,36,.15)}
475+
:root[data-theme="dark"] .filter-tag{background:#101420;border-color:#2a3142;color:#e8ecf4}
476+
:root[data-theme="dark"] .filter-tag-remove{color:#99a2b5}
477+
:root[data-theme="dark"] .filter-tag-remove:hover{color:#f87171}
478+
:root[data-theme="dark"] .umap-link{background:#1a1f2e;border-color:#6ea6f0}
479+
:root[data-theme="dark"] .umap-link h2{color:#6ea6f0}
480+
:root[data-theme="dark"] .umap-link p{color:#99a2b5}
481+
:root[data-theme="dark"] .umap-link a{background:#6ea6f0;color:#101420}
482+
:root[data-theme="dark"] .umap-link a:hover{background:#8fbcf5}
483+
:root[data-theme="dark"] .community-card{background:#1a1f2e;border-color:#2a3142}
484+
:root[data-theme="dark"] .community-card h2{color:#6ea6f0}
485+
:root[data-theme="dark"] .community-card .description{color:#99a2b5}
486+
:root[data-theme="dark"] .badge-category{background:#232a3d;color:#cbd5e1}
487+
:root[data-theme="dark"] .badge-member-count{background:#232a3d;color:#cbd5e1}
488+
:root[data-theme="dark"] footer{border-top-color:#2a3142;color:#99a2b5}
489+
@media (prefers-reduced-motion: reduce){
490+
*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important;}
491+
}
492+
</style>
417493
</head>
418494
<body>
419495
<header>
@@ -519,8 +595,8 @@ <h3>Metal Relevance</h3>
519595
<!-- Right side: Community grid -->
520596
<div class="content-area">
521597
<div class="umap-link">
522-
<h2>📊 Explore Community Relationships</h2>
523-
<p>View the UMAP projection of all communities based on their taxonomic composition embeddings from KG-Microbe.</p>
598+
<h2>Explore Community Relationships</h2>
599+
<p>View the PaCMAP projection of all communities based on their taxonomic composition embeddings from KG-Microbe.</p>
524600
<a href="community_umap.html">View Community Embedding Space →</a>
525601
</div>
526602

@@ -9155,5 +9231,6 @@ <h2>m-CAFEs Brachypodium Reduced Complexity Consortia</h2>
91559231
// Initialize facets when page loads
91569232
initializeFacets();
91579233
</script>
9234+
<script src="theme-toggle.js"></script>
91589235
</body>
91599236
</html>

docs/communities/AMD_Acidophile_Heterotroph_Network.html

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,29 @@
342342
.network-tooltip strong {
343343
color: #93c5fd;
344344
}
345-
</style>
345+
/* ---- Dark theme (OS default; superseded by the toggle) ---- */
346+
@media (prefers-color-scheme: dark){
347+
:root:not([data-theme="light"]){--primary:#6ea6f0; --secondary:#99a2b5; --background:#101420; --card:#1a1f2e; --border:#2a3142; --text:#e8ecf4; --text-muted:#99a2b5; --success:#34d399; --warning:#fbbf24; --net-label:#cbd5e1;}
348+
:root:not([data-theme="light"]) header{background:linear-gradient(135deg,#1d2740,#101420);border-bottom-color:#2a3142}
349+
:root:not([data-theme="light"]) th{background:#232a3d}
350+
:root:not([data-theme="light"]) .interaction-type{background:rgba(52,211,153,.14);color:#34d399}
351+
:root:not([data-theme="light"]) .interaction-flow{background:rgba(255,255,255,.04)}
352+
:root:not([data-theme="light"]) .evidence-item{background:rgba(251,191,36,.10);border-left-color:#fbbf24}
353+
:root:not([data-theme="light"]) .empty-state{background:rgba(255,255,255,.03);border-color:#2a3142;color:#99a2b5}
354+
:root:not([data-theme="light"]) .role-badge{background:rgba(180,153,240,.16);color:#c4b5fd}
355+
}
356+
:root[data-theme="dark"]{--primary:#6ea6f0; --secondary:#99a2b5; --background:#101420; --card:#1a1f2e; --border:#2a3142; --text:#e8ecf4; --text-muted:#99a2b5; --success:#34d399; --warning:#fbbf24; --net-label:#cbd5e1;}
357+
:root[data-theme="dark"] header{background:linear-gradient(135deg,#1d2740,#101420);border-bottom-color:#2a3142}
358+
:root[data-theme="dark"] th{background:#232a3d}
359+
:root[data-theme="dark"] .interaction-type{background:rgba(52,211,153,.14);color:#34d399}
360+
:root[data-theme="dark"] .interaction-flow{background:rgba(255,255,255,.04)}
361+
:root[data-theme="dark"] .evidence-item{background:rgba(251,191,36,.10);border-left-color:#fbbf24}
362+
:root[data-theme="dark"] .empty-state{background:rgba(255,255,255,.03);border-color:#2a3142;color:#99a2b5}
363+
:root[data-theme="dark"] .role-badge{background:rgba(180,153,240,.16);color:#c4b5fd}
364+
@media (prefers-reduced-motion: reduce){
365+
*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important;}
366+
}
367+
</style>
346368
</head>
347369
<body>
348370
<header>
@@ -2014,15 +2036,15 @@ <h2>Environmental Factors</h2>
20142036
.attr("text-anchor", "middle")
20152037
.attr("dy", function(d) { return d.abundance === "DOMINANT" ? 30 : 24; })
20162038
.attr("font-size", "10px")
2017-
.attr("fill", "#475569");
2039+
.style("fill", "var(--net-label, #475569)");
20182040

20192041
// Labels for interactions (multi-line, centered in rectangle)
20202042
node.filter(function(d) { return d.type === "interaction"; })
20212043
.each(function(d) {
20222044
var textElem = d3.select(this).append("text")
20232045
.attr("text-anchor", "middle")
20242046
.attr("font-size", "9px")
2025-
.attr("fill", "#475569")
2047+
.style("fill", "var(--net-label, #475569)")
20262048
.style("pointer-events", "none");
20272049

20282050
// Word-wrap text to fit in rectangle (max ~24 chars per line)
@@ -2140,5 +2162,6 @@ <h2>Environmental Factors</h2>
21402162
})();
21412163
</script>
21422164

2165+
<script src="../theme-toggle.js"></script>
21432166
</body>
21442167
</html>

docs/communities/AMD_Nitrososphaerota_Archaeal.html

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,29 @@
342342
.network-tooltip strong {
343343
color: #93c5fd;
344344
}
345-
</style>
345+
/* ---- Dark theme (OS default; superseded by the toggle) ---- */
346+
@media (prefers-color-scheme: dark){
347+
:root:not([data-theme="light"]){--primary:#6ea6f0; --secondary:#99a2b5; --background:#101420; --card:#1a1f2e; --border:#2a3142; --text:#e8ecf4; --text-muted:#99a2b5; --success:#34d399; --warning:#fbbf24; --net-label:#cbd5e1;}
348+
:root:not([data-theme="light"]) header{background:linear-gradient(135deg,#1d2740,#101420);border-bottom-color:#2a3142}
349+
:root:not([data-theme="light"]) th{background:#232a3d}
350+
:root:not([data-theme="light"]) .interaction-type{background:rgba(52,211,153,.14);color:#34d399}
351+
:root:not([data-theme="light"]) .interaction-flow{background:rgba(255,255,255,.04)}
352+
:root:not([data-theme="light"]) .evidence-item{background:rgba(251,191,36,.10);border-left-color:#fbbf24}
353+
:root:not([data-theme="light"]) .empty-state{background:rgba(255,255,255,.03);border-color:#2a3142;color:#99a2b5}
354+
:root:not([data-theme="light"]) .role-badge{background:rgba(180,153,240,.16);color:#c4b5fd}
355+
}
356+
:root[data-theme="dark"]{--primary:#6ea6f0; --secondary:#99a2b5; --background:#101420; --card:#1a1f2e; --border:#2a3142; --text:#e8ecf4; --text-muted:#99a2b5; --success:#34d399; --warning:#fbbf24; --net-label:#cbd5e1;}
357+
:root[data-theme="dark"] header{background:linear-gradient(135deg,#1d2740,#101420);border-bottom-color:#2a3142}
358+
:root[data-theme="dark"] th{background:#232a3d}
359+
:root[data-theme="dark"] .interaction-type{background:rgba(52,211,153,.14);color:#34d399}
360+
:root[data-theme="dark"] .interaction-flow{background:rgba(255,255,255,.04)}
361+
:root[data-theme="dark"] .evidence-item{background:rgba(251,191,36,.10);border-left-color:#fbbf24}
362+
:root[data-theme="dark"] .empty-state{background:rgba(255,255,255,.03);border-color:#2a3142;color:#99a2b5}
363+
:root[data-theme="dark"] .role-badge{background:rgba(180,153,240,.16);color:#c4b5fd}
364+
@media (prefers-reduced-motion: reduce){
365+
*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important;}
366+
}
367+
</style>
346368
</head>
347369
<body>
348370
<header>
@@ -1768,15 +1790,15 @@ <h2>Environmental Factors</h2>
17681790
.attr("text-anchor", "middle")
17691791
.attr("dy", function(d) { return d.abundance === "DOMINANT" ? 30 : 24; })
17701792
.attr("font-size", "10px")
1771-
.attr("fill", "#475569");
1793+
.style("fill", "var(--net-label, #475569)");
17721794

17731795
// Labels for interactions (multi-line, centered in rectangle)
17741796
node.filter(function(d) { return d.type === "interaction"; })
17751797
.each(function(d) {
17761798
var textElem = d3.select(this).append("text")
17771799
.attr("text-anchor", "middle")
17781800
.attr("font-size", "9px")
1779-
.attr("fill", "#475569")
1801+
.style("fill", "var(--net-label, #475569)")
17801802
.style("pointer-events", "none");
17811803

17821804
// Word-wrap text to fit in rectangle (max ~24 chars per line)
@@ -1894,5 +1916,6 @@ <h2>Environmental Factors</h2>
18941916
})();
18951917
</script>
18961918

1919+
<script src="../theme-toggle.js"></script>
18971920
</body>
18981921
</html>

0 commit comments

Comments
 (0)