mgbam commited on
Commit
88bd42a
ยท
verified ยท
1 Parent(s): 8c9aece

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +110 -112
app.py CHANGED
@@ -3,7 +3,6 @@ import json
3
  import zipfile
4
  import io
5
  import time
6
- import textwrap
7
  import requests
8
  from agents import TopicAgent, ContentAgent, SlideAgent, CodeAgent, DesignAgent, VoiceoverAgent
9
 
@@ -22,24 +21,51 @@ voiceover_agent = VoiceoverAgent()
22
  st.set_page_config(
23
  page_title="Workshop in a Box Pro",
24
  layout="wide",
25
- initial_sidebar_state="expanded",
26
  page_icon="๐ŸŽ“"
27
  )
28
 
29
- # Custom CSS for premium styling
30
  st.markdown("""
31
  <style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  .stApp {
33
  background: linear-gradient(135deg, #0f2027 0%, #203a43 100%);
34
  color: #fff;
35
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
36
  }
 
37
  .stTextInput>div>div>input {
38
  background-color: rgba(255,255,255,0.1) !important;
39
  color: white !important;
40
  border: 1px solid #4CAF50;
41
  border-radius: 8px;
42
  }
 
43
  .stButton>button {
44
  background: linear-gradient(to right, #0d8bf2, #04befe) !important;
45
  color: white !important;
@@ -51,20 +77,11 @@ st.markdown("""
51
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
52
  transition: all 0.3s ease;
53
  }
