UCS2014 commited on
Commit
f639641
·
verified ·
1 Parent(s): f9d59bf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +93 -123
app.py CHANGED
@@ -9,9 +9,9 @@ BASE_DIR = Path(__file__).parent
9
  ASSETS = BASE_DIR / "assets"
10
 
11
  # ========= CONTROLS =========
12
- HERO_LOGO_SIZE = 172
13
- TOP_SPACER = 140
14
- GRID_GAP = 48
15
  BUTTON_TEXT = "Open App"
16
  OPEN_IN_NEW_TAB = False
17
 
@@ -19,15 +19,15 @@ OPEN_IN_NEW_TAB = False
19
  COMPANY_NAME = "Smart Thinking - Logging"
20
  TAGLINE = "We Deliver Smart AI-Based Solutions For O&G Industry"
21
  SUITE_NAME = "ST_LOG SUITE"
22
- ACCENT = "#0E7490" # start
23
- ACCENT_END = "#14B8A6" # end
24
 
25
  # ========= APPS =========
26
  APP1 = {
27
  "title": "ST_Log_GR",
28
  "url": "https://smart-thinking-gr.hf.space/",
29
  "blurb": "Real-time gamma-ray log prediction.",
30
- "icon": ASSETS / "app1_icon.png", # optional tiny glyph (24–32px)
31
  }
