UCS2014 commited on
Commit
5b186ea
·
verified ·
1 Parent(s): fbab1da

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -85
app.py CHANGED
@@ -1,68 +1,74 @@
1
- # STEP 2 CLEAN BRANDED UI
2
  import base64, mimetypes
3
  from html import escape
4
  from pathlib import Path
5
  import streamlit as st
6
 
7
- # --------- META FIRST ---------
8
- st.set_page_config(page_title="Smart Thinking - Logging — Apps", page_icon="🧭", layout="wide")
9
-
10
- # --------- PATHS ---------
11
  BASE_DIR = Path(__file__).parent
12
  ASSETS = BASE_DIR / "assets"
13
- LOGO_PATH = ASSETS / "logo.png" # optional; renders if present
14
 
15
- # --------- BRAND / DATA ---------
 
 
 
16
  COMPANY_NAME = "Smart Thinking - Logging"
17
  TAGLINE = "We Deliver Smart AI-Based Solutions For O&G Industry"
18
- SUITE_NAME = "ST_LOG SUITE"
19
- ACCENT = "#0E7490" # start
20
- ACCENT_END = "#14B8A6" # end
 
 
 
 
 
 
 
21
 
22
  APPS = [
23
  {
24
  "title": "ST_Log_GR",
25
  "url": "https://smart-thinking-gr.hf.space/",
26
  "blurb": "Real-time gamma-ray log prediction.",
27
- "icon": ASSETS / "app1_icon.png", # optional tiny glyph
28
  },
29
  {
30
  "title": "ST_Log_Sonic (Ts)",
31
  "url": "https://smart-thinking-sonic-ts.hf.space",
32
- "blurb": "Predict shear slowness (DtS) in real time.", # ASCII only to avoid encoding issues
33
- "icon": ASSETS / "app2_icon.png",
34
  },
35
  {
36
  "title": "ST_Log_Sonic (Tc)",
37
  "url": "https://smart-thinking-sonic-tc.hf.space",
38
  "blurb": "Predict compressional slowness (DtC) in real time.",
39
- "icon": ASSETS / "app3_icon.png",
40
  },
41
  ]
42
 
43
- # --------- HELPERS ---------
44
  def data_uri(path: Path) -> str | None:
45
  if not path or not path.exists():
46
  return None
47
  mime, _ = mimetypes.guess_type(path.name)
48
  if not mime:
49
  mime = "image/png"
50
- import base64
51
  b64 = base64.b64encode(path.read_bytes()).decode("utf-8")
52
  return f"data:{mime};base64,{b64}"
53
 
54
- def img_tag(path: Path, alt: str, cls: str = "") -> str:
55
  uri = data_uri(path)
56
- if uri:
57
- cls_attr = f' class="{cls}"' if cls else ""
58
- return f'<img{cls_attr} src="{uri}" alt="{escape(alt)}" />'
59
- return "" # silently skip if missing
 
60
 
61
- def tiny_icon_html(path: Path) -> str:
62
  uri = data_uri(path)
63
- return f"<img src='{uri}' alt='icon' style='width:18px;height:18px;display:block;border-radius:4px;'>" if uri else ""
64
 
65
- # --------- SAFE CSS (ONE BLOCK) ---------
66
  st.markdown(f"""
67
  <style>
68
  :root {{
@@ -75,39 +81,40 @@ st.markdown(f"""
75
  padding-top: 0 !important; padding-bottom: 0 !important;
76
  }}
77
 
 
78
  .block-container {{
79
- max-width: 1080px;
80
  min-height: 100vh;
81
  display: flex; flex-direction: column;
82
- gap: 8px;
83
- padding: 100px 0 24px !important; /* generous top space */
84
  background:
85
- radial-gradient(900px 420px at 50% -120px,
86
  rgba(20,184,166,0.10) 0%,
87
- rgba(14,116,144,0.06) 28%,
88
- rgba(255,255,255,0.98) 64%,
89
  rgba(255,255,255,1) 100%);
90
  }}
91
 
92
  /* HERO */
93
- .hero {{ text-align:center; margin: 0 0 6px; }}
94
  .hero img {{
95
- width: 160px; max-width: 95vw; height: auto;
96
- display:block; margin: 0 auto 8px;
97
- filter: drop-shadow(0 4px 12px rgba(0,0,0,.08));
98
  }}
99
  .hero h1 {{
100
- font-size: 2.3rem; line-height: 1.15; margin: .25rem 0 .15rem;
101
  letter-spacing: .2px; color: #0F172A;
102
  }}
103
- .hero p {{
104
- color: #445066; margin: 2px auto 10px; max-width: 720px; font-style: italic;
105
  }}
106
 
