/* === 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; } }