Analyse my hair
| Concern | Recommendation |
|---|---|
| Frizz & dryness | Sulfate-free, hydrating shampoo + moisturizing conditioner (focus on mid-lengths/ends) |
| Wavy hair definition | Apply a small amount of argan or jojoba oil on damp hair |
| Scalp health | Part your hair in multiple places under good light periodically to self-check for scaling or redness |
| Crown monitoring | Photograph your crown every 2-3 months to track any changes in the whorl size |
Create a hair care guide with specific product recommendations
best shampoo conditioner for wavy coarse hair men frizz control 2025
best hair products for crown thinning prevention men minoxidil alternatives 2025
ls -la /tmp/workspace/ 2>/dev/null || mkdir -p /tmp/workspace && echo "created"
mkdir -p /tmp/workspace/hair-guide && python3 << 'EOF' from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import mm, cm from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable, KeepTogether from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY from reportlab.platypus import PageBreak OUTPUT = "/tmp/workspace/hair-guide/Hair_Care_Guide.pdf" doc = SimpleDocTemplate( OUTPUT, pagesize=A4, rightMargin=2*cm, leftMargin=2*cm, topMargin=2*cm, bottomMargin=2*cm ) # Colors DARK = colors.HexColor("#1A1A2E") ACCENT = colors.HexColor("#E94560") SOFT = colors.HexColor("#16213E") LIGHT_BG = colors.HexColor("#F5F5F5") GOLD = colors.HexColor("#C9A84C") TEAL = colors.HexColor("#0F3460") WHITE = colors.white LIGHT_GREY = colors.HexColor("#EEEEEE") MID_GREY = colors.HexColor("#888888") # Styles styles = getSampleStyleSheet() title_style = ParagraphStyle( "title_style", parent=styles["Normal"], fontName="Helvetica-Bold", fontSize=28, textColor=WHITE, spaceAfter=4, alignment=TA_CENTER ) subtitle_style = ParagraphStyle( "subtitle_style", parent=styles["Normal"], fontName="Helvetica", fontSize=12, textColor=colors.HexColor("#CCCCCC"), spaceAfter=2, alignment=TA_CENTER ) section_header = ParagraphStyle( "section_header", parent=styles["Normal"], fontName="Helvetica-Bold", fontSize=15, textColor=DARK, spaceBefore=12, spaceAfter=6, borderPadding=(0, 0, 3, 0) ) sub_header = ParagraphStyle( "sub_header", parent=styles["Normal"], fontName="Helvetica-Bold", fontSize=11, textColor=TEAL, spaceBefore=8, spaceAfter=4 ) body_style = ParagraphStyle( "body_style", parent=styles["Normal"], fontName="Helvetica", fontSize=9.5, textColor=colors.HexColor("#333333"), spaceBefore=2, spaceAfter=3, leading=14 ) note_style = ParagraphStyle( "note_style", parent=styles["Normal"], fontName="Helvetica-Oblique", fontSize=9, textColor=MID_GREY, spaceBefore=2, spaceAfter=4, leading=13 ) bullet_style = ParagraphStyle( "bullet_style", parent=styles["Normal"], fontName="Helvetica", fontSize=9.5, textColor=colors.HexColor("#333333"), spaceBefore=1, spaceAfter=2, leftIndent=14, leading=14, bulletIndent=4 ) tag_style = ParagraphStyle( "tag_style", parent=styles["Normal"], fontName="Helvetica-Bold", fontSize=8, textColor=WHITE ) story = [] # ─── COVER HEADER ─────────────────────────────────────────────────────────── cover_data = [[ Paragraph("PERSONALISED HAIR CARE GUIDE", title_style), ]] cover_table = Table(cover_data, colWidths=[17*cm]) cover_table.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,-1), DARK), ("ROUNDEDCORNERS", (0,0), (-1,-1), 8), ("TOPPADDING", (0,0), (-1,-1), 20), ("BOTTOMPADDING", (0,0), (-1,-1), 8), ("LEFTPADDING", (0,0), (-1,-1), 10), ("RIGHTPADDING", (0,0), (-1,-1), 10), ])) story.append(cover_table) subtitle_data = [[ Paragraph("Curated for: Wavy • Coarse • High-Density Hair | Concerns: Frizz · Crown Thinning · Scalp Health", subtitle_style) ]] sub_t = Table(subtitle_data, colWidths=[17*cm]) sub_t.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,-1), SOFT), ("TOPPADDING", (0,0), (-1,-1), 7), ("BOTTOMPADDING", (0,0), (-1,-1), 7), ("LEFTPADDING", (0,0), (-1,-1), 10), ("RIGHTPADDING", (0,0), (-1,-1), 10), ])) story.append(sub_t) story.append(Spacer(1, 10)) # ─── HAIR PROFILE SUMMARY BOX ─────────────────────────────────────────────── def make_tag(text, bg): tag_data = [[Paragraph(text, tag_style)]] t = Table(tag_data, colWidths=[None]) t.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,-1), bg), ("TOPPADDING", (0,0), (-1,-1), 3), ("BOTTOMPADDING", (0,0), (-1,-1), 3), ("LEFTPADDING", (0,0), (-1,-1), 6), ("RIGHTPADDING", (0,0), (-1,-1), 6), ("ROUNDEDCORNERS", (0,0), (-1,-1), 3), ])) return t profile_rows = [ [Paragraph("<b>Your Hair Profile</b>", ParagraphStyle("ph", fontName="Helvetica-Bold", fontSize=11, textColor=DARK)), "", "", ""], [ Paragraph("Type: Wavy 2B/2C", body_style), Paragraph("Texture: Medium-Coarse", body_style), Paragraph("Density: High", body_style), Paragraph("Color: Deep Black", body_style), ], [ Paragraph("Frizz Prone: Yes", body_style), Paragraph("Crown: Monitor for thinning", body_style), Paragraph("Scalp: Normal-Oily", body_style), Paragraph("Styling: Volume-rich", body_style), ] ] profile_table = Table(profile_rows, colWidths=[4.25*cm]*4) profile_table.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,-1), LIGHT_BG), ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#D0E8FF")), ("SPAN", (0,0), (-1,0)), ("TOPPADDING", (0,0), (-1,-1), 6), ("BOTTOMPADDING", (0,0), (-1,-1), 6), ("LEFTPADDING", (0,0), (-1,-1), 8), ("RIGHTPADDING", (0,0), (-1,-1), 8), ("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#CCCCCC")), ])) story.append(profile_table) story.append(Spacer(1, 12)) # ─── SECTION 1: DAILY ROUTINE ──────────────────────────────────────────────── story.append(HRFlowable(width="100%", thickness=2, color=ACCENT, spaceAfter=5)) story.append(Paragraph("01 | DAILY & WEEKLY ROUTINE", section_header)) routine_data = [ [Paragraph("<b>Step</b>", body_style), Paragraph("<b>Frequency</b>", body_style), Paragraph("<b>Action</b>", body_style), Paragraph("<b>Why</b>", body_style)], [Paragraph("1. Shampoo", body_style), Paragraph("2-3x / week", body_style), Paragraph("Use a sulfate-free shampoo. Wet hair thoroughly, massage scalp for 60 sec.", body_style), Paragraph("Sulfate-free avoids stripping natural oils from coarse, wave-prone hair", body_style)], [Paragraph("2. Conditioner", body_style), Paragraph("Every wash", body_style), Paragraph("Apply from mid-lengths to ends. Leave in 2-3 min. Rinse with cool water.", body_style), Paragraph("Cool water seals the cuticle, reducing frizz", body_style)], [Paragraph("3. Leave-In", body_style), Paragraph("Every wash", body_style), Paragraph("Apply a dime-sized amount to damp hair before drying.", body_style), Paragraph("Locks in moisture, defines waves, prevents frizz", body_style)], [Paragraph("4. Scalp Serum\n(if thinning concern)", body_style), Paragraph("Daily", body_style), Paragraph("Apply to crown area on dry or slightly damp scalp. Do not rinse.", body_style), Paragraph("Stimulates blood flow to follicles; most effective with daily consistency", body_style)], [Paragraph("5. Deep Condition", body_style), Paragraph("Once / week", body_style), Paragraph("Apply a hair mask after shampooing, leave 10-15 min with a shower cap.", body_style), Paragraph("Replenishes moisture in coarse, wavy hair prone to dryness", body_style)], [Paragraph("6. Scalp Exfoliation", body_style), Paragraph("Once / 2 weeks", body_style), Paragraph("Use a scalp scrub or salicylic-acid shampoo on the scalp only.", body_style), Paragraph("Removes buildup, unclogs follicles, improves product absorption", body_style)], ] routine_table = Table(routine_data, colWidths=[3.2*cm, 2.5*cm, 6*cm, 5.3*cm]) routine_table.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,0), DARK), ("TEXTCOLOR", (0,0), (-1,0), WHITE), ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"), ("FONTSIZE", (0,0), (-1,-1), 9), ("BACKGROUND", (0,1), (-1,1), colors.HexColor("#EAF4FF")), ("BACKGROUND", (0,2), (-1,2), WHITE), ("BACKGROUND", (0,3), (-1,3), colors.HexColor("#EAF4FF")), ("BACKGROUND", (0,4), (-1,4), WHITE), ("BACKGROUND", (0,5), (-1,5), colors.HexColor("#EAF4FF")), ("BACKGROUND", (0,6), (-1,6), WHITE), ("ROWBACKGROUNDS", (0,0), (-1,-1), [DARK, colors.HexColor("#EAF4FF"), WHITE]), ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")), ("TOPPADDING", (0,0), (-1,-1), 5), ("BOTTOMPADDING", (0,0), (-1,-1), 5), ("LEFTPADDING", (0,0), (-1,-1), 6), ("RIGHTPADDING", (0,0), (-1,-1), 6), ("VALIGN", (0,0), (-1,-1), "TOP"), ])) story.append(routine_table) story.append(Spacer(1, 14)) # ─── SECTION 2: PRODUCT RECOMMENDATIONS ───────────────────────────────────── story.append(HRFlowable(width="100%", thickness=2, color=ACCENT, spaceAfter=5)) story.append(Paragraph("02 | PRODUCT RECOMMENDATIONS", section_header)) story.append(Paragraph("Products are grouped by category and budget tier. All recommendations are suited to your wavy, coarse, high-density hair type.", body_style)) story.append(Spacer(1, 8)) def product_block(category, emoji, products, bg=LIGHT_BG): """products = list of dicts: name, price, key_ingredients, best_for, tier""" rows = [ [Paragraph(f"<b>{emoji} {category}</b>", ParagraphStyle("cat", fontName="Helvetica-Bold", fontSize=10, textColor=DARK)), "", "", "", ""] ] rows.append([ Paragraph("<b>Product</b>", ParagraphStyle("th", fontName="Helvetica-Bold", fontSize=8.5, textColor=WHITE)), Paragraph("<b>Price</b>", ParagraphStyle("th", fontName="Helvetica-Bold", fontSize=8.5, textColor=WHITE)), Paragraph("<b>Key Ingredients</b>", ParagraphStyle("th", fontName="Helvetica-Bold", fontSize=8.5, textColor=WHITE)), Paragraph("<b>Best For</b>", ParagraphStyle("th", fontName="Helvetica-Bold", fontSize=8.5, textColor=WHITE)), Paragraph("<b>Tier</b>", ParagraphStyle("th", fontName="Helvetica-Bold", fontSize=8.5, textColor=WHITE)), ]) for i, p in enumerate(products): row_bg = colors.HexColor("#F0F6FF") if i % 2 == 0 else WHITE rows.append([ Paragraph(p["name"], ParagraphStyle("pn", fontName="Helvetica-Bold", fontSize=9, textColor=TEAL)), Paragraph(p["price"], body_style), Paragraph(p["ingredients"], body_style), Paragraph(p["best_for"], body_style), Paragraph(p["tier"], ParagraphStyle("tier", fontName="Helvetica-Bold", fontSize=8.5, textColor=ACCENT if p["tier"]=="Budget" else TEAL if p["tier"]=="Mid" else GOLD)), ]) t = Table(rows, colWidths=[4.5*cm, 1.8*cm, 4.2*cm, 4.2*cm, 2.3*cm]) style = [ ("SPAN", (0,0), (-1,0)), ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#D0E8FF")), ("BACKGROUND", (0,1), (-1,1), SOFT), ("TOPPADDING", (0,0), (-1,-1), 5), ("BOTTOMPADDING", (0,0), (-1,-1), 5), ("LEFTPADDING", (0,0), (-1,-1), 7), ("RIGHTPADDING", (0,0), (-1,-1), 7), ("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#CCCCCC")), ("VALIGN", (0,0), (-1,-1), "TOP"), ("FONTSIZE", (0,2), (-1,-1), 9), ] for i in range(2, len(rows)): bg_c = colors.HexColor("#F0F6FF") if (i-2) % 2 == 0 else WHITE style.append(("BACKGROUND", (0,i), (-1,i), bg_c)) t.setStyle(TableStyle(style)) return t # Shampoos shampoos = [ {"name": "Nizoral Anti-Dandruff Shampoo (1% Ketoconazole)", "price": "~$15", "ingredients": "Ketoconazole 1%", "best_for": "Scalp health + early thinning prevention (anti-DHT effect)", "tier": "Budget"}, {"name": "Nexxus Ultralight Smooth Shampoo", "price": "~$14", "ingredients": "Protein fusion, elastin", "best_for": "Frizz control for thick wavy hair, 72-hr smoothing", "tier": "Budget"}, {"name": "DS Laboratories Revita Shampoo", "price": "~$30", "ingredients": "Caffeine, biotin, ketoconazole, spin traps", "best_for": "Crown thinning prevention + frizz control — dual purpose", "tier": "Mid"}, {"name": "Kerastase Densifique Bodifying Shampoo", "price": "~$40", "ingredients": "Stemoxydine, hyaluronic acid", "best_for": "Density + volume for high-density wavy hair", "tier": "Premium"}, ] story.append(product_block("SHAMPOOS", "🧴", shampoos)) story.append(Spacer(1, 8)) # Conditioners conditioners = [ {"name": "Verb Hydrating Conditioner", "price": "~$16", "ingredients": "Argan oil, quinoa protein, pro-vitamin B5", "best_for": "Dryness, frizz, and thickness in one affordable formula", "tier": "Budget"}, {"name": "The Ordinary Behentrimonium Chloride 2%", "price": "~$9", "ingredients": "Behentrimonium chloride, sunflower oil, glycerin", "best_for": "Ultra-budget, lightweight detangling for coarse hair", "tier": "Budget"}, {"name": "Redken Acidic Bonding Concentrate Conditioner", "price": "~$28", "ingredients": "Citric acid, amino acids", "best_for": "Strengthening + smoothing wavy coarse hair", "tier": "Mid"}, {"name": "Ouai Medium Hair Conditioner", "price": "~$32", "ingredients": "Keratin, shea butter, tamarind seed extract", "best_for": "Wavy coarse hair: moisture + definition without heaviness", "tier": "Premium"}, ] story.append(product_block("CONDITIONERS", "💧", conditioners)) story.append(Spacer(1, 8)) # Leave-ins & serums leavein = [ {"name": "Mielle Organics Rosemary Mint Strengthening Leave-In", "price": "~$10", "ingredients": "Rosemary, biotin, mint, castor oil", "best_for": "Frizz control + scalp stimulation, great for wavy hair", "tier": "Budget"}, {"name": "Moroccanoil Treatment (Light)", "price": "~$16", "ingredients": "Argan oil, keratin proteins", "best_for": "Taming frizz on coarse wavy hair; adds shine without grease", "tier": "Mid"}, {"name": "Virtue Flourish Density Booster", "price": "~$48", "ingredients": "Alpha Keratin 60ku, Capixyl, Redensyl", "best_for": "Crown thinning support + frizz reduction", "tier": "Premium"}, ] story.append(product_block("LEAVE-IN / SERUMS", "✨", leavein)) story.append(Spacer(1, 8)) # Hair loss / thinning thinning = [ {"name": "Rogaine 5% Minoxidil Foam", "price": "~$50/3mo", "ingredients": "5% Minoxidil", "best_for": "FDA-approved crown thinning treatment — most evidence-backed option", "tier": "Mid"}, {"name": "Hims Topical Minoxidil Solution", "price": "~$35/mo", "ingredients": "5% Minoxidil", "best_for": "Easy subscription model; effective for crown and vertex thinning", "tier": "Mid"}, {"name": "Nutrafol Men (oral supplement)", "price": "~$88/mo", "ingredients": "Saw palmetto, ashwagandha, biotin, marine collagen", "best_for": "Hormonal + stress-related thinning; pairs well with topical minoxidil", "tier": "Premium"}, {"name": "Maelove Full Follicle Scalp Serum", "price": "~$22", "ingredients": "Caffeine, peptides, niacinamide", "best_for": "Gentle minoxidil-free option for early-stage prevention", "tier": "Budget"}, ] story.append(product_block("HAIR THINNING / GROWTH TREATMENTS", "💊", thinning)) story.append(Spacer(1, 8)) # Deep conditioning masks = [ {"name": "Mielle Babassu & Mint Deep Conditioner", "price": "~$10", "ingredients": "Babassu oil, mint, amino acids", "best_for": "Weekly deep conditioning for wavy coarse hair", "tier": "Budget"}, {"name": "Olaplex No.3 Hair Perfector", "price": "~$28", "ingredients": "Bis-aminopropyl diglycol dimaleate", "best_for": "Strengthening + repairing damaged or overprocessed wavy hair", "tier": "Mid"}, {"name": "Nutrafol Build-Up Blocker Exfoliating Scalp Mask", "price": "~$42", "ingredients": "Salicylic acid, kaolin, niacinamide", "best_for": "Scalp detox + unclogging follicles at the crown area", "tier": "Premium"}, ] story.append(product_block("HAIR MASKS & SCALP TREATMENTS", "🎭", masks)) story.append(Spacer(1, 14)) # ─── SECTION 3: STARTER KITS ───────────────────────────────────────────────── story.append(HRFlowable(width="100%", thickness=2, color=ACCENT, spaceAfter=5)) story.append(Paragraph("03 | RECOMMENDED STARTER KITS BY BUDGET", section_header)) kit_data = [ [ Paragraph("<b>BUDGET KIT</b>\n~$44/month", ParagraphStyle("kt", fontName="Helvetica-Bold", fontSize=10, textColor=WHITE, alignment=TA_CENTER)), Paragraph("<b>MID-RANGE KIT</b>\n~$93/month", ParagraphStyle("kt", fontName="Helvetica-Bold", fontSize=10, textColor=WHITE, alignment=TA_CENTER)), Paragraph("<b>PREMIUM KIT</b>\n~$200/month", ParagraphStyle("kt", fontName="Helvetica-Bold", fontSize=10, textColor=WHITE, alignment=TA_CENTER)), ], [ Paragraph("• Nizoral Shampoo\n• Verb Hydrating Conditioner\n• Mielle Leave-In\n• Mielle Deep Conditioner\n• Maelove Scalp Serum", body_style), Paragraph("• DS Laboratories Revita Shampoo\n• Redken Acidic Bonding Conditioner\n• Moroccanoil Treatment\n• Olaplex No.3\n• Hims Minoxidil Solution", body_style), Paragraph("• Kerastase Densifique Shampoo\n• Ouai Medium Conditioner\n• Virtue Flourish Density Booster\n• Nutrafol Men Supplement\n• Nutrafol Scalp Mask", body_style), ] ] kit_table = Table(kit_data, colWidths=[5.5*cm, 5.5*cm, 6*cm]) kit_table.setStyle(TableStyle([ ("BACKGROUND", (0,0), (0,0), ACCENT), ("BACKGROUND", (1,0), (1,0), TEAL), ("BACKGROUND", (2,0), (2,0), GOLD), ("BACKGROUND", (0,1), (-1,-1), LIGHT_BG), ("TOPPADDING", (0,0), (-1,-1), 8), ("BOTTOMPADDING", (0,0), (-1,-1), 8), ("LEFTPADDING", (0,0), (-1,-1), 10), ("RIGHTPADDING", (0,0), (-1,-1), 10), ("VALIGN", (0,0), (-1,-1), "TOP"), ("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")), ])) story.append(kit_table) story.append(Spacer(1, 14)) # ─── SECTION 4: INGREDIENT GUIDE ───────────────────────────────────────────── story.append(HRFlowable(width="100%", thickness=2, color=ACCENT, spaceAfter=5)) story.append(Paragraph("04 | INGREDIENTS TO SEEK vs. AVOID", section_header)) ing_data = [ [Paragraph("<b>SEEK THESE</b>", ParagraphStyle("seek", fontName="Helvetica-Bold", fontSize=10, textColor=colors.HexColor("#006400"), alignment=TA_CENTER)), Paragraph("<b>AVOID THESE</b>", ParagraphStyle("avoid", fontName="Helvetica-Bold", fontSize=10, textColor=ACCENT, alignment=TA_CENTER))], [ Paragraph( "• <b>Argan oil</b> — frizz control, shine\n" "• <b>Shea butter</b> — deep moisture for coarse hair\n" "• <b>Glycerin</b> — humectant, locks in moisture\n" "• <b>Biotin</b> — supports hair shaft strength\n" "• <b>Ketoconazole</b> — anti-dandruff + anti-DHT (scalp)\n" "• <b>Caffeine</b> — stimulates scalp blood flow\n" "• <b>Rosemary extract</b> — clinically shown to rival minoxidil\n" "• <b>Hydrolyzed keratin/proteins</b> — fills in coarse cuticle gaps\n" "• <b>Hyaluronic acid</b> — scalp hydration\n" "• <b>Salicylic acid (scalp only)</b> — clears buildup, unclogs follicles", body_style ), Paragraph( "• <b>Sulfates</b> (SLS, SLES) — strips oils from wavy hair\n" "• <b>Parabens</b> — potential hormonal disruption\n" "• <b>Heavy silicones</b> (dimethicone) — buildup on wavy hair, blocks follicles\n" "• <b>Drying alcohols</b> (isopropyl, SD alcohol) — dehydrates coarse hair\n" "• <b>Mineral oil / petrolatum</b> — seals out moisture on high-density hair\n" "• <b>Fragrance (parfum)</b> — common scalp irritant, can worsen inflammation\n" "• <b>Formaldehyde releasers</b> — damaging to hair protein structure", body_style ) ] ] ing_table = Table(ing_data, colWidths=[8.5*cm, 8.5*cm]) ing_table.setStyle(TableStyle([ ("BACKGROUND", (0,0), (0,0), colors.HexColor("#E8F5E9")), ("BACKGROUND", (1,0), (1,0), colors.HexColor("#FDECEA")), ("BACKGROUND", (0,1), (0,1), colors.HexColor("#F1FAF2")), ("BACKGROUND", (1,1), (1,1), colors.HexColor("#FFF5F5")), ("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")), ("TOPPADDING", (0,0), (-1,-1), 8), ("BOTTOMPADDING", (0,0), (-1,-1), 8), ("LEFTPADDING", (0,0), (-1,-1), 10), ("RIGHTPADDING", (0,0), (-1,-1), 10), ("VALIGN", (0,0), (-1,-1), "TOP"), ])) story.append(ing_table) story.append(Spacer(1, 14)) # ─── SECTION 5: CROWN THINNING MONITORING ──────────────────────────────────── story.append(HRFlowable(width="100%", thickness=2, color=ACCENT, spaceAfter=5)) story.append(Paragraph("05 | CROWN THINNING: MONITORING & ACTION PLAN", section_header)) crown_data = [ [ Paragraph("<b>Monthly Self-Check</b>", sub_header), Paragraph("<b>When to See a Dermatologist</b>", sub_header), ], [ Paragraph( "1. Photograph your crown under consistent bright light once a month.\n\n" "2. Part your hair in 4 directions at the crown and inspect with a mirror.\n\n" "3. Check your shower drain — >100 hairs/day is a flag.\n\n" "4. Run fingers through dry hair and note how many hairs pull out.", body_style ), Paragraph( "• Crown spot appears visibly larger vs. 3 months ago\n\n" "• Seeing more than 100-150 hairs shed daily\n\n" "• Family history of early male pattern baldness (MPB)\n\n" "• Topical products not slowing progression after 6 months\n\n" "• Scalp irritation, redness, or scaling persists", body_style ), ] ] crown_table = Table(crown_data, colWidths=[8.5*cm, 8.5*cm]) crown_table.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,0), colors.HexColor("#EEF4FF")), ("BACKGROUND", (0,1), (-1,1), WHITE), ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")), ("TOPPADDING", (0,0), (-1,-1), 8), ("BOTTOMPADDING", (0,0), (-1,-1), 8), ("LEFTPADDING", (0,0), (-1,-1), 10), ("RIGHTPADDING", (0,0), (-1,-1), 10), ("VALIGN", (0,0), (-1,-1), "TOP"), ])) story.append(crown_table) story.append(Spacer(1, 8)) story.append(Paragraph( "<b>Evidence note:</b> A 2023 study in JAAD found topical rosemary oil to be comparable to 2% minoxidil for " "androgenetic alopecia after 6 months. For stronger evidence, 5% minoxidil (topical) remains the gold standard " "FDA-approved non-prescription treatment for crown thinning. Oral finasteride requires a prescription and is " "significantly more effective but carries potential side effects — discuss with a dermatologist.", note_style )) story.append(Spacer(1, 14)) # ─── SECTION 6: LIFESTYLE ───────────────────────────────────────────────────── story.append(HRFlowable(width="100%", thickness=2, color=ACCENT, spaceAfter=5)) story.append(Paragraph("06 | LIFESTYLE TIPS FOR HAIR HEALTH", section_header)) life_data = [ [ Paragraph("🍽️ <b>Nutrition</b>", sub_header), Paragraph("😴 <b>Sleep & Stress</b>", sub_header), Paragraph("🌊 <b>Styling Habits</b>", sub_header), ], [ Paragraph( "• Protein: 0.8–1g/kg body weight daily\n" "• Iron + Zinc: eggs, lentils, pumpkin seeds\n" "• Vitamin D: fish, fortified foods, or supplement\n" "• Omega-3s: flaxseeds, walnuts, fatty fish\n" "• Biotin: eggs, almonds, sweet potato", body_style ), Paragraph( "• Aim for 7-8 hrs sleep — growth hormone peaks at night\n" "• Chronic stress spikes cortisol → telogen effluvium (sudden shedding)\n" "• Try scalp massage 4 min daily — shown to increase hair thickness in 24 weeks\n" "• Reduce tight hairstyles — traction can accelerate crown thinning", body_style ), Paragraph( "• Avoid heat styling >180°C without heat protectant\n" "• Microfiber towel or cotton t-shirt to dry — regular towels rough up the cuticle\n" "• Air-dry 80% before diffusing on low heat\n" "• Avoid sleeping with wet hair — increases breakage\n" "• Wash pillowcase weekly to avoid oil/bacteria buildup", body_style ), ] ] life_table = Table(life_data, colWidths=[5.5*cm, 5.5*cm, 6*cm]) life_table.setStyle(TableStyle([ ("BACKGROUND", (0,0), (-1,0), LIGHT_BG), ("BACKGROUND", (0,1), (-1,-1), WHITE), ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")), ("TOPPADDING", (0,0), (-1,-1), 7), ("BOTTOMPADDING", (0,0), (-1,-1), 7), ("LEFTPADDING", (0,0), (-1,-1), 8), ("RIGHTPADDING", (0,0), (-1,-1), 8), ("VALIGN", (0,0), (-1,-1), "TOP"), ])) story.append(life_table) story.append(Spacer(1, 14)) # ─── FOOTER ────────────────────────────────────────────────────────────────── story.append(HRFlowable(width="100%", thickness=1, color=MID_GREY, spaceAfter=5)) story.append(Paragraph( "This guide is personalised based on a visual hair analysis and is for informational purposes only. " "It does not constitute medical advice. For hair loss, scalp conditions, or persistent concerns, " "consult a qualified dermatologist or trichologist.", ParagraphStyle("footer", fontName="Helvetica-Oblique", fontSize=8, textColor=MID_GREY, alignment=TA_CENTER) )) story.append(Paragraph( "Generated by Orris AI • July 2026", ParagraphStyle("footer2", fontName="Helvetica", fontSize=7.5, textColor=MID_GREY, alignment=TA_CENTER) )) doc.build(story) print("PDF created successfully at", OUTPUT) EOF
Hair Care Guide
PDF Document · PDF