107
- /* SUITE BANNER */
108
  .suite-banner {{
109
  display:flex; gap:12px; justify-content:center; align-items:center;
110
- margin: 6px 0 18px;
111
  }}
112
  .suite-pill {{
113
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand2) 100%);
@@ -117,31 +124,32 @@ st.markdown(f"""
117
  }}
118
  .suite-sub {{ color:#3b4656; font-weight:500; opacity:.92; }}
119
 
120
- /* GRID */
121
  .grid {{
122
  display: grid;
123
- grid-template-columns: repeat(3, 280px);
124
  gap: 36px;
125
  justify-content: center;
126
  align-items: stretch;
127
- margin-top: 4px;
128
  }}
129
- @media (max-width: 1040px) {{
130
- .grid {{ grid-template-columns: repeat(2, 280px); gap: 28px; }}
131
  }}
132
- @media (max-width: 640px) {{
133
  .grid {{ grid-template-columns: 1fr; }}
134
  }}
135
 
136
  /* CARD */
137
  .card {{
138
- width: 280px;
 
139
  background: #ffffff;
140
  border: 1px solid rgba(2,20,35,.06);
141
- border-radius:16px; padding:16px 16px 16px;
142
  box-shadow: 0 8px 28px rgba(2,20,35,.06);
143
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
144
- text-align:center; display:flex; flex-direction:column; gap:10px;
145
  align-items: center;
146
  }}
147
  .card:hover {{
@@ -150,31 +158,32 @@ st.markdown(f"""
150
  border-color: rgba(14,116,144,0.18);
151
  }}
152
 
153
- /* Small corner chip (keeps branding without crowding) */
154
- .chip {{
155
- align-self: stretch;
156
- display:flex; justify-content:flex-start; align-items:center; gap:8px;
157
- height: 30px; margin: 0 0 6px 0;
158
- }}
159
- .chip .pill {{
160
- display:flex; align-items:center; gap:8px;
161
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand2) 100%);
162
  color:#fff; padding:5px 10px; border-radius:999px;
163
- font-weight:700; font-size:.82rem; letter-spacing:.2px;
164
  box-shadow: 0 6px 14px rgba(14,116,144,.22);
165
  }}
166
- .chip .dot {{
167
- width: 22px; height: 22px; border-radius: 7px;
168
- background: rgba(255,255,255,.18);
169
- display:grid; place-items:center; overflow:hidden;
 
 
 
 
 
 
 
170
  }}
171
- .chip .dot img {{ width:16px; height:16px; display:block; }}
172
 
173
  .card h3 {{
174
- margin: 6px 0 0; font-size: 1.05rem; font-weight: 800; color:#0b1220;
175
  }}
176
  .card p {{
177
- color:#536071; min-height: 32px; margin: 4px 8px 0; font-size: .96rem;
178
  }}
179
 
180
  /* BUTTON */
@@ -197,12 +206,12 @@ st.markdown(f"""
197
  </style>
198
  """, unsafe_allow_html=True)
199
 
