Mutation-XAI / ui_styles.py
nileshhanotia's picture
ui_styles.py
140a146 verified
"""
ui_styles.py
============
All CSS, theme, and HTML string constants.
Imported by ui_layout.py and app.py.
"""
import gradio as gr
# ── Gradio 6 theme (constructor args only β€” no .set()) ───────────────────────
THEME = gr.themes.Base(
primary_hue=gr.themes.colors.blue,
secondary_hue=gr.themes.colors.slate,
neutral_hue=gr.themes.colors.slate,
font=[gr.themes.GoogleFont("JetBrains Mono"), "monospace"],
font_mono=[gr.themes.GoogleFont("JetBrains Mono"), "monospace"],
)
# ── CSS (passed to demo.launch()) ────────────────────────────────────────────
CSS = """
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;600;700&family=Space+Grotesk:wght@300;400;600;700&display=swap');
html, body, .gradio-container { background: #080C14 !important; color: #C9D1D9 !important; }
.xai-header {
background: linear-gradient(160deg, #080C14 0%, #0D1117 50%, #0a1628 100%);
border-bottom: 1px solid #21262D;
padding: 2rem 2.5rem 1.4rem;
position: relative; overflow: hidden;
}
.xai-header::before {
content: '';
position: absolute; inset: 0;
background:
repeating-linear-gradient(0deg, transparent, transparent 39px, #21262D40 39px, #21262D40 40px),
repeating-linear-gradient(90deg, transparent, transparent 39px, #21262D30 39px, #21262D30 40px);
pointer-events: none;
}
.xai-inner { position: relative; z-index: 1; }
.xai-header h1 {
font-family: 'Space Grotesk', sans-serif;
font-size: 1.9rem; font-weight: 700;
letter-spacing: -0.04em; margin: 0 0 0.4rem; color: #E6EDF3; line-height: 1.1;
}
.xai-header h1 .ac {
background: linear-gradient(90deg, #58A6FF, #39D353);
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.xai-header .sub {
font-family: 'JetBrains Mono', monospace;
font-size: 0.70rem; color: #8B949E; letter-spacing: 0.04em; line-height: 1.9;
}
.badge {
display: inline-block; background: #161B22;
border: 1px solid #30363D; border-radius: 3px;
padding: 1px 7px; font-size: 0.62rem; color: #58A6FF;
letter-spacing: 0.06em; margin-right: 4px;
font-family: 'JetBrains Mono', monospace;
}
.sec {
display: flex; align-items: center; gap: 8px;
font-family: 'JetBrains Mono', monospace;
font-size: 0.58rem; font-weight: 600;
letter-spacing: 0.18em; text-transform: uppercase; color: #8B949E;
border-bottom: 1px solid #21262D;
padding-bottom: 0.45rem; margin-bottom: 0.9rem;
}
.sec .n { background: #21262D; border-radius: 3px; padding: 1px 6px; color: #58A6FF; font-size: 0.66rem; }
.expl-box {
border: 1px solid #58A6FF !important;
border-left: 3px solid #58A6FF !important;
border-radius: 6px !important;
background: rgba(88,166,255,0.04) !important;
}
.run-btn > button {
background: linear-gradient(135deg,#1f6feb,#388bfd) !important;
border: none !important; border-radius: 5px !important;
color: #fff !important; font-weight: 700 !important;
font-family: 'JetBrains Mono', monospace !important;
font-size: 0.86rem !important; letter-spacing: 0.05em !important;
padding: 0.7rem 1.4rem !important;
transition: transform 0.15s, box-shadow 0.15s !important;
}
.run-btn > button:hover {
transform: translateY(-2px) !important;
box-shadow: 0 6px 20px rgba(88,166,255,0.28) !important;
}
.gradio-markdown table { width: 100%; border-collapse: collapse; font-family: 'JetBrains Mono', monospace; font-size: 0.79rem; }
.gradio-markdown th { background: #161B22 !important; color: #8B949E !important; font-size: 0.62rem; letter-spacing: 0.10em; text-transform: uppercase; padding: 0.42rem 0.75rem; border: 1px solid #21262D; }
.gradio-markdown td { padding: 0.40rem 0.75rem; border: 1px solid #21262D; color: #C9D1D9; }
.gradio-markdown code { background: #161B22; padding: 1px 6px; border-radius: 3px; color: #39D353; font-family: 'JetBrains Mono', monospace; font-size: 0.82em; }
.xai-footer { font-family: 'JetBrains Mono', monospace; font-size: 0.60rem; color: #484F58; text-align: center; padding: 1rem 0 0.5rem; border-top: 1px solid #21262D; letter-spacing: 0.04em; line-height: 2; }
"""
# ── HTML blocks ───────────────────────────────────────────────────────────────
HEADER_HTML = """
<div class="xai-header">
<div class="xai-inner">
<h1>Mutation <span class="ac">Explainability</span><br>Intelligence System</h1>
<div class="sub">
<span class="badge">3-MODEL ENSEMBLE</span>
<span class="badge">EXPLANATION FIRST</span>
<span class="badge">XAI</span>
<br>
conv3 activations Β· gradient attribution Β· counterfactual Β· feature ablation Β· splice distance Β· cross-model locality
</div>
</div>
</div>
"""
FOOTER_HTML = """
<div class="xai-footer">
nileshhanotia / mutation-predictor-splice Β· mutation-predictor-v4 Β· mutation-pathogenicity-predictor<br>
For Research Use Only Β· Not for Clinical Diagnosis
</div>
"""
def sec(num: str, label: str, mt: str = "0") -> str:
s = f' style="margin-top:{mt}"' if mt != "0" else ""
return f'<div class="sec"{s}><span class="n">{num}</span>{label}</div>'