1. Psoriasis 2. Scabies 3. Stevens–Johnson Syndrome (SJS) 4. Pemphigus vulgaris 5. Acne vulgaris 6. Leprosy (Hansen’s disease) 7. Syphilis 8. Lichen planus
What level of detail do you need for each topic? · Who is this for?
mkdir -p /tmp/workspace/dermatology-notes && ls /tmp/workspace/dermatology-notes/
~/dermatology-notes/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
OUTPUT = "/tmp/workspace/dermatology-notes/Dermatology_MBBS_Notes.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=2*cm,
leftMargin=2*cm,
topMargin=2.2*cm,
bottomMargin=2*cm,
title="Dermatology - Detailed MBBS Notes",
author="Orris Medical AI"
)
styles = getSampleStyleSheet()
# Custom styles
TEAL = colors.HexColor("#006666")
DARK = colors.HexColor("#1a1a2e")
LIGHT_TEAL = colors.HexColor("#e0f2f2")
YELLOW = colors.HexColor("#fff8e1")
RED_LIGHT = colors.HexColor("#fdecea")
BORDER = colors.HexColor("#006666")
title_style = ParagraphStyle(
"MainTitle", parent=styles["Title"],
fontSize=26, leading=32, textColor=TEAL,
spaceAfter=6, alignment=TA_CENTER, fontName="Helvetica-Bold"
)
subtitle_style = ParagraphStyle(
"Subtitle", parent=styles["Normal"],
fontSize=12, leading=16, textColor=colors.HexColor("#444444"),
spaceAfter=4, alignment=TA_CENTER
)
topic_title_style = ParagraphStyle(
"TopicTitle", parent=styles["Heading1"],
fontSize=18, leading=24, textColor=colors.white,
spaceAfter=0, spaceBefore=0, fontName="Helvetica-Bold",
alignment=TA_LEFT
)
h2_style = ParagraphStyle(
"H2", parent=styles["Heading2"],
fontSize=12, leading=16, textColor=TEAL,
spaceAfter=4, spaceBefore=8, fontName="Helvetica-Bold"
)
h3_style = ParagraphStyle(
"H3", parent=styles["Heading3"],
fontSize=11, leading=14, textColor=DARK,
spaceAfter=3, spaceBefore=6, fontName="Helvetica-Bold"
)
body_style = ParagraphStyle(
"Body", parent=styles["Normal"],
fontSize=10, leading=14, textColor=colors.HexColor("#222222"),
spaceAfter=4, spaceBefore=2, alignment=TA_JUSTIFY
)
bullet_style = ParagraphStyle(
"Bullet", parent=styles["Normal"],
fontSize=10, leading=13, textColor=colors.HexColor("#222222"),
spaceAfter=2, spaceBefore=1, leftIndent=12, bulletIndent=0
)
key_style = ParagraphStyle(
"Key", parent=styles["Normal"],
fontSize=10, leading=13, textColor=colors.HexColor("#7b0000"),
spaceAfter=2, spaceBefore=2, fontName="Helvetica-Bold"
)
note_style = ParagraphStyle(
"Note", parent=styles["Normal"],
fontSize=9.5, leading=13, textColor=colors.HexColor("#2c5f2e"),
spaceAfter=2, spaceBefore=2, fontName="Helvetica-Oblique"
)
def topic_header(num, title):
"""Returns a colored header block for a topic."""
data = [[Paragraph(f"{num}. {title}", topic_title_style)]]
t = Table(data, colWidths=[17*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), TEAL),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING", (0,0), (-1,-1), 10),
("LEFTPADDING", (0,0), (-1,-1), 14),
("RIGHTPADDING", (0,0), (-1,-1), 14),
("ROUNDEDCORNERS", [6, 6, 6, 6]),
]))
return t
def highlight_box(text, bg=LIGHT_TEAL, text_color=DARK):
"""A highlighted info/key-point box."""
p = Paragraph(text, ParagraphStyle(
"BoxText", parent=styles["Normal"],
fontSize=9.5, leading=13.5, textColor=text_color,
spaceAfter=0, spaceBefore=0
))
data = [[p]]
t = Table(data, colWidths=[16.6*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING", (0,0), (-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 0.8, BORDER),
("ROUNDEDCORNERS", [4, 4, 4, 4]),
]))
return t
def clinical_table(headers, rows):
"""A styled 2-column table for clinical features."""
col_widths = [5*cm, 11.6*cm]
data = [headers] + rows
t = Table(data, colWidths=col_widths)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, colors.HexColor("#f0f9f9")]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
return t
def B(text): return f"<b>{text}</b>"
def I(text): return f"<i>{text}</i>"
# ── Build story ──────────────────────────────────────────────────────────────
story = []
# ── Cover page ───────────────────────────────────────────────────────────────
story.append(Spacer(1, 3*cm))
story.append(Paragraph("Dermatology", title_style))
story.append(Paragraph("Detailed MBBS Notes", subtitle_style))
story.append(Spacer(1, 0.4*cm))
story.append(HRFlowable(width="100%", thickness=2, color=TEAL))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
"Covering: Psoriasis · Scabies · Stevens-Johnson Syndrome · Pemphigus Vulgaris · "
"Acne Vulgaris · Leprosy (Hansen's Disease) · Syphilis · Lichen Planus",
ParagraphStyle("CoverTopics", parent=styles["Normal"], fontSize=11,
leading=16, textColor=colors.HexColor("#444"), alignment=TA_CENTER,
spaceAfter=6)
))
story.append(Spacer(1, 0.5*cm))
story.append(Paragraph(
"Based on: Fitzpatrick's Dermatology · Harrison's Principles of Internal Medicine · "
"Robbins & Cotran Pathology · Andrews' Clinical Dermatology",
ParagraphStyle("CoverSources", parent=styles["Normal"], fontSize=9,
leading=13, textColor=colors.HexColor("#777"), alignment=TA_CENTER)
))
story.append(Spacer(1, 6*cm))
toc_data = [
[Paragraph(B("No."), body_style), Paragraph(B("Topic"), body_style), Paragraph(B("Page"), body_style)],
["1", "Psoriasis", "3"],
["2", "Scabies", "6"],
["3", "Stevens-Johnson Syndrome (SJS)", "9"],
["4", "Pemphigus Vulgaris", "12"],
["5", "Acne Vulgaris", "15"],
["6", "Leprosy (Hansen's Disease)", "18"],
["7", "Syphilis", "21"],
["8", "Lichen Planus", "24"],
]
toc = Table(toc_data, colWidths=[1.5*cm, 12*cm, 3*cm])
toc.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 10),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("ALIGN", (2,0), (2,-1), "CENTER"),
]))
story.append(Paragraph("Table of Contents", h2_style))
story.append(toc)
story.append(PageBreak())
# ═════════════════════════════════════════════════════════════
# 1. PSORIASIS
# ═════════════════════════════════════════════════════════════
story.append(topic_header("1", "Psoriasis"))
story.append(Spacer(1, 0.3*cm))
story.append(highlight_box(
B("Definition: ") + "A common, chronic, immune-mediated inflammatory skin disease characterized by "
"well-demarcated, erythematous plaques covered with silvery-white (micaceous) scales, "
"occurring at sites of predilection. It is a systemic disease affecting ~2% of the world population.",
bg=LIGHT_TEAL
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Etiology & Pathogenesis", h2_style))
story.append(Paragraph(
"Psoriasis results from a complex interplay between genetic susceptibility (HLA-Cw6 association), "
"environmental triggers, and immune dysregulation. The disease is driven by a Th1/Th17 inflammatory "
"axis. Key cytokines: <b>TNF-α, IL-17, IL-23, IL-12, IFN-γ.</b>",
body_style
))
story.append(Paragraph("Key pathogenic steps:", h3_style))
items = [
"Dendritic cells produce IL-23 → Th17 cell development",
"Th17 cells produce IL-17 → keratinocyte hyperproliferation and neutrophil recruitment",
"Th1 cells produce IFN-γ and TNF-α → sustained inflammation",
"Keratinocyte transit time reduced from 28 days → 3–4 days (hyperproliferation)",
"Capillary loop elongation in papillary dermis with 'squirting papillae' (leukocyte extravasation into epidermis)",
"Neutrophils form Munro microabscesses in the stratum corneum",
]
for it in items:
story.append(Paragraph(f"• {it}", bullet_style))
story.append(Paragraph("Triggers", h3_style))
triggers = [
"Koebner phenomenon (trauma)", "Streptococcal pharyngitis (especially guttate psoriasis)",
"Drugs: lithium, beta-blockers, antimalarials, NSAIDs, withdrawal of systemic corticosteroids",
"Stress (psychological)", "HIV infection", "Alcohol and smoking"
]
for t in triggers:
story.append(Paragraph(f"• {t}", bullet_style))
story.append(Paragraph("Clinical Features", h2_style))
rows = [
[Paragraph("Plaque psoriasis\n(Psoriasis vulgaris)", body_style),
Paragraph("Most common (80–90%). Well-defined, erythematous plaques with silvery scales. "
"Sites: extensor surfaces (elbows, knees), scalp, sacrum, umbilicus.", body_style)],
[Paragraph("Guttate psoriasis", body_style),
Paragraph("Small drop-like lesions, often post-streptococcal. Common in children/young adults.", body_style)],
[Paragraph("Inverse psoriasis", body_style),
Paragraph("Smooth, red plaques in skin folds (axilla, groin, inframammary). No scales due to moisture.", body_style)],
[Paragraph("Pustular psoriasis", body_style),
Paragraph("Generalized (von Zumbusch) — sterile pustules on erythematous background; life-threatening. "
"Localized — palmoplantar pustulosis.", body_style)],
[Paragraph("Erythrodermic\npsoriasis", body_style),
Paragraph("Generalized erythema and scaling >90% BSA. Can cause thermoregulatory failure, high-output cardiac failure.", body_style)],
[Paragraph("Nail psoriasis", body_style),
Paragraph("Pitting (most common), onycholysis, oil drop sign (salmon patch), subungual hyperkeratosis. "
"Presence increases risk of psoriatic arthritis.", body_style)],
]
story.append(clinical_table(
[Paragraph(B("Type"), body_style), Paragraph(B("Features"), body_style)], rows
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Special Signs", h3_style))
signs = [
B("Auspitz sign:") + " pinpoint bleeding on removal of scale (exposure of dilated capillaries)",
B("Koebner phenomenon:") + " psoriatic lesions appearing at sites of trauma/injury",
B("Candle grease sign:") + " scraping reveals silvery scales resembling candle grease",
B("Woronoff ring:") + " pale halo around healing psoriatic lesion after treatment",
]
for s in signs:
story.append(Paragraph(f"• {s}", bullet_style))
story.append(Paragraph("Psoriatic Arthritis", h3_style))
story.append(Paragraph(
"Occurs in 20–30% of patients. Patterns: asymmetric oligoarthritis (most common), "
"symmetric polyarthritis (RA-like), distal interphalangeal joint involvement (classic), "
"arthritis mutilans, and axial disease (sacroiliitis). Seronegative (RF negative).",
body_style
))
story.append(Paragraph("Histopathology", h2_style))
histo = [
"Acanthosis (epidermal thickening) with regular elongation of rete ridges",
"Thinning of suprapapillary epidermis",
"Parakeratosis (retained nuclei in stratum corneum)",
"Absence of stratum granulosum",
"Munro microabscesses (neutrophils in stratum corneum)",
"Spongiform pustule of Kogoj (neutrophils in spinous layer — seen in pustular psoriasis)",
"Dilated tortuous capillaries in papillary dermis",
"Lymphocytic and neutrophilic perivascular infiltrate",
]
for h in histo:
story.append(Paragraph(f"• {h}", bullet_style))
story.append(Paragraph("Treatment", h2_style))
story.append(Paragraph(B("Topical (mild-moderate):"), body_style))
for item in ["Corticosteroids (mainstay)", "Vitamin D analogues: calcipotriol/calcipotriene",
"Tar preparations", "Dithranol (anthralin)", "Tazarotene (retinoid)", "Calcineurin inhibitors (tacrolimus) — face/folds"]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph(B("Phototherapy:"), body_style))
for item in ["Narrowband UVB (NB-UVB) — first-line phototherapy",
"PUVA (psoralen + UVA) — for severe/refractory cases"]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph(B("Systemic (severe/refractory):"), body_style))
for item in ["Methotrexate — most widely used; monitor LFTs and CBC",
"Cyclosporine — effective but nephrotoxic; for short-term use",
"Acitretin (retinoid) — especially pustular and erythrodermic; teratogenic",
"Apremilast (PDE4 inhibitor) — oral; fewer adverse effects"]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph(B("Biologics (moderate-severe):"), body_style))
biologic_data = [
[Paragraph(B("Class"), body_style), Paragraph(B("Drug(s)"), body_style)],
["Anti-TNF-α", "Adalimumab, Etanercept, Infliximab, Certolizumab"],
["Anti-IL-12/23 (p40)", "Ustekinumab"],
["Anti-IL-17A", "Secukinumab, Ixekizumab"],
["Anti-IL-17RA", "Brodalumab"],
["Anti-IL-23 (p19)", "Guselkumab, Risankizumab, Tildrakizumab"],
]
bio_t = Table(biologic_data, colWidths=[5*cm, 11.6*cm])
bio_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
]))
story.append(bio_t)
story.append(Spacer(1, 0.3*cm))
story.append(highlight_box(
B("Exam Tip: ") + "Psoriasis is the most common dermatosis associated with arthritis. "
"Koebner phenomenon is also seen in lichen planus, vitiligo, and warts. "
"Methotrexate is contraindicated in pregnancy, renal failure, and hepatic disease.",
bg=YELLOW
))
story.append(PageBreak())
# ═════════════════════════════════════════════════════════════
# 2. SCABIES
# ═════════════════════════════════════════════════════════════
story.append(topic_header("2", "Scabies"))
story.append(Spacer(1, 0.3*cm))
story.append(highlight_box(
B("Definition: ") + "A highly contagious, intensely pruritic skin infestation caused by the mite "
I("Sarcoptes scabiei") + " var. " + I("hominis") + ", an obligate human ectoparasite. "
"Transmitted by direct prolonged skin-to-skin contact (sexually or household).",
bg=LIGHT_TEAL
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Etiology & Life Cycle", h2_style))
items = [
I("Sarcoptes scabiei") + " — 0.2–0.4 mm, eight-legged mite (female is larger)",
"Female mite burrows into stratum corneum at ~2–3 mm/day, lays 3 eggs/day for 4–6 weeks",
"Larvae hatch in 3–4 days, mature in 10–15 days; total life cycle ~17 days",
"Fecal material (scybala) and shed exoskeleton cause delayed hypersensitivity reaction (Type IV)",
"Pruritus is due to sensitization — may not appear for 4–6 weeks after first infestation",
"On re-infestation, symptoms appear within 1–3 days",
"Transmission: requires prolonged direct skin contact (>10 minutes); can survive off host 24–36 hours"
]
for it in items:
story.append(Paragraph(f"• {it}", bullet_style))
story.append(Paragraph("Clinical Features", h2_style))
story.append(Paragraph(
B("Cardinal symptom: ") + "Severe pruritus, characteristically " + B("worse at night") +
" (nocturnal pruritus) and after a hot bath. Multiple family members affected simultaneously.",
body_style
))
story.append(Paragraph("Skin Lesions:", h3_style))
lesions = [
B("Burrows:") + " Pathognomonic. Thin, grayish-white, tortuous linear tracks 5–10 mm long in the stratum corneum. "
"The mite can be visualized as a dark dot at the advancing end.",
B("Papules and vesicles:") + " Inflammatory lesions in areas of high density",
B("Excoriations:") + " Due to scratching",
B("Nodules:") + " Reddish-brown, 5–20 mm; typically on genitalia, axillae, areolae (hypersensitivity reaction)",
B("Secondary changes:") + " Eczematization, impetigo (secondary bacterial infection with S. aureus/Group A Strep)"
]
for l in lesions:
story.append(Paragraph(f"• {l}", bullet_style))
story.append(Paragraph("Distribution of Lesions:", h3_style))
story.append(Paragraph(
"Interdigital spaces (first sign), flexor aspects of wrists, anterior axillary folds, "
"periumbilical region, buttocks, genitalia (penis/scrotum — highly characteristic in males), "
"areolae in women. " + B("Head and neck spared in adults (but involved in infants/young children)."),
body_style
))
story.append(Paragraph("Crusted (Norwegian) Scabies", h3_style))
story.append(highlight_box(
B("Crusted Scabies: ") + "A hyperinfested form occurring in immunocompromised patients (HIV, transplant recipients, "
"elderly in nursing homes, Down syndrome). Characterized by widespread hyperkeratotic, crusted plaques "
"on elbows, knees, palms, soles, and scalp. Millions of mites present (vs. 10–15 in classic scabies). "
"Highly contagious — causes institutional outbreaks. Pruritus may be minimal.",
bg=RED_LIGHT, text_color=colors.HexColor("#7b0000")
))
story.append(Paragraph("Diagnosis", h2_style))
diag = [
B("Clinical:") + " Typical distribution, nocturnal pruritus, multiple affected contacts",
B("Mineral oil preparation:") + " Scraping of burrow in mineral oil/KOH — demonstrates mites, eggs (oval), "
"and fecal pellets (scybala) under microscopy — confirmatory",
B("Dermoscopy:") + " 'Delta-wing jet' or 'hang glider' sign — mite at end of burrow",
B("Ink burrow test:") + " India ink applied and wiped — ink remains in burrows",
B("PCR:") + " Available but not routine"
]
for d in diag:
story.append(Paragraph(f"• {d}", bullet_style))
story.append(Paragraph("Treatment", h2_style))
story.append(Paragraph(B("First-line Scabicides:"), body_style))
tx_data = [
[Paragraph(B("Drug"), body_style), Paragraph(B("Application"), body_style), Paragraph(B("Notes"), body_style)],
["Permethrin 5% cream", "Apply neck-to-toe, wash off after 8–14 hours. Repeat in 1–2 weeks.",
"Drug of choice (SOR:A). Safe in pregnancy (2nd/3rd trimester) and children >2 months"],
["Ivermectin 200 µg/kg oral", "Single dose; repeat in 2 weeks",
"Drug of choice for crusted scabies and mass treatment. Not approved in children <15 kg"],
["Benzyl benzoate 25%", "Apply all over, leave 24 hours",
"Cheaper; irritant; avoid in children"],
["Sulfur 6–10% ointment", "Apply nightly for 3 nights",
"Oldest; safe in pregnancy and infants <2 months"],
["Lindane 1% lotion", "Apply, wash off after 8 hours",
"Avoid — neurotoxic, not first line"],
["Malathion 0.5%", "Apply, wash off after 24 hours", "Alternative"],
]
tx_t = Table(tx_data, colWidths=[3.5*cm, 7*cm, 6.1*cm])
tx_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(tx_t)
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Environmental Measures:", h3_style))
for item in [
"Treat ALL household and sexual contacts simultaneously (even if asymptomatic)",
"Wash clothing, bed linens, towels in hot water (>50°C) and dry on high heat",
"Items not washable: seal in plastic bags for 1 week (mites cannot survive off host >3 days)",
"Pruritus may persist for 4–6 weeks after successful treatment (post-scabetic eczema) — treat with topical steroids and antihistamines; does NOT indicate treatment failure"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Spacer(1, 0.2*cm))
story.append(highlight_box(
B("Exam Tip: ") + "Burrows are pathognomonic of scabies. "
"Nodular scabies on penis/scrotum is highly characteristic. "
"Post-treatment pruritus does not mean treatment failure. "
"Crusted scabies = immunocompromised patient + hyperkeratotic plaques.",
bg=YELLOW
))
story.append(PageBreak())
# ═════════════════════════════════════════════════════════════
# 3. STEVENS-JOHNSON SYNDROME (SJS)
# ═════════════════════════════════════════════════════════════
story.append(topic_header("3", "Stevens-Johnson Syndrome (SJS)"))
story.append(Spacer(1, 0.3*cm))
story.append(highlight_box(
B("Definition: ") + "SJS and Toxic Epidermal Necrolysis (TEN) represent a spectrum of life-threatening, "
"acute mucocutaneous drug reactions characterized by widespread keratinocyte apoptosis, "
"epidermal detachment, and mucous membrane involvement. "
"SJS: <10% BSA detachment. SJS-TEN overlap: 10–30%. TEN (Lyell syndrome): >30% BSA.",
bg=LIGHT_TEAL
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Epidemiology & Etiology", h2_style))
story.append(Paragraph(
"Incidence: SJS 1–6 per million/year; TEN 0.4–1.9 per million/year. Mortality: SJS ~5–10%, TEN ~25–35%. "
"Predominantly drug-induced (>80%). Genetic associations: " +
B("HLA-B*1502") + " (carbamazepine → SJS in Han Chinese/SE Asians), " +
B("HLA-B*5801") + " (allopurinol → SJS).",
body_style
))
story.append(Paragraph("Causative Drugs (Most Common):", h3_style))
drug_data = [
[Paragraph(B("High Risk"), body_style), Paragraph(B("Moderate Risk"), body_style)],
["Allopurinol (most common cause worldwide)", "Fluoroquinolones"],
["Aromatic anticonvulsants: carbamazepine, phenytoin, phenobarbital", "Cephalosporins"],
["Sulfonamides (cotrimoxazole)", "Oxicam NSAIDs"],
["Nevirapine", "Paracetamol (acetaminophen)"],
["Lamotrigine", "Aminopenicillins"],
]
drug_t = Table(drug_data, colWidths=[8.3*cm, 8.3*cm])
drug_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(drug_t)
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Other Causes:", h3_style))
for item in [
"Infections: Mycoplasma pneumoniae (most common in children), HSV (recurrent SJS)",
"Radiation therapy", "Graft-versus-host disease (GVHD)", "Idiopathic (~10–25%)"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Pathogenesis", h2_style))
story.append(Paragraph(
"Drug-specific CD8+ cytotoxic T cells and NK cells target keratinocytes expressing drug-MHC complexes. "
"Fas-FasL interaction, perforin-granzyme B pathway, and granulysin (a cytotoxic protein released "
"by CTLs — " + B("key mediator in SJS/TEN") + ") induce widespread keratinocyte apoptosis. "
"Pharmacogenetic factors (HLA alleles) influence susceptibility.",
body_style
))
story.append(Paragraph("Clinical Features", h2_style))
story.append(Paragraph(B("Prodrome (1–3 days):"), body_style))
for item in ["High fever, malaise, pharyngitis, conjunctivitis", "Burning/painful skin — important early warning"]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph(B("Mucosal involvement (almost universal in SJS):"), body_style))
for item in [
"Oral mucosa: painful erosions, hemorrhagic crusting of lips, difficulty eating",
"Ocular: purulent conjunctivitis, corneal erosions → risk of blindness",
"Genital: erosive urethritis, vulvovaginitis",
"Respiratory: tracheobronchial involvement → ARDS"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph(B("Skin lesions:"), body_style))
for item in [
"Start on face/trunk, spread centrifugally",
"Atypical target lesions (flat, 2 zones, macular — unlike EM which has 3 zones/raised lesions)",
"Vesicles and bullae on erythematous/dusky macules",
B("Nikolsky sign: ") + "positive (lateral pressure on normal-appearing skin causes epidermal shearing)",
B("Asboe-Hansen sign: ") + "pressure on bulla causes lateral spread of blister"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Distinction: SJS vs. TEN vs. Erythema Multiforme", h3_style))
dist_data = [
[Paragraph(B("Feature"), body_style), Paragraph(B("SJS"), body_style),
Paragraph(B("SJS-TEN"), body_style), Paragraph(B("TEN"), body_style)],
["BSA detachment", "<10%", "10–30%", ">30%"],
["Mucosal involvement", "Yes (>2 sites)", "Yes", "Yes"],
["Target lesions", "Atypical, flat", "Atypical", "Atypical"],
["Fever", "Present", "Present", "Present"],
["Mortality", "~5–10%", "~10–15%", "~25–35%"],
]
dist_t = Table(dist_data, colWidths=[3.5*cm, 3.5*cm, 3.5*cm, 6.1*cm])
dist_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(dist_t)
story.append(Paragraph("SCORTEN Score (Severity Assessment)", h3_style))
story.append(Paragraph(
"Validated mortality predictor for TEN. One point each for: age >40, heart rate >120/min, "
"cancer/hematologic malignancy, BSA >10% on Day 1, serum urea >10 mmol/L, "
"serum glucose >14 mmol/L, serum bicarbonate <20 mmol/L. "
"Score 0–1: mortality ~3%; Score ≥5: mortality ~90%.",
body_style
))
story.append(Paragraph("Management", h2_style))
story.append(highlight_box(
B("IMMEDIATE: ") + "Stop ALL suspected causative drugs immediately — this is the single most important intervention. "
"Mortality increases with delay in drug withdrawal.",
bg=RED_LIGHT, text_color=colors.HexColor("#7b0000")
))
story.append(Spacer(1, 0.15*cm))
for item in [
B("Hospitalization:") + " ICU or burns unit; strict reverse barrier nursing",
B("Fluid/electrolyte resuscitation:") + " IV fluids similar to burns management",
B("Wound care:") + " Non-adhesive dressings; avoid debridement where possible",
B("Eye care:") + " Ophthalmology consult; lubricant eye drops, lysis of adhesions, topical steroids",
B("Nutritional support:") + " Enteral via NG tube",
B("Analgesics:") + " Opioids often required",
B("Cyclosporine:") + " Most promising pharmacologic intervention (arrests progression); 3–5 mg/kg/day",
B("IVIG:") + " Evidence conflicting; may block Fas-FasL interaction",
B("Systemic corticosteroids:") + " Controversial; may increase infection risk if used late; some use early",
B("Anti-TNF (etanercept/infliximab):") + " Promising in TEN, especially refractory cases",
B("Prophylactic antibiotics:") + " NOT recommended unless signs of infection"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Spacer(1, 0.2*cm))
story.append(highlight_box(
B("Exam Tip: ") + "SJS is distinguished from Erythema Multiforme (EM major) by: atypical (2-zone) "
"vs. typical (3-zone) targets, more BSA involvement, and more severe mucosal involvement. "
"Granulysin is the key cytotoxic mediator. "
"Nikolsky sign is positive in SJS/TEN and pemphigus.",
bg=YELLOW
))
story.append(PageBreak())
# ═════════════════════════════════════════════════════════════
# 4. PEMPHIGUS VULGARIS
# ═════════════════════════════════════════════════════════════
story.append(topic_header("4", "Pemphigus Vulgaris"))
story.append(Spacer(1, 0.3*cm))
story.append(highlight_box(
B("Definition: ") + "A potentially life-threatening, autoimmune blistering disease characterized by "
"intraepidermal bullae due to autoantibodies (IgG) against desmosomal proteins (desmogleins), "
"leading to acantholysis (loss of cohesion between epidermal keratinocytes).",
bg=LIGHT_TEAL
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Variants and Target Antigens", h2_style))
var_data = [
[Paragraph(B("Variant"), body_style), Paragraph(B("Target Antigen"), body_style),
Paragraph(B("Clinical Features"), body_style)],
["Pemphigus Vulgaris (PV)", "Desmoglein 3 (DSG3) — all cases\n± Desmoglein 1 (DSG1)",
"Flaccid blisters; mucosa ± skin. Most common pemphigus."],
["Pemphigus Foliaceus (PF)", "Desmoglein 1 (DSG1) only",
"Superficial erosions, no mucosal involvement (DSG3 protects mucosa). 'Corn flake' scale."],
["Paraneoplastic Pemphigus (PNP)", "Desmoplakins, envoplakin,\nperiplakin, others",
"Associated with lymphoma, thymoma, CLL. Polymorphous lesions; severe stomatitis."],
["Fogo Selvagem", "DSG1", "Endemic Brazilian pemphigus; triggered by insect bites."],
["IgA Pemphigus", "Desmocollin 1", "Vesiculopustular lesions; IgA deposits."],
]
var_t = Table(var_data, colWidths=[3.8*cm, 5.2*cm, 7.6*cm])
var_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(var_t)
story.append(Paragraph("Pathogenesis", h2_style))
story.append(Paragraph(
"Desmogleins are transmembrane glycoproteins of desmosomes belonging to the cadherin superfamily "
"of calcium-dependent cell-adhesion molecules. " +
B("Anti-DSG3 IgG autoantibodies") + " bind to desmogleins → steric hindrance of adhesive "
"interface + activation of intracellular signaling (p38 MAPK, protein kinase C) → "
B("acantholysis") + " (epidermal cell separation) → intraepidermal bullae. "
"The level of blister formation correlates with desmoglein distribution: "
"DSG3 is predominant in mucosa and deep epidermis (suprabasal), DSG1 in superficial epidermis.",
body_style
))
story.append(Paragraph("Desmoglein Compensation Hypothesis:", h3_style))
for item in [
"Mucosal surfaces express predominantly DSG3 (not DSG1) → anti-DSG1 alone cannot cause mucosal blisters",
"PF (anti-DSG1 only) affects superficial skin (where DSG1 is sole adhesion) but not mucosa",
"PV (anti-DSG3 ± DSG1) → blisters in mucosa and skin"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Clinical Features", h2_style))
story.append(Paragraph(
B("Most often begins in the mouth (>50% of cases)") + " — painful oral erosions that heal slowly. "
"Mean delay from oral to skin lesions: several months.",
body_style
))
for item in [
B("Blisters:") + " Flaccid (thin-roofed), easily ruptured → painful, slow-healing erosions",
B("Nikolsky sign:") + " Positive (friction on perilesional skin causes new blister formation)",
B("Asboe-Hansen sign:") + " Pressure on intact blister → lateral extension",
"Distribution: scalp, face, trunk, groin, axillae, oral mucosa, conjunctiva, oropharynx, esophagus, genitals",
"Nails: periungual involvement, beau's lines",
"Rarely: nasal, laryngeal, cervical mucosa involvement"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Diagnosis", h2_style))
diag_data = [
[Paragraph(B("Test"), body_style), Paragraph(B("Finding"), body_style)],
["Tzanck smear", "Acantholytic (Tzanck) cells — large rounded keratinocytes with prominent nuclei and basophilic halos"],
["Histopathology (H&E)", "Suprabasal acantholysis; 'tombstone' row of basal cells along dermal-epidermal junction"],
["Direct immunofluorescence (DIF)\n(skin biopsy — perilesional)", "IgG and C3 deposits in intercellular spaces (net/fishnet/chicken-wire pattern) — gold standard for diagnosis"],
["Indirect immunofluorescence (IDIF)", "Circulating IgG anti-epithelial antibodies; titers correlate with disease activity"],
["ELISA (anti-DSG3/DSG1 antibodies)", "Confirmatory; useful for monitoring response to treatment"],
]
diag_t = Table(diag_data, colWidths=[4.5*cm, 12.1*cm])
diag_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(diag_t)
story.append(Paragraph("Treatment", h2_style))
for item in [
B("Systemic corticosteroids (prednisolone 1 mg/kg/day):") + " Mainstay; taper slowly after remission",
B("Rituximab (anti-CD20):") + " Now first-line alongside steroids in moderate-severe PV; induces B-cell depletion",
B("Azathioprine / Mycophenolate mofetil:") + " Steroid-sparing agents",
B("Cyclophosphamide:") + " Severe refractory disease",
B("Dapsone:") + " Adjunct, especially for IgA pemphigus",
B("IVIG:") + " Refractory cases; rapid response",
B("Plasmapheresis:") + " Rapid reduction of circulating antibodies; short-term use",
B("Local care:") + " Wound dressings, oral antiseptic rinses, topical steroids for mucosal lesions"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Spacer(1, 0.2*cm))
story.append(highlight_box(
B("Exam Tip: ") + "Pemphigus vulgaris — suprabasal split, flaccid blisters, + Nikolsky sign, "
"DIF = intercellular IgG. "
"Bullous pemphigoid (subepidermal split, tense blisters, - or + Nikolsky, DIF = linear IgG at BMZ) is the main differential. "
"Tzanck smear shows acantholytic cells in pemphigus AND herpes infections.",
bg=YELLOW
))
story.append(PageBreak())
# ═════════════════════════════════════════════════════════════
# 5. ACNE VULGARIS
# ═════════════════════════════════════════════════════════════
story.append(topic_header("5", "Acne Vulgaris"))
story.append(Spacer(1, 0.3*cm))
story.append(highlight_box(
B("Definition: ") + "A chronic, self-limited inflammatory disorder of the pilosebaceous unit, "
"primarily affecting adolescents, characterized by comedones, inflammatory papules, pustules, "
"nodules, and cysts, predominantly on the face, chest, and back.",
bg=LIGHT_TEAL
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Pathogenesis — Four Key Factors", h2_style))
story.append(Paragraph("Remember: " + B("S-H-C-I") + " — Sebum, Hyperkeratinization, Colonization, Inflammation", body_style))
path_data = [
[Paragraph(B("Factor"), body_style), Paragraph(B("Details"), body_style)],
["1. Increased sebum\nproduction", "Androgens (especially DHT) stimulate sebaceous gland activity → excess sebum. "
"Puberty is the permissive factor. Sebum is comedogenic."],
["2. Follicular\nhyperkeratinization", "Abnormal desquamation of follicular epithelium + excess keratin → plugging "
"of follicular orifice → microcomedone formation (earliest lesion)"],
["3. Cutibacterium acnes\n(C. acnes)", "Formerly Propionibacterium acnes. Colonizes comedones, metabolizes triglycerides "
"in sebum → free fatty acids → inflammation. Activates toll-like receptors (TLR-2) on monocytes/neutrophils."],
["4. Inflammation", "TLR-2 activation → IL-1β, IL-8, TNF-α → neutrophilic and lymphocytic infiltration → "
"cyst wall rupture → foreign body reaction → nodules and scarring"],
]
path_t = Table(path_data, colWidths=[3.8*cm, 12.8*cm])
path_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(path_t)
story.append(Paragraph("Aggravating Factors", h3_style))
for item in [
"Drugs: glucocorticoids (steroid acne), progestin-only OCP, lithium, isoniazid, phenytoin, androgens, halogens (iodides, bromides), epidermal growth factor receptor (EGFR) inhibitors",
"Cosmetics and occlusive topical agents (acne cosmetica)",
"Mechanical friction/pressure (acne mechanica) — helmets, shoulder pads, chin straps",
"Polycystic ovary syndrome (PCOS) — hyperandrogenism",
"Congenital adrenal hyperplasia", "Diet: high glycemic index foods, dairy (controversial evidence)"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Clinical Features & Grading", h2_style))
story.append(Paragraph("Lesion Types:", h3_style))
lesions = [
B("Closed comedone (whitehead):") + " 1–2 mm pebbly white papule; follicular orifice closed; contents not easily expressed; precursor of inflammatory acne",
B("Open comedone (blackhead):") + " Dilated follicular orifice with oxidized (black — melanin, not dirt) oily debris; rarely inflamed",
B("Papule:") + " Solid red raised lesion <5 mm",
B("Pustule:") + " Visible pus",
B("Nodule:") + " >5 mm, deeply seated; heals with scarring",
B("Pseudocyst (fluctuant nodule):") + " Pus-filled fluctuant nodule",
B("Sinus/conglobata:") + " Interconnecting tunnels under skin"
]
for l in lesions:
story.append(Paragraph(f"• {l}", bullet_style))
story.append(Paragraph("Severity Grading (Global Alliance):", h3_style))
grade_data = [
[Paragraph(B("Grade"), body_style), Paragraph(B("Features"), body_style)],
["Mild", "Comedones, few papules/pustules (<20); no nodules"],
["Moderate", "20–100 comedones, 15–50 papules/pustules, <5 nodules"],
["Severe/Nodulocystic", ">5 nodules, extensive papulopustular lesions, risk of scarring"],
]
grade_t = Table(grade_data, colWidths=[3*cm, 13.6*cm])
grade_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(grade_t)
story.append(Paragraph("Special Variants", h3_style))
for item in [
B("Acne conglobata:") + " Severe nodular acne with interconnected abscesses and sinus tracts; primarily in males",
B("Acne fulminans:") + " Acute, febrile, ulcerating acne with systemic features (fever, arthralgia); treat with systemic steroids first, then isotretinoin",
B("Infantile acne:") + " Present in first year of life due to maternal androgens; usually resolves spontaneously",
B("Gram-negative folliculitis:") + " Complication of long-term oral antibiotics; presents as multiple pustules"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Management", h2_style))
mgmt_data = [
[Paragraph(B("Severity"), body_style), Paragraph(B("Treatment"), body_style)],
["Mild\n(comedonal)", "Topical retinoids (tretinoin, adapalene, tazarotene) — first-line\n+ Benzoyl peroxide (BPO)"],
["Mild-Moderate\n(papulopustular)", "Topical retinoid + BPO ± topical antibiotic (clindamycin/erythromycin)\nAlways combine antibiotic with BPO to prevent resistance"],
["Moderate-Severe", "Oral antibiotics (doxycycline/minocycline 100 mg/day) + topical retinoid + BPO\nOral combined OCP (estrogen-containing) — females with hormonal acne\nSpironolactone (anti-androgen) — females"],
["Severe/Nodulocystic\n/Scarring", "Oral isotretinoin (0.5–1 mg/kg/day; cumulative dose 120–150 mg/kg)\n— most effective treatment; targets all 4 pathogenic factors"],
]
mgmt_t = Table(mgmt_data, colWidths=[3.2*cm, 13.4*cm])
mgmt_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(mgmt_t)
story.append(Paragraph("Isotretinoin — Key Points", h3_style))
for item in [
B("Mechanism:") + " Reduces sebaceous gland size and sebum production; normalizes follicular desquamation; anti-inflammatory; decreases C. acnes colonization",
B("Indications:") + " Severe nodulocystic acne, moderate acne resistant to other therapies, acne with scarring",
B("Teratogenicity:") + " Pregnancy Category X; absolute contraindication in pregnancy; iPLEDGE program (USA)",
B("Side effects:") + " Cheilitis (most common), xerosis, epistaxis, myalgia, elevated triglycerides/LFTs, night blindness, pseudotumor cerebri (if combined with tetracyclines), IBD (controversial)"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Spacer(1, 0.2*cm))
story.append(highlight_box(
B("Exam Tip: ") + "Blackhead color is due to melanin/oxidation, not dirt. "
"Isotretinoin is the only drug targeting all 4 pathogenic factors. "
"Never combine systemic tetracyclines with isotretinoin (pseudotumor cerebri risk). "
"Always combine topical antibiotics with BPO to prevent antibiotic resistance.",
bg=YELLOW
))
story.append(PageBreak())
# ═════════════════════════════════════════════════════════════
# 6. LEPROSY (HANSEN'S DISEASE)
# ═════════════════════════════════════════════════════════════
story.append(topic_header("6", "Leprosy (Hansen's Disease)"))
story.append(Spacer(1, 0.3*cm))
story.append(highlight_box(
B("Definition: ") + "A chronic, slowly progressive, infectious granulomatous disease caused by "
I("Mycobacterium leprae") + " (and rarely " + I("M. lepromatosis") + "), primarily affecting "
"the skin and peripheral nerves. Despite low communicability, remains endemic with ~200,000 new "
"infections/year globally, mainly in Southeast Asia, East Africa, and Brazil.",
bg=LIGHT_TEAL
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Microbiology", h2_style))
for item in [
I("M. leprae") + " — an obligate intracellular acid-fast bacillus; cannot be cultured in vitro",
"Optimum growth temperature: 27–30°C (explains predilection for cooler areas — skin, peripheral nerves, testes, anterior chamber of eye)",
"Incubation period: 2–5 years (tuberculoid) to 8–12 years (lepromatous) — longest of any bacterial disease",
"Bacterial lipid PGL-1 is critical for host cell invasion",
"BCG vaccination confers variable (25–80%) protection against leprosy",
"Animal reservoir: nine-banded armadillo (Dasypus novemcinctus) in the USA",
"Route of transmission: respiratory droplets from nasal secretions of lepromatous patients (most likely)"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Ridley-Jopling Classification", h2_style))
story.append(Paragraph(
"Based on the immunological response of the host. A spectrum from high cell-mediated immunity (TT) "
"to absent CMI (LL).",
body_style
))
rj_data = [
[Paragraph(B("Type"), body_style), Paragraph(B("Abbr."), body_style),
Paragraph(B("Skin lesions"), body_style), Paragraph(B("AFB\n(BI)"), body_style),
Paragraph(B("Nerve involvement"), body_style)],
["Tuberculoid", "TT", "1–3 well-defined, hypopigmented/erythematous macules with raised edges, dry, hairless, anesthetic", "0", "Single nerve; severe early"],
["Borderline Tuberculoid", "BT", "Few lesions; less defined edges; satellite lesions", "+/−", "Asymmetric; multiple"],
["Borderline Borderline", "BB", "Multiple lesions; 'punched-out' appearance; immune to immune", "2+", "Moderate; variable"],
["Borderline Lepromatous", "BL", "Many lesions; irregular; beginning nodularity", "3–4+", "Multiple nerves"],
["Lepromatous", "LL", "Multiple symmetrical nodules, plaques, papules; diffuse thickening; leonine facies; madarosis; saddle nose", "5–6+", "Glove-and-stocking; bilateral symmetric; late anesthesia"],
]
rj_t = Table(rj_data, colWidths=[2.5*cm, 1.2*cm, 5.8*cm, 1.5*cm, 6.6*cm])
rj_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(rj_t)
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph("WHO Classification (Operational)", h3_style))
who_data = [
[Paragraph(B("Type"), body_style), Paragraph(B("Criteria"), body_style), Paragraph(B("MDT Regimen"), body_style)],
["Paucibacillary (PB)", "≤5 skin lesions; single nerve\n(TT + BT spectrum)", "Rifampicin 600 mg/month + Dapsone 100 mg/day × 6 months"],
["Multibacillary (MB)", "≥6 skin lesions OR >1 nerve\n(BB + BL + LL spectrum)", "Rifampicin 600 mg/month + Clofazimine 300 mg/month + Dapsone 100 mg/day × 12 months"],
]
who_t = Table(who_data, colWidths=[3.5*cm, 5.5*cm, 7.6*cm])
who_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(who_t)
story.append(Paragraph("Nerve Involvement (Peripheral Neuropathy)", h2_style))
nerve_data = [
[Paragraph(B("Nerve"), body_style), Paragraph(B("Deformity / Effect"), body_style)],
["Ulnar nerve (most common)", "Clawing of ring/little fingers; loss of hypothenar muscles"],
["Median nerve", "Clawing of index/middle fingers; thenar atrophy; ape hand"],
["Radial nerve", "Wrist drop"],
["Common peroneal nerve", "Foot drop"],
["Posterior tibial nerve", "Clawing of toes; plantar anesthesia → trophic ulcers"],
["Facial nerve (zygomatic branch)", "Lagophthalmos → corneal exposure → blindness"],
["Greater auricular nerve", "Thickened, palpable nerve; enlarged visible in neck"],
]
nerve_t = Table(nerve_data, colWidths=[5.5*cm, 11.1*cm])
nerve_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(nerve_t)
story.append(Paragraph("Leprosy Reactions", h2_style))
story.append(Paragraph(
"Acute inflammatory episodes that occur before, during, or after treatment — NOT relapses.",
body_style
))
rx_data = [
[Paragraph(B("Feature"), body_style), Paragraph(B("Type 1 (Reversal Reaction)"), body_style),
Paragraph(B("Type 2 (ENL — Erythema Nodosum Leprosum)"), body_style)],
["Spectrum", "BT, BB, BL", "BL, LL"],
["Mechanism", "Delayed hypersensitivity (Type IV)", "Immune complex (Type III) + neutrophil activation"],
["Skin lesions", "Existing lesions become red, swollen, tender", "New painful red nodules/papules"],
["Nerve involvement", "Common — acute neuritis; can be serious", "Less common"],
["Systemic features", "Rare", "Fever, malaise, arthritis, episcleritis, orchitis, proteinuria"],
["Treatment", "Prednisolone 40–60 mg/day (taper over months)", "Thalidomide (most effective) or prednisolone; clofazimine for recurrent ENL"],
]
rx_t = Table(rx_data, colWidths=[2.8*cm, 6.5*cm, 7.3*cm])
rx_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(rx_t)
story.append(Paragraph("Diagnosis", h3_style))
for item in [
B("Slit-skin smear:") + " AFB from earlobes, eyebrows, elbows; Bacterial Index (BI) 0–6+",
B("Skin biopsy:") + " Tuberculoid — epithelioid granulomas around nerves; Lepromatous — foamy (Virchow) macrophages packed with AFB (globi/lepra cells)",
B("Lepromin test (Mitsuda):") + " Indicates CMI, NOT diagnostic; positive in TT/BT, negative in LL",
B("PCR:") + " Highly sensitive; useful for MB leprosy"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Spacer(1, 0.2*cm))
story.append(highlight_box(
B("Exam Tip: ") + "Leprosy is the most common cause of peripheral neuropathy worldwide. "
"Ulnar nerve is most commonly involved. Single anesthetic hypopigmented patch = leprosy until proven otherwise. "
"Never-administer dapsone without testing G6PD (hemolysis risk). "
"Thalidomide is drug of choice for Type 2 (ENL) reactions.",
bg=YELLOW
))
story.append(PageBreak())
# ═════════════════════════════════════════════════════════════
# 7. SYPHILIS
# ═════════════════════════════════════════════════════════════
story.append(topic_header("7", "Syphilis"))
story.append(Spacer(1, 0.3*cm))
story.append(highlight_box(
B("Definition: ") + "A chronic systemic sexually transmitted infection (STI) caused by the spirochete "
I("Treponema pallidum") + " subsp. " + I("pallidum") + ", capable of involving virtually every organ "
"and classically progressing through distinct stages.",
bg=LIGHT_TEAL
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("Microbiology", h2_style))
for item in [
I("T. pallidum") + " — motile, spiral spirochete; 5–20 μm long with 4–14 spirals",
"Cannot be cultured in vitro; cannot be seen on Gram stain",
"Visualized by: " + B("darkfield microscopy") + " (primary/secondary lesions) or " + B("DFA (direct fluorescent antibody)"),
"Genome ~1 million bp — only ~1/4 of genes compared to most bacteria; minimal metabolic capacity",
"Disseminates rapidly — reaches bloodstream within hours; CNS within 18 hours of inoculation",
"Risk of transmission per sexual contact with infected person: 16–30%",
"Incubation period: 9–90 days (mean 21 days)"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Stages of Acquired Syphilis", h2_style))
stage_data = [
[Paragraph(B("Stage"), body_style), Paragraph(B("Timing"), body_style),
Paragraph(B("Clinical Features"), body_style), Paragraph(B("Infectivity"), body_style)],
["Primary", "9–90 days post-exposure",
"Painless indurated ulcer (CHANCRE) at site of inoculation; firm, clean base; associated painless regional lymphadenopathy; heals spontaneously in 3–6 weeks",
"Highly infectious"],
["Secondary", "6–8 weeks after chancre (can overlap)",
"Maculopapular rash involving PALMS and SOLES (highly characteristic); condylomata lata; mucous patches; 'moth-eaten' alopecia; systemic symptoms (fever, malaise, lymphadenopathy, hepatosplenomegaly); meningitis, uveitis, hepatitis",
"Highly infectious"],
["Early Latent", "<2 years",
"Asymptomatic; serology positive; may relapse to secondary",
"Can transmit sexually"],
["Late Latent", ">2 years",
"Asymptomatic; serology positive; not infectious sexually",
"Not infectious"],
["Tertiary", "Years to decades later",
"Gumma (granulomatous lesion — skin, bone, viscera); Cardiovascular syphilis (aortitis, aortic regurgitation, aneurysm); Neurosyphilis (tabes dorsalis, general paresis, meningovascular)",
"Not infectious"],
]
stage_t = Table(stage_data, colWidths=[2.3*cm, 2.3*cm, 8.5*cm, 3.5*cm])
stage_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(stage_t)
story.append(Paragraph("Neurosyphilis", h3_style))
for item in [
B("Meningitis:") + " 2° stage or early 3°; headache, CSF pleocytosis",
B("Meningovascular syphilis:") + " Stroke-like picture in young patients",
B("General paresis (GPI — General Paralysis of the Insane):") + " Cognitive decline, psychiatric features, seizures",
B("Tabes dorsalis:") + " Dorsal column degeneration → Argyll Robertson pupil (accommodates but does not react to light), lightning pains, ataxia, loss of deep tendon reflexes, Charcot joints",
B("Argyll Robertson pupil:") + " 'Prostitute's pupil' — accommodates but does not react to direct light"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Congenital Syphilis", h3_style))
story.append(Paragraph(
I("T. pallidum") + " crosses placenta (usually after 16th week). Risk of transmission: ~80% in primary/secondary syphilis.",
body_style
))
story.append(Paragraph("Early congenital (birth to 2 years):", body_style))
for item in ["Saddle nose, snuffles (syphilitic rhinitis)", "Skin: diffuse maculopapular rash, condylomata lata, bullous lesions on palms/soles",
"Hepatosplenomegaly, jaundice", "Osteochondritis and periostitis (Wimberger sign)"]:
story.append(Paragraph(f" • {item}", bullet_style))
story.append(Paragraph("Late congenital (>2 years — features of host response):", body_style))
late = [
B("Hutchinson triad:") + " Hutchinson's teeth + interstitial keratitis + eighth nerve deafness",
"Moon's molars (dome-shaped first molars)",
B("Sabre tibia") + " (anterior bowing due to periostitis)",
"Clutton's joints (knee joint effusions)", "Saddle nose, frontal bossing",
"Rhagades (perioral fissures)"
]
for l in late:
story.append(Paragraph(f" • {l}", bullet_style))
story.append(Paragraph("Serology", h2_style))
sero_data = [
[Paragraph(B("Test Type"), body_style), Paragraph(B("Tests"), body_style),
Paragraph(B("Uses"), body_style)],
["Non-treponemal\n(Non-specific)", "VDRL, RPR", "Screening; monitoring response to treatment (titers fall with treatment); can be FALSELY POSITIVE in SLE, pregnancy, malaria, TB, infections"],
["Treponemal\n(Specific)", "TPHA, FTA-ABS, MHA-TP, TPPA", "Confirmation; remain positive for life; cannot distinguish active from treated disease"],
]
sero_t = Table(sero_data, colWidths=[2.8*cm, 3.5*cm, 10.3*cm])
sero_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(sero_t)
story.append(Paragraph("Treatment", h2_style))
tx_syph_data = [
[Paragraph(B("Stage"), body_style), Paragraph(B("Treatment of Choice"), body_style),
Paragraph(B("PCN Allergy"), body_style)],
["Primary / Secondary / Early Latent", "Benzathine Penicillin G 2.4 MU IM single dose",
"Doxycycline 100 mg PO BD × 14 days OR Azithromycin 2 g PO single dose"],
["Late Latent / Tertiary (non-CNS)", "Benzathine Penicillin G 2.4 MU IM weekly × 3 doses",
"Doxycycline 100 mg PO BD × 28 days"],
["Neurosyphilis", "Aqueous Crystalline Penicillin G 18–24 MU/day IV × 10–14 days",
"Desensitize and treat with penicillin (no reliable alternative)"],
["Congenital syphilis", "Aqueous Penicillin G 50,000 U/kg/dose IV q12h (≤7d) or q8h (>7d) × 10 days",
"No alternative — desensitize"],
["Pregnancy", "Benzathine Penicillin G (same as non-pregnant)", "Desensitize to penicillin; azithromycin has resistance concerns"],
]
tx_syph_t = Table(tx_syph_data, colWidths=[3.5*cm, 6.5*cm, 6.6*cm])
tx_syph_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(tx_syph_t)
story.append(Spacer(1, 0.2*cm))
story.append(highlight_box(
B("Jarisch-Herxheimer Reaction: ") + "Flu-like reaction (fever, rigors, myalgia) within 2–12 hours of first "
"dose of penicillin. Due to massive release of treponemal antigens and cytokines. "
"More common in secondary syphilis. Treat symptomatically with antipyretics; do NOT stop antibiotics.",
bg=RED_LIGHT, text_color=colors.HexColor("#7b0000")
))
story.append(Spacer(1, 0.2*cm))
story.append(highlight_box(
B("Exam Tip: ") + "Syphilis is the 'Great Imitator.' Secondary syphilis rash on palms and soles is classic. "
"VDRL monitors treatment response (titer should fall 4-fold at 6 months). "
"Tabes dorsalis + Argyll Robertson pupil = neurosyphilis. "
"Penicillin G remains the drug of choice for all stages.",
bg=YELLOW
))
story.append(PageBreak())
# ═════════════════════════════════════════════════════════════
# 8. LICHEN PLANUS
# ═════════════════════════════════════════════════════════════
story.append(topic_header("8", "Lichen Planus"))
story.append(Spacer(1, 0.3*cm))
story.append(highlight_box(
B("Definition: ") + "A chronic, pruritic, immune-mediated inflammatory papulosquamous disorder "
"affecting skin, mucous membranes, nails, and hair follicles, characterized by "
"the 6 P's of lichen planus.",
bg=LIGHT_TEAL
))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("The 6 P's of Lichen Planus", h2_style))
six_p_data = [
[Paragraph(B("P"), body_style), Paragraph(B("Description"), body_style)],
["Pruritic", "Intensely itchy (can be severe)"],
["Purple / Violaceous", "Characteristic violaceous (purple) color of papules"],
["Polygonal", "Flat-topped papules with angular/polygonal borders"],
["Planar (Flat-topped)", "Surface is flat (planar), not dome-shaped"],
["Papules", "Primary lesion — 1–10 mm flat-topped papules"],
["Wickham's striae", "Lacy white lines on surface of papules (better seen with oil immersion)"],
]
six_t = Table(six_p_data, colWidths=[3.5*cm, 13.1*cm])
six_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 10),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(six_t)
story.append(Paragraph("Etiology & Pathogenesis", h2_style))
story.append(Paragraph(
"Autoimmune — CD8+ T cells (cytotoxic) target basal layer keratinocytes. "
"Trigger may be autoantigens exposed by infection, drugs, or contact sensitizers. "
"Strong association with " + B("Hepatitis C virus (HCV)") + " — especially oral lichen planus.",
body_style
))
story.append(Paragraph("Associations / Triggers:", h3_style))
for item in [
"Hepatitis C (strongest for oral LP)", "Hepatitis B (less strong)",
"Drugs (lichenoid reactions): antimalarials, gold, penicillamine, thiazides, beta-blockers, ACE inhibitors, NSAIDs, allopurinol, methyldopa",
"Dental amalgam (oral LP — contact sensitization)",
"Graft-versus-host disease (GVHD)",
"Koebner phenomenon (LP appears at sites of trauma)",
"Emotional stress may exacerbate"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Clinical Features — Distribution", h2_style))
story.append(Paragraph(
"Most common in adults aged 30–60 years. M = F. Affects 1–2% of population.",
body_style
))
dist_data = [
[Paragraph(B("Site"), body_style), Paragraph(B("Features"), body_style)],
["Skin", "Flexor surfaces: wrists (most characteristic), forearms, ankles. Also lower back, genitalia. "
"Violaceous, flat-topped polygonal papules with Wickham's striae."],
["Oral mucosa\n(~50–60%)", "Reticular form: white lacy Wickham's striae on buccal mucosa — most common, asymptomatic. "
"Erosive/atrophic form: painful, can develop into oral squamous cell carcinoma (1–3% risk)."],
["Nails", "20% of cases. Thinning, ridging, pterygium unguis (most characteristic — forward growth "
"of cuticle over nail plate), onycholysis, anonychia."],
["Scalp (lichen\nplanopilaris)", "Scarring alopecia; follicular papules; can cause permanent hair loss."],
["Genitalia", "Wickham's striae; erosive LP in females (vulvo-vaginal-gingival syndrome)."],
]
dist_lp = Table(dist_data, colWidths=[3.2*cm, 13.4*cm])
dist_lp.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(dist_lp)
story.append(Paragraph("Histopathology", h2_style))
for item in [
B("Sawtooth rete ridges") + " (irregular, pointed elongation of rete ridges)",
B("Civatte (colloid/hyaline) bodies") + " — eosinophilic globules in lower epidermis/upper dermis (apoptotic keratinocytes)",
"Dense, band-like (lichenoid) lymphocytic infiltrate at the dermal-epidermal junction (DEJ)",
"Vacuolar degeneration of basal layer (liquefaction degeneration)",
B("Max Joseph spaces") + " — clefts between epidermis and dermis (supepidermal cleft in erosive LP)",
"DIF: shaggy fibrinogen deposits at BMZ; cytoid bodies with IgM/IgG deposits"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Variants of Lichen Planus", h3_style))
var_lp = [
[Paragraph(B("Variant"), body_style), Paragraph(B("Features"), body_style)],
["Hypertrophic LP", "Thick verrucous plaques, mainly on shins/ankles; most pruritic; may scar"],
["Atrophic LP", "Blue-grey atrophic macules; rare"],
["Bullous LP", "Subepidermal blisters within LP lesions"],
["Linear LP", "Koebner phenomenon along scratch line"],
["Lichen planopilaris", "Follicular LP → scarring alopecia"],
["Lichen planus pigmentosus", "Brown-grey pigmentation; flexures/sun-exposed skin; more in darker skin types"],
]
var_lp_t = Table(var_lp, colWidths=[3.8*cm, 12.8*cm])
var_lp_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_TEAL]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#b0cccc")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(var_lp_t)
story.append(Paragraph("Prognosis", h3_style))
for item in [
"Cutaneous LP: spontaneous resolution in ~50% within 6 months; most within 18 months",
"Oral LP: chronic; persists for years; monitor for malignant transformation (squamous cell carcinoma)",
"Post-inflammatory hyperpigmentation common after resolution"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Paragraph("Treatment", h2_style))
for item in [
B("First-line:") + " High-potency topical corticosteroids (e.g., clobetasol 0.05%) twice daily",
B("Intralesional triamcinolone:") + " For hypertrophic and mucosal LP",
B("Systemic steroids:") + " Severe widespread/mucosal disease; prednisolone 30–60 mg/day",
B("Acitretin:") + " Second-line systemic option, especially for hypertrophic LP",
B("Cyclosporine:") + " Oral or topical (mouth rinse) for oral LP",
B("Hydroxychloroquine:") + " Moderate systemic LP",
B("Narrowband UVB or PUVA:") + " Widespread cutaneous LP",
B("Stop offending drugs:") + " Review and discontinue any causative medications",
B("HCV treatment:") + " Treating underlying hepatitis C may improve oral LP"
]:
story.append(Paragraph(f"• {item}", bullet_style))
story.append(Spacer(1, 0.2*cm))
story.append(highlight_box(
B("Exam Tip: ") + "Lichen planus is characterized by 6 P's. Wickham's striae on oral mucosa are diagnostic. "
"HCV is the most common association. "
"Histology: sawtooth rete ridges + Civatte bodies + band-like lymphocytic infiltrate. "
"Oral LP (erosive form) has malignant potential (1–3%). "
"Koebner phenomenon occurs in LP, psoriasis, vitiligo, and warts.",
bg=YELLOW
))
# ── Build the PDF ──────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved to: {OUTPUT}")