200
- # --------- HERO ---------
201
- hero_logo = img_tag(LOGO_PATH, "logo", "")
202
  st.markdown(
203
  f"""
204
  <div class="hero">
205
- {hero_logo}
206
  <h1>{escape(COMPANY_NAME)}</h1>
207
  <p>{escape(TAGLINE)}</p>
208
  </div>
@@ -210,7 +219,7 @@ st.markdown(
210
  unsafe_allow_html=True,
211
  )
212
 
213
- # --------- SUITE BANNER ---------
214
  st.markdown(
215
  f"""
216
  <div class="suite-banner">
@@ -221,33 +230,25 @@ st.markdown(
221
  unsafe_allow_html=True,
222
  )
223
 
224
- # --------- CARDS ---------
225
- def card_chip(icon_path: Path | None) -> str:
226
- icon_html = tiny_icon_html(icon_path) if icon_path else ""
227
- return f"""
228
- <div class="chip">
229
- <div class="pill">
230
- <div class="dot">{icon_html}</div>
231
- {escape(SUITE_NAME)}
232
- </div>
233
- </div>
234
- """
235
-
236
  def app_card(app: dict) -> str:
237
- target = "_blank" if False else "_self"
 
 
238
  return (
239
- f"<div class='card'>"
240
- + card_chip(app.get("icon"))
 
241
  + f"<h3>{escape(app['title'])}</h3>"
242
  + f"<p>{escape(app['blurb'])}</p>"
243
- + f"<a class='btn' href='{escape(app['url'])}' target='{target}' rel='noopener'>{escape('Open App')}</a>"
244
  + "</div>"
245
  )
246
 
247
  cards_html = "".join(app_card(a) for a in APPS)
248
  st.markdown(f"<div class='grid'>{cards_html}</div>", unsafe_allow_html=True)
249
 
250
- # --------- FOOTER ---------
251
  st.markdown(
252
  """
253
  <hr>
 
1
+ # -*- coding: utf-8 -*-
2
  import base64, mimetypes
3
  from html import escape
4
  from pathlib import Path
5
  import streamlit as st
6
 
7
+ # ========= PATHS =========
 
 
 
8
  BASE_DIR = Path(__file__).parent
9
  ASSETS = BASE_DIR / "assets"
 
10
 
11
+ # ========= META FIRST =========
12
+ st.set_page_config(page_title="Smart Thinking - Logging — Apps", page_icon="🧭", layout="wide")
13
+
14
+ # ========= BRAND / DATA =========
15
  COMPANY_NAME = "Smart Thinking - Logging"
16
  TAGLINE = "We Deliver Smart AI-Based Solutions For O&G Industry"
17
+ SUITE_NAME = "ST_LOG SUITE" # shown in chip + banner
18
+
19
+ ACCENT = "#0E7490" # teal start
20
+ ACCENT_END = "#14B8A6" # teal end
21
+
22
+ # Logos (place in assets/)
23
+ HERO_LOGO = ASSETS / "AI_Suite_Log_logo.png"
24
+ ICON_GR = ASSETS / "GR_logo.png"
25
+ ICON_TS = ASSETS / "Ts_logo.png"
26
+ ICON_TC = ASSETS / "Tc_logo.png"
27
 
28
  APPS = [
29
  {
30
  "title": "ST_Log_GR",
31
  "url": "https://smart-thinking-gr.hf.space/",
32
  "blurb": "Real-time gamma-ray log prediction.",
33
+ "icon": ICON_GR,
34
  },
35
  {
36
  "title": "ST_Log_Sonic (Ts)",
37
  "url": "https://smart-thinking-sonic-ts.hf.space",
38
+ "blurb": "Predict shear slowness (DtS) in real time.",
39
+ "icon": ICON_TS,
40
  },
41
  {
42
  "title": "ST_Log_Sonic (Tc)",
43
  "url": "https://smart-thinking-sonic-tc.hf.space",
44
  "blurb": "Predict compressional slowness (DtC) in real time.",
45
+ "icon": ICON_TC,
46
  },
47
  ]
48
 
49
+ # ========= HELPERS =========
50
  def data_uri(path: Path) -> str | None:
51
  if not path or not path.exists():
52
  return None
53
  mime, _ = mimetypes.guess_type(path.name)
54
  if not mime:
55
  mime = "image/png"
 
56
  b64 = base64.b64encode(path.read_bytes()).decode("utf-8")
57
  return f"data:{mime};base64,{b64}"
58
 
59
+ def img_tag(path: Path, alt: str, cls: str = "", style: str = "") -> str:
60
  uri = data_uri(path)
61
+ if not uri:
62
+ return ""
63
+ cls_attr = f' class="{cls}"' if cls else ""
64
+ style_attr = f' style="{style}"' if style else ""
65
+ return f'<img{cls_attr}{style_attr} src="{uri}" alt="{escape(alt)}" />'
66
 
67
+ def tiny_icon_html(path: Path, size: int = 18) -> str:
68
  uri = data_uri(path)
69
+ return f"<img src='{uri}' alt='icon' style='width:{size}px;height:{size}px;display:block;border-radius:4px;'>" if uri else ""
70
 
71
+ # ========= BACKGROUND (simple & safe gradient) =========
72
  st.markdown(f"""
73
  <style>
74
  :root {{
 
81
  padding-top: 0 !important; padding-bottom: 0 !important;
82
  }}
83
 
84
+ /* Page container with calm gradient */
85
  .block-container {{
86
+ max-width: 1100px;
87
  min-height: 100vh;
88
  display: flex; flex-direction: column;
89
+ gap: 16px;
90
+ padding: 100px 0 28px !important;
91
  background:
92
+ radial-gradient(980px 460px at 50% -140px,
93
  rgba(20,184,166,0.10) 0%,
94
+ rgba(14,116,144,0.06) 26%,
95
+ rgba(255,255,255,0.98) 60%,
96
  rgba(255,255,255,1) 100%);
97
  }}
98
 
99
  /* HERO */
100
+ .hero {{ text-align:center; margin: 0; }}
101
  .hero img {{
102
+ width: 520px; max-width: 92vw; height: auto;
103
+ display:block; margin: 0 auto 10px;
104
+ filter: drop-shadow(0 6px 16px rgba(0,0,0,.10));
105
  }}
106
  .hero h1 {{
107
+ font-size: 2.2rem; line-height: 1.15; margin: .25rem 0 .15rem;
108
  letter-spacing: .2px; color: #0F172A;
109
  }}
110
+ .hero p {{
111
+ color: #455268; margin: 4px auto 14px; max-width: 800px; font-style: italic;
112
  }}
113
 
114
+ /* SUITE BANNER (light) */
115
  .suite-banner {{
116
  display:flex; gap:12px; justify-content:center; align-items:center;
117
+ margin: 2px 0 12px;
118
  }}
119
  .suite-pill {{
120
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand2) 100%);
 
124
  }}
