Shape2Force / static /s2f_styles.css
kaveh's picture
optimised, removed dead codes
fd5af45
/* === Accent variables (fixed teal; used by buttons, sidebar focus, etc.) === */
:root {
--s2f-primary: #0d9488;
--s2f-primary-dark: #0f766e;
--s2f-primary-darker: #115e59;
--s2f-primary-rgb: 13, 148, 136;
/* Space for Streamlit’s fixed top toolbar (Deploy / menu). Set when header exists (see below). */
--s2f-streamlit-header-offset: 0px;
/* Sidebar grouped blocks: faint surface, no heavy chrome */
--s2f-sidebar-panel-bg: rgba(255, 255, 255, 0.42);
--s2f-sidebar-panel-border: rgba(203, 213, 225, 0.34);
/* Match Streamlit’s sidebar horizontal padding so panels can full-bleed the track */
--s2f-sidebar-inline-inset: 1rem;
--s2f-sidebar-width: 360px;
}
/* Streamlit renders a fixed header; without this offset, the sidebar and first main block sit underneath it. */
.stApp:has(header[data-testid="stHeader"]) {
--s2f-streamlit-header-offset: 2rem;
}
/* === Typography === */
html, body, .stApp {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}
/*
* Scroll layout (local app + HF iframe):
* - Lock document scroll so only one vertical scrollbar exists inside the app (avoids double scrollbars
* when the Space is embedded and the iframe has a fixed height).
* - The main column is the scroll container; the sidebar stays fixed beside it while main content scrolls.
* - Requires matching --s2f-streamlit-header-offset so fixed sidebar/top padding clear Streamlit’s toolbar.
*/
html, body {
height: 100% !important;
overflow: hidden !important;
margin: 0 !important;
}
/* App shell: flex column, dot grid background */
.stApp {
height: 100vh !important;
max-height: 100dvh !important;
overflow: hidden !important;
display: flex !important;
flex-direction: column !important;
background-color: #fafbfc !important;
background-image:
radial-gradient(circle at 1px 1px, rgba(148, 163, 184, 0.12) 1px, transparent 0);
background-size: 28px 28px !important;
background-position: 0 0, 0 0 !important;
}
/* Flex row: sidebar + main */
.stApp > div {
display: flex !important;
flex: 1 !important;
min-height: 0 !important;
overflow: hidden !important;
}
/* Soft gradient overlay for depth */
.stApp::before {
content: '';
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
radial-gradient(ellipse 80% 50% at 70% -20%, rgba(var(--s2f-primary-rgb), 0.06) 0%, transparent 50%),
radial-gradient(ellipse 60% 40% at 0% 100%, rgba(var(--s2f-primary-rgb), 0.04) 0%, transparent 50%);
pointer-events: none;
z-index: 0;
}
/* Ensure content sits above background */
.stApp > div,
.block-container,
section[data-testid="stSidebar"] {
position: relative;
z-index: 1;
}
/* === Header banner === */
.s2f-header {
background:
/* Subtle grid overlay (drawn on top) */
linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px),
linear-gradient(135deg, var(--s2f-primary) 0%, var(--s2f-primary-dark) 40%, var(--s2f-primary-darker) 100%);
background-size: 20px 20px, 20px 20px, 100% 100%;
padding: 1.1rem 1.5rem 1rem;
border-radius: 12px;
margin-bottom: 0.5rem;
color: white;
position: relative;
overflow: hidden;
box-shadow: 0 4px 20px rgba(var(--s2f-primary-rgb), 0.25);
}
.s2f-header::before {
content: '';
position: absolute;
top: -50%;
right: -15%;
width: 300px;
height: 300px;
background: radial-gradient(circle, rgba(255,255,255,0.08) 0%, transparent 70%);
border-radius: 50%;
}
.s2f-header::after {
content: '';
position: absolute;
bottom: -30%;
left: 10%;
width: 200px;
height: 200px;
background: radial-gradient(circle, rgba(255,255,255,0.05) 0%, transparent 70%);
border-radius: 50%;
}
.s2f-header h1 {
font-size: 1.85rem !important;
font-weight: 700 !important;
margin: 0 0 0.35rem !important;
color: white !important;
letter-spacing: -0.02em;
position: relative;
z-index: 1;
}
.s2f-header p {
font-size: 0.95rem !important;
color: rgba(255,255,255,0.85) !important;
margin: 0 !important;
font-weight: 400;
position: relative;
z-index: 1;
}
/* === Sidebar === */
section[data-testid="stSidebar"] {
position: fixed !important;
top: var(--s2f-streamlit-header-offset, 0px) !important;
left: 0 !important;
width: var(--s2f-sidebar-width) !important;
height: calc(100dvh - var(--s2f-streamlit-header-offset, 0px)) !important;
max-height: calc(100dvh - var(--s2f-streamlit-header-offset, 0px)) !important;
overflow-x: hidden !important;
overflow-y: auto !important;
scrollbar-gutter: stable !important;
background:
linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%),
/* Subtle vertical rhythm */
repeating-linear-gradient(
90deg,
transparent,
transparent 89px,
rgba(203, 213, 225, 0.25) 89px,
rgba(203, 213, 225, 0.25) 90px
) !important;
border-right: 1px solid #e2e8f0 !important;
}
@media (max-width: 768px) {
section[data-testid="stSidebar"] { width: 100% !important; max-width: 100% !important; }
[data-testid="stAppViewContainer"],
.appview-container .main {
margin-left: 0 !important;
}
}
section[data-testid="stSidebar"] [data-testid="stWidgetLabel"],
section[data-testid="stSidebar"] [data-testid="stWidgetLabel"] p {
font-size: 0.9rem !important;
font-weight: 500 !important;
color: #334155 !important;
}
.sidebar-brand {
display: flex;
align-items: center;
gap: 10px;
padding-bottom: 0.65rem;
margin-bottom: 0.35rem;
}
.sidebar-brand .brand-text {
font-size: 1.1rem;
font-weight: 700;
color: var(--s2f-primary-dark);
letter-spacing: -0.01em;
}
/*
* Sidebar panels (model+ckp, conditions, force scale): horizontal bands — faded fill
* with top/bottom dividers; stretch edge-to-edge in the sidebar (bleed past content padding).
*/
section[data-testid="stSidebar"] .st-key-s2f_grp_model,
section[data-testid="stSidebar"] .st-key-s2f_grp_conditions,
section[data-testid="stSidebar"] .st-key-s2f_grp_force {
box-sizing: border-box !important;
margin-left: calc(-1 * var(--s2f-sidebar-inline-inset)) !important;
margin-right: calc(-1 * var(--s2f-sidebar-inline-inset)) !important;
margin-bottom: 0.45rem !important;
width: calc(100% + 2 * var(--s2f-sidebar-inline-inset)) !important;
max-width: none !important;
padding: 0.58rem var(--s2f-sidebar-inline-inset) 0.62rem !important;
border-radius: 0 !important;
background: var(--s2f-sidebar-panel-bg) !important;
border: none !important;
border-top: 1px solid var(--s2f-sidebar-panel-border) !important;
border-bottom: 1px solid var(--s2f-sidebar-panel-border) !important;
box-shadow: none !important;
}
/* Inner layout flex — no inner frame */
section[data-testid="stSidebar"] .st-key-s2f_grp_model > div,
section[data-testid="stSidebar"] .st-key-s2f_grp_conditions > div,
section[data-testid="stSidebar"] .st-key-s2f_grp_force > div {
border: none !important;
box-shadow: none !important;
background: transparent !important;
}
/* === Metric cards === */
[data-testid="stMetric"] {
background: linear-gradient(145deg, #ffffff 0%, #f8fafc 100%);
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 0.85rem 1rem !important;
box-shadow: 0 1px 4px rgba(0,0,0,0.06);
transition: box-shadow 0.2s ease, transform 0.2s ease;
}
[data-testid="stMetric"]:hover {
box-shadow: 0 4px 14px rgba(0,0,0,0.1);
transform: translateY(-1px);
}
[data-testid="stMetric"] label {
font-size: 0.75rem !important;
font-weight: 600 !important;
color: #64748b !important;
text-transform: uppercase;
letter-spacing: 0.04em;
}
[data-testid="stMetric"] [data-testid="stMetricValue"] {
font-size: 1.25rem !important;
font-weight: 700 !important;
color: var(--s2f-primary-dark) !important;
}
/* === Buttons === */
.stButton > button[kind="primary"], button[kind="primary"] {
background: linear-gradient(135deg, var(--s2f-primary), var(--s2f-primary-dark)) !important;
border: none !important;
border-radius: 10px !important;
font-weight: 600 !important;
letter-spacing: 0.02em !important;
box-shadow: 0 2px 10px rgba(var(--s2f-primary-rgb), 0.3) !important;
transition: all 0.2s ease !important;
}
.stButton > button[kind="primary"]:hover, button[kind="primary"]:hover {
background: linear-gradient(135deg, var(--s2f-primary-dark), var(--s2f-primary-darker)) !important;
box-shadow: 0 4px 18px rgba(var(--s2f-primary-rgb), 0.4) !important;
transform: translateY(-1px) !important;
}
.stButton > button:not([kind="primary"]) {
border-radius: 10px !important;
font-weight: 500 !important;
border: 1px solid #cbd5e1 !important;
transition: all 0.2s ease !important;
}
.stButton > button:not([kind="primary"]):hover {
border-color: var(--s2f-primary) !important;
color: var(--s2f-primary) !important;
background: rgba(var(--s2f-primary-rgb), 0.04) !important;
}
[data-testid="stDownloadButton"] button {
border-radius: 10px !important;
font-weight: 500 !important;
transition: all 0.2s ease !important;
}
[data-testid="stDownloadButton"] button:hover {
border-color: var(--s2f-primary) !important;
color: var(--s2f-primary) !important;
}
/* === Action buttons row (measure + downloads) === */
div[data-testid="stHorizontalBlock"]:has([data-testid="stDownloadButton"]):has([data-testid="stButton"]) {
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 14px;
padding: 0.65rem 0.6rem !important;
margin-top: 0.5rem;
gap: 0.5rem !important;
}
div[data-testid="stHorizontalBlock"]:has([data-testid="stDownloadButton"]):has([data-testid="stButton"]) > div {
flex: 1 1 0 !important; min-width: 0 !important;
}
div[data-testid="stHorizontalBlock"]:has([data-testid="stDownloadButton"]):has([data-testid="stButton"]) button {
width: 100% !important;
min-width: 0 !important;
white-space: nowrap !important;
border-radius: 10px !important;
font-size: 0.82rem !important;
font-weight: 600 !important;
padding: 0.55rem 0.8rem !important;
letter-spacing: 0.01em !important;
}
div[data-testid="stHorizontalBlock"]:has([data-testid="stDownloadButton"]):has([data-testid="stButton"]) > div:nth-child(1) button {
background: linear-gradient(135deg, var(--s2f-primary), var(--s2f-primary-dark)) !important;
color: white !important;
border-color: transparent !important;
box-shadow: 0 2px 8px rgba(var(--s2f-primary-rgb), 0.25) !important;
}
div[data-testid="stHorizontalBlock"]:has([data-testid="stDownloadButton"]):has([data-testid="stButton"]) > div:nth-child(1) button:hover {
background: linear-gradient(135deg, var(--s2f-primary-dark), var(--s2f-primary-darker)) !important;
box-shadow: 0 4px 14px rgba(var(--s2f-primary-rgb), 0.35) !important;
transform: translateY(-1px) !important;
}
div[data-testid="stHorizontalBlock"]:has([data-testid="stDownloadButton"]):has([data-testid="stButton"]) [data-testid="stDownloadButton"] button {
background: white !important;
border: 1px solid #e2e8f0 !important;
color: #334155 !important;
box-shadow: 0 1px 2px rgba(0,0,0,0.04) !important;
}
div[data-testid="stHorizontalBlock"]:has([data-testid="stDownloadButton"]):has([data-testid="stButton"]) [data-testid="stDownloadButton"] button:hover {
background: rgba(var(--s2f-primary-rgb), 0.06) !important;
border-color: var(--s2f-primary) !important;
color: var(--s2f-primary-dark) !important;
box-shadow: 0 2px 6px rgba(var(--s2f-primary-rgb), 0.12) !important;
transform: translateY(-1px) !important;
}
/* === Expanders === */
.stExpander {
border: 1px solid #e2e8f0 !important;
border-radius: 12px !important;
overflow: hidden;
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}
/* === File uploader === */
[data-testid="stFileUploader"] section {
border: 2px dashed #cbd5e1 !important;
border-radius: 12px !important;
transition: border-color 0.2s ease;
}
[data-testid="stFileUploader"] section:hover {
border-color: var(--s2f-primary) !important;
}
/* === Result labels === */
.result-label {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.92rem;
font-weight: 600;
color: #334155;
padding: 0.4rem 0;
}
.result-badge {
font-size: 0.68rem;
font-weight: 700;
padding: 2px 8px;
border-radius: 4px;
letter-spacing: 0.06em;
}
.result-badge.input {
background: #e2e8f0;
color: #475569;
}
.result-badge.output {
background: rgba(var(--s2f-primary-rgb), 0.15);
color: var(--s2f-primary-dark);
}
/* === Run prediction info bar === */
.run-info {
display: flex;
align-items: center;
gap: 10px;
height: 42px;
font-size: 0.85rem;
color: #64748b;
}
.run-info-tag {
background: rgba(var(--s2f-primary-rgb), 0.1);
color: var(--s2f-primary-dark);
font-weight: 600;
font-size: 0.78rem;
padding: 3px 10px;
border-radius: 6px;
}
.run-info code {
background: #f1f5f9;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.8rem;
color: #475569;
}
/* === Messages === */
.stSuccess {
background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%) !important;
border-left: 4px solid #10b981 !important;
border-radius: 8px !important;
}
.stWarning { border-radius: 8px !important; }
.stInfo { border-radius: 8px !important; }
/* === Selectbox, multiselect, toggle (accent on focus) === */
[data-testid="stSelectbox"] > div > div,
[data-testid="stSelectbox"] input,
[data-testid="stMultiSelect"] > div > div {
color: #1e293b !important;
background-color: #ffffff !important;
}
/* Multiselect input: transparent so it doesn't show as a white block before the tags */
[data-testid="stMultiSelect"] input {
background-color: transparent !important;
color: #1e293b !important;
min-width: 2ch !important;
}
[data-testid="stSelectbox"] > div > div,
[data-testid="stMultiSelect"] > div > div {
border-radius: 8px !important;
border: 1px solid #cbd5e1 !important;
transition: border-color 0.15s ease, box-shadow 0.15s ease !important;
}
section[data-testid="stSidebar"] [data-testid="stSelectbox"] > div > div:focus-within,
section[data-testid="stSidebar"] [data-testid="stMultiSelect"] > div > div:focus-within {
border-color: var(--s2f-primary) !important;
box-shadow: 0 0 0 1px rgba(var(--s2f-primary-rgb), 0.28) !important;
}
/* Radio: accent color */
[data-testid="stRadio"] input {
accent-color: var(--s2f-primary);
}
/* Toggle: on state uses --s2f-primary */
[data-testid="stToggle"] [data-baseweb="toggleTrack"] {
background-color: #cbd5e1 !important;
}
[data-testid="stToggle"] [data-baseweb="toggleTrack"][aria-checked="true"] {
background-color: var(--s2f-primary) !important;
}
[data-testid="stToggle"] [data-baseweb="toggleTrack"][data-state="checked"] {
background-color: var(--s2f-primary) !important;
}
[data-testid="stToggle"] [data-baseweb="toggleTrack"][data-state="unchecked"] {
background-color: #cbd5e1 !important;
}
/* Newer Streamlit may render a switch button instead of Base Web track */
[data-testid="stToggle"] button[role="switch"][aria-checked="true"] {
background-color: var(--s2f-primary) !important;
}
[data-testid="stToggle"] button[role="switch"][aria-checked="false"] {
background-color: #cbd5e1 !important;
}
/* Dropdown options: ensure visible text on light background */
[role="listbox"] [role="option"],
[data-baseweb="menu"] li,
ul[role="listbox"] li {
color: #1e293b !important;
background-color: #ffffff !important;
}
/* Sidebar / form labels (colormap row, section titles) */
.s2f-form-label {
font-size: 0.95rem;
font-weight: 500;
color: #334155;
line-height: 1.2;
margin: 0;
}
.s2f-form-label--colormap {
padding-top: 0.4rem;
}
.s2f-form-label--section {
margin-bottom: 0.5rem;
}
/* === Dataframe === */
[data-testid="stDataFrame"] {
border-radius: 10px !important;
overflow: hidden;
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
/* === Batch colorbar (minimal, no box) === */
.colorbar-table-header {
width: 100%;
margin-bottom: 0.5rem;
padding: 0;
background: transparent;
border: none;
box-shadow: none;
}
.colorbar-ticks {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
padding: 0 1px;
font-size: 0.65rem;
font-weight: 600;
color: #64748b;
letter-spacing: 0.03em;
}
.colorbar-ticks .cb-tick {
font-variant-numeric: tabular-nums;
}
.colorbar-bar {
width: 100%;
height: 6px;
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
border-radius: 3px;
box-shadow: inset 0 1px 1px rgba(0,0,0,0.05);
}
/* === Divider === */
hr { border-color: #cbd5e1 !important; opacity: 0.7; }
/* === Plotly chart === */
.stPlotlyChart { border-radius: 12px; overflow: hidden; }
/* === Footer citation === */
.footer-citation {
position: fixed;
bottom: 0;
left: var(--s2f-sidebar-width);
right: 0;
z-index: 999;
padding: 0.5rem 1rem 0.55rem;
background: #f1f5f9;
border-top: 1px solid #e2e8f0;
font-size: 0.7rem;
color: #64748b;
text-align: center;
line-height: 1.45;
}
/*
* Main column: horizontal offset for fixed sidebar + vertical scroll only here.
* Header offset is on stMain only (avoids doubling if container and .main both match).
*/
[data-testid="stAppViewContainer"],
.appview-container .main {
margin-left: var(--s2f-sidebar-width) !important;
flex: 1 !important;
min-height: 0 !important;
overflow-y: auto !important;
overflow-x: hidden !important;
scrollbar-gutter: stable !important;
-webkit-overflow-scrolling: touch !important;
box-sizing: border-box !important;
}
/* Clear Streamlit’s fixed toolbar so the custom banner / first widgets aren’t clipped */
section[data-testid="stMain"] {
padding-top: var(--s2f-streamlit-header-offset, 0px) !important;
box-sizing: border-box !important;
}
.block-container {
padding-top: 0.75rem !important;
padding-bottom: 3.25rem !important;
max-width: 1050px !important;
}
section[data-testid="stSidebar"] > div:first-child {
padding-top: 0.85rem !important;
padding-bottom: 0.5rem !important;
}
/* Measure tool: value panel (replaces inline styles in measure_tool.py) */
.s2f-measure-vals-heading {
font-weight: 400;
color: #334155;
font-size: 0.95rem;
margin: 0 20px 4px 4px;
}
.s2f-measure-vals-panel {
width: 100%;
box-sizing: border-box;
border: 1px solid #e2e8f0;
border-radius: 10px;
padding: 10px 12px;
margin: 0 10px 20px 10px;
background: linear-gradient(145deg, #f8fafc 0%, #f1f5f9 100%);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}
.s2f-measure-vals-grid {
display: flex;
flex-wrap: wrap;
gap: 5px;
font-size: 0.9rem;
}
/* Dialog / expander: measure canvas layout */
[data-testid="stDialog"] [data-testid="stSelectbox"],
[data-testid="stExpander"] [data-testid="stSelectbox"],
[data-testid="stDialog"] [data-testid="stSelectbox"] > div,
[data-testid="stExpander"] [data-testid="stSelectbox"] > div {
width: 100% !important;
max-width: 100% !important;
}
[data-testid="stDialog"] [data-testid="stMetric"] label,
[data-testid="stDialog"] [data-testid="stMetric"] [data-testid="stMetricValue"],
[data-testid="stExpander"] [data-testid="stMetric"] label,
[data-testid="stExpander"] [data-testid="stMetric"] [data-testid="stMetricValue"] {
font-size: 0.95rem !important;
}
[data-testid="stDialog"] img,
[data-testid="stExpander"] img {
border-radius: 0 !important;
}
/* === Responsive === */
@media (max-width: 768px) {
.s2f-header {
padding: 1.5rem;
border-radius: 12px;
}
.s2f-header h1 {
font-size: 1.4rem !important;
}
.footer-citation {
left: 0 !important;
padding-left: 0.75rem !important;
padding-right: 0.75rem !important;
}
}