Download utils/css.py from nsrek/ECGLight: direct link, hf CLI and curl.
- Browser
- Download file 4.93 kB
-
https://huggingface.co/nsrek/ECGLight/resolve/refs%2Fpr%2F1/utils/css.py
- Command line
-
hf download hf://nsrek/ECGLight@refs/pr/1/utils/css.py
-
curl -L -o css.py https://huggingface.co/nsrek/ECGLight/resolve/refs%2Fpr%2F1/utils/css.py
4.93 kB
| # utils/css.py | |
| """ | |
| Centralized CSS theming for the ECG Dashboard. | |
| Injects the complete light clinical theme stylesheet. | |
| """ | |
| import streamlit as st | |
| def inject_custom_css(): | |
| """Inject the full custom CSS theme into the Streamlit page.""" | |
| st.markdown(""" | |
| <style> | |
| /* ===== Light clinical theme variables ===== */ | |
| :root { | |
| --accent: #E63946; | |
| --accent-light: #FFF1F2; | |
| --accent-dark: #BE1622; | |
| --teal: #0D9488; | |
| --teal-light: #CCFBF1; | |
| --card-bg: #FFFFFF; | |
| --card-border: #E2E8F0; | |
| --card-shadow: rgba(15, 23, 42, 0.06); | |
| --text-primary: #1E293B; | |
| --text-secondary: #64748B; | |
| --text-muted: #94A3B8; | |
| --bg-main: #F8FAFC; | |
| --bg-grid-major: rgba(226, 232, 240, 0.5); | |
| --bg-grid-minor: rgba(226, 232, 240, 0.25); | |
| } | |
| /* ===== Global: clean white with subtle ECG paper grid ===== */ | |
| .stApp { | |
| background-color: var(--bg-main) !important; | |
| background-image: | |
| linear-gradient(var(--bg-grid-major) 1px, transparent 1px), | |
| linear-gradient(90deg, var(--bg-grid-major) 1px, transparent 1px), | |
| linear-gradient(var(--bg-grid-minor) 0.5px, transparent 0.5px), | |
| linear-gradient(90deg, var(--bg-grid-minor) 0.5px, transparent 0.5px); | |
| background-size: 100px 100px, 100px 100px, 20px 20px, 20px 20px; | |
| background-attachment: fixed; | |
| } | |
| /* ===== Typography ===== */ | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap'); | |
| html, body, [class*="css"] { | |
| font-family: 'Inter', sans-serif; | |
| } | |
| /* ===== Header gradient text ===== */ | |
| .glow-text { | |
| background: linear-gradient(135deg, #E63946 0%, #D62828 40%, #0D9488 100%); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| color: transparent; | |
| font-weight: 800; | |
| letter-spacing: -0.5px; | |
| display: inline-block; | |
| } | |
| /* ===== Elevated white cards ===== */ | |
| .glass-card { | |
| background: var(--card-bg); | |
| border: 1px solid var(--card-border); | |
| border-radius: 14px; | |
| padding: 24px; | |
| margin-bottom: 20px; | |
| box-shadow: 0 1px 3px var(--card-shadow), 0 4px 16px var(--card-shadow); | |
| transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease; | |
| } | |
| .glass-card:hover { | |
| border-color: #CBD5E1; | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 20px rgba(15, 23, 42, 0.1); | |
| } | |
| /* ===== Subtitle ===== */ | |
| .section-subtitle { | |
| color: var(--text-secondary); | |
| font-size: 0.95rem; | |
| margin-top: -10px; | |
| margin-bottom: 25px; | |
| } | |
| /* ===== Metric cards ===== */ | |
| .metric-container { | |
| display: flex; | |
| justify-content: space-between; | |
| margin-bottom: 15px; | |
| flex-wrap: wrap; | |
| gap: 15px; | |
| } | |
| .metric-card { | |
| flex: 1; | |
| min-width: 140px; | |
| background: linear-gradient(135deg, #FFF1F2 0%, #FFFFFF 100%); | |
| border: 1px solid #FECDD3; | |
| border-radius: 12px; | |
| padding: 18px; | |
| text-align: center; | |
| transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease; | |
| } | |
| .metric-card:hover { | |
| border-color: var(--accent); | |
| box-shadow: 0 4px 16px rgba(230, 57, 70, 0.12); | |
| transform: translateY(-2px); | |
| } | |
| .metric-label { | |
| font-size: 0.75rem; | |
| color: var(--text-muted); | |
| text-transform: uppercase; | |
| letter-spacing: 1.2px; | |
| margin-bottom: 6px; | |
| font-weight: 600; | |
| } | |
| .metric-value { | |
| font-size: 1.8rem; | |
| font-weight: 800; | |
| background: linear-gradient(135deg, #E63946, #0D9488); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| } | |
| /* ===== Sidebar ===== */ | |
| section[data-testid="stSidebar"] { | |
| background-color: #FFFFFF !important; | |
| border-right: 1px solid #E2E8F0 !important; | |
| } | |
| section[data-testid="stSidebar"] .stRadio label { | |
| color: var(--text-primary) !important; | |
| } | |
| /* ===== Buttons ===== */ | |
| .stButton > button { | |
| background: linear-gradient(135deg, #E63946 0%, #D62828 100%) !important; | |
| color: #FFFFFF !important; | |
| border: none !important; | |
| border-radius: 10px !important; | |
| font-weight: 600 !important; | |
| padding: 0.6rem 1.2rem !important; | |
| transition: transform 0.15s ease, box-shadow 0.15s ease !important; | |
| } | |
| .stButton > button:hover { | |
| transform: translateY(-1px) !important; | |
| box-shadow: 0 6px 20px rgba(230, 57, 70, 0.3) !important; | |
| } | |
| /* ===== Notifications ===== */ | |
| div[data-testid="stNotification"] { | |
| border-radius: 10px !important; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |