| """ |
| OIRseg Theme β Dark Gold Glassmorphism |
| Inspired by aged stone / weathered metal with champagne gold accents. |
| """ |
|
|
| import streamlit as st |
| import streamlit.components.v1 as components |
|
|
| |
| GOLD = "#C5A55A" |
| GOLD_BRIGHT = "#D4B96A" |
| GOLD_LIGHT = "#E8D5A3" |
| GOLD_DARK = "#8B7635" |
| GOLD_MUTED = "#9A8B6F" |
| BG_DEEP = "#0c0a08" |
| TEXT_BODY = "#BFB39A" |
|
|
|
|
| def inject_theme(): |
| """Call once after st.set_page_config to apply the full custom theme.""" |
| st.markdown( |
| '<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:' |
| "ital,wght@0,400..900;1,400..900&family=Inter:wght@300;400;500;600" |
| '&display=swap" rel="stylesheet">', |
| unsafe_allow_html=True, |
| ) |
| st.markdown(_CSS, unsafe_allow_html=True) |
| components.html(_JS, height=0) |
|
|
|
|
| |
|
|
|
|
| def page_header(title: str, subtitle: str, caption: str): |
| st.markdown( |
| f""" |
| <div style="padding:0.5rem 0 0.8rem 0;position:relative;"> |
| <div style="display:flex;align-items:center;gap:0.7rem;margin-bottom:0.35rem;"> |
| <span style=" |
| display:inline-flex;align-items:center;justify-content:center; |
| width:30px;height:30px;border-radius:50%; |
| border:1px solid rgba(197,165,90,0.45); |
| color:{GOLD};font-size:0.85rem; |
| ">β¦</span> |
| <h1 style=" |
| margin:0;padding:0; |
| font-family:'Playfair Display',serif; |
| font-size:2.6rem;font-weight:700;font-style:italic; |
| background:linear-gradient(135deg,{GOLD_LIGHT},{GOLD},{GOLD_DARK}); |
| -webkit-background-clip:text;-webkit-text-fill-color:transparent; |
| background-clip:text; |
| ">{title}</h1> |
| </div> |
| <p style=" |
| color:{GOLD_MUTED};font-family:'Inter',sans-serif; |
| font-size:0.85rem;letter-spacing:0.12em;text-transform:uppercase; |
| margin:0 0 1rem 2.9rem;font-weight:400; |
| ">{subtitle}</p> |
| <div style="height:1px;background:linear-gradient(90deg,{GOLD},rgba(197,165,90,0.12),transparent);margin-bottom:0.55rem;"></div> |
| <p style=" |
| color:#5A5345;font-family:'Inter',sans-serif; |
| font-size:0.7rem;letter-spacing:0.12em;text-transform:uppercase;margin:0; |
| ">{caption}</p> |
| </div> |
| """, |
| unsafe_allow_html=True, |
| ) |
|
|
|
|
| def section_header(title: str): |
| st.markdown( |
| f""" |
| <div style="margin:2rem 0 1rem 0;"> |
| <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.45rem;"> |
| <span style="color:{GOLD};font-size:0.8rem;">β¦</span> |
| <h3 style=" |
| margin:0;padding:0; |
| font-family:'Playfair Display',serif; |
| color:{GOLD_LIGHT};font-weight:600;font-size:1.35rem; |
| ">{title}</h3> |
| </div> |
| <div style="height:1px;background:linear-gradient(90deg,rgba(197,165,90,0.5),rgba(197,165,90,0.08),transparent);max-width:400px;"></div> |
| </div> |
| """, |
| unsafe_allow_html=True, |
| ) |
|
|
|
|
| def gold_divider(): |
| st.markdown( |
| f'<div style="height:1px;margin:1.5rem 0;background:linear-gradient(90deg,transparent,{GOLD_DARK},{GOLD},{GOLD_DARK},transparent);"></div>', |
| unsafe_allow_html=True, |
| ) |
|
|
|
|
| def sidebar_legend(items: list): |
| """items: [(label, description, (r_float, g_float, b_float)), ...]""" |
| for label, desc, rgb in items: |
| r, g, b = (int(c * 255) for c in rgb) |
| st.sidebar.markdown( |
| f""" |
| <div style="display:flex;align-items:center;gap:10px;margin:7px 0;"> |
| <div style=" |
| width:13px;height:13px;border-radius:50%;flex-shrink:0; |
| background:rgb({r},{g},{b}); |
| border:1px solid rgba(197,165,90,0.3); |
| box-shadow:0 0 8px rgba({r},{g},{b},0.35); |
| "></div> |
| <span style="color:{GOLD_MUTED};font-size:0.82rem;font-family:'Inter',sans-serif;"> |
| <strong style="color:{GOLD_LIGHT};">{label}</strong> β {desc} |
| </span> |
| </div> |
| """, |
| unsafe_allow_html=True, |
| ) |
|
|
|
|
| def sidebar_status(text: str): |
| st.sidebar.markdown( |
| f""" |
| <div style=" |
| background:rgba(197,165,90,0.08); |
| border:1px solid rgba(197,165,90,0.25); |
| border-radius:8px;padding:0.55rem 0.8rem;margin-bottom:0.5rem; |
| color:{GOLD_LIGHT};font-family:'Inter',sans-serif;font-size:0.82rem; |
| display:flex;align-items:center;gap:8px; |
| "> |
| <span style="color:{GOLD};font-size:0.7rem;">β¦</span> {text} |
| </div> |
| """, |
| unsafe_allow_html=True, |
| ) |
|
|
|
|
| |
| |
| |
|
|
| _CSS = """<style> |
| /* ββ Palette variables ββ */ |
| :root{ |
| --bg-deep:#0c0a08;--bg-primary:#141210;--bg-secondary:#1c1917; |
| --bg-card:rgba(22,19,16,0.75);--bg-card-hover:rgba(30,26,22,0.88); |
| --gold:#C5A55A;--gold-bright:#D4B96A;--gold-light:#E8D5A3; |
| --gold-dark:#8B7635;--gold-muted:#9A8B6F; |
| --border-gold:rgba(197,165,90,0.22);--border-gold-s:rgba(197,165,90,0.48); |
| --text-primary:#E8D5A3;--text-body:#BFB39A;--text-sec:#9A8B6F; |
| --glass-bg:rgba(20,18,14,0.62);--glass-shadow:rgba(0,0,0,0.4); |
| } |
| |
| /* ββ Background with grunge texture ββ */ |
| .stApp{ |
| background-color:var(--bg-deep)!important; |
| background-image: |
| url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='600' height='600' filter='url(%23n)' opacity='0.055'/%3E%3C/svg%3E"), |
| radial-gradient(ellipse at center,transparent 30%,rgba(0,0,0,0.55) 100%), |
| radial-gradient(ellipse at 15% 25%,rgba(75,50,22,0.09) 0%,transparent 50%), |
| radial-gradient(ellipse at 70% 65%,rgba(55,40,18,0.07) 0%,transparent 45%), |
| radial-gradient(ellipse at 45% 80%,rgba(65,45,20,0.08) 0%,transparent 55%), |
| radial-gradient(ellipse at 88% 12%,rgba(50,35,15,0.05) 0%,transparent 40%), |
| linear-gradient(170deg,#12100e 0%,#0c0a08 50%,#100e0c 100%); |
| background-attachment:fixed; |
| } |
| |
| /* ββ Hide Streamlit chrome ββ */ |
| [data-testid="stHeader"]{background:transparent!important;border:none!important} |
| #MainMenu,footer{visibility:hidden} |
| |
| /* ββ Typography ββ */ |
| .stApp{font-family:'Inter',sans-serif;color:var(--text-body)} |
| p,span,label,div,li,td,th{font-family:'Inter',sans-serif} |
| h1,h2,h3,.stApp h1,.stApp h2,.stApp h3{ |
| color:var(--gold-light)!important;font-weight:600!important;letter-spacing:.02em; |
| } |
| |
| /* ββ Sidebar ββ */ |
| [data-testid="stSidebar"]{ |
| background:linear-gradient(180deg,rgba(18,16,13,0.96),rgba(10,9,7,0.98))!important; |
| border-right:1px solid var(--border-gold)!important; |
| } |
| [data-testid="stSidebar"] [data-testid="stMarkdown"] p{color:var(--text-sec)!important} |
| [data-testid="stSidebar"] hr{border-color:var(--border-gold)!important} |
| [data-testid="stSidebar"] h1,[data-testid="stSidebar"] h2,[data-testid="stSidebar"] h3{ |
| font-family:'Playfair Display',serif!important;color:var(--gold)!important; |
| } |
| |
| /* ββ Sidebar collapse/expand button ββ */ |
| [data-testid="stSidebarCollapsedControl"], |
| [data-testid="collapsedControl"]{ |
| display:flex!important;visibility:visible!important;opacity:1!important; |
| } |
| button[data-testid="baseButton-headerNoPadding"], |
| [data-testid="stSidebarCollapsedControl"] button, |
| [data-testid="collapsedControl"] button{ |
| background:rgba(197,165,90,0.14)!important; |
| border:1px solid var(--border-gold-s)!important; |
| border-radius:10px!important; |
| color:var(--gold)!important; |
| width:36px!important;height:36px!important; |
| min-width:36px!important;min-height:36px!important; |
| padding:0!important; |
| position:relative!important; |
| transition:all .25s ease!important; |
| } |
| button[data-testid="baseButton-headerNoPadding"]:hover, |
| [data-testid="stSidebarCollapsedControl"] button:hover, |
| [data-testid="collapsedControl"] button:hover{ |
| background:rgba(197,165,90,0.28)!important; |
| border-color:var(--gold)!important; |
| box-shadow:0 0 18px rgba(197,165,90,0.25)!important; |
| } |
| /* Colour the existing Streamlit sidebar toggle SVG β no DOM surgery needed */ |
| button[data-testid="baseButton-headerNoPadding"] svg, |
| [data-testid="stSidebarCollapsedControl"] button svg, |
| [data-testid="collapsedControl"] button svg{ |
| color:var(--gold)!important; |
| stroke:var(--gold)!important; |
| fill:none!important; |
| } |
| |
| /* ββ Glassmorphism metric cards ββ */ |
| [data-testid="stMetric"]{ |
| background:var(--glass-bg)!important; |
| border:1px solid var(--border-gold)!important; |
| border-radius:12px!important;padding:1rem 1.2rem!important; |
| backdrop-filter:blur(16px)!important;-webkit-backdrop-filter:blur(16px)!important; |
| box-shadow:0 8px 32px var(--glass-shadow),inset 0 1px 0 rgba(197,165,90,0.07)!important; |
| transition:all .3s ease!important; |
| } |
| [data-testid="stMetric"]:hover{ |
| background:var(--bg-card-hover)!important; |
| border-color:var(--border-gold-s)!important; |
| box-shadow:0 12px 40px var(--glass-shadow),0 0 20px rgba(197,165,90,0.05)!important; |
| transform:translateY(-2px); |
| } |
| [data-testid="stMetricLabel"]{ |
| color:var(--gold)!important;font-family:'Playfair Display',serif!important; |
| font-size:.95rem!important;font-weight:600!important;letter-spacing:.06em; |
| } |
| [data-testid="stMetricValue"]{ |
| color:var(--gold-light)!important;font-family:'Playfair Display',serif!important;font-weight:700!important; |
| } |
| [data-testid="stMetricDelta"]{color:var(--gold-muted)!important} |
| |
| /* ββ Buttons ββ */ |
| .stButton>button{ |
| background:linear-gradient(135deg,rgba(197,165,90,0.14),rgba(197,165,90,0.04))!important; |
| border:1px solid var(--border-gold-s)!important; |
| color:var(--gold-light)!important;font-family:'Playfair Display',serif!important; |
| font-weight:600!important;font-size:1rem!important;letter-spacing:.05em; |
| border-radius:10px!important;padding:.6rem 1.5rem!important; |
| backdrop-filter:blur(12px)!important; |
| transition:all .3s cubic-bezier(.4,0,.2,1)!important; |
| box-shadow:0 4px 16px rgba(0,0,0,.3),inset 0 1px 0 rgba(197,165,90,.08)!important; |
| } |
| .stButton>button:hover{ |
| background:linear-gradient(135deg,rgba(197,165,90,.28),rgba(197,165,90,.12))!important; |
| border-color:var(--gold)!important; |
| box-shadow:0 8px 24px rgba(0,0,0,.4),0 0 25px rgba(197,165,90,.08)!important; |
| transform:translateY(-1px); |
| } |
| |
| /* Primary button β shimmer */ |
| @keyframes gold-shimmer{ |
| 0%{background-position:-200% center} |
| 100%{background-position:200% center} |
| } |
| button[data-testid="stBaseButton-primary"]{ |
| background:linear-gradient(90deg,#8B7635 0%,#C5A55A 25%,#D4B96A 50%,#C5A55A 75%,#8B7635 100%)!important; |
| background-size:200% 100%!important; |
| animation:gold-shimmer 4s ease-in-out infinite!important; |
| color:var(--bg-deep)!important;border:none!important;font-weight:700!important; |
| box-shadow:0 4px 20px rgba(197,165,90,.3),inset 0 1px 0 rgba(255,255,255,.1)!important; |
| } |
| button[data-testid="stBaseButton-primary"]:hover{ |
| box-shadow:0 8px 30px rgba(197,165,90,.45),inset 0 1px 0 rgba(255,255,255,.15)!important; |
| } |
| |
| /* Download buttons */ |
| .stDownloadButton>button{ |
| background:linear-gradient(135deg,rgba(197,165,90,.1),rgba(197,165,90,.03))!important; |
| border:1px solid var(--border-gold)!important;color:var(--gold-light)!important; |
| font-family:'Inter',sans-serif!important;font-weight:500!important; |
| border-radius:8px!important;backdrop-filter:blur(12px)!important;transition:all .3s ease!important; |
| } |
| .stDownloadButton>button:hover{ |
| background:linear-gradient(135deg,rgba(197,165,90,.22),rgba(197,165,90,.08))!important; |
| border-color:var(--gold)!important; |
| } |
| |
| /* ββ File Uploader β compact, expands on focus/drag ββ */ |
| [data-testid="stFileUploader"]{ |
| background:var(--glass-bg)!important; |
| border:1px solid var(--border-gold)!important; |
| border-radius:10px!important;padding:0.6rem 1rem!important; |
| backdrop-filter:blur(16px)!important; |
| transition:all .35s cubic-bezier(.4,0,.2,1)!important; |
| max-width:520px; |
| } |
| [data-testid="stFileUploader"]:hover, |
| [data-testid="stFileUploader"]:focus-within{ |
| max-width:80%!important; |
| padding:1.2rem 1.4rem!important; |
| border-color:var(--gold)!important; |
| background:var(--bg-card-hover)!important; |
| box-shadow:0 0 28px rgba(197,165,90,0.12)!important; |
| } |
| [data-testid="stFileUploaderDropzone"]{ |
| background:transparent!important;border:none!important; |
| padding:0.4rem 0!important;min-height:0!important; |
| } |
| [data-testid="stFileUploaderDropzone"] div[data-testid="stMarkdownContainer"]{ |
| font-size:0.78rem!important; |
| } |
| [data-testid="stFileUploaderDropzone"] button{ |
| display:none!important; |
| } |
| [data-testid="stFileUploaderDropzone"] small{ |
| font-size:0.7rem!important; |
| } |
| [data-testid="stFileUploader"] section{ |
| padding:0!important; |
| } |
| [data-testid="stFileUploader"] label, |
| [data-testid="stFileUploader"] span, |
| [data-testid="stFileUploader"] small{color:var(--text-sec)!important} |
| [data-testid="stFileUploader"] label p{ |
| font-size:0.82rem!important;margin-bottom:0.2rem!important; |
| } |
| |
| /* ββ Slider ββ */ |
| [data-testid="stSlider"] label{color:var(--text-body)!important} |
| .stSlider [role="slider"]{ |
| background-color:var(--gold)!important;border:2px solid var(--gold-light)!important; |
| box-shadow:0 0 10px rgba(197,165,90,.3)!important; |
| } |
| .stSlider>div>div>div>div{background-color:var(--gold)!important} |
| [data-testid="stSlider"] [data-testid="stThumbValue"]{color:var(--gold-light)!important} |
| |
| /* ββ Checkbox ββ */ |
| [data-testid="stCheckbox"] label span{color:var(--gold-light)!important} |
| |
| /* ββ Alerts ββ */ |
| .stAlert,[data-testid="stAlert"]{ |
| background:var(--glass-bg)!important; |
| border:1px solid var(--border-gold)!important; |
| border-radius:10px!important;backdrop-filter:blur(12px)!important; |
| } |
| [data-testid="stAlert"] p{color:var(--text-body)!important} |
| |
| /* ββ Images ββ */ |
| [data-testid="stImage"]{ |
| border-radius:12px!important;overflow:hidden!important; |
| border:1px solid var(--border-gold)!important; |
| box-shadow:0 8px 32px rgba(0,0,0,.4)!important;transition:all .3s ease!important; |
| } |
| [data-testid="stImage"]:hover{ |
| border-color:var(--border-gold-s)!important; |
| box-shadow:0 12px 40px rgba(0,0,0,.5),0 0 20px rgba(197,165,90,.06)!important; |
| } |
| [data-testid="stImage"] img{border-radius:11px!important} |
| [data-testid="stImage"] [data-testid="caption"]{ |
| color:var(--gold-muted)!important;font-family:'Inter',sans-serif!important; |
| font-size:.82rem!important;letter-spacing:.03em; |
| } |
| |
| /* ββ Spinner ββ */ |
| .stSpinner>div{border-top-color:var(--gold)!important} |
| |
| /* ββ Scrollbar ββ */ |
| ::-webkit-scrollbar{width:7px;height:7px} |
| ::-webkit-scrollbar-track{background:var(--bg-deep)} |
| ::-webkit-scrollbar-thumb{background:var(--gold-dark);border-radius:4px} |
| ::-webkit-scrollbar-thumb:hover{background:var(--gold)} |
| |
| /* ββ Layout ββ */ |
| [data-testid="stHorizontalBlock"]{gap:1rem} |
| .block-container{padding-top:2rem!important} |
| |
| /* ββ Toast ββ */ |
| .stToast{ |
| background:var(--bg-card)!important;border:1px solid var(--border-gold)!important; |
| color:var(--text-body)!important; |
| } |
| [data-testid="stTooltipIcon"]{color:var(--gold-muted)!important} |
| |
| /* ββ Inputs ββ */ |
| .stSelectbox>div>div,.stTextInput>div>div>input{ |
| background:var(--glass-bg)!important;border:1px solid var(--border-gold)!important; |
| color:var(--text-primary)!important;border-radius:8px!important; |
| } |
| |
| /* ββ Widget labels (global) ββ */ |
| .stNumberInput label p, |
| .stTextInput label p, |
| .stTextArea label p, |
| .stSelectbox label p, |
| .stRadio label p, |
| .stFileUploader label p{ |
| color:var(--gold-light)!important; |
| } |
| .stRadio [role="radiogroup"] label span{color:var(--text-body)!important} |
| |
| /* ββ Tabs ββ */ |
| .stTabs [data-baseweb="tab-list"]{ |
| border-bottom:1px solid var(--border-gold)!important; |
| gap:0!important; |
| } |
| .stTabs [data-baseweb="tab"]{ |
| color:var(--text-sec)!important; |
| font-family:'Inter',sans-serif!important;font-weight:500!important; |
| font-size:0.95rem!important;letter-spacing:0.03em; |
| border-bottom:2px solid transparent!important; |
| padding:0.6rem 1.4rem!important; |
| transition:all .25s ease!important; |
| } |
| .stTabs [data-baseweb="tab"]:hover{ |
| color:var(--gold-light)!important; |
| background:rgba(197,165,90,0.06)!important; |
| } |
| .stTabs [aria-selected="true"]{ |
| color:var(--gold-light)!important; |
| border-bottom:2px solid var(--gold)!important; |
| } |
| .stTabs [data-baseweb="tab-highlight"]{background-color:var(--gold)!important} |
| .stTabs [data-baseweb="tab-border"]{display:none!important} |
| |
| /* ββ Chat input ββ */ |
| .stChatInput textarea{ |
| background:var(--glass-bg)!important;border:1px solid var(--border-gold)!important; |
| color:var(--text-primary)!important; |
| } |
| .stChatInput textarea::placeholder{color:var(--text-sec)!important} |
| |
| /* ββ Expander ββ */ |
| .stExpander{ |
| border:1px solid var(--border-gold)!important; |
| border-radius:10px!important; |
| background:var(--glass-bg)!important; |
| } |
| .stExpander summary span{color:var(--gold-light)!important} |
| </style>""" |
|
|
|
|
| |
| |
| |
|
|
| _JS = """<script> |
| (function(){ |
| var d=window.parent.document; |
| |
| // ββ Mouse-tracking golden light ββββββββββββββββββββββββββββββββββββββββββ |
| if(!d.getElementById('oirseg-light')){ |
| var o=d.createElement('div'); |
| o.id='oirseg-light'; |
| o.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;' |
| +'pointer-events:none;z-index:9999;transition:background .18s ease-out;'; |
| d.body.appendChild(o); |
| d.addEventListener('mousemove',function(e){ |
| o.style.background='radial-gradient(280px circle at ' |
| +e.clientX+'px '+e.clientY+'px,rgba(197,165,90,0.13),rgba(197,165,90,0.04) 45%,transparent 70%)'; |
| }); |
| d.addEventListener('mouseleave',function(){o.style.background='transparent';}); |
| } |
| |
| })(); |
| </script>""" |
|
|