UCS2014 commited on
Commit
dd16bfb
·
verified ·
1 Parent(s): d5b988e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -75
app.py CHANGED
@@ -11,22 +11,49 @@ ASSETS = BASE_DIR / "assets"
11
  # ========= META =========
12
  st.set_page_config(page_title="ST_LOG SUITE — Apps", page_icon="🧭", layout="wide")
13
 
14
- # ========= SUITE / BRAND =========
15
  SUITE_NAME = "ST_LOG SUITE"
16
  SUITE_TAGLINE = "Generating AI-Based Well Logging Profiles While Drilling"
17
 
18
- # Buttons: deep navy for strong contrast
19
- BTN_DARK_1 = "#0B1220"
20
- BTN_DARK_2 = "#1F2937"
 
 
 
 
21
 
22
- # Suite strip base (navy bg). Text will be gold.
23
- STRIP_BG_1 = "#0B1220"
24
- STRIP_BG_2 = "#1F2937"
25
- GOLD_TEXT = "#EAB308" # gold text inside the strip
 
 
 
26
 
27
- # Per-card options
28
- SHOW_CARD_CHIP = False # small chip inside each card? (False = cleaner)
29
- USE_TINTED_CARD_BG = False # try soft tints per app background
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  # ========= ASSETS =========
32
  HERO_LOGO = ASSETS / "AI_Suite_Log_logo.png"