54
- .stButton>button:hover {
55
- transform: translateY(-2px);
56
- box-shadow: 0 6px 8px rgba(0,0,0,0.15);
57
- }
58
  .stDownloadButton>button {
59
  background: linear-gradient(to right, #00c853, #64dd17) !important;
60
  }
61
- .stExpander {
62
- background: rgba(15, 32, 39, 0.8) !important;
63
- border-radius: 10px;
64
- padding: 20px;
65
- border: 1px solid #1e88e5;
66
- box-shadow: 0 4px 20px rgba(0,0,0,0.25);
67
- }
68
  .premium-badge {
69
  background: linear-gradient(45deg, #ffd700, #ff9800);
70
  color: #000;
@@ -75,18 +92,7 @@ st.markdown("""
75
  display: inline-block;
76
  margin-left: 10px;
77
  }
78
- .section-header {
79
- border-left: 4px solid #0d8bf2;
80
- padding-left: 15px;
81
- margin-top: 30px;
82
- }
83
- .testimonial {
84
- background: rgba(255,255,255,0.05);
85
- border-radius: 10px;
86
- padding: 15px;
87
- margin: 15px 0;
88
- border-left: 4px solid #00c853;
89
- }
90
  .pricing-card {
91
  background: rgba(255,255,255,0.05);
92
  border-radius: 10px;
@@ -94,16 +100,15 @@ st.markdown("""
94
  margin: 10px 0;
95
  border: 1px solid #0d8bf2;
96
  }
97
- .executive-summary {
98
- background: linear-gradient(to right, #1a2980, #26d0ce);
99
- padding: 25px;
100
- border-radius: 15px;
101
- margin-bottom: 25px;
102
- box-shadow: 0 10px 20px rgba(0,0,0,0.2);
103
- }
104
- .stAlert {
105
  border-radius: 10px;
 
 
 
106
  }
 
107
  .disabled-widget {
108
  opacity: 0.6;
109
  pointer-events: none;
@@ -130,7 +135,7 @@ if 'generating' not in st.session_state:
130
  if 'voiceovers' not in st.session_state:
131
  st.session_state.voiceovers = {}
132
  if 'selected_voice' not in st.session_state:
133
- st.session_state.selected_voice = "21m00Tcm4TlvDq8ikWAM" # Default voice ID
134
  if 'duration' not in st.session_state:
135
  st.session_state.duration = 4.0
136
  if 'difficulty' not in st.session_state:
@@ -147,22 +152,17 @@ if 'premium_mode' not in st.session_state:
147
  # Sidebar configuration
148
  with st.sidebar:
149
  st.header("โš™๏ธ Executive Workshop Configuration")
150
-
151
- # Workshop topic input
152
  st.session_state.workshop_topic = st.text_input(
153
  "Workshop Focus",
154
  st.session_state.workshop_topic,
155
  help="Strategic business topic (e.g., 'AI for Financial Services Transformation')"
156
  )
157
 
158
- # Check if topic is empty
159
  topic_empty = st.session_state.workshop_topic.strip() == ""
160
 
161
- # Show warning if topic is empty
162
  if topic_empty:
163
  st.warning("Please enter a strategic workshop focus to enable configuration")
164
 
165
- # Always show config controls but disable when topic is empty
166
  st.session_state.duration = st.slider(
167
  "Duration (hours)",
168
  2.0, 8.0, st.session_state.duration, 0.5,
@@ -195,7 +195,6 @@ with st.sidebar:
195
  disabled=topic_empty
196
  )
197
 
198
- # Voice selection
199
  if st.session_state.include_voiceover and not topic_empty:
200
  st.subheader("๐ŸŽ™๏ธ Voice Selection")
201
  voices = voiceover_agent.get_voices()
@@ -213,7 +212,6 @@ with st.sidebar:
213
  else:
214
  st.warning("ElevenLabs API key not set. Voiceovers disabled.")
215
 
216
- # Quality assurance checkbox
217
  st.divider()
218
  st.markdown("**Quality Assurance**")
219
  st.session_state.premium_mode = st.checkbox(
@@ -223,7 +221,6 @@ with st.sidebar:
223
  disabled=topic_empty
224
  )
225
 
226
- # Generate button - disabled when topic is empty
227
  generate_disabled = topic_empty or st.session_state.generating
228
  if st.button(
229
  "โœจ Generate Premium Workshop",
@@ -232,14 +229,13 @@ with st.sidebar:
232
  disabled=generate_disabled
233
  ):
234
  st.session_state.generating = True
235
- st.session_state.voiceovers = {} # Reset previous voiceovers
236
 
237
  # Generation pipeline
238
  if st.session_state.generating and not topic_empty:
239
  with st.spinner(f"๐Ÿš€ Creating your executive workshop on '{st.session_state.workshop_topic}'..."):
240
  start_time = time.time()
241
 
242
- # Agent pipeline
243
  outline = topic_agent.generate_outline(
244
  st.session_state.workshop_topic,
245
  st.session_state.duration,
@@ -250,7 +246,6 @@ if st.session_state.generating and not topic_empty:
250
  code_labs = code_agent.generate_code(content) if st.session_state.include_code else None
251
  design_url = design_agent.generate_design(slides) if st.session_state.include_design else None
252
 
253
- # Generate voiceovers if enabled
254
  voiceovers = {}
255
  if st.session_state.include_voiceover and voiceover_agent.api_key:
256
  for i, module in enumerate(content.get("modules", [])):
@@ -263,7 +258,6 @@ if st.session_state.generating and not topic_empty:
263
  if audio_data:
264
  voiceovers[f"module_{i+1}_intro.mp3"] = audio_data
265
 
266
- # Prepare download package
267
  zip_buffer = io.BytesIO()
268
  with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED) as zip_file:
269
  zip_file.writestr("executive_summary.json", json.dumps(outline, indent=2))
@@ -277,11 +271,9 @@ if st.session_state.generating and not topic_empty:
277
  zip_file.writestr("slide_design.png", img_data)
278
  except Exception as e:
279
  st.error(f"Design download error: {str(e)}")
280
- # Add voiceovers to ZIP
281
  for filename, audio_data in voiceovers.items():
282
  zip_file.writestr(f"voiceovers/{filename}", audio_data)
283
 
284
- # Store results
285
  st.session_state.outline = outline
286
  st.session_state.content = content
287
  st.session_state.slides = slides
@@ -293,11 +285,10 @@ if st.session_state.generating and not topic_empty:
293
  st.session_state.generated = True
294
  st.session_state.generating = False
295
 
296
- # Results display
297
  if st.session_state.generated and not topic_empty:
298
  st.success(f"โœ… Executive workshop generated in {st.session_state.gen_time} seconds!")
299
 
300
- # Download button
301
  st.download_button(
302
  label="๐Ÿ“ฅ Download Executive Package",
303
  data=st.session_state.zip_buffer.getvalue(),
@@ -306,65 +297,75 @@ if st.session_state.generated and not topic_empty:
306
  use_container_width=True
307
  )
308
 
309
- # Executive summary
310
- with st.expander("๐Ÿ“Š Executive Overview", expanded=True):
311
- st.markdown(f"<div class='executive-summary'>", unsafe_allow_html=True)
312
- st.subheader(st.session_state.outline.get("title", "Strategic Workshop"))
313
- st.caption(f"Duration: {st.session_state.outline.get('duration', '4 hours')} | Level: {st.session_state.outline.get('difficulty', 'Executive')}")
314
-
315
- st.markdown("**Business Value Proposition**")
316
- if "learning_goals" in st.session_state.outline:
317
- for goal in st.session_state.outline["learning_goals"]:
318
- st.markdown(f"- {goal}")
319
-
320
- st.markdown("**Key Deliverables**")
321
- st.markdown("- Boardroom-ready presentation\n"
322
- "- Implementation toolkit\n"
323
- "- ROI calculation framework\n"
324
- "- Enterprise integration guide")
325
- st.markdown("</div>", unsafe_allow_html=True)
326
 
327
- # Workshop content
328
- with st.expander("๐Ÿ“ Strategic Content Framework"):
329
- if "modules" in st.session_state.content:
330
- for module in st.session_state.content["modules"]:
331
- st.subheader(module.get("title", "Business Module"))
332
- st.markdown(module.get("script", ""))
333
-
334
- st.markdown("**Executive Discussion Points**")
335
- if "discussion_questions" in module:
336
- for q in module["discussion_questions"]:
337
- st.markdown(f"- **{q.get('question', '')}**")
338
- st.caption(q.get("response", ""))
 
 
 
339
 
340
- # Slide preview
341
- with st.expander("๐Ÿ–ฅ๏ธ Boardroom Presentation Preview"):
342
- st.markdown("```markdown\n" + textwrap.dedent(st.session_state.slides[:2000]) + "\n```")
 
 
343
 
344
- # Technical implementation
345
  if st.session_state.code_labs:
346
- with st.expander("๐Ÿ’ป Enterprise Implementation Toolkit"):
347
- st.code(st.session_state.code_labs)
 
 
348
 
349
- # Design preview
350
  if st.session_state.design_url:
351
- with st.expander("๐ŸŽจ Premium Visual Design"):
352
- try:
353
- st.image(st.session_state.design_url, caption="Corporate Slide Design")
354
- except:
355
- st.warning("Design preview unavailable")
 
 
356
 
357
- # Voiceover player
358
  if st.session_state.voiceovers:
359
- with st.expander("๐Ÿ”Š Voiceover Previews"):
360
- for i, (filename, audio_bytes) in enumerate(st.session_state.voiceovers.items()):
361
- module_num = filename.split("_")[1]
362
- st.subheader(f"Module {module_num} Introduction")
363
- st.audio(audio_bytes, format="audio/mp3")
 
 
364
 
365
- # Executive engagement section
366
- st.divider()
367
- st.subheader("๐Ÿš€ Premium Corporate Offering")
368
  st.markdown(f"""
369
  ### {st.session_state.workshop_topic} Executive Program
370
  <div class="pricing-card">
@@ -390,9 +391,8 @@ st.markdown(f"""
390
  - Executive briefing package
391
  """, unsafe_allow_html=True)
392
 
393
- # Testimonials
394
- st.divider()
395
- st.subheader("๐Ÿ’ผ Executive Testimonials")
396
  st.markdown("""
397
  <div class="testimonial">
398
  <p>"This platform helped us create a $50K training program in one afternoon. The ROI was immediate."</p>
@@ -404,23 +404,22 @@ st.markdown("""
404
  </div>
405
  """, unsafe_allow_html=True)
406
 
407
- # CTA
408
- st.divider()
409
  col1, col2 = st.columns(2)
410
  with col1:
411
  st.link_button("๐Ÿ“… Book Strategy Session", "https://calendly.com/your-link", use_container_width=True)
412
  with col2:
413
  st.link_button("๐Ÿ’ผ Enterprise Solutions", "https://your-company.com/enterprise", use_container_width=True)
414
 
415
- # Footer
416
- st.divider()
417
  st.markdown("""
418
- <div style="text-align: center; padding: 20px; color: #aaa;">
419
  Workshop in a Box Proยฎ | Enterprise-Grade AI Training Solutions | ยฉ 2025
420
  </div>
421
  """, unsafe_allow_html=True)
422
 
423
- # Debug info
424
  with st.sidebar:
425
  st.divider()
426
  if hasattr(topic_agent, 'openai_client') and topic_agent.openai_client:
@@ -442,5 +441,4 @@ with st.sidebar:
442
  - Professional slide designs
443
  - Real-world case studies
444
  - Practical code labs
445
- """)
446
-
 
3
  import zipfile
4
  import io
5
  import time
 
6
  import requests
7
  from agents import TopicAgent, ContentAgent, SlideAgent, CodeAgent, DesignAgent, VoiceoverAgent
8
 
 
21
  st.set_page_config(
22
  page_title="Workshop in a Box Pro",
23
  layout="wide",
 
24
  page_icon="๐ŸŽ“"
25
  )
26
 
27
+ # Custom CSS for permanent visibility
28
  st.markdown("""
29
  <style>
30
+ /* Permanent visibility styles */
31
+ .workshop-container {
32
+ background: rgba(255, 255, 255, 0.05);
33
+ border-radius: 10px;
34
+ padding: 25px;
35
+ margin-bottom: 20px;
36
+ border: 1px solid #0d8bf2;
37
+ box-shadow: 0 4px 20px rgba(0,0,0,0.25);
38
+ }
39
+
40
+ .section-header {
41
+ border-left: 4px solid #0d8bf2;
42
+ padding-left: 15px;
43
+ margin-top: 10px;
44
+ margin-bottom: 20px;
45
+ }
46
+
47
+ .executive-summary {
48
+ background: linear-gradient(to right, #1a2980, #26d0ce);
49
+ padding: 25px;
50
+ border-radius: 15px;
51
+ margin-bottom: 25px;
52
+ box-shadow: 0 10px 20px rgba(0,0,0,0.2);
53
+ }
54
+
55
+ /* Override expander styles */
56
  .stApp {
57
  background: linear-gradient(135deg, #0f2027 0%, #203a43 100%);
58
  color: #fff;
59
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
60
  }
61
+
62
  .stTextInput>div>div>input {
63
  background-color: rgba(255,255,255,0.1) !important;
64
  color: white !important;
65
  border: 1px solid #4CAF50;
66
  border-radius: 8px;
67
  }
68
+
69
  .stButton>button {
70
  background: linear-gradient(to right, #0d8bf2, #04befe) !important;
71
  color: white !important;
 
77
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
78
  transition: all 0.3s ease;
79
  }
80
+
 
 
 
81
  .stDownloadButton>button {
82
  background: linear-gradient(to right, #00c853, #64dd17) !important;
83
  }
84
+
 
 
 
 
 
 
85
  .premium-badge {
86
  background: linear-gradient(45deg, #ffd700, #ff9800);
87
  color: #000;
 
92
  display: inline-block;
93
  margin-left: 10px;
94
  }
95
+
 
 
 
 
 
 
 
 
 
 
 
96
  .pricing-card {
97
  background: rgba(255,255,255,0.05);
98
  border-radius: 10px;
 
100
  margin: 10px 0;
101
  border: 1px solid #0d8bf2;
102
  }
103
+
104
+ .testimonial {
105
+ background: rgba(255,255,255,0.05);
 
 
 
 
 
106
  border-radius: 10px;
107
+ padding: 15px;
108
+ margin: 15px 0;
109
+ border-left: 4px solid #00c853;
110
  }
111
+
112
  .disabled-widget {
113
  opacity: 0.6;
114
  pointer-events: none;
 
135
  if 'voiceovers' not in st.session_state:
136
  st.session_state.voiceovers = {}
137
  if 'selected_voice' not in st.session_state:
138
+ st.session_state.selected_voice = "21m00Tcm4TlvDq8ikWAM"
139
  if 'duration' not in st.session_state:
140
  st.session_state.duration = 4.0
141
  if 'difficulty' not in st.session_state:
 
152
  # Sidebar configuration
153
  with st.sidebar:
154
  st.header("โš™๏ธ Executive Workshop Configuration")
 
 
155
  st.session_state.workshop_topic = st.text_input(
156
  "Workshop Focus",
157
  st.session_state.workshop_topic,
158
  help="Strategic business topic (e.g., 'AI for Financial Services Transformation')"
159
  )
160
 
 
161
  topic_empty = st.session_state.workshop_topic.strip() == ""
162
 
 
163
  if topic_empty:
164
  st.warning("Please enter a strategic workshop focus to enable configuration")
165
 
 
166
  st.session_state.duration = st.slider(
167
  "Duration (hours)",
168
  2.0, 8.0, st.session_state.duration, 0.5,
 
195
  disabled=topic_empty
196
  )
197
 
 
198
  if st.session_state.include_voiceover and not topic_empty:
199
  st.subheader("๐ŸŽ™๏ธ Voice Selection")
200
  voices = voiceover_agent.get_voices()
 
212
  else:
213
  st.warning("ElevenLabs API key not set. Voiceovers disabled.")
214
 
 
215
  st.divider()
216
  st.markdown("**Quality Assurance**")
217
  st.session_state.premium_mode = st.checkbox(
 
221
  disabled=topic_empty
222
  )
223
 
 
224
  generate_disabled = topic_empty or st.session_state.generating
225
  if st.button(
226
  "โœจ Generate Premium Workshop",
 
229
  disabled=generate_disabled
230
  ):
231
  st.session_state.generating = True
232
+ st.session_state.voiceovers = {}
233
 
234
  # Generation pipeline
235
  if st.session_state.generating and not topic_empty:
236
  with st.spinner(f"๐Ÿš€ Creating your executive workshop on '{st.session_state.workshop_topic}'..."):
237
  start_time = time.time()
238
 
 
239
  outline = topic_agent.generate_outline(
240
  st.session_state.workshop_topic,
241
  st.session_state.duration,
 
246
  code_labs = code_agent.generate_code(content) if st.session_state.include_code else None
247
  design_url = design_agent.generate_design(slides) if st.session_state.include_design else None
248
 
 
249
  voiceovers = {}
250
  if st.session_state.include_voiceover and voiceover_agent.api_key:
251
  for i, module in enumerate(content.get("modules", [])):
 
258
  if audio_data:
259
  voiceovers[f"module_{i+1}_intro.mp3"] = audio_data
260
 
 
261
  zip_buffer = io.BytesIO()
262
  with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED) as zip_file:
263
  zip_file.writestr("executive_summary.json", json.dumps(outline, indent=2))
 
271
  zip_file.writestr("slide_design.png", img_data)
272
  except Exception as e:
273
  st.error(f"Design download error: {str(e)}")
 
274
  for filename, audio_data in voiceovers.items():
275
  zip_file.writestr(f"voiceovers/{filename}", audio_data)
276
 
 
277
  st.session_state.outline = outline
278
  st.session_state.content = content
279
  st.session_state.slides = slides
 
285
  st.session_state.generated = True
286
  st.session_state.generating = False
287
 
288
+ # Results display - PERMANENTLY VISIBLE SECTION
289
  if st.session_state.generated and not topic_empty:
290
  st.success(f"โœ… Executive workshop generated in {st.session_state.gen_time} seconds!")
291
 
 
292
  st.download_button(
293
  label="๐Ÿ“ฅ Download Executive Package",
294
  data=st.session_state.zip_buffer.getvalue(),
 
297
  use_container_width=True
298
  )
299
 
300
+ # Executive summary - ALWAYS VISIBLE
301
+ st.markdown("<div class='section-header'><h2>๐Ÿ“Š Executive Overview</h2></div>", unsafe_allow_html=True)
302
+ st.markdown(f"<div class='executive-summary'>", unsafe_allow_html=True)
303
+ st.subheader(st.session_state.outline.get("title", "Strategic Workshop"))
304
+ st.caption(f"Duration: {st.session_state.outline.get('duration', '4 hours')} | Level: {st.session_state.outline.get('difficulty', 'Executive')}")
305
+
306
+ st.markdown("**Business Value Proposition**")
307
+ if "learning_goals" in st.session_state.outline:
308
+ for goal in st.session_state.outline["learning_goals"]:
309
+ st.markdown(f"- {goal}")
310
+
311
+ st.markdown("**Key Deliverables**")
312
+ st.markdown("- Boardroom-ready presentation\n"
313
+ "- Implementation toolkit\n"
314
+ "- ROI calculation framework\n"
315
+ "- Enterprise integration guide")
316
+ st.markdown("</div>", unsafe_allow_html=True)
317
 
318
+ # Workshop content - ALWAYS VISIBLE
319
+ st.markdown("<div class='section-header'><h2>๐Ÿ“ Strategic Content Framework</h2></div>", unsafe_allow_html=True)
320
+ st.markdown("<div class='workshop-container'>", unsafe_allow_html=True)
321
+ if "modules" in st.session_state.content:
322
+ for module in st.session_state.content["modules"]:
323
+ st.subheader(module.get("title", "Business Module"))
324
+ st.markdown(module.get("script", ""))
325
+
326
+ st.markdown("**Executive Discussion Points**")
327
+ if "discussion_questions" in module:
328
+ for q in module["discussion_questions"]:
329
+ st.markdown(f"- **{q.get('question', '')}**")
330
+ st.caption(q.get("response", ""))
331
+ st.divider()
332
+ st.markdown("</div>", unsafe_allow_html=True)
333
 
334
+ # Slide preview - ALWAYS VISIBLE
335
+ st.markdown("<div class='section-header'><h2>๐Ÿ–ฅ๏ธ Boardroom Presentation Preview</h2></div>", unsafe_allow_html=True)
336
+ st.markdown("<div class='workshop-container'>", unsafe_allow_html=True)
337
+ st.markdown(st.session_state.slides[:2000])
338
+ st.markdown("</div>", unsafe_allow_html=True)
339
 
340
+ # Technical implementation - ALWAYS VISIBLE
341
  if st.session_state.code_labs:
342
+ st.markdown("<div class='section-header'><h2>๐Ÿ’ป Enterprise Implementation Toolkit</h2></div>", unsafe_allow_html=True)
343
+ st.markdown("<div class='workshop-container'>", unsafe_allow_html=True)
344
+ st.code(st.session_state.code_labs)
345
+ st.markdown("</div>", unsafe_allow_html=True)
346
 
347
+ # Design preview - ALWAYS VISIBLE
348
  if st.session_state.design_url:
349
+ st.markdown("<div class='section-header'><h2>๐ŸŽจ Premium Visual Design</h2></div>", unsafe_allow_html=True)
350
+ st.markdown("<div class='workshop-container'>", unsafe_allow_html=True)
351
+ try:
352
+ st.image(st.session_state.design_url, caption="Corporate Slide Design")
353
+ except:
354
+ st.warning("Design preview unavailable")
355
+ st.markdown("</div>", unsafe_allow_html=True)
356
 
357
+ # Voiceover player - ALWAYS VISIBLE
358
  if st.session_state.voiceovers:
359
+ st.markdown("<div class='section-header'><h2>๐Ÿ”Š Voiceover Previews</h2></div>", unsafe_allow_html=True)
360
+ st.markdown("<div class='workshop-container'>", unsafe_allow_html=True)
361
+ for i, (filename, audio_bytes) in enumerate(st.session_state.voiceovers.items()):
362
+ module_num = filename.split("_")[1]
363
+ st.subheader(f"Module {module_num} Introduction")
364
+ st.audio(audio_bytes, format="audio/mp3")
365
+ st.markdown("</div>", unsafe_allow_html=True)
366
 
367
+ # Pricing section - ALWAYS VISIBLE
368
+ st.markdown("<div class='section-header'><h2>๐Ÿš€ Premium Corporate Offering</h2></div>", unsafe_allow_html=True)
 
369
  st.markdown(f"""
370
  ### {st.session_state.workshop_topic} Executive Program
371
  <div class="pricing-card">
 
391
  - Executive briefing package
392
  """, unsafe_allow_html=True)
393
 
394
+ # Testimonials - ALWAYS VISIBLE
395
+ st.markdown("<div class='section-header'><h2>๐Ÿ’ผ Executive Testimonials</h2></div>", unsafe_allow_html=True)
 
396
  st.markdown("""
397
  <div class="testimonial">
398
  <p>"This platform helped us create a $50K training program in one afternoon. The ROI was immediate."</p>
 
404
  </div>
405
  """, unsafe_allow_html=True)
406
 
407
+ # CTA - ALWAYS VISIBLE
408
+ st.markdown("<div class='section-header'><h2>Get Started</h2></div>", unsafe_allow_html=True)
409
  col1, col2 = st.columns(2)
410
  with col1:
411
  st.link_button("๐Ÿ“… Book Strategy Session", "https://calendly.com/your-link", use_container_width=True)
412
  with col2:
413
  st.link_button("๐Ÿ’ผ Enterprise Solutions", "https://your-company.com/enterprise", use_container_width=True)
414
 
415
+ # Footer - ALWAYS VISIBLE
 
416
  st.markdown("""
417
+ <div style="text-align: center; padding: 20px; color: #aaa; margin-top: 30px;">
418
  Workshop in a Box Proยฎ | Enterprise-Grade AI Training Solutions | ยฉ 2025
419
  </div>
420
  """, unsafe_allow_html=True)
421
 
422
+ # Debug info - ALWAYS VISIBLE
423
  with st.sidebar:
424
  st.divider()
425
  if hasattr(topic_agent, 'openai_client') and topic_agent.openai_client:
 
441
  - Professional slide designs
442
  - Real-world case studies
443
  - Practical code labs
444
+ """)