125
  .suite-sub {{ color:#3b4656; font-weight:500; opacity:.92; }}
126
 
127
+ /* GRID (3 → 2 → 1) */
128
  .grid {{
129
  display: grid;
130
+ grid-template-columns: repeat(3, 300px);
131
  gap: 36px;
132
  justify-content: center;
133
  align-items: stretch;
134
+ margin-top: 8px;
135
  }}
136
+ @media (max-width: 1080px) {{
137
+ .grid {{ grid-template-columns: repeat(2, 300px); gap: 28px; }}
138
  }}
139
+ @media (max-width: 680px) {{
140
  .grid {{ grid-template-columns: 1fr; }}
141
  }}
142
 
143
  /* CARD */
144
  .card {{
145
+ position: relative;
146
+ width: 300px;
147
  background: #ffffff;
148
  border: 1px solid rgba(2,20,35,.06);
149
+ border-radius:18px; padding:18px 16px 16px;
150
  box-shadow: 0 8px 28px rgba(2,20,35,.06);
151
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
152
+ text-align:center; display:flex; flex-direction:column; gap:12px;
153
  align-items: center;
154
  }}
155
  .card:hover {{
 
158
  border-color: rgba(14,116,144,0.18);
159
  }}
160
 
161
+ /* Corner suite chip (keeps branding without crowding) */
162
+ .suite-chip {{
163
+ position: absolute; top: 12px; right: 12px;
 
 
 
 
 
164
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand2) 100%);
165
  color:#fff; padding:5px 10px; border-radius:999px;
166
+ font-weight:700; font-size:.80rem; letter-spacing:.2px;
167
  box-shadow: 0 6px 14px rgba(14,116,144,.22);
168
  }}
169
+
170
+ /* Centered round icon */
171
+ .icon-wrap {{
172
+ width: 72px; height: 72px; border-radius: 9999px;
173
+ background: #E6F4F7;
174
+ display:grid; place-items:center;
175
+ border: 1px solid rgba(14,116,144,0.20);
176
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.9), 0 6px 16px rgba(2,20,35,.06);
177
+ }}
178
+ .icon-wrap img {{
179
+ width: 62px; height: 62px; border-radius:9999px; display:block;
180
  }}
 
181
 
182
  .card h3 {{
183
+ margin: 2px 0 0; font-size: 1.08rem; font-weight: 800; color:#0b1220;
184
  }}
185
  .card p {{
186
+ color:#536071; min-height: 38px; margin: 2px 8px 0; font-size: .96rem;
187
  }}
188
 
189
  /* BUTTON */
 
206
  </style>
207
  """, unsafe_allow_html=True)
208
 
209
+ # ========= HERO =========
210
+ hero_img = img_tag(HERO_LOGO, "ST_LOG SUITE", "")
211
  st.markdown(
212
  f"""
213
  <div class="hero">
214
+ {hero_img}
215
  <h1>{escape(COMPANY_NAME)}</h1>
216
  <p>{escape(TAGLINE)}</p>
217
  </div>
 
219
  unsafe_allow_html=True,
220
  )
221
 
222
+ # ========= SUITE BANNER =========
223
  st.markdown(
224
  f"""
225
  <div class="suite-banner">
 
230
  unsafe_allow_html=True,
231
  )
232
 
233
+ # ========= CARDS =========
 
 
 
 
 
 
 
 
 
 
 
234
  def app_card(app: dict) -> str:
235
+ icon_html = img_tag(app.get("icon"), "icon", style="width:62px;height:62px;border-radius:9999px;") \
236
+ if app.get("icon") and (app["icon"]).exists() else ""
237
+ target = "_self" # set to "_blank" if you want new tab
238
  return (
239
+ "<div class='card'>"
240
+ + f"<div class='suite-chip'>{escape(SUITE_NAME)}</div>"
241
+ + f"<div class='icon-wrap'>{icon_html}</div>"
242
  + f"<h3>{escape(app['title'])}</h3>"
243
  + f"<p>{escape(app['blurb'])}</p>"
244
+ + f"<a class='btn' href='{escape(app['url'])}' target='{target}' rel='noopener'>Open App</a>"
245
  + "</div>"
246
  )
247
 
248
  cards_html = "".join(app_card(a) for a in APPS)
249
  st.markdown(f"<div class='grid'>{cards_html}</div>", unsafe_allow_html=True)
250
 
251
+ # ========= FOOTER =========
252
  st.markdown(
253
  """
254
  <hr>