# -*- coding: utf-8 -*- from typing import Optional, Dict, Any import base64, mimetypes from html import escape from pathlib import Path import streamlit as st # ========= PATHS ========= BASE_DIR = Path(__file__).parent ASSETS = BASE_DIR / "assets" # ========= META ========= st.set_page_config(page_title="Smart Thinking — AI Suite", layout="wide") # ========= GLOBAL THEME (all knobs live here) ========= THEME: Dict[str, Any] = { "page": { "container_width": 1120, "bg_radial": True, "section_gap": 44, "footer_gap": 36, "top_padding": 40, }, "hero": { "logo": ASSETS / "logo.png", "width": 340, "tagline": "We Deliver AI-Based Solutions For O&G Industry", "tagline_size": 22, "tagline_weight": 500, # lighter than bold "tagline_italic": True, # italic tagline "tagline_color": "#0B1220", "logo_bottom": 14, "block_bottom": 22, }, "grid": { "columns": 4, "gap": 40, "card_width": 400, }, "card": { "radius": 22, "border_width": 2, "border": "#0B1220", "border_hover": "#243447", "bg_top": "#FFFFFF", "bg_bot": "#FBFCFE", "pad_v": 24, "pad_h": 22, "gap": 12, # base gap between stacked elements # Title & paragraph (FULL CONTROL) "title_color": "#0B1220", "title_size": 26, "title_weight": 900, "title_mt": 0, # space above title "title_mb": 0, # space below title "blurb_color": "#566275", "blurb_size": 16, "blurb_mt": 0, # space above blurb "blurb_mb": 40, # space below blurb # Card logo controls (no frame/border) "logo_max_w": 350, "logo_area_h": 300, # fixed area so top spacing is identical across cards "logo_top": 6, "logo_bottom": 0, }, "button": { "pad_v": 12, "pad_h": 20, "radius": 14, "bg1": "#0B1220", "bg2": "#162338", "text": "#FFFFFF", "border": "rgba(11,18,32,.55)", "font_size": 16, "font_weight": 800, "btn_mt": 8, # space above the button }, } # ========= CARDS ========= CARDS = [ { "title": "\u00A0Geomechanics", "blurb": "Predict Rock Mechanical Behaviour Using AI", "url": "https://smart-thinking-ai-suite-geomech.hf.space", "icon": ASSETS / "GeoMech_logo.png", "style": { "bg_top": "#EEF7FF", "bg_bot": "#F7FBFF", "border": "#0E4A6E", }, }, { "title": "\u00A0TOC", "blurb": "Generate Synthetic Logging Profiles Using AI", "url": "https://smart-thinking-ai-suite-log.hf.space", "icon": ASSETS / "log_logo.png", "style": { "bg_top": "#F8FFF4", "bg_bot": "#FBFFF8", "border": "#0F3D3E", }, }, { "title": "\u00A0Permeability", "blurb": "Predict K Via AI", "url": "https://smart-thinking-ai-suite-perm.hf.space", "icon": ASSETS / "AI Permeability Prediction Logo.png", "style": { "bg_top": "#FFF7E6", "bg_bot": "#FFFDF8", "border": "#8B5E00", }, }, { "title": "\u00A0Porosity", "blurb": "Predict Porosity Via AI", "url": "https://smart-thinking-ai-suite-poro.hf.space", "icon": ASSETS / "Porosity logo.png", "style": { "bg_top": "#F3E8FF", "bg_bot": "#FAF7FF", "border": "#4B0082", }, }, ] # ========= Helpers ========= def data_uri(path: Path) -> Optional[str]: if not path or not path.exists(): return None mime, _ = mimetypes.guess_type(path.name) if not mime: mime = "image/png" b64 = base64.b64encode(path.read_bytes()).decode("utf-8") return f"data:{mime};base64,{b64}" def img_tag(path: Path, alt: str, cls: str = "", style: str = "") -> str: uri = data_uri(path) if not uri: return "" cls_attr = f' class="{cls}"' if cls else "" style_attr = f' style="{style}"' if style else "" return f'' # ========= CSS ========= page = THEME["page"]; hero = THEME["hero"] grid = THEME["grid"]; card = THEME["card"]; button = THEME["button"] bg_radial_css = """ background: radial-gradient(980px 460px at 50% -140px, rgba(2,12,30,0.06) 0%, rgba(2,12,30,0.04) 28%, rgba(255,255,255,0.98) 60%, rgba(255,255,255,1) 100%); """ if page["bg_radial"] else "background: #fff;" st.markdown(f""" """, unsafe_allow_html=True) # ========= HERO ========= hero_html = img_tag(hero["logo"], "Company Logo") st.markdown( f"""
{hero_html}
{escape(hero["tagline"])}
""", unsafe_allow_html=True, ) # ========= Cards ========= def build_card_vars(style: Dict[str, Any]) -> str: s = [] if "width" in style: s.append(f"--c-w:{int(style['width'])}px") if "radius" in style: s.append(f"--c-radius:{int(style['radius'])}px") if "pad_v" in style: s.append(f"--c-pv:{int(style['pad_v'])}px") if "pad_h" in style: s.append(f"--c-ph:{int(style['pad_h'])}px") if "bg_top" in style: s.append(f"--c-bg-top:{style['bg_top']}") if "bg_bot" in style: s.append(f"--c-bg-bot:{style['bg_bot']}") # ← FIXED QUOTES if "border" in style: s.append(f"--c-border:{style['border']}") if "border_width" in style: s.append(f"--c-bw:{int(style['border_width'])}px") if "title_color" in style: s.append(f"--c-title-color:{style['title_color']}") if "title_fs" in style: s.append(f"--c-title-fs:{int(style['title_fs'])}px") if "blurb_color" in style: s.append(f"--c-blurb-color:{style['blurb_color']}") if "blurb_fs" in style: s.append(f"--c-blurb-fs:{int(style['blurb_fs'])}px") return "; ".join(s) def app_card(card_cfg: Dict[str, Any]) -> str: style = card_cfg.get("style", {}) vars_inline = build_card_vars(style) icon_html = img_tag(card_cfg.get("icon"), "logo", cls="logo-img") if card_cfg.get("icon") and card_cfg["icon"].exists() else "" target = "_self" return ( f"
" + f"
{icon_html}
" + f"

{escape(card_cfg['title'])}

" + f"

{escape(card_cfg['blurb'])}

" + f"Explore" + "
" ) st.markdown("
" + "".join(app_card(c) for c in CARDS) + "
", unsafe_allow_html=True) # ========= Footer ========= st.markdown( """
""", unsafe_allow_html=True, )