32
  APP2 = {
33
  "title": "ST_Log_Sonic (Ts)",
@@ -44,20 +44,16 @@ APP3 = {
44
 
45
  LOGO_PATH = ASSETS / "logo.png"
46
 
47
- # ========= PAGE META (set first) =========
48
  page_icon = str(LOGO_PATH) if LOGO_PATH.exists() else "🧭"
49
  st.set_page_config(page_title=f"{COMPANY_NAME} — Apps", page_icon=page_icon, layout="wide")
50
 
51
- # Quick debug line so you can confirm the script rendered
52
- st.caption("✅ Page loaded. If you ever see a blank page, this line helps diagnose execution.")
53
-
54
  # ========= HELPERS =========
55
  def data_uri(path: Path) -> str | None:
56
  if not path or not path.exists():
57
  return None
58
  mime, _ = mimetypes.guess_type(path.name)
59
- if not mime:
60
- mime = "image/png"
61
  b64 = base64.b64encode(path.read_bytes()).decode("utf-8")
62
  return f"data:{mime};base64,{b64}"
63
 
@@ -66,66 +62,33 @@ def img_tag(path: Path, alt: str, cls: str = "") -> str:
66
  if uri:
67
  cls_attr = f' class="{cls}"' if cls else ""
68
  return f'<img{cls_attr} src="{uri}" alt="{escape(alt)}" />'
69
- # simple fallback if missing
70
- return f'<div class="{cls}" style="display:flex;align-items:center;justify-content:center;color:#50545c;background:#eef2f7;border-radius:8px;">{escape(alt)}</div>'
71
-
72
- def card_header_badge(icon_path: Path | None, suite_label: str) -> str:
73
- icon_uri = data_uri(icon_path) if icon_path else None
74
- icon_html = f"<img src='{icon_uri}' alt='icon' style='width:22px;height:22px;display:block;'>" if icon_uri else ""
75
- return f"""
76
- <div class="badge">
77
- <div class="badge-left">{icon_html}</div>
78
- <div class="badge-right">{escape(suite_label)}</div>
79
- </div>
80
- """
81
 
82
- # ========= BACKGROUND (simple & safe) =========
83
- # No images, no complex CSS: just a soft gradient + very faint SVG grid pattern
84
- def inject_subtle_bg() -> None:
85
- pattern_svg = (
86
- "data:image/svg+xml;utf8,"
87
- "<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64' viewBox='0 0 64 64'>"
88
- "<defs><pattern id='p' width='32' height='32' patternUnits='userSpaceOnUse'>"
89
- "<path d='M0 16 H32 M16 0 V32' stroke='rgba(15,23,42,0.06)' stroke-width='1'/>"
90
- "</pattern></defs>"
91
- "<rect width='100%' height='100%' fill='url(#p)'/>"
92
- "</svg>"
93
- )
94
-
95
- st.markdown(f"""
96
- <style>
97
- /* Base gradient */
98
- .stApp {{
99
- position: relative !important;
100
- background:
101
- radial-gradient(900px 420px at 50% 0%,
102
- rgba(20,184,166,0.12) 0%,
103
- rgba(14,116,144,0.08) 32%,
104
- rgba(255,255,255,0.94) 70%,
105
- rgba(255,255,255,1) 100%) !important;
106
- }}
107
- /* Faint pattern on top of the gradient */
108
- .stApp::before {{
109
- content: "";
110
- position: fixed; inset: 0; z-index: 0;
111
- background-image: url("{pattern_svg}");
112
- opacity: .45;
113
- pointer-events: none;
114
- }}
115
- /* Ensure all content sits above */
116
- .stApp > * {{ position: relative; z-index: 1; }}
117
-
118
- [data-testid="stAppViewContainer"],
119
- [data-testid="stAppViewContainer"] > .main,
120
- html, body {{
121
- background: transparent !important;
122
- }}
123
- </style>
124
- """, unsafe_allow_html=True)
125
 
126
- inject_subtle_bg()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
- # ========= CORE CSS (lean & reliable) =========
129
  st.markdown(
130
  f"""
131
  <style>
@@ -147,102 +110,99 @@ st.markdown(
147
  display: flex; flex-direction: column;
148
  justify-content: flex-start;
149
  gap: 14px;
150
- padding: var(--top-spacer) 0 16px !important;
151
  }}
152
 
153
  /* HERO */
154
- .hero {{ text-align:center; margin: 0 0 6px; }}
155
  .hero img {{
156
  width: {HERO_LOGO_SIZE}px; max-width: 95vw; height: auto;
157
  display:block; margin: 0 auto 8px;
158
- filter: drop-shadow(0 4px 14px rgba(0,0,0,.10));
159
  }}
160
  .hero h1 {{
161
- font-size: 2.4rem; line-height: 1.15; margin: .25rem 0 .25rem;
162
- letter-spacing: .3px;
163
- color: #0F172A;
164
  }}
165
  .hero p {{
166
- color: #364152;
167
- margin: 6px auto 0;
168
- max-width: 720px;
169
- font-style: italic;
170
  }}
171
 
172
- /* SUITE BANNER */
173
  .suite-banner {{
174
  display:flex; gap:12px; justify-content:center; align-items:center;
175
- margin: 10px 0 12px;
176
  }}
177
  .suite-pill {{
178
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand2) 100%);
179
- color:#fff; padding:8px 12px; border-radius:999px;
180
  font-weight:700; letter-spacing:.2px;
181
- box-shadow: 0 8px 18px rgba(14,116,144,.25);
182
  }}
183
  .suite-sub {{
184
- color:#334155; font-weight:500; opacity:.95;
185
  }}
186
 
187
  /* GRID (3 → 2 → 1) */
188
  .grid {{
189
  display: grid;
190
- grid-template-columns: repeat(3, 260px);
191
- gap: 48px;
192
  justify-content: center;
193
  align-items: stretch;
194
- margin-top: 24px;
195
  }}
196
- @media (max-width: 1024px) {{
197
- .grid {{ grid-template-columns: repeat(2, 260px); gap: 36px; }}
198
  }}
199
- @media (max-width: 620px) {{
200
  .grid {{ grid-template-columns: 1fr; }}
201
  }}
202
 
203
- /* CARD */
204
  .card {{
205
- width: 260px;
206
- background: rgba(255,255,255,0.94);
207
  border: 1px solid rgba(2,20,35,.06);
208
- border-radius:16px; padding:16px 14px;
209
- box-shadow: 0 6px 28px rgba(2,20,35,.06);
210
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
211
  text-align:center; display:flex; flex-direction:column; gap:10px;
212
  align-items: center;
213
- backdrop-filter: saturate(1.05) blur(2px);
214
  }}
215
  .card:hover {{
216
  transform: translateY(-4px);
217
- box-shadow: 0 14px 40px rgba(2,20,35,.12);
218
- border-color: rgba(14,116,144,0.22);
219
  }}
220
 
221
- /* BADGE (replaces large logos) */
222
- .badge {{
223
- width:100%;
224
- display:flex; align-items:center; justify-content:flex-start;
225
- gap:10px;
 
 
 
 
 
226
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand2) 100%);
227
- color:#fff;
228
- padding:10px 12px;
229
- border-radius:12px;
230
- box-shadow: 0 8px 18px rgba(14,116,144,.25);
231
  }}
232
- .badge-left {{
233
- width:30px; height:30px;
234
- display:grid; place-items:center;
235
- background: rgba(255,255,255,.14);
236
- border-radius:10px; overflow:hidden;
237
  }}
238
- .badge-left img {{ width:22px; height:22px; display:block; }}
239
- .badge-right {{ font-weight:700; letter-spacing:.2px; }}
240
 
241
  .card h3 {{
242
- margin: 10px 0 0; font-size: 1.06rem; font-weight: 800; color:#0b1220;
243
  }}
244
  .card p {{
245
- color:#495464; min-height: 32px; margin: 6px 6px 0; font-size: .95rem;
246
  }}
247
 
248
  /* BUTTON */
@@ -251,17 +211,17 @@ st.markdown(
251
  border:1px solid rgba(14,116,144,0.25); text-decoration:none;
252
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand2) 100%);
253
  color: white; font-weight: 600; letter-spacing:.2px;
254
- margin: 8px auto 0;
255
- box-shadow: 0 6px 18px rgba(20,184,166,.28);
256
  }}
257
  .btn:hover {{
258
  filter: brightness(0.98) saturate(1.05);
259
  transform: translateY(-1px);
260
- box-shadow: 0 10px 26px rgba(20,184,166,.35);
261
  }}
262
 
263
- .footer {{ text-align:center; color:#334155; font-size:0.98em; margin-top: 18px; }}
264
- .footer hr {{ margin: 10px 0; border-color: rgba(0,0,0,.08); }}
265
  </style>
266
  """,
267
  unsafe_allow_html=True,
@@ -292,12 +252,22 @@ st.markdown(
292
  )
293
 
294
  # ========= CARDS =========
 
 
 
 
 
 
 
 
 
 
 
295
  def app_card(app: dict) -> str:
296
  target = "_blank" if OPEN_IN_NEW_TAB else "_self"
297
- header = card_header_badge(app.get("icon"), SUITE_NAME)
298
  return (
299
  f"<div class='card'>"
300
- + header
301
  + f"<h3>{escape(app['title'])}</h3>"
302
  + f"<p>{escape(app['blurb'])}</p>"
303
  + f"<a class='btn' href='{escape(app['url'])}' target='{target}' rel='noopener'>{escape(BUTTON_TEXT)}</a>"
 
9
  ASSETS = BASE_DIR / "assets"
10
 
11
  # ========= CONTROLS =========
12
+ HERO_LOGO_SIZE = 168
13
+ TOP_SPACER = 120
14
+ GRID_GAP = 40
15
  BUTTON_TEXT = "Open App"
16
  OPEN_IN_NEW_TAB = False
17
 
 
19
  COMPANY_NAME = "Smart Thinking - Logging"
20
  TAGLINE = "We Deliver Smart AI-Based Solutions For O&G Industry"
21
  SUITE_NAME = "ST_LOG SUITE"
22
+ ACCENT = "#0E7490" # teal start
23
+ ACCENT_END = "#14B8A6" # teal end
24
 
25
  # ========= APPS =========
26
  APP1 = {
27
  "title": "ST_Log_GR",
28
  "url": "https://smart-thinking-gr.hf.space/",
29
  "blurb": "Real-time gamma-ray log prediction.",
30
+ "icon": ASSETS / "app1_icon.png", # optional 24–32px glyph
31
  }
32
  APP2 = {
33
  "title": "ST_Log_Sonic (Ts)",
 
44
 
45
  LOGO_PATH = ASSETS / "logo.png"
46
 
47
+ # ========= PAGE META =========
48
  page_icon = str(LOGO_PATH) if LOGO_PATH.exists() else "🧭"
49
  st.set_page_config(page_title=f"{COMPANY_NAME} — Apps", page_icon=page_icon, layout="wide")
50
 
 
 
 
51
  # ========= HELPERS =========
52
  def data_uri(path: Path) -> str | None:
53
  if not path or not path.exists():
54
  return None
55
  mime, _ = mimetypes.guess_type(path.name)
56
+ if not mime: mime = "image/png"
 
57
  b64 = base64.b64encode(path.read_bytes()).decode("utf-8")
58
  return f"data:{mime};base64,{b64}"
59
 
 
62
  if uri:
63
  cls_attr = f' class="{cls}"' if cls else ""
64
  return f'<img{cls_attr} src="{uri}" alt="{escape(alt)}" />'
65
+ return f'<div class="{cls}" style="display:flex;align-items:center;justify-content:center;color:#6b7280;background:#eef2f7;border-radius:8px;">{escape(alt)}</div>'
 
 
 
 
 
 
 
 
 
 
 
66
 
67
+ def tiny_icon_html(path: Path) -> str:
68
+ uri = data_uri(path)
69
+ return f"<img src='{uri}' alt='icon' style='width:22px;height:22px;display:block;'>" if uri else ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
+ # ========= BACKGROUND (calm gradient) =========
72
+ st.markdown(f"""
73
+ <style>
74
+ .stApp {{
75
+ position: relative !important;
76
+ background:
77
+ radial-gradient(1200px 520px at 50% -80px,
78
+ rgba(20,184,166,0.10) 0%,
79
+ rgba(14,116,144,0.06) 28%,
80
+ rgba(255,255,255,0.96) 64%,
81
+ rgba(255,255,255,1) 100%) !important;
82
+ }}
83
+ [data-testid="stAppViewContainer"],
84
+ [data-testid="stAppViewContainer"] > .main,
85
+ html, body {{
86
+ background: transparent !important;
87
+ }}
88
+ </style>
89
+ """, unsafe_allow_html=True)
90
 
91
+ # ========= CORE CSS =========
92
  st.markdown(
93
  f"""
94
  <style>
 
110
  display: flex; flex-direction: column;
111
  justify-content: flex-start;
112
  gap: 14px;
113
+ padding: var(--top-spacer) 0 20px !important;
114
  }}
115
 
116
  /* HERO */
117
+ .hero {{ text-align:center; margin: 0 0 0; }}
118
  .hero img {{
119
  width: {HERO_LOGO_SIZE}px; max-width: 95vw; height: auto;
120
  display:block; margin: 0 auto 8px;
121
+ filter: drop-shadow(0 4px 14px rgba(0,0,0,.08));
122
  }}
123
  .hero h1 {{
124
+ font-size: 2.4rem; line-height: 1.15; margin: .25rem 0 .15rem;
125
+ letter-spacing: .2px; color: #0F172A;
 
126
  }}
127
  .hero p {{
128
+ color: #445066; margin: 2px auto 10px; max-width: 720px; font-style: italic;
 
 
 
129
  }}
130
 
131
+ /* SUITE BANNER (lighter) */
132
  .suite-banner {{
133
  display:flex; gap:12px; justify-content:center; align-items:center;
134
+ margin: 4px 0 16px;
135
  }}
136
  .suite-pill {{
137
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand2) 100%);
138
+ color:#fff; padding:7px 12px; border-radius:999px;
139
  font-weight:700; letter-spacing:.2px;
140
+ box-shadow: 0 6px 14px rgba(14,116,144,.22);
141
  }}
142
  .suite-sub {{
143
+ color:#3b4656; font-weight:500; opacity:.92;
144
  }}
145
 
146
  /* GRID (3 → 2 → 1) */
147
  .grid {{
148
  display: grid;
149
+ grid-template-columns: repeat(3, 280px);
150
+ gap: var(--grid-gap);
151
  justify-content: center;
152
  align-items: stretch;
153
+ margin-top: 8px;
154
  }}
155
+ @media (max-width: 1040px) {{
156
+ .grid {{ grid-template-columns: repeat(2, 280px); gap: 28px; }}
157
  }}
158
+ @media (max-width: 640px) {{
159
  .grid {{ grid-template-columns: 1fr; }}
160
  }}
161
 
162
+ /* CARD (clean + roomy) */
163
  .card {{
164
+ width: 280px;
165
+ background: #ffffff;
166
  border: 1px solid rgba(2,20,35,.06);
167
+ border-radius:16px; padding:18px 16px 16px;
168
+ box-shadow: 0 8px 28px rgba(2,20,35,.06);
169
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
170
  text-align:center; display:flex; flex-direction:column; gap:10px;
171
  align-items: center;
 
172
  }}
173
  .card:hover {{
174
  transform: translateY(-4px);
175
+ box-shadow: 0 16px 44px rgba(2,20,35,.12);
176
+ border-color: rgba(14,116,144,0.18);
177
  }}
178
 
179
+ /* Top-left chip instead of big badge */
180
+ .chip {{
181
+ position: relative;
182
+ align-self: stretch;
183
+ display:flex; justify-content:flex-start; align-items:center; gap:8px;
184
+ height: 34px;
185
+ margin: 0 0 6px 0;
186
+ }}
187
+ .chip .pill {{
188
+ display:flex; align-items:center; gap:8px;
189
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand2) 100%);
190
+ color:#fff; padding:6px 10px; border-radius:999px;
191
+ font-weight:700; font-size:.85rem; letter-spacing:.2px;
192
+ box-shadow: 0 6px 14px rgba(14,116,144,.22);
 
193
  }}
194
+ .chip .dot {{
195
+ width: 26px; height: 26px; border-radius: 8px;
196
+ background: rgba(255,255,255,.18);
197
+ display:grid; place-items:center; overflow:hidden;
 
198
  }}
199
+ .chip .dot img {{ width:18px; height:18px; display:block; }}
 
200
 
201
  .card h3 {{
202
+ margin: 8px 0 0; font-size: 1.05rem; font-weight: 800; color:#0b1220;
203
  }}
204
  .card p {{
205
+ color:#536071; min-height: 32px; margin: 4px 8px 0; font-size: .96rem;
206
  }}
207
 
208
  /* BUTTON */
 
211
  border:1px solid rgba(14,116,144,0.25); text-decoration:none;
212
  background: linear-gradient(90deg, var(--brand) 0%, var(--brand2) 100%);
213
  color: white; font-weight: 600; letter-spacing:.2px;
214
+ margin: 10px auto 0;
215
+ box-shadow: 0 6px 18px rgba(20,184,166,.26);
216
  }}
217
  .btn:hover {{
218
  filter: brightness(0.98) saturate(1.05);
219
  transform: translateY(-1px);
220
+ box-shadow: 0 12px 28px rgba(20,184,166,.34);
221
  }}
222
 
223
+ .footer {{ text-align:center; color:#3f4a5a; font-size:0.98em; margin-top: 24px; }}
224
+ .footer hr {{ margin: 12px 0; border-color: rgba(0,0,0,.08); }}
225
  </style>
226
  """,
227
  unsafe_allow_html=True,
 
252
  )
253
 
254
  # ========= CARDS =========
255
+ def card_chip(icon_path: Path | None) -> str:
256
+ icon_html = f"{tiny_icon_html(icon_path)}" if icon_path else ""
257
+ return f"""
258
+ <div class="chip">
259
+ <div class="pill">
260
+ <div class="dot">{icon_html}</div>
261
+ {escape(SUITE_NAME)}
262
+ </div>
263
+ </div>
264
+ """
265
+
266
  def app_card(app: dict) -> str:
267
  target = "_blank" if OPEN_IN_NEW_TAB else "_self"
 
268
  return (
269
  f"<div class='card'>"
270
+ + card_chip(app.get("icon"))
271
  + f"<h3>{escape(app['title'])}</h3>"
272
  + f"<p>{escape(app['blurb'])}</p>"
273
  + f"<a class='btn' href='{escape(app['url'])}' target='{target}' rel='noopener'>{escape(BUTTON_TEXT)}</a>"