')
+ continue
+
+ # ── Bullet ─────────────────────────────────────────────────
+ if stripped and stripped[0] in ("-", "*", "•"):
+ close_lists()
+ if not in_ul and not in_pep:
+ output.append('
"
+ f"Targets: {targets_str} "
+ f"Cycle: {s['cycle']}", meta_s)
+
+ left_content = Table([
+ [desc_para],
+ [Spacer(1, 4)],
+ [pep_pills_tbl],
+ ], colWidths=[pw - 2.0*inch])
+ left_content.setStyle(TableStyle([
+ ("LEFTPADDING", (0,0),(-1,-1), 0),
+ ("RIGHTPADDING", (0,0),(-1,-1), 0),
+ ("TOPPADDING", (0,0),(-1,-1), 0),
+ ("BOTTOMPADDING", (0,0),(-1,-1), 0),
+ ]))
+
+ # Right: pricing box - mid-tier as representative (convert monthly to weekly)
+ wk_price_26 = ps_data['monthly_26wk'] * 12.0 / 52.0
+ wk_price_52 = ps_data['monthly_52wk'] * 12.0 / 52.0
+ price_inner = Table([
+ [Paragraph("52-WEEK · PER WEEK", wk_lbl_s)],
+ [Paragraph(f"${wk_price_52:,.2f}", wk_s)],
+ [HRFlowable(width="80%", thickness=0.5, color=C_BORDER, spaceAfter=2)],
+ [Paragraph("26-WEEK · PER WEEK", wk_lbl_s)],
+ [Paragraph(f"${wk_price_26:,.2f}", pr_s)],
+ ], colWidths=[1.55*inch])
+ price_inner.setStyle(TableStyle([
+ ("ALIGN", (0,0),(-1,-1), "CENTER"),
+ ("TOPPADDING", (0,0),(-1,-1), 2),
+ ("BOTTOMPADDING",(0,0),(-1,-1), 2),
+ ]))
+
+ card_tbl = Table([[left_content, price_inner]], colWidths=[pw - 1.7*inch, 1.7*inch])
+ card_tbl.setStyle(TableStyle([
+ ("BACKGROUND", (0,0),(0,0), C_CARD),
+ ("BACKGROUND", (1,0),(1,0), C_WARMWH),
+ ("BOX", (0,0),(-1,-1),0.75, C_BORDER),
+ ("LINEBEFORE", (1,0),(1,-1), 2, C_ORANGE),
+ ("LEFTPADDING", (0,0),(0,-1), 10), ("RIGHTPADDING", (0,0),(0,-1), 10),
+ ("TOPPADDING", (0,0),(-1,-1),10), ("BOTTOMPADDING",(0,0),(-1,-1),10),
+ ("VALIGN", (0,0),(0,0), "TOP"),
+ ("VALIGN", (1,0),(1,0), "MIDDLE"),
+ ]))
+
+ # Stack name banner
+ sn_banner = banner(Paragraph(f" {sn}", sn_s), colors.HexColor("#012233"), line_below=C_TEAL)
+
+ stack_block = KeepTogether([
+ sn_banner,
+ card_tbl,
+ Spacer(1, 12),
+ ])
+ story.append(stack_block)
+
+ story.append(Paragraph(
+ "* Pricing shown is the mid-tier option. Multiple tier options available with different service levels.", disc_s))
+ story.append(Spacer(1, 6))
+
+ # =========================================================================
+ # PAGE BREAK before the protocol narrative
+ # =========================================================================
+ story.append(PageBreak())
+
+ # ── Protocol narrative with robust markdown parsing ──────────────────────
+
+ hit_treatment_page = False
+ current_pep_hdr = None
+ pending_bullets = []
+
+ skip_headings = {"how your stack works", "your personalized wellness protocol",
+ "your wellness protocol — how it works", "your wellness protocol - how it works"}
+
+ # Condensed styles for the final summary page
+ cond_bullet_s = ps("Cb", fontName="Helvetica", fontSize=8.5, leading=12,
+ textColor=C_NAVY, leftIndent=12, spaceAfter=2)
+ cond_sub_bullet_s = ps("Csb", fontName="Helvetica", fontSize=8, leading=11,
+ textColor=C_NAVY, leftIndent=26, spaceAfter=1)
+ cond_num_s = ps("Cn", fontName="Helvetica", fontSize=8.5, leading=12,
+ textColor=C_NAVY, leftIndent=12, spaceAfter=3)
+ cond_body_s = ps("CB", fontName="Helvetica", fontSize=8.5, leading=12,
+ textColor=C_NAVY, spaceAfter=3)
+ cond_sh_s = ps("CS", fontName="Helvetica-Bold", fontSize=9,
+ textColor=colors.white, spaceBefore=0, spaceAfter=0)
+
+ sub_bullet_s = ps("Sb", fontName="Helvetica", fontSize=9, leading=14,
+ textColor=C_NAVY, leftIndent=28, spaceAfter=2)
+
+ for raw_line in pathway_content.split("\n"):
+ line = raw_line.strip()
+ indent = len(raw_line) - len(raw_line.lstrip())
+
+ if not line:
+ if current_pep_hdr is None and not hit_treatment_page:
+ story.append(Spacer(1, 2))
+ elif hit_treatment_page:
+ story.append(Spacer(1, 1))
+ continue
+
+ # ── Service subsection ### Name ──────────────────────────────────────
+ if line.startswith("###"):
+ # Flush previous service block
+ if current_pep_hdr is not None:
+ story.append(KeepTogether(list(current_pep_hdr) + list(pending_bullets)))
+ pending_bullets.clear()
+
+ pep_name = re.split(r'\s*[\(\[]', line.replace("###","").strip())[0].strip()
+ pep_bar = banner(Paragraph(f" {pep_name}", pep_hdr_s),
+ C_TEAL, line_below=C_NAVY, pad_v=5)
+ moa = SERVICE_MOA.get(pep_name, "")
+ moa_paras = []
+ if moa:
+ moa_paras = [Paragraph(f"{moa}", disc_s)]
+ current_pep_hdr = [Spacer(1, 5), pep_bar] + moa_paras
+ pending_bullets = []
+ continue
+
+ # ── Major section **Bold** or **Bold:** – ROBUST HANDLING ────────────
+ is_section = False
+ if line.startswith("**"):
+ # Handle trailing colon variants: **Header** or **Header:**
+ test = line.rstrip(":").rstrip()
+ if test.endswith("**") and test.count("**") == 2:
+ is_section = True
+
+ if is_section:
+ # Flush any open service block
+ if current_pep_hdr is not None:
+ story.append(KeepTogether(list(current_pep_hdr) + list(pending_bullets)))
+ pending_bullets.clear()
+ current_pep_hdr = None
+
+ clean = line.replace("**","").rstrip(":").strip()
+
+ # Skip redundant headings
+ if clean.lower() in skip_headings:
+ continue
+
+ # Treatment Protocol triggers a new page
+ if not hit_treatment_page and "Treatment Protocol" in clean:
+ hit_treatment_page = True
+ story.append(PageBreak())
+
+ sec_bar = banner(Paragraph(f" {clean}", cond_sh_s),
+ colors.HexColor("#034a6e"), line_below=C_ORANGE,
+ pad_v=5 if hit_treatment_page else 6)
+ spacer_before = 6 if hit_treatment_page else 10
+ spacer_after = 3 if hit_treatment_page else 5
+ story.append(KeepTogether([Spacer(1, spacer_before), sec_bar, Spacer(1, spacer_after)]))
+ continue
+
+ # ── H2 ## ────────────────────────────────────────────────────────────
+ if line.startswith("##"):
+ clean = line.replace("##","").replace("**","").strip()
+ if clean.lower() in skip_headings:
+ continue
+ sp = 2 if hit_treatment_page else 4
+ story.append(KeepTogether([
+ Spacer(1, sp),
+ Paragraph(clean, h3_s),
+ HRFlowable(width="100%", thickness=0.75, color=C_TEAL, spaceAfter=1 if hit_treatment_page else 2),
+ ]))
+ continue
+
+ # ── Bullet ────────────────────────────────────────────────────────────
+ if line and line[0] in ("-","*","•"):
+ clean = re.sub(r"\*\*([^*]+)\*\*", r"\1", line.lstrip("-*• "))
+ is_sub = indent >= 2
+ if hit_treatment_page:
+ sty = cond_sub_bullet_s if is_sub else cond_bullet_s
+ else:
+ sty = sub_bullet_s if is_sub else bullet_s
+ marker = "–" if is_sub else "•"
+ p = Paragraph(f"{marker} {clean}", sty)
+ if current_pep_hdr is not None:
+ pending_bullets.append(p)
+ else:
+ story.append(p)
+ continue
+
+ # ── Numbered list ─────────────────────────────────────────────────────
+ nm = re.match(r'^(\d+)[.)]\s+(.*)', line)
+ if nm:
+ clean = re.sub(r"\*\*([^*]+)\*\*", r"\1", nm.group(2))
+ sty = cond_num_s if hit_treatment_page else num_s
+ story.append(Paragraph(f"{nm.group(1)}. {clean}", sty))
+ continue
+
+ # ── Paragraph — include as body text ─────────────────────────────────
+ if current_pep_hdr is not None:
+ story.append(KeepTogether(list(current_pep_hdr) + list(pending_bullets)))
+ pending_bullets.clear()
+ current_pep_hdr = None
+
+ clean = re.sub(r"\*\*([^*]+)\*\*", r"\1", line)
+ clean = re.sub(r"\*([^*]+)\*", r"\1", clean)
+ sty = cond_body_s if hit_treatment_page else body_s
+ story.append(Paragraph(clean, sty))
+
+ # Flush any trailing service block
+ if current_pep_hdr is not None:
+ story.append(KeepTogether(list(current_pep_hdr) + list(pending_bullets)))
+
+ # ── Footer ────────────────────────────────────────────────────────────────
+ story.append(Spacer(1, 10))
+ story.append(HRFlowable(width="100%", thickness=3, color=C_ORANGE, spaceAfter=0))
+
+ ft_brand_s = ps("Fb", fontName="Helvetica-Bold", fontSize=10, textColor=C_ORANGE, spaceAfter=1, alignment=TA_CENTER)
+ ft_tag_s = ps("Fg", fontName="Helvetica-Bold", fontSize=7.5, textColor=C_ORANGE, spaceAfter=4, alignment=TA_CENTER)
+ ft_info_s = ps("Fi", fontName="Helvetica", fontSize=8, leading=12, textColor=colors.white, spaceAfter=1, alignment=TA_CENTER)
+ ft_web_s = ps("Fw", fontName="Helvetica-Bold", fontSize=8, textColor=C_SKY, spaceAfter=0, alignment=TA_CENTER)
+
+ ft_tbl = Table([
+ [Paragraph("IGNITE PERFORMANCE & HEALTH", ft_brand_s)],
+ [Paragraph("Ignition Sequence™ — Science · Strength · Nutrition", ft_tag_s)],
+ [Paragraph("14830 Clayton Rd, Chesterfield, MO 63017 | (314) 887-0858 | info@ignitepah.com", ft_info_s)],
+ [Paragraph("www.ignitepah.com", ft_web_s)],
+ ], colWidths=[pw])
+ ft_tbl.setStyle(TableStyle([
+ ("BACKGROUND", (0,0),(-1,-1), C_NAVY),
+ ("TOPPADDING", (0,0),(0,0), 8),
+ ("BOTTOMPADDING", (0,-1),(0,-1), 8),
+ ("TOPPADDING", (0,1),(-1,-1), 1),
+ ("BOTTOMPADDING", (0,1),(-1,-1), 1),
+ ("ALIGN", (0,0),(-1,-1), "CENTER"),
+ ]))
+ story.append(ft_tbl)
+
+ doc.build(story)
+ buffer.seek(0)
+ return buffer
+
+
+# =============================================================================
+# CSV EXPORT
+# =============================================================================
+def generate_csv_export(intake_data, recommended_stacks):
+ """Generate CSV export of assessment data."""
+ sio = StringIO()
+ fieldnames = [
+ "Timestamp","First_Name","Last_Name","Email","Phone","Age","Sex",
+ "Primary_Goals","Energy_Recovery_Level","Current_Issues","Physical_Activity_Level",
+ "Medical_Considerations","Medical_Details","Contraindication_Flags","Additional_Information",
+ "Recommended_Stack_1","Recommended_Stack_2","Recommended_Stack_3",
+ "Stack_1_26Week_Price","Stack_1_52Week_Price",
+ "Stack_2_26Week_Price","Stack_2_52Week_Price",
+ "Stack_3_26Week_Price","Stack_3_52Week_Price",
+ "All_Recommended_Services","Top_Targets",
+ ]
+ writer = csv.DictWriter(sio, fieldnames=fieldnames)
+ writer.writeheader()
+
+ def ps_str(idx, field):
+ if idx >= len(recommended_stacks): return ""
+ ps = get_pricing_summary(recommended_stacks[idx])
+ if field == "26_week":
+ return f"${ps['monthly_26wk']:,.2f}"
+ elif field == "52_week":
+ return f"${ps['monthly_52wk']:,.2f}"
+ return ""
+
+ flags = [f for f in intake_data.get("contraindication_flags", []) if f != "None of the above"]
+ row = {
+ "Timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
+ "First_Name": intake_data.get("first_name",""),
+ "Last_Name": intake_data.get("last_name",""),
+ "Email": intake_data.get("email",""),
+ "Phone": intake_data.get("phone",""),
+ "Age": intake_data.get("age",""),
+ "Sex": intake_data.get("sex",""),
+ "Primary_Goals": "; ".join(intake_data.get("primary_goals",[])),
+ "Energy_Recovery_Level": intake_data.get("energy_recovery",""),
+ "Current_Issues": "; ".join(intake_data.get("current_issues",[])),
+ "Physical_Activity_Level": intake_data.get("activity_level",""),
+ "Medical_Considerations": intake_data.get("medical_considerations",""),
+ "Medical_Details": intake_data.get("medical_details",""),
+ "Contraindication_Flags": "; ".join(flags) if flags else "None",
+ "Additional_Information": intake_data.get("additional_info",""),
+ "Recommended_Stack_1": recommended_stacks[0] if len(recommended_stacks) > 0 else "",
+ "Recommended_Stack_2": recommended_stacks[1] if len(recommended_stacks) > 1 else "",
+ "Recommended_Stack_3": recommended_stacks[2] if len(recommended_stacks) > 2 else "",
+ "Stack_1_26Week_Price": ps_str(0,"26_week"), "Stack_1_52Week_Price": ps_str(0,"52_week"),
+ "Stack_2_26Week_Price": ps_str(1,"26_week"), "Stack_2_52Week_Price": ps_str(1,"52_week"),
+ "Stack_3_26Week_Price": ps_str(2,"26_week"), "Stack_3_52Week_Price": ps_str(2,"52_week"),
+ "All_Recommended_Services": "; ".join(set(p for sn in recommended_stacks for p in WELLNESS_PROGRAMS[sn]["services"])),
+ "Top_Targets": "; ".join(set(t for sn in recommended_stacks for t in WELLNESS_PROGRAMS[sn]["targets"])),
+ }
+ writer.writerow(row)
+ buf = BytesIO(sio.getvalue().encode("utf-8"))
+ buf.seek(0)
+ return buf
+
+
+# =============================================================================
+# JSON EXPORT
+# =============================================================================
+def generate_json_export(intake_data, recommended_stacks):
+ """Generate JSON export of assessment data."""
+ flags = [f for f in intake_data.get("contraindication_flags", []) if f != "None of the above"]
+ stack_details = []
+ for sn in recommended_stacks:
+ si = WELLNESS_PROGRAMS[sn]
+ ps = get_pricing_summary(sn)
+ stack_details.append({
+ "name": sn, "targets": si["targets"], "description": si["description"],
+ "services": si["services"], "type": si["type"],
+ "cycle": si["cycle"],
+ "contraindication_flags": get_stack_contraindication_summary(sn, flags),
+ "pricing": {
+ "monthly_26week": round(ps["monthly_26wk"], 2),
+ "monthly_52week": round(ps["monthly_52wk"], 2),
+ "all_tiers": ps["all_tiers"],
+ },
+ })
+ export_data = {
+ "timestamp": datetime.now().isoformat(),
+ "patient_info": {
+ "first_name": intake_data.get("first_name",""), "last_name": intake_data.get("last_name",""),
+ "email": intake_data.get("email",""), "phone": intake_data.get("phone",""),
+ "age": intake_data.get("age",""), "sex": intake_data.get("sex",""),
+ },
+ "assessment": {
+ "primary_goals": intake_data.get("primary_goals",[]),
+ "energy_recovery_level": intake_data.get("energy_recovery",""),
+ "current_issues": intake_data.get("current_issues",[]),
+ "physical_activity": intake_data.get("activity_level",""),
+ "medical_considerations": intake_data.get("medical_considerations",""),
+ "medical_details": intake_data.get("medical_details",""),
+ "contraindication_flags": flags,
+ "additional_info": intake_data.get("additional_info",""),
+ },
+ "recommendations": {
+ "stacks": stack_details,
+ "all_services": list(set(p for sn in recommended_stacks for p in WELLNESS_PROGRAMS[sn]["services"])),
+ "top_targets": list(set(t for sn in recommended_stacks for t in WELLNESS_PROGRAMS[sn]["targets"])),
+ },
+ }
+ buf = BytesIO(json.dumps(export_data, indent=2).encode("utf-8"))
+ buf.seek(0)
+ return buf
+
+
+# =============================================================================
+# EMAIL DELIVERY (Outlook SMTP)
+# =============================================================================
+log = logging.getLogger("ignite_email")
+
+def _smtp_send(to_addr, subject, body_text, attachments=None):
+ """Send an email via Outlook SMTP. Returns True on success, error string on failure."""
+ user = os.getenv("SMTP_USER", "").strip()
+ pw = os.getenv("SMTP_PASSWORD", "").strip()
+ if not user or not pw:
+ return "SMTP credentials not configured (SMTP_USER / SMTP_PASSWORD)"
+
+ msg = MIMEMultipart()
+ msg["From"] = user
+ msg["To"] = to_addr
+ msg["Subject"] = subject
+ msg.attach(MIMEText(body_text, "plain"))
+
+ for filename, data, mime_type in (attachments or []):
+ part = MIMEBase(*mime_type.split("/", 1))
+ part.set_payload(data)
+ encoders.encode_base64(part)
+ part.add_header("Content-Disposition", f'attachment; filename="{filename}"')
+ msg.attach(part)
+
+ try:
+ with smtplib.SMTP(EMAIL["smtp_server"], EMAIL["smtp_port"], timeout=15) as srv:
+ srv.ehlo()
+ srv.starttls()
+ srv.ehlo()
+ srv.login(user, pw)
+ srv.sendmail(user, to_addr, msg.as_string())
+ return True
+ except Exception as exc:
+ log.warning("SMTP send failed to %s: %s", to_addr, exc)
+ return str(exc)
+
+
+def send_client_email(patient_email, pdf_bytes):
+ """Send the wellness plan PDF to the patient."""
+ body = EMAIL["client_body"].format(scheduling_url=BRAND["scheduling_url"])
+ return _smtp_send(
+ to_addr=patient_email,
+ subject=EMAIL["client_subject"],
+ body_text=body,
+ attachments=[("Ignite_Ignition_Sequence.pdf", pdf_bytes, "application/pdf")],
+ )
+
+
+def send_clinic_email(intake_data, pdf_bytes, csv_bytes, json_bytes):
+ """Send full intake data + exports to the clinic."""
+ flags = intake_data.get("contraindication_flags", [])
+ flag_str = ", ".join(flags) if flags else "None"
+ body = (
+ f"New assessment completed — {intake_data.get('name', 'Unknown')}\n"
+ f"{'=' * 50}\n\n"
+ f"Email: {intake_data.get('email', '')}\n"
+ f"Phone: {intake_data.get('phone', '')}\n"
+ f"Age: {intake_data.get('age', '')} | Sex: {intake_data.get('sex', '')}\n\n"
+ f"Primary Goals: {', '.join(intake_data.get('primary_goals', []))}\n"
+ f"Energy & Recovery: {intake_data.get('energy_recovery', '')}\n"
+ f"Current Issues: {', '.join(intake_data.get('current_issues', []))}\n"
+ f"Activity Level: {intake_data.get('activity_level', '')}\n"
+ f"Contraindication Flags: {flag_str}\n"
+ f"Medical Considerations: {intake_data.get('medical_considerations', '')}\n"
+ f"Additional Info: {intake_data.get('additional_info', '')}\n\n"
+ f"PDF, CSV, and JSON exports attached."
+ )
+ safe_name = (intake_data.get("name", "patient")).replace(" ", "_")
+ return _smtp_send(
+ to_addr=EMAIL["clinic_recipient"],
+ subject=f"{EMAIL['clinic_subject']} — {intake_data.get('name', '')}",
+ body_text=body,
+ attachments=[
+ (f"Ignite_{safe_name}.pdf", pdf_bytes, "application/pdf"),
+ (f"Ignite_{safe_name}.csv", csv_bytes, "text/csv"),
+ (f"Ignite_{safe_name}.json", json_bytes, "application/json"),
+ ],
+ )
+
+
+# =============================================================================
+# FOOTER RENDERER
+# =============================================================================
+def render_footer():
+ """Render the footer with contact and disclaimer info."""
+ st.markdown(
+ '',
+ unsafe_allow_html=True,
+ )
+
+
+# =============================================================================
+# PAGE CONFIG & CSS
+# =============================================================================
+st.set_page_config(page_title="Ignite Performance & Health — Ignition Sequence", layout="wide", initial_sidebar_state="collapsed")
+
+# ── Preload fonts via instead of @import (non-blocking, parallelized) ──
+st.markdown(
+ ''
+ ''
+ '',
+ unsafe_allow_html=True,
+)
+
+st.markdown("""
+
+""", unsafe_allow_html=True)
+
+# ── Shared tooltip (one DOM node replaces ~30 hidden tooltips) ──
+# JS must run via components.html — st.markdown strips
+""", height=0)
+
+# ── Branded spinner overlay (separate block for dynamic logo injection) ──
+st.markdown(
+ f"""""",
+ unsafe_allow_html=True,
+)
+
+
+# =============================================================================
+# SESSION STATE INIT
+# =============================================================================
+if "wellness_pathway" not in st.session_state:
+ st.session_state["wellness_pathway"] = None
+ st.session_state["recommended_stacks"] = []
+ st.session_state["all_eligible_stacks"] = []
+ st.session_state["intake_data"] = {}
+ st.session_state["patient_name"] = ""
+ st.session_state["patient_email"] = ""
+ st.session_state["patient_phone"] = ""
+ st.session_state["patient_age"] = ""
+ st.session_state["patient_sex"] = ""
+ st.session_state["contraindication_flags"] = []
+ st.session_state["scroll_to_top"] = False
+ st.session_state["results_scroll_done"] = False
+
+
+# =============================================================================
+# RESULTS PAGE
+# =============================================================================
+if st.session_state["wellness_pathway"]:
+
+ import streamlit.components.v1 as components
+ st.markdown('', unsafe_allow_html=True)
+
+ pname = st.session_state.get("patient_name", "")
+ pemail = st.session_state.get("patient_email", "")
+ pphone = st.session_state.get("patient_phone", "")
+ page = st.session_state.get("patient_age", "")
+ psex = st.session_state.get("patient_sex", "")
+
+ # ── Results hero ──────────────────────────────────────────────────────────
+ st.markdown(
+ '
'
+ f''
+ '
Your
Ignition Sequence™
'
+ '
Unlock Your Peak Performance
'
+ f'
Prepared for {pname}
'
+ '
Physician-Supervised • Personalized to Your Physiology • Tailored to Your Goals
'
+ '
',
+ unsafe_allow_html=True,
+ )
+
+ # ── All eligible programs — sorted: robust/expensive first, med-only last ─
+ primary_recs = set(st.session_state["recommended_stacks"])
+ all_eligible = st.session_state.get("all_eligible_stacks", list(primary_recs))
+ patient_flags = st.session_state.get("contraindication_flags", [])
+ active_flags = [f for f in patient_flags if f != "None of the above"]
+
+ display_stacks = sorted(
+ all_eligible,
+ key=lambda sn: WELLNESS_PROGRAMS[sn].get("display_order", 50),
+ )
+
+ all_stack_services = set()
+ for sn in display_stacks:
+ all_stack_services.update(WELLNESS_PROGRAMS[sn]["services"])
+
+ for i, sn in enumerate(display_stacks):
+ stack = WELLNESS_PROGRAMS[sn]
+ targets_str = " · ".join(stack["targets"])
+
+ # Badge label — top 3 always get BEST / BETTER / GOOD
+ if i < 3:
+ tier_label = ["BEST", "BETTER", "GOOD"][i]
+ badge_html = f'
{tier_label}
'
+ else:
+ badge_html = ''
+
+ # Contraindication check
+ contra_html = ""
+ if active_flags:
+ hits = check_contraindications(stack["services"], active_flags)
+ if hits:
+ svc_list = ", ".join(sex_label(s, psex) for s in hits.keys())
+ contra_html = (
+ f'
'
+ f'⚠ Physician Review Required — '
+ f'{svc_list} may need adjustment based on your health history. '
+ f'Our medical team will evaluate during your consultation.'
+ f'
'
+ )
+
+ # Service pills (MOA shown via shared tooltip on hover)
+ badges = ""
+ for p in stack["services"]:
+ display_name = sex_label(p, psex)
+ moa = sex_moa(p, psex)
+ esc_moa = moa.replace('"', '"').replace("'", "'") if moa else ""
+ badges += f'
{display_name}
'
+
+ # Build tier pricing grid (config values are monthly — convert to weekly)
+ sorted_tiers = sorted(stack["tiers"].items(), key=lambda x: x[1]["sort_order"])
+ tier_cells = ""
+ for tier_name, tier_data in sorted_tiers:
+ tier_desc = ""
+ if stack["type"] == "training":
+ tier_info = TRAINING_TIERS.get(tier_name, {})
+ desc_text = tier_info.get("training_desc", "")
+ if desc_text:
+ tier_desc = f'
{desc_text}
'
+ us_text = tier_info.get("ultrasound", "")
+ if us_text:
+ tier_desc += f'
',
+ unsafe_allow_html=True,
+ )
+
+ # ── Downloads ─────────────────────────────────────────────────────────────
+ st.markdown('', unsafe_allow_html=True)
+ st.markdown("#### Download Your Results")
+ st.caption("Save your Ignition Sequence recommendation or export data for clinic use.")
+
+ c1, c2, c3 = st.columns(3)
+ with c1:
+ pdf_buf = generate_wellness_pdf(
+ st.session_state["wellness_pathway"],
+ {"name": pname, "email": pemail, "phone": pphone,
+ "age": page, "sex": psex,
+ "date": datetime.now().strftime("%B %d, %Y")},
+ st.session_state["recommended_stacks"],
+ st.session_state.get("contraindication_flags", []),
+ )
+ st.download_button(
+ "PDF Report", data=pdf_buf, file_name="ignite_ignition_sequence.pdf",
+ mime="application/pdf", use_container_width=True,
+ )
+ with c2:
+ csv_buf = generate_csv_export(st.session_state.get("intake_data", {}), st.session_state["recommended_stacks"])
+ safe_name = (pname or "patient").replace(" ", "_")
+ st.download_button(
+ "CSV Export", data=csv_buf, file_name=f"ignite_{safe_name}.csv",
+ mime="text/csv", use_container_width=True,
+ )
+ with c3:
+ json_buf = generate_json_export(st.session_state.get("intake_data", {}), st.session_state["recommended_stacks"])
+ st.download_button(
+ "JSON Export", data=json_buf, file_name=f"ignite_{safe_name}.json",
+ mime="application/json", use_container_width=True,
+ )
+
+ st.info(
+ "**Clinic staff:** CSV and JSON exports include full intake data, contraindication flags, "
+ "and per-week / per-month / total pricing — ready for your EMR or CRM.",
+ icon="ℹ️",
+ )
+
+ # ── Start over button ─────────────────────────────────────────────────────
+ st.markdown('', unsafe_allow_html=True)
+ if st.button("← Start New Assessment", use_container_width=True):
+ for key in ["wellness_pathway", "recommended_stacks", "all_eligible_stacks", "intake_data",
+ "patient_name", "patient_email", "patient_phone", "patient_age", "patient_sex",
+ "contraindication_flags", "email_status"]:
+ st.session_state[key] = None if key == "wellness_pathway" else (
+ [] if key in ["recommended_stacks", "all_eligible_stacks", "contraindication_flags", "email_status"] else ""
+ )
+ st.session_state["scroll_to_top"] = True
+ st.rerun()
+
+ render_footer()
+
+ # ── Scroll to top (fires ONCE on first results render, then stops) ──────
+ if not st.session_state.get("results_scroll_done", False):
+ st.session_state["results_scroll_done"] = True
+ components.html(
+ """
+
+ """,
+ height=0,
+ )
+
+ st.stop()
+
+
+# =============================================================================
+# INTAKE FORM PAGE
+# =============================================================================
+
+st.markdown('', unsafe_allow_html=True)
+
+if st.session_state.pop("scroll_to_top", False):
+ components.html(
+ """
+
+ """,
+ height=0,
+ )
+
+st.markdown(
+ '
'
+ f''
+ '
Ignition Sequence™
'
+ '
Unlock Your Peak Performance
'
+ '
Physician-Supervised • Personalized to Your Physiology • Tailored to Your Goals
'
+ '
',
+ unsafe_allow_html=True,
+)
+st.markdown(
+ "Answer a few questions about your goals and where you are right now. "
+ "We'll match you to the Ignition Sequence program that fits best. "
+ "Our team reviews every result and will reach out within 24\u201348 hours to schedule your consultation.",
+)
+
+# ── Intake form ───────────────────────────────────────────────────────────────
+with st.form("wellness_intake_form"):
+
+ st.markdown('
Your Information
', unsafe_allow_html=True)
+ c1, c2 = st.columns(2)
+ with c1:
+ first_name = st.text_input("First Name *")
+ last_name = st.text_input("Last Name *")
+ email = st.text_input("Email Address *")
+ with c2:
+ phone = st.text_input("Cell Phone *")
+ age = st.number_input("Age *", min_value=18, max_value=100, value=35)
+ sex = st.radio("Biological Sex *", ["Male", "Female"], index=None)
+
+ st.markdown('
1 — Current Symptoms
', unsafe_allow_html=True)
+ st.caption("Check anything you're currently experiencing.")
+
+ # Split symptoms dynamically into two columns
+ symptom_keys = list(CURRENT_SYMPTOMS.keys())
+ mid = (len(symptom_keys) + 1) // 2
+ symptom_checks = {}
+
+ c1, c2 = st.columns(2)
+ with c1:
+ for symptom in symptom_keys[:mid]:
+ symptom_checks[symptom] = st.checkbox(symptom, key=f"symptom_{symptom}")
+ with c2:
+ for symptom in symptom_keys[mid:]:
+ symptom_checks[symptom] = st.checkbox(symptom, key=f"symptom_{symptom}")
+
+ st.markdown('
2 — Primary Goals
', unsafe_allow_html=True)
+ st.caption("Select everything that applies to you.")
+
+ # Split goals dynamically into two columns
+ goal_keys = list(PRIMARY_GOALS.keys())
+ mid = (len(goal_keys) + 1) // 2
+ goal_checks = {}
+
+ c1, c2 = st.columns(2)
+ with c1:
+ for goal in goal_keys[:mid]:
+ goal_checks[goal] = st.checkbox(goal, key=f"goal_{goal}")
+ with c2:
+ for goal in goal_keys[mid:]:
+ goal_checks[goal] = st.checkbox(goal, key=f"goal_{goal}")
+
+ st.markdown('
3 — Physical Activity
', unsafe_allow_html=True)
+ activity_level = st.radio(
+ "What best describes your current activity level? *",
+ ACTIVITY_LEVELS,
+ index=None,
+ )
+
+ st.markdown('
4 — Energy & Recovery
', unsafe_allow_html=True)
+ energy_recovery = st.radio(
+ "How would you describe your current energy and physical recovery? *",
+ list(ENERGY_RECOVERY_OPTIONS.keys()),
+ index=None,
+ )
+
+ st.markdown('
5 — Medical History
', unsafe_allow_html=True)
+ medical_care = st.radio(
+ "Are you currently receiving care for hormone imbalances, cancer, or other chronic conditions not listed above? *",
+ ["No", "Yes — please describe below"], index=None,
+ )
+ medical_details = st.text_area(
+ "If yes, please provide details:",
+ placeholder="Current conditions, medications, or recent treatments...",
+ )
+
+ st.markdown('
6 — Safety Screening
', unsafe_allow_html=True)
+ st.caption(
+ "Check any of the following that apply. This allows our physician team to identify services "
+ "requiring modification or review. Checking an item does not exclude you from therapy."
+ )
+ flag_options = [f for f in ALL_CONTRAINDICATION_FLAGS if f != "None of the above"]
+ mid = (len(flag_options) + 1) // 2
+ contra_checks = {}
+ cf1, cf2 = st.columns(2)
+ with cf1:
+ for flag in flag_options[:mid]:
+ contra_checks[flag] = st.checkbox(flag, key=f"cf_{flag}")
+ with cf2:
+ for flag in flag_options[mid:]:
+ contra_checks[flag] = st.checkbox(flag, key=f"cf_{flag}")
+ none_of_above = st.checkbox("None of the above", key="cf_none")
+
+ st.markdown('
Anything Else?
', unsafe_allow_html=True)
+ additional_info = st.text_area(
+ "Previous experience with training programs, specific concerns, or timeline goals:",
+ placeholder="Optional — any context that may help our physician team.",
+ )
+
+ # ── Consent & Disclaimers ──────────────────────────────────────────────────
+ st.markdown('
Consent & Privacy
', unsafe_allow_html=True)
+
+ st.markdown(
+ '
'
+ 'Important: This platform is '
+ 'not HIPAA-compliant. Any personal or health information you '
+ 'enter may be transmitted and stored on servers that do not meet HIPAA security '
+ 'standards. Please do not share sensitive medical records, Social Security numbers, '
+ 'or information you would not be comfortable disclosing on a non-secure platform.
',
+ unsafe_allow_html=True,
+ )
+
+ consent_privacy = st.checkbox(
+ "I understand this platform is NOT HIPAA-compliant and that any information "
+ "I provide may not be protected under HIPAA privacy regulations.",
+ key="consent_privacy",
+ )
+ consent_contact = st.checkbox(
+ "I consent to being contacted by Ignite Performance & Health via the email "
+ "address and phone number I have provided above regarding my assessment "
+ "and available programs.",
+ key="consent_contact",
+ )
+
+ submitted = st.form_submit_button("Generate My Ignition Sequence", use_container_width=True)
+
+# ── Form processing ───────────────────────────────────────────────────────────
+if submitted:
+ primary_goals = [g for g, checked in goal_checks.items() if checked]
+ current_issues = [i for i, checked in symptom_checks.items() if checked]
+
+ if none_of_above:
+ selected_flags = ["None of the above"]
+ else:
+ selected_flags = [flag for flag, checked in contra_checks.items() if checked]
+ if not selected_flags:
+ selected_flags = ["None of the above"]
+
+ errors = []
+ if not first_name: errors.append("First Name")
+ if not last_name: errors.append("Last Name")
+ if not email: errors.append("Email Address")
+ if not phone: errors.append("Cell Phone")
+ if sex is None: errors.append("Biological Sex")
+ if not primary_goals: errors.append("Primary Goals (select at least one)")
+ if energy_recovery is None: errors.append("Energy & Recovery level")
+ if activity_level is None: errors.append("Physical Activity level")
+ if medical_care is None: errors.append("Medical History")
+ if not consent_privacy: errors.append("Privacy acknowledgment (required)")
+ if not consent_contact: errors.append("Consent to contact (required)")
+
+ # ── Male-specific restrictions ────────────────────────────────────────────
+ male_conflicts = []
+ if sex == "Male":
+ male_restricted_goals = [g for g in primary_goals if g in MALE_RESTRICTED_GOALS]
+ male_restricted_syms = [s for s in current_issues if s in MALE_RESTRICTED_SYMPTOMS]
+ male_restricted_flags = [f for f in selected_flags if f in MALE_RESTRICTED_FLAGS]
+
+ if male_restricted_goals:
+ male_conflicts.append(f"Primary Goals: {', '.join(male_restricted_goals)}")
+ if male_restricted_syms:
+ male_conflicts.append(f"Symptoms: {', '.join(male_restricted_syms)}")
+ if male_restricted_flags:
+ male_conflicts.append(f"Flags: {', '.join(male_restricted_flags)}")
+
+ if errors:
+ st.error(f"Please complete the following required fields: **{', '.join(errors)}**")
+ st.stop()
+
+ # ── "None of the above" conflict check ────────────────────────────────────
+ other_flags_checked = [flag for flag, checked in contra_checks.items() if checked]
+ if none_of_above and other_flags_checked:
+ st.error(
+ "⚠ You selected **\"None of the above\"** in Safety Screening but also checked: "
+ f"**{', '.join(other_flags_checked)}**. Please select one or the other."
+ )
+ st.stop()
+
+ if male_conflicts:
+ st.error(
+ f"⚠ The following selections are not applicable for male patients: "
+ f"**{', '.join(male_conflicts)}**. Please uncheck them and resubmit."
+ )
+ st.stop()
+
+ # Scroll parent to top AND force-position spinner when it appears
+ components.html(
+ """""",
+ height=0,
+ )
+ with st.spinner("Generating Your Ignition Sequence..."):
+ goals_data = {"primary_goals": primary_goals, "energy_recovery": energy_recovery,
+ "current_issues": current_issues, "activity_level": activity_level}
+ target_scores = map_goals_to_targets(goals_data)
+ rec_stacks, _, all_eligible = recommend_programs(target_scores, len(primary_goals), patient_sex=sex, patient_flags=selected_flags)
+ med = medical_details if medical_care == "Yes — please describe below" else "No current conditions reported"
+
+ intake_data = {
+ "name": f"{first_name} {last_name}", "first_name": first_name, "last_name": last_name,
+ "email": email, "phone": phone, "age": age, "sex": sex,
+ "primary_goals": primary_goals, "energy_recovery": energy_recovery,
+ "current_issues": current_issues, "activity_level": activity_level,
+ "medical_considerations": med, "medical_details": medical_details or "",
+ "contraindication_flags": selected_flags,
+ "additional_info": additional_info or "None provided",
+ }
+
+ pathway = generate_wellness_pathway(intake_data, rec_stacks, selected_flags)
+
+ st.session_state["wellness_pathway"] = pathway
+ st.session_state["results_scroll_done"] = False # allow one scroll-to-top on results load
+ st.session_state["recommended_stacks"] = rec_stacks
+ st.session_state["all_eligible_stacks"] = all_eligible
+ st.session_state["intake_data"] = intake_data
+ st.session_state["patient_name"] = f"{first_name} {last_name}"
+ st.session_state["patient_email"] = email
+ st.session_state["patient_phone"] = phone
+ st.session_state["patient_age"] = age
+ st.session_state["patient_sex"] = sex
+ st.session_state["contraindication_flags"] = selected_flags
+
+ # ── Auto-send emails ──────────────────────────────────────────────
+ patient_info = {
+ "name": f"{first_name} {last_name}", "email": email, "phone": phone,
+ "age": age, "sex": sex, "date": datetime.now().strftime("%B %d, %Y"),
+ }
+ pdf_buf = generate_wellness_pdf(pathway, patient_info, rec_stacks, selected_flags)
+ pdf_bytes = pdf_buf.getvalue()
+ csv_buf = generate_csv_export(intake_data, rec_stacks)
+ csv_bytes = csv_buf.getvalue()
+ json_buf = generate_json_export(intake_data, rec_stacks)
+ json_bytes = json_buf.getvalue()
+
+ client_result = send_client_email(email, pdf_bytes)
+ clinic_result = send_clinic_email(intake_data, pdf_bytes, csv_bytes, json_bytes)
+
+ email_status = []
+ if client_result is True and clinic_result is True:
+ email_status = [("success", "Your results have been sent to your email.")]
+ else:
+ if client_result is not True:
+ email_status.append(("warning", f"Patient email not sent: {client_result}"))
+ if clinic_result is not True:
+ email_status.append(("warning", f"Clinic email not sent: {clinic_result}"))
+ st.session_state["email_status"] = email_status
+
+ st.rerun()
+
+render_footer()