@@ -60,8 +87,7 @@ APPS = [
60
 
61
  # ========= HELPERS =========
62
  def data_uri(path: Path) -> str | None:
63
- if not path or not path.exists():
64
- return None
65
  mime, _ = mimetypes.guess_type(path.name)
66
  if not mime: mime = "image/png"
67
  b64 = base64.b64encode(path.read_bytes()).decode("utf-8")
@@ -69,23 +95,52 @@ def data_uri(path: Path) -> str | None:
69
 
70
  def img_tag(path: Path, alt: str, cls: str = "", style: str = "") -> str:
71
  uri = data_uri(path)
72
- if not uri:
73
- return ""
74
  cls_attr = f' class="{cls}"' if cls else ""
75
  style_attr = f' style="{style}"' if style else ""
76
  return f'<img{cls_attr}{style_attr} src="{uri}" alt="{escape(alt)}" />'
77
 
78
- # ========= STYLES =========
79
  st.markdown(f"""
80
  <style>
81
  :root {{
82
- --btn1: {BTN_DARK_1};
83
- --btn2: {BTN_DARK_2};
84
- --stripBg1: {STRIP_BG_1};
85
- --stripBg2: {STRIP_BG_2};
86
- --stripGold: {GOLD_TEXT};
87
- --cardStroke: #0B1220; /* dark outline */
88
- --cardStrokeHover: #1E293B;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  }}
90
 
91
  html, body, [data-testid="stAppViewContainer"] {{ height: 100%; }}
@@ -98,7 +153,7 @@ st.markdown(f"""
98
  min-height: 100vh;
99
  display: flex; flex-direction: column;
100
  gap: 14px;
101
- padding: 28px 0 28px !important; /* smaller top padding since strip sits at top-left */
102
  background:
103
  radial-gradient(980px 460px at 50% -140px,
104
  rgba(2,12,30,0.06) 0%,
@@ -109,112 +164,118 @@ st.markdown(f"""
109
 
110
  /* ===== TOP-LEFT STRIP ROW ===== */
111
  .suite-row {{
112
- display:flex; align-items:center; gap:12px;
113
- justify-content:flex-start;
114
- margin: 0 0 8px 0; flex-wrap: wrap;
115
  }}
116
  .suite-pill {{
117
- background: linear-gradient(90deg, var(--stripBg1) 0%, var(--stripBg2) 100%);
118
- color: var(--stripGold); padding:8px 14px; border-radius:999px;
119
- font-weight:800; letter-spacing:.25px;
 
 
 
120
  box-shadow: 0 6px 14px rgba(2,12,30,.18);
121
  white-space: nowrap;
122
  }}
123
  .suite-tagline {{
124
- color:#344054; font-weight:600; opacity:.95; white-space: nowrap;
 
 
125
  }}
126
 
127
  /* HERO LOGO (below the strip) */
128
- .hero {{ text-align:center; margin: 0 0 6px; }}
129
  .hero img {{
130
- width: 520px; max-width: 92vw; height: auto;
131
- display:block; margin: 0 auto 6px;
132
  filter: drop-shadow(0 6px 16px rgba(0,0,0,.10));
133
  }}
134
 
135
- /* GRID (3 → 2 → 1) */
136
  .grid {{
137
  display: grid;
138
- grid-template-columns: repeat(3, 340px);
139
- gap: 40px;
140
  justify-content: center;
141
  align-items: stretch;
142
  margin-top: 10px;
143
  }}
144
  @media (max-width: 1120px) {{
145
- .grid {{ grid-template-columns: repeat(2, 340px); gap: 28px; }}
146
  }}
147
  @media (max-width: 720px) {{
148
  .grid {{ grid-template-columns: 1fr; }}
149
  }}
150
 
151
- /* CARD — dark outline + premium elevation */
152
  .card {{
153
  position: relative;
154
- width: 340px;
155
- border-radius:22px;
156
- padding: 24px 20px 20px;
157
- background: var(--card-bg, linear-gradient(#FFFFFF, #FBFCFE));
158
- border: 2px solid var(--card-stroke, var(--cardStroke));
 
159
  box-shadow:
160
- 0 10px 32px rgba(2,20,35,.10),
161
- 0 1px 0 rgba(255,255,255,0.85) inset;
 
162
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease, filter .18s ease;
163
  text-align:center; display:flex; flex-direction:column; gap:16px;
164
  align-items: center;
165
  }}
166
  .card:hover {{
167
- transform: translateY(-4px);
168
- border-color: var(--cardStrokeHover);
169
- box-shadow: 0 18px 52px rgba(2,20,35,.16);
170
- filter: saturate(1.02);
 
 
 
171
  }}
172
 
173
- /* (optional) small chip inside each card */
174
  .suite-chip {{
175
  position: absolute; top: 12px; right: 12px;
176
- background: linear-gradient(90deg, var(--stripBg1) 0%, var(--stripBg2) 100%);
177
- color: var(--stripGold); padding:6px 10px; border-radius:999px;
178
- font-weight:700; font-size:.82rem; letter-spacing:.2px;
179
  box-shadow: 0 6px 14px rgba(2,12,30,.18);
180
  }}
181
 
182
- /* Big round icon */
183
  .icon-wrap {{
184
- width: 118px; height: 118px; border-radius: 9999px;
185
  background: #F1F5F9;
186
  display:grid; place-items:center;
187
  border: 1px solid rgba(12,18,32,0.10);
188
  box-shadow: inset 0 1px 0 rgba(255,255,255,.95), 0 10px 22px rgba(2,20,35,.07);
189
  }}
190
  .icon-wrap img {{
191
- width: 106px; height: 106px; border-radius:9999px; display:block;
192
  }}
193
 
194
  .card h3 {{
195
- margin: 0; font-size: 1.55rem; font-weight: 900; color:#0b1220;
196
  letter-spacing: .15px;
197
  }}
198
  .card p {{
199
- color:#566275; min-height: 40px; margin: 0 10px; font-size: 1.0rem;
200
  }}
201
 
202
- /* BUTTON (navy) */
203
  .btn {{
204
- display:inline-block; padding:12px 20px; border-radius:14px;
205
  border: 1px solid rgba(11,18,32,.45);
206
- background: linear-gradient(180deg, var(--btn1) 0%, var(--btn2) 100%);
207
- font-weight: 800; letter-spacing:.3px;
208
  margin: 6px auto 0;
209
  box-shadow: 0 12px 28px rgba(11,18,32,.28), inset 0 1px 0 rgba(255,255,255,.10);
210
  }}
211
-
212
  /* Force white text + no underline on CTA in ALL states */
213
  a.btn, a.btn:link, a.btn:visited, a.btn:hover, a.btn:active, a.btn:focus {{
214
- color: #ffffff !important;
215
- text-decoration: none !important;
216
  }}
217
-
218
  .btn:hover {{
219
  filter: brightness(1.03) saturate(1.04);
220
  transform: translateY(-1px);
@@ -230,7 +291,7 @@ st.markdown(f"""
230
  </style>
231
  """, unsafe_allow_html=True)
232
 
233
- # ========= TOP-LEFT STRIP (then hero below) =========
234
  st.markdown(
235
  f"""
236
  <div class="suite-row">
@@ -241,19 +302,19 @@ st.markdown(
241
  unsafe_allow_html=True,
242
  )
243
 
244
- # ========= HERO (logo below the strip) =========
245
  hero_html = img_tag(HERO_LOGO, "ST_LOG SUITE")
246
  st.markdown(f"<div class='hero'>{hero_html}</div>", unsafe_allow_html=True)
247
 
248
- # ========= CARDS =========
249
  def app_card(app: dict) -> str:
250
- # choose background: white vs subtle tint
251
- tint = app.get("tint") if USE_TINTED_CARD_BG else "linear-gradient(#FFFFFF, #FBFCFE)"
252
  icon_html = img_tag(app.get("icon"), "icon",
253
- style="width:106px;height:106px;border-radius:9999px;") if app.get("icon") and app["icon"].exists() else ""
 
254
  target = "_self"
255
  chip = f"<div class='suite-chip'>{escape(SUITE_NAME)}</div>" if SHOW_CARD_CHIP else ""
256
- style_vars = f"--card-bg:{tint}; --card-stroke: var(--cardStroke);"
257
  return (
258
  f"<div class='card' style='{style_vars}'>"
259
  + chip
@@ -267,7 +328,7 @@ def app_card(app: dict) -> str:
267
  cards_html = "".join(app_card(a) for a in APPS)
268
  st.markdown(f"<div class='grid'>{cards_html}</div>", unsafe_allow_html=True)
269
 
270
- # ========= FOOTER =========
271
  st.markdown(
272
  """
273
  <hr>
 
11
  # ========= META =========
12
  st.set_page_config(page_title="ST_LOG SUITE — Apps", page_icon="🧭", layout="wide")
13
 
14
+ # ========= TEXT =========
15
  SUITE_NAME = "ST_LOG SUITE"
16
  SUITE_TAGLINE = "Generating AI-Based Well Logging Profiles While Drilling"
17
 
18
+ # ========= COLOR PALETTE =========
19
+ NAVY_900 = "#0B1220"
20
+ NAVY_700 = "#1F2937"
21
+ SLATE_600 = "#344054"
22
+ PAPER_TOP = "#FFFFFF"
23
+ PAPER_BOT = "#FBFCFE"
24
+ GOLD = "#EAB308"
25
 
26
+ # ========= SIZE & SPACING CONTROLS (EDIT THESE) =========
27
+ TOP_PADDING_PX = 40 # top padding of the whole page
28
+ STRIP_GAP_PX = 10 # space between pill and tagline
29
+ STRIP_PILL_PAD_V_PX = 8
30
+ STRIP_PILL_PAD_H_PX = 14
31
+ STRIP_PILL_FONT_PX = 16
32
+ TAGLINE_FONT_PX = 15
33
 
34
+ HERO_LOGO_WIDTH_PX = 520 # width of the hero logo
35
+ HERO_MARGIN_BOTTOM_PX= 6 # space under the hero logo
36
+
37
+ GRID_GAP_PX = 50 # space between cards
38
+ CARD_WIDTH_PX = 340 # card width
39
+ CARD_RADIUS_PX = 22
40
+ CARD_BORDER_PX = 2
41
+ CARD_PAD_V_PX = 24
42
+ CARD_PAD_H_PX = 20
43
+
44
+ ICON_DIAM_PX = 118 # outer circle
45
+ ICON_IMG_PX = 106 # image inside the circle
46
+
47
+ TITLE_FONT_PX = 25 # app title size
48
+ BLURB_FONT_PX = 16
49
+ BUTTON_FONT_PX = 16
50
+ BUTTON_PAD_V_PX = 12
51
+ BUTTON_PAD_H_PX = 20
52
+ BUTTON_RADIUS_PX = 14
53
+
54
+ # ========= BEHAVIOR / OPTIONS =========
55
+ SHOW_CARD_CHIP = False # show small suite chip inside each card?
56
+ USE_TINTED_CARD_BG = True # very light background tint per card (3–5%)
57
 
58
  # ========= ASSETS =========
59
  HERO_LOGO = ASSETS / "AI_Suite_Log_logo.png"
 
87
 
88
  # ========= HELPERS =========
89
  def data_uri(path: Path) -> str | None:
90
+ if not path or not path.exists(): return None
 
91
  mime, _ = mimetypes.guess_type(path.name)
92
  if not mime: mime = "image/png"
93
  b64 = base64.b64encode(path.read_bytes()).decode("utf-8")
 
95
 
96
  def img_tag(path: Path, alt: str, cls: str = "", style: str = "") -> str:
97
  uri = data_uri(path)
98
+ if not uri: return ""
 
99
  cls_attr = f' class="{cls}"' if cls else ""
100
  style_attr = f' style="{style}"' if style else ""
101
  return f'<img{cls_attr}{style_attr} src="{uri}" alt="{escape(alt)}" />'
102
 
103
+ # ========= CSS =========
104
  st.markdown(f"""
105
  <style>
106
  :root {{
107
+ /* sizes */
108
+ --top-pad: {TOP_PADDING_PX}px;
109
+ --strip-gap: {STRIP_GAP_PX}px;
110
+ --strip-pill-pv: {STRIP_PILL_PAD_V_PX}px;
111
+ --strip-pill-ph: {STRIP_PILL_PAD_H_PX}px;
112
+ --strip-pill-fs: {STRIP_PILL_FONT_PX}px;
113
+ --tagline-fs: {TAGLINE_FONT_PX}px;
114
+
115
+ --hero-w: {HERO_LOGO_WIDTH_PX}px;
116
+ --hero-mb: {HERO_MARGIN_BOTTOM_PX}px;
117
+
118
+ --grid-gap: {GRID_GAP_PX}px;
119
+ --card-w: {CARD_WIDTH_PX}px;
120
+ --card-r: {CARD_RADIUS_PX}px;
121
+ --card-bw: {CARD_BORDER_PX}px;
122
+ --card-pv: {CARD_PAD_V_PX}px;
123
+ --card-ph: {CARD_PAD_H_PX}px;
124
+
125
+ --icon-d: {ICON_DIAM_PX}px;
126
+ --icon-img: {ICON_IMG_PX}px;
127
+
128
+ --title-fs: {TITLE_FONT_PX}px;
129
+ --blurb-fs: {BLURB_FONT_PX}px;
130
+ --btn-fs: {BUTTON_FONT_PX}px;
131
+ --btn-pv: {BUTTON_PAD_V_PX}px;
132
+ --btn-ph: {BUTTON_PAD_H_PX}px;
133
+ --btn-r: {BUTTON_RADIUS_PX}px;
134
+
135
+ /* colors */
136
+ --navy1: {NAVY_900};
137
+ --navy2: {NAVY_700};
138
+ --gold: {GOLD};
139
+ --slate6:{SLATE_600};
140
+
141
+ /* outlines / 3D */
142
+ --card-stroke: {NAVY_900};
143
+ --card-stroke-hover: #1E293B;
144
  }}
145
 
146
  html, body, [data-testid="stAppViewContainer"] {{ height: 100%; }}
 
153
  min-height: 100vh;
154
  display: flex; flex-direction: column;
155
  gap: 14px;
156
+ padding: var(--top-pad) 0 28px !important;
157
  background:
158
  radial-gradient(980px 460px at 50% -140px,
159
  rgba(2,12,30,0.06) 0%,
 
164
 
165
  /* ===== TOP-LEFT STRIP ROW ===== */
166
  .suite-row {{
167
+ display:flex; align-items:center; gap: var(--strip-gap);
168
+ justify-content:flex-start; flex-wrap: wrap;
 
169
  }}
170
  .suite-pill {{
171
+ background: linear-gradient(90deg, var(--navy1) 0%, var(--navy2) 100%);
172
+ color: var(--gold);
173
+ padding: var(--strip-pill-pv) var(--strip-pill-ph);
174
+ border-radius: 999px;
175
+ font-weight: 800; letter-spacing: .25px;
176
+ font-size: var(--strip-pill-fs);
177
  box-shadow: 0 6px 14px rgba(2,12,30,.18);
178
  white-space: nowrap;
179
  }}
180
  .suite-tagline {{
181
+ color: var(--slate6); font-weight: 600; opacity: .95;
182
+ font-size: var(--tagline-fs);
183
+ white-space: nowrap;
184
  }}
185
 
186
  /* HERO LOGO (below the strip) */
187
+ .hero {{ text-align:center; margin: 0 0 var(--hero-mb); }}
188
  .hero img {{
189
+ width: var(--hero-w); max-width: 92vw; height: auto;
190
+ display:block; margin: 0 auto var(--hero-mb);
191
  filter: drop-shadow(0 6px 16px rgba(0,0,0,.10));
192
  }}
193
 
194
+ /* GRID */
195
  .grid {{
196
  display: grid;
197
+ grid-template-columns: repeat(3, var(--card-w));
198
+ gap: var(--grid-gap);
199
  justify-content: center;
200
  align-items: stretch;
201
  margin-top: 10px;
202
  }}
203
  @media (max-width: 1120px) {{
204
+ .grid {{ grid-template-columns: repeat(2, var(--card-w)); gap: calc(var(--grid-gap) - 12px); }}
205
  }}
206
  @media (max-width: 720px) {{
207
  .grid {{ grid-template-columns: 1fr; }}
208
  }}
209
 
210
+ /* CARD — dark outline + premium 3D look */
211
  .card {{
212
  position: relative;
213
+ width: var(--card-w);
214
+ border-radius: var(--card-r);
215
+ padding: var(--card-pv) var(--card-ph);
216
+ background: var(--card-bg, linear-gradient(180deg, {PAPER_TOP} 0%, {PAPER_BOT} 100%));
217
+ border: var(--card-bw) solid var(--card-stroke);
218
+ /* 3D: dual drop shadows + subtle internal highlights */
219
  box-shadow:
220
+ 0 14px 32px rgba(2,20,35,.12),
221
+ 0 1px 0 rgba(255,255,255,0.90) inset,
222
+ 0 -1px 10px rgba(255,255,255,0.40) inset;
223
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease, filter .18s ease;
224
  text-align:center; display:flex; flex-direction:column; gap:16px;
225
  align-items: center;
226
  }}
227
  .card:hover {{
228
+ transform: translateY(-6px) scale(1.01);
229
+ border-color: var(--card-stroke-hover);
230
+ box-shadow:
231
+ 0 22px 56px rgba(2,20,35,.18),
232
+ 0 1px 0 rgba(255,255,255,0.92) inset,
233
+ 0 -1px 12px rgba(255,255,255,0.45) inset;
234
+ filter: saturate(1.03);
235
  }}
236
 
237
+ /* (optional) chip inside each card */
238
  .suite-chip {{
239
  position: absolute; top: 12px; right: 12px;
240
+ background: linear-gradient(90deg, var(--navy1) 0%, var(--navy2) 100%);
241
+ color: var(--gold); padding: 6px 10px; border-radius: 999px;
242
+ font-weight: 700; font-size: 13px; letter-spacing: .2px;
243
  box-shadow: 0 6px 14px rgba(2,12,30,.18);
244
  }}
245
 
246
+ /* Icon circle */
247
  .icon-wrap {{
248
+ width: var(--icon-d); height: var(--icon-d); border-radius: 9999px;
249
  background: #F1F5F9;
250
  display:grid; place-items:center;
251
  border: 1px solid rgba(12,18,32,0.10);
252
  box-shadow: inset 0 1px 0 rgba(255,255,255,.95), 0 10px 22px rgba(2,20,35,.07);
253
  }}
254
  .icon-wrap img {{
255
+ width: var(--icon-img); height: var(--icon-img); border-radius:9999px; display:block;
256
  }}
257
 
258
  .card h3 {{
259
+ margin: 0; font-size: var(--title-fs); font-weight: 900; color:#0b1220;
260
  letter-spacing: .15px;
261
  }}
262
  .card p {{
263
+ color:#566275; min-height: 40px; margin: 0 10px; font-size: var(--blurb-fs);
264
  }}
265
 
266
+ /* Button (navy) */
267
  .btn {{
268
+ display:inline-block; padding: var(--btn-pv) var(--btn-ph); border-radius: var(--btn-r);
269
  border: 1px solid rgba(11,18,32,.45);
270
+ background: linear-gradient(180deg, var(--navy1) 0%, var(--navy2) 100%);
271
+ font-weight: 800; letter-spacing:.3px; font-size: var(--btn-fs);
272
  margin: 6px auto 0;
273
  box-shadow: 0 12px 28px rgba(11,18,32,.28), inset 0 1px 0 rgba(255,255,255,.10);
274
  }}
 
275
  /* Force white text + no underline on CTA in ALL states */
276
  a.btn, a.btn:link, a.btn:visited, a.btn:hover, a.btn:active, a.btn:focus {{
277
+ color: #ffffff !important; text-decoration: none !important;
 
278
  }}
 
279
  .btn:hover {{
280
  filter: brightness(1.03) saturate(1.04);
281
  transform: translateY(-1px);
 
291
  </style>
292
  """, unsafe_allow_html=True)
293
 
294
+ # ===== TOP-LEFT STRIP (then hero below) =====
295
  st.markdown(
296
  f"""
297
  <div class="suite-row">
 
302
  unsafe_allow_html=True,
303
  )
304
 
305
+ # ===== HERO (logo below the strip) =====
306
  hero_html = img_tag(HERO_LOGO, "ST_LOG SUITE")
307
  st.markdown(f"<div class='hero'>{hero_html}</div>", unsafe_allow_html=True)
308
 
309
+ # ===== CARDS =====
310
  def app_card(app: dict) -> str:
311
+ tint = app.get("tint") if USE_TINTED_CARD_BG else f"linear-gradient(180deg, {PAPER_TOP} 0%, {PAPER_BOT} 100%)"
 
312
  icon_html = img_tag(app.get("icon"), "icon",
313
+ style=f"width:{ICON_IMG_PX}px;height:{ICON_IMG_PX}px;border-radius:9999px;") \
314
+ if app.get("icon") and app["icon"].exists() else ""
315
  target = "_self"
316
  chip = f"<div class='suite-chip'>{escape(SUITE_NAME)}</div>" if SHOW_CARD_CHIP else ""
317
+ style_vars = f"--card-bg:{tint};"
318
  return (
319
  f"<div class='card' style='{style_vars}'>"
320
  + chip
 
328
  cards_html = "".join(app_card(a) for a in APPS)
329
  st.markdown(f"<div class='grid'>{cards_html}</div>", unsafe_allow_html=True)
330
 
331
+ # ===== FOOTER =====
332
  st.markdown(
333
  """
334
  <hr>