Make comprehensive data of breast cancer from multiple standard textbooks (Bailey & Love 28th edition and Sabiston) with figures.

Reading File
Finding Sources
Searching PubMed

"breast cancer" AND management

Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Loading Image
Loading Image
Reading File
Reading File
Reading File
Reading File
Finding Sources
Finding Sources
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Loading Image
Loading Image
Here is the complete comprehensive breast cancer reference compiled directly from both textbooks, with key figures included.

What's Covered

This document integrates data from 14 major sections across both surgical textbooks:
SectionPrimary Source
EpidemiologyB&L Ch. 58
Anatomy (with 2 diagrams)Sabiston Ch. 68
Risk Factors (full table)B&L Table 58.3
Pathology - all histological typesB&L + Sabiston
Nottingham grading systemBoth
Molecular classification (5 subtypes)B&L Table 58.4 + Sabiston
Clinical features + 2 clinical photosB&L
Triple assessment & investigationsB&L
TNM Staging (AJCC 8th Ed.)B&L + Sabiston
Surgical treatment (BCS, mastectomy, axilla)Sabiston
RadiotherapySabiston
Systemic therapy (chemo, endocrine, HER2, CDK4/6i)Both
Chemoprevention (4-drug table with trials)Sabiston
Special scenarios (hereditary, pregnancy, DCIS, inflammatory, male, recurrence, metastatic)Both
ReconstructionB&L
Screening + Prognosis + Multigene assaysBoth
Figures included:
  1. Sabiston Fig. 68.1 - Breast anatomy cutaway diagram
  2. Sabiston Fig. 68.2 - TDLU microscopic anatomy
  3. B&L Fig. 58.28 - Inflammatory carcinoma + peau d'orange (clinical photo)
  4. Sabiston Fig. 68.9A - IDC histology (low power)

Make pdf of this

Reading File
Running Command

ls /home/daytona/workspace/ && mkdir -p /home/daytona/workspace/breast-cancer-pdf

Writing File

~/breast-cancer-pdf/generate_pdf.py

#!/usr/bin/env python3
"""Generate a comprehensive breast cancer PDF from Bailey & Love + Sabiston content."""

from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, PageBreak, Image, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus.flowables import Flowable
import urllib.request
import os
import io

# ── Output path ──────────────────────────────────────────────────────────────
OUTPUT = "/home/daytona/workspace/breast-cancer-pdf/Breast_Cancer_Comprehensive_Reference.pdf"
IMG_DIR = "/home/daytona/workspace/breast-cancer-pdf/images"
os.makedirs(IMG_DIR, exist_ok=True)

# ── Download images ──────────────────────────────────────────────────────────
IMAGES = {
    "anatomy_breast.png":     "https://cdn.orris.care/cdss_images/a4d4069712df041821571dfb308c52e6ebf541afb9976f23c8c860c10c1f05a0.png",
    "tdlu_diagram.png":       "https://cdn.orris.care/cdss_images/b845f6af92644f552b1a45fa82cbd900948b40f1159f127632a589b337f2dda2.png",
    "inflammatory_ca.png":    "https://cdn.orris.care/cdss_images/7c1307190782fab9bf42e74ad602793b17aa812d69dbc97d345f39a5c6dfc5c8.png",
    "idc_histology.png":      "https://cdn.orris.care/cdss_images/a7976dc8796d45630b8035ab7b9d9a51d19ab1a1da0a00fe3a1a2be2d02c2b2c.png",
}

for fname, url in IMAGES.items():
    dest = os.path.join(IMG_DIR, fname)
    if not os.path.exists(dest):
        print(f"Downloading {fname}...")
        try:
            urllib.request.urlretrieve(url, dest)
            print(f"  OK: {dest}")
        except Exception as e:
            print(f"  FAILED: {e}")

# ── Colour palette ───────────────────────────────────────────────────────────
DARK_BLUE   = colors.HexColor("#1a3a5c")
MID_BLUE    = colors.HexColor("#2e6da4")
LIGHT_BLUE  = colors.HexColor("#dce9f5")
ACCENT      = colors.HexColor("#c0392b")   # red accent for headings
TABLE_HDR   = colors.HexColor("#2e6da4")
TABLE_ALT   = colors.HexColor("#f0f5fb")
WHITE       = colors.white
GRAY_TEXT   = colors.HexColor("#444444")
BORDER      = colors.HexColor("#aec6e0")

# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

def S(name, **kw):
    return ParagraphStyle(name, **kw)

TITLE_STYLE = S("MainTitle",
    fontName="Helvetica-Bold", fontSize=22, textColor=WHITE,
    alignment=TA_CENTER, spaceAfter=4)

SUBTITLE_STYLE = S("Subtitle",
    fontName="Helvetica", fontSize=11, textColor=colors.HexColor("#cce0f5"),
    alignment=TA_CENTER, spaceAfter=2)

H1 = S("H1",
    fontName="Helvetica-Bold", fontSize=14, textColor=WHITE,
    backColor=DARK_BLUE, borderPadding=(6,8,6,8),
    spaceBefore=14, spaceAfter=6)

H2 = S("H2",
    fontName="Helvetica-Bold", fontSize=12, textColor=DARK_BLUE,
    spaceBefore=10, spaceAfter=4, borderPadding=(2,0,2,0))

H3 = S("H3",
    fontName="Helvetica-BoldOblique", fontSize=10.5, textColor=MID_BLUE,
    spaceBefore=7, spaceAfter=3)

BODY = S("Body",
    fontName="Helvetica", fontSize=9.5, textColor=GRAY_TEXT,
    leading=14, spaceAfter=5, alignment=TA_JUSTIFY)

BODY_B = S("BodyBold",
    fontName="Helvetica-Bold", fontSize=9.5, textColor=GRAY_TEXT,
    leading=14, spaceAfter=5)

BULLET = S("Bullet",
    fontName="Helvetica", fontSize=9.5, textColor=GRAY_TEXT,
    leading=13, leftIndent=14, firstLineIndent=-10, spaceAfter=3,
    alignment=TA_LEFT)

BULLET2 = S("Bullet2",
    fontName="Helvetica", fontSize=9, textColor=GRAY_TEXT,
    leading=12, leftIndent=26, firstLineIndent=-10, spaceAfter=2)

CAPTION = S("Caption",
    fontName="Helvetica-Oblique", fontSize=8.5, textColor=colors.HexColor("#555555"),
    alignment=TA_CENTER, spaceAfter=8, spaceBefore=3)

SOURCE = S("Source",
    fontName="Helvetica-Oblique", fontSize=8, textColor=colors.HexColor("#777777"),
    alignment=TA_RIGHT, spaceAfter=3)

NOTE = S("Note",
    fontName="Helvetica-Oblique", fontSize=8.5, textColor=colors.HexColor("#555555"),
    backColor=colors.HexColor("#fff8e1"), borderPadding=6,
    borderColor=colors.HexColor("#f0c040"), borderWidth=1,
    leading=12, spaceAfter=8)

# ── Helper: table style ──────────────────────────────────────────────────────
def make_table(data, col_widths, hdr_rows=1, alt=True):
    ts = TableStyle([
        ("BACKGROUND",   (0,0), (-1, hdr_rows-1), TABLE_HDR),
        ("TEXTCOLOR",    (0,0), (-1, hdr_rows-1), WHITE),
        ("FONTNAME",     (0,0), (-1, hdr_rows-1), "Helvetica-Bold"),
        ("FONTSIZE",     (0,0), (-1, hdr_rows-1), 9),
        ("ALIGN",        (0,0), (-1,-1), "LEFT"),
        ("VALIGN",       (0,0), (-1,-1), "TOP"),
        ("FONTNAME",     (0,hdr_rows), (-1,-1), "Helvetica"),
        ("FONTSIZE",     (0,hdr_rows), (-1,-1), 8.5),
        ("TEXTCOLOR",    (0,hdr_rows), (-1,-1), GRAY_TEXT),
        ("ROWBACKGROUNDS", (0,hdr_rows), (-1,-1),
         [TABLE_ALT, WHITE] if alt else [WHITE]),
        ("GRID",         (0,0), (-1,-1), 0.5, BORDER),
        ("LEFTPADDING",  (0,0), (-1,-1), 6),
        ("RIGHTPADDING", (0,0), (-1,-1), 6),
        ("TOPPADDING",   (0,0), (-1,-1), 4),
        ("BOTTOMPADDING",(0,0), (-1,-1), 4),
        ("ROWBACKGROUNDS", (0,0), (-1, hdr_rows-1), [TABLE_HDR]),
    ])
    t = Table(data, colWidths=col_widths, repeatRows=hdr_rows)
    t.setStyle(ts)
    return t

# ── Helper: section banner ────────────────────────────────────────────────────
def section_banner(number, title):
    return Paragraph(f"<b>{number}. {title}</b>", H1)

def h2(text):
    return Paragraph(f"<b>{text}</b>", H2)

def h3(text):
    return Paragraph(text, H3)

def body(text):
    return Paragraph(text, BODY)

def bullet(text, level=1):
    st = BULLET if level == 1 else BULLET2
    return Paragraph(f"• {text}", st)

def sp(h=6):
    return Spacer(1, h)

def hr():
    return HRFlowable(width="100%", thickness=0.5, color=BORDER, spaceAfter=4, spaceBefore=4)

def img(path, width, caption=""):
    items = []
    if os.path.exists(path):
        im = Image(path, width=width, kind="proportional")
        im.hAlign = "CENTER"
        items.append(im)
        if caption:
            items.append(Paragraph(caption, CAPTION))
    return items

# ── Cover page builder ────────────────────────────────────────────────────────
class ColorRect(Flowable):
    def __init__(self, w, h, fill_color, radius=4):
        super().__init__()
        self.width = w; self.height = h
        self.fill_color = fill_color; self.radius = radius
    def draw(self):
        self.canv.setFillColor(self.fill_color)
        self.canv.roundRect(0, 0, self.width, self.height, self.radius, fill=1, stroke=0)

def cover_elements(page_w, page_h):
    """Return flowables for a styled cover page."""
    elems = []
    elems.append(sp(60))
    # Title box
    box_w = page_w - 4*cm
    box = Table([[Paragraph(
        "<b>BREAST CANCER</b><br/>"
        "<font size=14 color='#cce0f5'>Comprehensive Surgical Reference</font>",
        S("CT", fontName="Helvetica-Bold", fontSize=26, textColor=WHITE, alignment=TA_CENTER, leading=34)
    )]], colWidths=[box_w])
    box.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
        ("LEFTPADDING", (0,0), (-1,-1), 20),
        ("RIGHTPADDING", (0,0), (-1,-1), 20),
        ("TOPPADDING", (0,0), (-1,-1), 28),
        ("BOTTOMPADDING", (0,0), (-1,-1), 28),
        ("ALIGN", (0,0), (-1,-1), "CENTER"),
        ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
    ]))
    elems.append(box)
    elems.append(sp(18))

    sources = [
        ["Primary Sources:"],
        ["Bailey & Love's Short Practice of Surgery, 28th Edition"],
        ["Sabiston Textbook of Surgery (The Biological Basis of Modern Surgical Practice)"],
    ]
    src_table = Table([[Paragraph(
        "<b>Primary Sources:</b><br/>"
        "• Bailey &amp; Love's Short Practice of Surgery, 28th Edition — Chapter 58: The Breast<br/>"
        "• Sabiston Textbook of Surgery — Chapter 68: Diseases of the Breast",
        S("ST", fontName="Helvetica", fontSize=10.5, textColor=DARK_BLUE, leading=16, alignment=TA_CENTER)
    )]], colWidths=[box_w])
    src_table.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), LIGHT_BLUE),
        ("LEFTPADDING", (0,0), (-1,-1), 18),
        ("RIGHTPADDING", (0,0), (-1,-1), 18),
        ("TOPPADDING", (0,0), (-1,-1), 14),
        ("BOTTOMPADDING", (0,0), (-1,-1), 14),
        ("ALIGN", (0,0), (-1,-1), "CENTER"),
        ("BOX", (0,0), (-1,-1), 1, BORDER),
    ]))
    elems.append(src_table)
    elems.append(sp(20))

    # Summary boxes
    topics = [
        "Epidemiology & Risk Factors", "Anatomy & Physiology",
        "Pathology & Molecular Classification", "Staging (AJCC 8th Ed.)",
        "Surgical Management", "Systemic Therapy",
        "Radiotherapy", "Screening & Prognosis",
        "Special Scenarios", "Breast Reconstruction",
    ]
    rows = []
    for i in range(0, len(topics), 2):
        row = []
        for j in range(2):
            if i+j < len(topics):
                row.append(Paragraph(f"✓  {topics[i+j]}",
                    S("TT", fontName="Helvetica", fontSize=9.5, textColor=DARK_BLUE, leading=13)))
            else:
                row.append("")
        rows.append(row)
    toc_box = Table(rows, colWidths=[box_w/2, box_w/2])
    toc_box.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#f4f8fd")),
        ("GRID", (0,0), (-1,-1), 0.4, BORDER),
        ("LEFTPADDING", (0,0), (-1,-1), 10),
        ("RIGHTPADDING", (0,0), (-1,-1), 10),
        ("TOPPADDING", (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ]))
    elems.append(toc_box)
    elems.append(sp(30))
    elems.append(Paragraph("Compiled June 2026", S("D",
        fontName="Helvetica-Oblique", fontSize=9, textColor=colors.HexColor("#888888"),
        alignment=TA_CENTER)))
    elems.append(PageBreak())
    return elems

# ── Main content builder ──────────────────────────────────────────────────────
def build_content():
    W = A4[0] - 4*cm   # usable width
    elems = []

    # ── SECTION 1: EPIDEMIOLOGY ───────────────────────────────────────────────
    elems.append(section_banner("1", "EPIDEMIOLOGY"))
    elems.append(body("Breast cancer is the most frequent cancer among women worldwide, with an estimated <b>2.3 million new cases</b> diagnosed globally in 2020, representing approximately <b>25%</b> of all cancers in women."))
    elems.append(sp(4))

    epi_data = [
        ["Region", "Incidence (per 100,000 women)"],
        ["Middle Africa / East Asia", "27"],
        ["South Asia", "~28–35"],
        ["North America", "92"],
        ["Western Europe", "~85–90"],
    ]
    elems.append(make_table(epi_data, [W*0.65, W*0.35]))
    elems.append(sp(4))

    for b_text in [
        "In Western Europe: <b>~1 in 9</b> women will develop breast cancer (3–5% of all female deaths)",
        "In resource-poor countries: <b>1 in 28</b> women; for every 2 diagnosed, 1 dies",
        "Median age at presentation: ~<b>60 years</b> (UK/USA); ~<b>48 years</b> in South Asia",
        "Breast cancer accounts for the <b>leading cause of cancer-related death</b> in women globally",
    ]:
        elems.append(bullet(b_text))
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Ch. 58</i>", SOURCE))

    # ── SECTION 2: ANATOMY ───────────────────────────────────────────────────
    elems.append(section_banner("2", "ANATOMY"))
    elems.append(h2("2.1 Gross Anatomy"))
    for b_text in [
        "The breast lies between the skin/subdermal adipose tissue and the <b>superficial pectoral fascia</b>, overlying the pectoralis major muscle",
        "<b>Cooper's ligaments</b> (suspensory ligaments) run between the chest wall and dermis — infiltration by cancer causes skin <b>dimpling / peau d'orange</b>",
        "Three principal tissue types: (1) glandular epithelium, (2) fibrous stroma, (3) adipose tissue",
        "<b>15–20 lobes</b>, each ending in a lactiferous duct opening at the nipple; each duct has a dilated lactiferous sinus below the NAC",
        "<b>Terminal duct lobular units (TDLUs)</b> = acini + small efferent ductules = the functional milk-forming unit",
        "In adolescents: predominant epithelium + stroma; in postmenopausal females: glandular structures largely replaced by adipose tissue",
    ]:
        elems.append(bullet(b_text))
    elems.append(Paragraph("<i>Source: Sabiston, Ch. 68</i>", SOURCE))

    # Anatomy image
    anat_img = os.path.join(IMG_DIR, "anatomy_breast.png")
    for el in img(anat_img, W,
        "FIGURE 68.1 (Sabiston): Cutaway diagram of a mature resting breast showing Cooper ligaments, "
        "lactiferous ducts, TDLU, nipple-areolar complex, pectoralis major, and retromammary fat."):
        elems.append(el)

    elems.append(h2("2.2 Microanatomy — Terminal Duct Lobular Unit (TDLU)"))
    tdlu_img = os.path.join(IMG_DIR, "tdlu_diagram.png")
    for el in img(tdlu_img, W*0.65,
        "FIGURE 68.2 (Sabiston): The terminal duct lobular unit (TDLU) showing intralobular terminal duct, "
        "lobular acini, intralobular stroma, and extralobular stroma."):
        elems.append(el)

    elems.append(h2("2.3 Lymphatic Drainage"))
    lymph_data = [
        ["Route", "Proportion", "Notes"],
        ["Axillary nodes (Levels I–III)", "~75%", "Primary drainage from all quadrants"],
        ["Internal mammary nodes", "~20%", "Medial / central tumours"],
        ["Rotter's nodes", "Minor", "Between pectoralis major and minor"],
        ["Supraclavicular nodes", "Advanced", "Skip metastasis or disease progression"],
    ]
    elems.append(make_table(lymph_data, [W*0.38, W*0.18, W*0.44]))
    elems.append(Paragraph("<i>Source: Sabiston, Ch. 68; Bailey &amp; Love, Ch. 58</i>", SOURCE))

    # ── SECTION 3: RISK FACTORS ───────────────────────────────────────────────
    elems.append(section_banner("3", "RISK FACTORS"))
    elems.append(Paragraph("Risk factors are divided into modifiable and non-modifiable categories (Table 58.3, Bailey &amp; Love).", BODY))

    rf_data = [
        ["Risk Factor", "Relative Risk / Details"],
        ["MODIFIABLE", ""],
        ["Obesity (BMI >30)", "RR = 1.29 in postmenopausal women"],
        ["Nulliparity / first pregnancy >35 yrs", "Increased oestrogenic exposure"],
        ["Breastfeeding >12 months", "Protective — greater effect with longer duration"],
        ["HRT use >10 years", "RR = 1.2"],
        ["Tobacco: >25 cigarettes/day", "RR = 1.14"],
        ["Alcohol: light (<1 drink/day)", "RR = 1.05"],
        ["Alcohol: moderate (3–4 drinks/day)", "RR = 1.32"],
        ["Alcohol: heavy (>4 drinks/day)", "RR = 1.46"],
        ["Radiation exposure", "RR = 6"],
        ["NON-MODIFIABLE", ""],
        ["Age", "Median presentation ~60 yrs (West), ~48 yrs (Asia)"],
        ["Early menarche / late menopause", "Prolonged oestrogen exposure"],
        ["BRCA1 mutation (17q21)", "50–85% lifetime breast cancer risk; 40% ovarian cancer"],
        ["BRCA2 mutation (13q12.3)", "50–60% lifetime breast cancer risk; 20% ovarian cancer"],
        ["Prior breast cancer / LCIS / ADH", "Significantly elevated risk"],
        ["Dense breast tissue", "Higher mammographic density = higher risk"],
        ["First-degree family history", "~2× relative risk"],
        ["Previous chest RT (e.g. lymphoma)", "High risk if exposure in adolescence"],
    ]
    # Style sub-headers
    rf_ts = TableStyle([
        ("BACKGROUND",   (0,0), (-1,0), TABLE_HDR),
        ("TEXTCOLOR",    (0,0), (-1,0), WHITE),
        ("FONTNAME",     (0,0), (-1,0), "Helvetica-Bold"),
        ("FONTSIZE",     (0,0), (-1,0), 9),
        ("BACKGROUND",   (0,1), (-1,1), colors.HexColor("#1a5276")),
        ("TEXTCOLOR",    (0,1), (-1,1), WHITE),
        ("FONTNAME",     (0,1), (-1,1), "Helvetica-Bold"),
        ("BACKGROUND",   (0,11), (-1,11), colors.HexColor("#1a5276")),
        ("TEXTCOLOR",    (0,11), (-1,11), WHITE),
        ("FONTNAME",     (0,11), (-1,11), "Helvetica-Bold"),
        ("ROWBACKGROUNDS", (0,2), (-1,10), [TABLE_ALT, WHITE]),
        ("ROWBACKGROUNDS", (0,12), (-1,-1), [TABLE_ALT, WHITE]),
        ("GRID",         (0,0), (-1,-1), 0.5, BORDER),
        ("FONTNAME",     (0,2), (-1,-1), "Helvetica"),
        ("FONTSIZE",     (0,2), (-1,-1), 8.5),
        ("TEXTCOLOR",    (0,2), (-1,-1), GRAY_TEXT),
        ("LEFTPADDING",  (0,0), (-1,-1), 6),
        ("RIGHTPADDING", (0,0), (-1,-1), 6),
        ("TOPPADDING",   (0,0), (-1,-1), 4),
        ("BOTTOMPADDING",(0,0), (-1,-1), 4),
        ("SPAN",         (0,1), (1,1)),
        ("SPAN",         (0,11),(1,11)),
    ])
    t = Table(rf_data, colWidths=[W*0.55, W*0.45], repeatRows=1)
    t.setStyle(rf_ts)
    elems.append(t)
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Table 58.3</i>", SOURCE))

    # ── SECTION 4: PATHOLOGY ─────────────────────────────────────────────────
    elems.append(section_banner("4", "PATHOLOGY"))
    elems.append(h2("4.1 Origin of Breast Carcinoma"))
    elems.append(body("<b>90%</b> arise from milk ducts (ductal carcinoma) | <b>10%</b> from lobules (lobular carcinoma)"))
    for b_text in [
        "<b>In situ disease</b>: malignant cells confined within duct/lobule without breaching the basement membrane",
        "<b>Invasive (infiltrating) carcinoma</b>: breach of basement membrane with invasion of surrounding tissue",
    ]:
        elems.append(bullet(b_text))

    elems.append(h2("4.2 Histological Types"))
    hist_data = [
        ["Histological Type", "Frequency", "Key Features", "Prognosis"],
        ["Invasive Ductal Carcinoma (IDC / NST)", "50–70%",
         "Grows as cohesive mass; discrete on mammogram; palpable lump", "Variable (grade-dependent)"],
        ["Invasive Lobular Carcinoma (ILC)", "5–15%",
         "Single-file infiltration; clinically occult; escapes mammography; CDH1 mutation (loss of E-cadherin)", "Often similar to IDC"],
        ["Tubular carcinoma", "~2–3%",
         "Small glands, single row of bland epithelium; Grade 1", "Excellent"],
        ["Mucinous / Colloid", "~2–3%",
         "Cells floating in copious mucin; Grade 1", "Excellent"],
        ["Medullary carcinoma", "~5%",
         "Bizarre high-grade cells; syncytial sheets; lymphocytic infiltrate; ER/PR/HER2 negative", "Moderate (despite grade 3)"],
        ["Papillary carcinoma", "0.5–1%",
         "Fibrovascular core + epithelial/myoepithelial cells; usually ER+; rarely node-positive", "Good"],
        ["Metaplastic carcinoma", "<1%",
         "High grade; ER/PR/HER2 negative; node-negative but high metastatic potential; ~50% relapse", "Poor"],
    ]
    elems.append(make_table(hist_data, [W*0.26, W*0.1, W*0.42, W*0.22]))

    elems.append(h2("4.3 Nottingham Histological Grade (Modified Bloom–Richardson Score)"))
    elems.append(body("Three criteria scored 1–3 each:"))
    grade_data = [
        ["Criterion", "Score 1", "Score 2", "Score 3"],
        ["Tubule/gland formation", ">75% of tumour", "10–75%", "<10%"],
        ["Nuclear pleomorphism", "Small, regular", "Moderate", "Marked variation"],
        ["Mitotic rate (per HPF)", "Low", "Intermediate", "High"],
    ]
    elems.append(make_table(grade_data, [W*0.3, W*0.23, W*0.23, W*0.24]))
    elems.append(sp(4))
    final_data = [
        ["Total Score", "Grade", "Differentiation"],
        ["3–5", "Grade I", "Well differentiated"],
        ["6–7", "Grade II", "Moderately differentiated"],
        ["8–9", "Grade III", "Poorly differentiated"],
    ]
    elems.append(make_table(final_data, [W*0.25, W*0.25, W*0.50]))

    elems.append(h2("4.4 Molecular Classification (PAM-50 / Immunohistochemistry)"))
    mol_data = [
        ["Subtype", "ER/PR Status", "HER2", "Ki-67", "Notes"],
        ["Luminal A", "Positive", "Negative", "Low", "Best prognosis; low-grade; endocrine-responsive"],
        ["Luminal B", "Positive", "Negative", "High", "Intermediate prognosis; may need chemo"],
        ["HER2/neu enriched", "Negative", "Positive", "High", "HER2-targeted therapy needed"],
        ["Basal (TNBC)", "Negative", "Negative", "Usually high", "Associated with BRCA1; chemotherapy backbone"],
        ["Claudin-low", "Negative", "Negative", "Variable", "Stem cell features; poor prognosis"],
    ]
    elems.append(make_table(mol_data, [W*0.2, W*0.14, W*0.1, W*0.1, W*0.46]))
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Table 58.4; Sabiston, Ch. 68</i>", SOURCE))

    elems.append(h2("4.5 Key Molecular Markers (Sabiston)"))
    marker_data = [
        ["Marker", "Method", "Cut-off / Scoring", "Clinical Use"],
        ["ER / PR", "IHC", ">1% positive nuclei = positive; 1–10% = low ER", "Endocrine therapy eligibility"],
        ["HER2", "IHC + ISH", "0/1+ = negative; 3+ = positive; 2+ → ISH confirmation", "HER2-targeted therapy"],
        ["Ki-67", "IHC", "% positive nuclei (high if >20–30%)", "Proliferation; luminal A vs B distinction"],
        ["Oncotype DX", "21-gene RT-PCR", "Recurrence score 0–100", "Chemo benefit in ER+/HER2-/node−"],
        ["MammaPrint", "70-gene array", "Low vs. high risk", "Adjuvant chemo decision (MINDACT trial)"],
    ]
    elems.append(make_table(marker_data, [W*0.15, W*0.15, W*0.35, W*0.35]))

    elems.append(h2("4.6 Ductal Carcinoma In Situ (DCIS)"))
    for b_text in [
        "Malignant cells confined within ducts without invasion of basement membrane",
        "Classified by nuclear grade (low/intermediate/high) and necrosis (comedonecrosis = most aggressive subtype)",
        "Detected predominantly by screening mammography (<b>microcalcifications</b>)",
        "Prevalence of lymphatic/metastatic spread in pure DCIS: <b>&lt;1%</b> → systemic chemotherapy NOT required",
        "<b>LCIS</b> = high-risk benign lesion, NOT a cancer (AJCC 8th edition); bilateral risk marker",
    ]:
        elems.append(bullet(b_text))

    # Histology image
    elems.append(h2("4.7 Histopathology — Invasive Ductal Carcinoma"))
    hist_img = os.path.join(IMG_DIR, "idc_histology.png")
    for el in img(hist_img, W*0.75,
        "FIGURE 68.9A (Sabiston): Low-power histology of invasive ductal carcinoma showing nests of "
        "malignant ductal cells embedded in desmoplastic fibrous stroma."):
        elems.append(el)
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Ch. 58; Sabiston, Ch. 68</i>", SOURCE))

    # ── SECTION 5: CLINICAL FEATURES ─────────────────────────────────────────
    elems.append(section_banner("5", "CLINICAL FEATURES & SPREAD"))
    elems.append(h2("5.1 Presenting Symptoms"))
    for b_text in [
        "Painless lump in the breast (most common presentation)",
        "New nipple retraction / inversion",
        "Blood-stained nipple discharge",
        "Skin changes: dimpling, puckering, peau d'orange",
        "Change in breast size or asymmetry",
        "Axillary lump (nodal metastasis)",
        "Bone pain, dyspnoea, jaundice (metastatic disease)",
    ]:
        elems.append(bullet(b_text))

    elems.append(h2("5.2 Clinical Signs — Photographs"))
    clin_img = os.path.join(IMG_DIR, "inflammatory_ca.png")
    for el in img(clin_img, W,
        "FIGURE 58.28 (Bailey & Love): (a) Inflammatory carcinoma — diffuse erythema and skin oedema "
        "involving >1/3 of the breast with enlarged left breast. (b) Peau d'orange — orange-peel "
        "skin appearance indicating locally advanced disease. In darker skin, erythema takes on a brownish hue."):
        elems.append(el)

    elems.append(h2("5.3 Mechanism of Skin Signs (Bailey & Love)"))
    mech_data = [
        ["Sign", "Mechanism"],
        ["Skin dimpling", "Single Cooper's ligament shortened by desmoplastic collagen contraction"],
        ["Puckering / tethering", "Multiple Cooper's ligaments contracted"],
        ["Nipple retraction", "Central subareolar involvement of Cooper's ligaments"],
        ["Peau d'orange", "Dermal lymphatic blockage → skin oedema; pores become prominent"],
        ["Skin ulceration", "Direct tumour invasion through dermis (T4b)"],
        ["Erythema (inflammatory)", "Dermal lymphatic invasion by tumour emboli; NOT infection"],
    ]
    elems.append(make_table(mech_data, [W*0.35, W*0.65]))
    elems.append(body("Tumour releases <b>FGF, TGFα, TGFβ, VEGF</b> → desmoplastic reaction (fibrocytes → fibroblasts → collagen) → contraction of Cooper's ligaments."))

    elems.append(h2("5.4 Modes of Spread"))
    spread_data = [
        ["Route", "Details", "Common Sites"],
        ["Local spread", "Skin → ulceration, satellite nodules; chest wall, pectoralis", "Ipsilateral breast"],
        ["Lymphatic", "Most common initial route; Level I→II→III axillary nodes; internal mammary", "Axilla (primary)"],
        ["Haematogenous", "Via intercostal perforators and internal mammary veins",
         "Bone (most common) > Lung > Liver > Brain > Adrenal"],
    ]
    elems.append(make_table(spread_data, [W*0.2, W*0.42, W*0.38]))
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Ch. 58</i>", SOURCE))

    # ── SECTION 6: INVESTIGATIONS ─────────────────────────────────────────────
    elems.append(section_banner("6", "INVESTIGATIONS — TRIPLE ASSESSMENT"))
    elems.append(body("The <b>triple assessment</b> is the gold standard for diagnosis:"))
    triple_data = [
        ["Component", "Methods", "Notes"],
        ["1. Clinical examination", "History + full breast/axilla examination", "Assess lump characteristics, skin, nodes"],
        ["2. Imaging", "Mammography ± Ultrasound ± MRI", "See below for details"],
        ["3. Pathology", "Core needle biopsy (preferred) or FNAC", "Gives histology, grade, ER/PR/HER2"],
    ]
    elems.append(make_table(triple_data, [W*0.22, W*0.38, W*0.40]))

    elems.append(h2("6.1 Imaging Modalities"))
    img_data = [
        ["Modality", "Indications", "Features of Malignancy"],
        ["Mammography (2-view: CC + MLO)",
         "Standard screening ≥40 yrs; symptomatic women",
         "Spiculate mass, pleomorphic/linear microcalcifications, architectural distortion"],
        ["Ultrasound",
         "Dense breasts, <35 yrs, palpable lumps, guided biopsy",
         "Irregular hypoechoic mass; posterior acoustic shadowing; vascularity"],
        ["MRI Breast",
         "BRCA carriers; extent assessment; neoadjuvant response; implants",
         "Highest sensitivity; low specificity → guided biopsy needed for MRI-only lesions"],
        ["PET-CT (18F-FDG)",
         "Metastatic work-up, treatment response",
         "FDG-avid primary + nodes + distant metastases"],
    ]
    elems.append(make_table(img_data, [W*0.28, W*0.32, W*0.40]))

    elems.append(h2("6.2 Staging Investigations"))
    for b_text in [
        "<b>T3/T4 or N2/N3 disease</b>: CT chest/abdomen/pelvis + isotope bone scan",
        "<b>Early cancer (T1/T2, N0/N1)</b>: staging work-up only if symptomatic or raised serum ALP",
        "<b>PET-CT</b> may be used as alternative for metastatic work-up",
    ]:
        elems.append(bullet(b_text))
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Ch. 58</i>", SOURCE))

    # ── SECTION 7: STAGING ────────────────────────────────────────────────────
    elems.append(section_banner("7", "STAGING — AJCC/UICC TNM 8TH EDITION"))

    elems.append(h2("7.1 T (Tumour) Classification"))
    t_data = [
        ["T Category", "Definition"],
        ["Tis", "In situ (DCIS); LCIS is NOT staged as cancer"],
        ["T1mi", "Microinvasion ≤1.0 mm"],
        ["T1a", ">1 mm to ≤5 mm"],
        ["T1b", ">5 mm to ≤10 mm"],
        ["T1c", ">10 mm to ≤20 mm"],
        ["T2", ">20 mm to ≤50 mm"],
        ["T3", ">50 mm"],
        ["T4a", "Extension to chest wall (not pectoralis muscle)"],
        ["T4b", "Ulceration / satellite nodules / peau d'orange (skin involvement)"],
        ["T4c", "Both T4a and T4b"],
        ["T4d", "Inflammatory carcinoma"],
    ]
    elems.append(make_table(t_data, [W*0.2, W*0.8]))

    elems.append(h2("7.2 N (Node) Classification"))
    n_data = [
        ["N Category", "Definition"],
        ["N0", "No regional node metastasis"],
        ["N1", "Movable ipsilateral Level I/II axillary nodes"],
        ["N2a", "Fixed/matted ipsilateral Level I/II axillary nodes"],
        ["N2b", "Clinically apparent internal mammary nodes only (no axillary)"],
        ["N3a", "Ipsilateral infraclavicular (Level III) nodes"],
        ["N3b", "Ipsilateral internal mammary + axillary nodes"],
        ["N3c", "Ipsilateral supraclavicular nodes"],
    ]
    elems.append(make_table(n_data, [W*0.15, W*0.85]))

    elems.append(h2("7.3 M (Metastasis) Classification"))
    m_data = [
        ["M Category", "Definition"],
        ["M0", "No clinical or radiographic evidence of distant metastasis"],
        ["cM0(i+)", "Circulating tumor cells / micrometastasis detected without distant metastasis"],
        ["M1", "Distant metastasis (bone, lung, liver, brain, distant nodes, etc.)"],
    ]
    elems.append(make_table(m_data, [W*0.2, W*0.8]))

    elems.append(h2("7.4 Key Points of 8th Edition AJCC (Bailey & Love — Summary Box 58.3)"))
    for b_text in [
        "LCIS = high-risk benign lesion — <b>NOT classified as cancer</b>",
        "Multiple synchronous tumours: use <b>(m) modifier</b> for T categorisation",
        "Post-neoadjuvant therapy status: prefix <b>(y)</b>",
        "<b>Pathological complete response (pCR)</b> = absence of tumour cells in breast AND axillary nodes",
        "Inflammatory carcinoma remains classified as inflammatory even after complete neoadjuvant remission",
        "T1mi = invasive foci <b>≤1.0 mm</b>; tumours >1 mm and <2 mm should be reported as 2 mm",
        "8th edition adds: histological grade, ER/PR/HER2/Ki-67, <b>Oncotype DX</b>, neoadjuvant response to refine prognosis",
    ]:
        elems.append(bullet(b_text))
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Ch. 58; Sabiston, Ch. 68</i>", SOURCE))

    # ── SECTION 8: TREATMENT ─────────────────────────────────────────────────
    elems.append(section_banner("8", "TREATMENT — MULTIMODAL APPROACH"))
    elems.append(body("Treatment is <b>multimodal</b> (surgery + radiotherapy + systemic therapy). "
        "All patients should be managed by a <b>multidisciplinary team (MDT)</b>: surgeon, radiologist, "
        "pathologist, radiation oncologist, medical oncologist, breast care nurse, reconstructive surgeon."))

    elems.append(h2("8.1 Breast-Conserving Surgery (BCS) / Lumpectomy"))
    elems.append(body("<i>Synonyms: lumpectomy, partial mastectomy, wide local excision, segmental mastectomy, tylectomy</i>"))
    for b_text in [
        "Tumour excised with surrounding rim of grossly normal parenchyma; remainder of breast preserved",
        "Non-palpable tumours: localization device required (wire, radioactive seed, SAVI Scout, ultrasound-guided)",
        "Specimen oriented and inked before sectioning; specimen radiography for non-palpable lesions",
        "Clips left in lumpectomy cavity for radiotherapy planning",
        "Cavity shave margins at time of lumpectomy reduce positive margin rates (Level I evidence)",
    ]:
        elems.append(bullet(b_text))

    elems.append(h3("Margin Standards (SSO/ASTRO/ASCO Consensus — Sabiston):"))
    margin_data = [
        ["Cancer Type", "Required Negative Margin", "Evidence Base"],
        ["Invasive breast cancer", '"No ink on tumour"',
         "Meta-analysis, 28,162 patients; wider margins do NOT further reduce recurrence"],
        ["DCIS", "2 mm",
         "Meta-analysis, 7,883 patients; 2 mm superior to 0–1 mm margins"],
    ]
    elems.append(make_table(margin_data, [W*0.28, W*0.28, W*0.44]))
    elems.append(body("Positive margins = <b>2-fold increase</b> in ipsilateral breast tumour recurrence risk."))

    elems.append(h2("8.2 Mastectomy — Types and Indications"))
    mast_data = [
        ["Type", "Description", "Main Indication"],
        ["Simple / Total mastectomy", "All breast tissue + NAC; no axillary dissection", "Prophylactic; DCIS; with SLNB"],
        ["Modified radical mastectomy (MRM)", "Simple mastectomy + Level I/II ALND; pectoralis preserved", "Node-positive invasive cancer"],
        ["Skin-sparing mastectomy", "Preserves skin envelope; removes NAC", "For immediate reconstruction"],
        ["Nipple-sparing mastectomy", "Preserves entire NAC", "BRCA prophylactic; selected small tumours away from NAC"],
    ]
    elems.append(make_table(mast_data, [W*0.28, W*0.38, W*0.34]))

    elems.append(h3("Indications for mastectomy over BCS:"))
    for b_text in [
        "Multicentric disease (multiple quadrants)",
        "Large tumour-to-breast ratio with poor cosmesis",
        "Prior radiotherapy to the ipsilateral breast",
        "Positive margins after re-excision",
        "BRCA mutation carriers (risk-reducing surgery)",
        "Patient preference",
    ]:
        elems.append(bullet(b_text))

    elems.append(h2("8.3 Axillary Management"))
    elems.append(h3("Sentinel Lymph Node Biopsy (SLNB):"))
    for b_text in [
        "Standard for clinically node-negative disease; uses blue dye ± radioisotope (Tc-99m)",
        "If SLN negative: no further axillary treatment required",
        "<b>ACOSOG Z0011 trial</b>: 1–2 positive SLNs in BCS + whole-breast RT → ALND NOT required",
    ]:
        elems.append(bullet(b_text))
    elems.append(h3("Axillary Lymph Node Dissection (ALND):"))
    for b_text in [
        "Level I and II nodes removed (typically ≥10 nodes)",
        "Indications: positive SLN (selected), clinically positive nodes",
        "Complications: lymphoedema (up to 20%), shoulder stiffness, sensory loss, seroma",
    ]:
        elems.append(bullet(b_text))

    elems.append(h2("8.4 Radiotherapy"))
    rt_data = [
        ["Setting", "Regimen", "Indication"],
        ["After BCS (adjuvant)", "Standard: 50 Gy/25 fractions OR Hypofractionation: 40 Gy/15 fractions",
         "All patients after BCS; hypofractionation now preferred"],
        ["Partial breast irradiation", "Various techniques (APBI, brachytherapy)",
         "Low-risk patients; avoids whole breast radiation"],
        ["Post-mastectomy RT (PMRT)", "Chest wall ± nodal basins",
         "T3/T4; ≥4 positive nodes; positive margins; N3 disease"],
        ["Nodal RT", "Axillary/supraclavicular/internal mammary",
         "High-risk patients with nodal involvement"],
    ]
    elems.append(make_table(rt_data, [W*0.22, W*0.42, W*0.36]))
    elems.append(body("Adjuvant RT reduces locoregional recurrence and improves breast cancer-related mortality by eradicating residual occult disease."))

    elems.append(h2("8.5 Systemic Therapy"))
    elems.append(h3("A. Chemotherapy"))
    chemo_data = [
        ["Regimen", "Drugs", "Use"],
        ["AC → T", "Doxorubicin + Cyclophosphamide → Paclitaxel/Docetaxel", "Standard adjuvant for high-risk"],
        ["TC", "Docetaxel + Cyclophosphamide", "Lower-risk HER2-negative"],
        ["AC → TH (+ P)", "AC → Taxane + Trastuzumab (+ Pertuzumab)", "HER2-positive (neoadjuvant/adjuvant)"],
        ["Capecitabine", "Oral fluoropyrimidine", "Residual TNBC after NACT (CREATE-X trial)"],
        ["T-DM1", "Ado-trastuzumab emtansine (antibody-drug conjugate)", "Residual HER2+ disease after NACT"],
    ]
    elems.append(make_table(chemo_data, [W*0.2, W*0.44, W*0.36]))

    elems.append(h3("B. Endocrine Therapy"))
    endo_data = [
        ["Agent", "Patients", "Duration", "Key Effects"],
        ["Tamoxifen (SERM)", "ER+ premenopausal", "5–10 years",
         "Reduces recurrence ~40%; contralateral BC ↓47%; risks: endometrial cancer, DVT/PE"],
        ["Aromatase Inhibitors (anastrozole, letrozole, exemestane)",
         "ER+ postmenopausal", "5 years (or switch after tamoxifen)",
         "Superior to tamoxifen in postmenopausal women; risks: osteoporosis, arthralgia"],
        ["GnRH agonist + AI", "High-risk premenopausal", "≥5 years", "For premenopausal women with high-risk ER+ cancer (SOFT/TEXT trials)"],
        ["CDK 4/6 inhibitors (palbociclib, ribociclib, abemaciclib)",
         "Advanced/metastatic ER+/HER2−", "Until progression", "Significantly improves PFS in metastatic; abemaciclib approved adjuvant high-risk"],
    ]
    elems.append(make_table(endo_data, [W*0.25, W*0.2, W*0.15, W*0.40]))

    elems.append(h3("C. HER2-Targeted Therapy"))
    her2_data = [
        ["Agent", "Mechanism", "Use"],
        ["Trastuzumab (Herceptin)", "Anti-HER2 monoclonal antibody", "1 year adjuvant; reduces recurrence ~50% in early HER2+ BC"],
        ["Pertuzumab", "HER2 dimerization inhibitor", "Combined with trastuzumab as dual blockade (neoadjuvant/adjuvant)"],
        ["T-DM1 (ado-trastuzumab emtansine)", "Antibody-drug conjugate", "Residual invasive HER2+ disease after NACT"],
        ["Lapatinib / Tucatinib / Neratinib", "Tyrosine kinase inhibitors", "Advanced/metastatic HER2+ disease"],
    ]
    elems.append(make_table(her2_data, [W*0.3, W*0.3, W*0.4]))

    elems.append(h3("D. Chemoprevention (Sabiston, Ch. 68)"))
    prev_data = [
        ["Agent", "Population", "Trial", "Risk Reduction"],
        ["Tamoxifen 20 mg/day × 5 yrs",
         "High-risk pre/postmenopausal (Gail score ≥1.7%, LCIS, ADH/ALH)",
         "NSABP P-1",
         "43% invasive BC; 59% in LCIS; 75% in ADH/ALH"],
        ["Raloxifene", "Postmenopausal women", "STAR trial",
         "Similar to tamoxifen; fewer uterine side effects"],
        ["Anastrozole", "Postmenopausal high-risk women", "IBIS-II",
         "~50% reduction"],
        ["Exemestane", "Postmenopausal high-risk women", "MAP.3",
         "65% reduction"],
    ]
    elems.append(make_table(prev_data, [W*0.28, W*0.28, W*0.14, W*0.30]))
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Ch. 58; Sabiston, Ch. 68</i>", SOURCE))

    # ── SECTION 9: SPECIAL SCENARIOS ─────────────────────────────────────────
    elems.append(section_banner("9", "SPECIAL SCENARIOS"))

    elems.append(h2("9.1 Hereditary & Familial Breast Cancer (Bailey & Love)"))
    for b_text in [
        "<b>Hereditary breast cancer (HBC)</b>: 5–10% of all breast cancers; identifiable genetic mutation; more aggressive, earlier onset, multicentric, bilateral",
        "<b>Familial breast cancer (FBC)</b>: 20–30%; family clustering without identified mutation",
        "<b>Sporadic</b>: ~70% of all breast cancers",
    ]:
        elems.append(bullet(b_text))

    gene_data = [
        ["Gene", "Chromosome", "Lifetime Breast Cancer Risk", "Other Cancers", "Tumour Subtype"],
        ["BRCA1", "17q21", "50–85%", "Ovarian (40%)", "Mostly TNBC"],
        ["BRCA2", "13q12.3", "50–60%", "Ovarian (20%), prostate, colon, pancreas", "ER+ (usually)"],
        ["TP53", "17p13.1", "~50%", "Li-Fraumeni syndrome (sarcoma, brain, adrenal)", "Variable"],
        ["PTEN", "10q23.3", "25–50%", "Cowden syndrome (thyroid, endometrium)", "Variable"],
        ["STK11", "19p13.3", "~50%", "Peutz-Jeghers syndrome (GI polyposis)", "Variable"],
        ["CDH1", "16q22.1", "39–52%", "Diffuse gastric cancer", "Lobular (ILC)"],
    ]
    elems.append(make_table(gene_data, [W*0.12, W*0.15, W*0.22, W*0.28, W*0.23]))

    elems.append(h3("Management of BRCA Mutation Carriers:"))
    for b_text in [
        "<b>Bilateral risk-reducing mastectomy + immediate reconstruction</b>: reduces breast cancer risk by <b>90%</b>",
        "<b>Chemoprophylaxis</b> (tamoxifen or anastrozole): reduces risk by <b>50%</b>",
        "<b>Bilateral salpingo-oophorectomy (BSO)</b>: after family completion at ~35–40 years",
        "Annual MRI + mammography from age 30 for surveillance",
    ]:
        elems.append(bullet(b_text))

    elems.append(h2("9.2 Breast Cancer in Pregnancy"))
    for b_text in [
        "Associated with aggressive tumour biology, particularly TNBC",
        "Imaging: ultrasound first; mammogram with abdominal shielding; MRI without gadolinium preferred",
        "Chemotherapy: generally safe <b>after 1st trimester</b>; avoid anthracyclines late in pregnancy",
        "<b>Trastuzumab: contraindicated</b> in pregnancy (fetal renal toxicity)",
        "Surgery can be performed in all trimesters",
        "Termination of pregnancy does NOT improve prognosis",
    ]:
        elems.append(bullet(b_text))

    elems.append(h2("9.3 Inflammatory Breast Cancer"))
    for b_text in [
        "Clinical diagnosis: erythema + oedema involving <b>&gt;1/3 of the breast</b>",
        "Classified as <b>T4d</b> regardless of tumour size",
        "Caused by <b>dermal lymphatic invasion</b> by tumour emboli — not infection",
        "<b>Treatment: NACT first</b> → MRM + post-mastectomy radiation (NOT upfront surgery alone)",
        "Remains classified as inflammatory carcinoma even after complete neoadjuvant remission (AJCC 8th)",
    ]:
        elems.append(bullet(b_text))

    elems.append(h2("9.4 Male Breast Cancer"))
    for b_text in [
        "Accounts for <b>&lt;1%</b> of all breast cancers",
        "BRCA2 mutation more common than BRCA1 in male breast cancer",
        "Mostly invasive ductal, ER positive",
        "Mastectomy preferred over BCS (small breast volume)",
        "Tamoxifen for hormonal therapy; AIs require concurrent GnRH agonist",
    ]:
        elems.append(bullet(b_text))

    elems.append(h2("9.5 DCIS Management (Sabiston)"))
    dcis_data = [
        ["Treatment Option", "Key Evidence / Notes"],
        ["BCS + adjuvant RT", "Standard; 2 mm negative margin required"],
        ["Mastectomy", "For multicentric DCIS, large DCIS, patient preference"],
        ["Tamoxifen (ER+ DCIS, premenopausal)", "NSABP B-24: reduces ipsilateral recurrence (16.6% → 13.2%), contralateral BC ↓40%"],
        ["Anastrozole (ER+ DCIS, postmenopausal <60 yrs)", "NSABP B-35: anastrozole superior to tamoxifen in breast cancer-free survival"],
        ["Adjuvant endocrine therapy overall", "Reduces DCIS recurrence risk by ~50%"],
    ]
    elems.append(make_table(dcis_data, [W*0.4, W*0.6]))

    elems.append(h2("9.6 Local Recurrence & Metastatic Disease (Bailey & Love)"))
    elems.append(h3("Local Recurrence:"))
    for b_text in [
        "Biopsy first — receptor status may change and influence therapy",
        "Whole-body MRI or PET-CT to exclude distant metastasis",
        "Systemic chemotherapy followed by surgical excision",
        "Most surgeons perform mastectomy; second BCS + re-RT may be considered in selected cases",
    ]:
        elems.append(bullet(b_text))
    elems.append(h3("Metastatic Disease:"))
    for b_text in [
        "Bony metastasis: palliative RT to weight-bearing lesions + <b>bisphosphonates/denosumab</b>",
        "Symptomatic pleural effusions: chest drainage + pleurodesis",
        "Surgical resection of <b>solitary visceral metastasis</b> in good performance status",
        "Systemic therapy: endocrine ± CDK4/6i (ER+), HER2 therapy (HER2+), chemotherapy, PARP inhibitors (BRCA mutation carriers)",
    ]:
        elems.append(bullet(b_text))
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Ch. 58; Sabiston, Ch. 68</i>", SOURCE))

    # ── SECTION 10: RECONSTRUCTION ───────────────────────────────────────────
    elems.append(section_banner("10", "BREAST RECONSTRUCTION"))
    rec_data = [
        ["Technique", "Description", "Advantages / Notes"],
        ["Tissue expander → implant", "Two-stage implant-based; expander placed, later exchanged for permanent implant ± ADM",
         "Simpler surgery; no donor site; may need revision"],
        ["Direct-to-implant", "Single-stage implant placement with ADM",
         "One operation; suitable for smaller breasts"],
        ["TRAM flap (pedicled/free)", "Transverse rectus abdominis myocutaneous flap from abdomen",
         "Autologous; natural feel; sacricifes rectus muscle → hernia risk"],
        ["DIEP flap (free)", "Deep inferior epigastric perforator flap; no muscle sacrifice",
         "Gold standard autologous; requires microsurgery; best donor site aesthetics"],
        ["LD flap", "Latissimus dorsi pedicled flap ± implant",
         "Reliable; well-vascularised; often used after RT; smaller volume"],
        ["SGAP / IGAP", "Superior/inferior gluteal artery perforator free flap",
         "Used when abdominal tissue unavailable; complex microsurgery"],
    ]
    elems.append(make_table(rec_data, [W*0.22, W*0.42, W*0.36]))
    elems.append(body("<b>Timing:</b> Immediate reconstruction (same operation as mastectomy — better psychological outcomes) "
        "vs. delayed (after adjuvant therapy — safer when post-mastectomy RT is planned)."))
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Ch. 58</i>", SOURCE))

    # ── SECTION 11: SCREENING ─────────────────────────────────────────────────
    elems.append(section_banner("11", "SCREENING"))
    screen_data = [
        ["Programme", "Age Range", "Frequency", "Modality"],
        ["UK NHS Breast Screening", "50–70 yrs (expanding 47–73)", "Every 3 years", "2-view mammography"],
        ["American Cancer Society (ACS)", "Annual from 40–45 yrs; biennial 55+", "Annual / biennial", "Mammography"],
        ["USPSTF", "50–74 yrs", "Every 2 years", "Mammography"],
        ["High-risk (BRCA/family hx)", "From age 30", "Annual", "MRI + mammography"],
    ]
    elems.append(make_table(screen_data, [W*0.32, W*0.25, W*0.18, W*0.25]))
    elems.append(body("Screening reduces breast cancer mortality by approximately <b>30–35%</b> in the screened population. "
        "Down-staging at detection is the primary mechanism of benefit."))

    # ── SECTION 12: PROGNOSIS ─────────────────────────────────────────────────
    elems.append(section_banner("12", "PROGNOSIS & SURVIVAL"))
    elems.append(h2("12.1 Prognostic Factors"))
    prog_data = [
        ["Factor", "Significance"],
        ["Axillary node status", "Most powerful single prognostic factor overall"],
        ["Tumour size (T stage)", "Most important anatomical factor"],
        ["Histological grade", "Grade III = significantly worse prognosis"],
        ["ER/PR status", "ER+ = better prognosis; endocrine therapy responsive"],
        ["HER2 status", "HER2+ = worse prognosis without targeted therapy; HER2 therapy reverses this"],
        ["Ki-67 / proliferation index", "High Ki-67 = higher recurrence risk"],
        ["Lymphovascular invasion (LVI)", "Independent adverse prognostic factor"],
        ["pCR after neoadjuvant therapy", "Excellent prognostic marker, especially in HER2+ and TNBC"],
        ["Oncotype DX recurrence score", "Guides chemotherapy need in ER+/HER2-/node- (TAILORx trial)"],
        ["MammaPrint", "Low vs. high risk for distant recurrence (MINDACT trial)"],
    ]
    elems.append(make_table(prog_data, [W*0.35, W*0.65]))

    elems.append(h2("12.2 5-Year Overall Survival by Stage"))
    surv_data = [
        ["Stage", "Approximate 5-Year Overall Survival"],
        ["Stage I (T1N0M0)", ">95%"],
        ["Stage IIA (T2N0 or T1N1)", "~85–90%"],
        ["Stage IIB (T2N1 or T3N0)", "~70–80%"],
        ["Stage IIIA–C (locally advanced)", "~50–70%"],
        ["Stage IV (metastatic)", "~25–30%"],
    ]
    surv_ts = TableStyle([
        ("BACKGROUND", (0,0), (-1,0), TABLE_HDR),
        ("TEXTCOLOR", (0,0), (-1,0), WHITE),
        ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
        ("FONTSIZE", (0,0), (-1,0), 9),
        ("ROWBACKGROUNDS", (0,1), (-1,-1),
         [colors.HexColor("#e8f5e9"), colors.HexColor("#fff9c4"),
          colors.HexColor("#fff9c4"), colors.HexColor("#ffe0b2"),
          colors.HexColor("#ffcdd2")]),
        ("GRID", (0,0), (-1,-1), 0.5, BORDER),
        ("FONTNAME", (0,1), (-1,-1), "Helvetica"),
        ("FONTSIZE", (0,1), (-1,-1), 9),
        ("TEXTCOLOR", (0,1), (-1,-1), GRAY_TEXT),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
        ("RIGHTPADDING", (0,0), (-1,-1), 8),
        ("TOPPADDING", (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("ALIGN", (1,0), (1,-1), "CENTER"),
    ])
    t = Table(surv_data, colWidths=[W*0.45, W*0.55])
    t.setStyle(surv_ts)
    elems.append(t)
    elems.append(Paragraph("<i>Source: Bailey &amp; Love, Ch. 58; Sabiston, Ch. 68</i>", SOURCE))

    # ── FOOTER NOTE ──────────────────────────────────────────────────────────
    elems.append(sp(12))
    elems.append(hr())
    elems.append(Paragraph(
        "<b>Sources:</b> Bailey &amp; Love's Short Practice of Surgery, 28th Edition — Chapter 58: The Breast | "
        "Sabiston Textbook of Surgery: The Biological Basis of Modern Surgical Practice — Chapter 68: Diseases of the Breast<br/>"
        "<b>Recent Evidence Note (PubMed 2024–2026):</b> Baker et al. (Breast, Dec 2024; PMID 39270543) — systematic review confirming "
        "that atypical ductal/lobular hyperplasia, LCIS, and flat epithelial atypia significantly elevate future breast cancer risk, "
        "consistent with current chemoprevention and surveillance protocols.",
        NOTE))

    return elems

# ── Page template with header/footer ─────────────────────────────────────────
def on_page(canvas, doc):
    canvas.saveState()
    w, h = A4
    # Header bar
    canvas.setFillColor(DARK_BLUE)
    canvas.rect(0, h - 1.8*cm, w, 1.8*cm, fill=1, stroke=0)
    canvas.setFont("Helvetica-Bold", 10)
    canvas.setFillColor(WHITE)
    canvas.drawString(1.5*cm, h - 1.2*cm, "BREAST CANCER — Comprehensive Surgical Reference")
    canvas.setFont("Helvetica", 8)
    canvas.drawRightString(w - 1.5*cm, h - 1.2*cm, "Bailey & Love 28th Ed. | Sabiston")
    # Footer
    canvas.setFillColor(DARK_BLUE)
    canvas.rect(0, 0, w, 1.2*cm, fill=1, stroke=0)
    canvas.setFont("Helvetica", 8)
    canvas.setFillColor(WHITE)
    canvas.drawString(1.5*cm, 0.45*cm, "© Compiled from standard surgical textbooks — for educational use")
    canvas.drawRightString(w - 1.5*cm, 0.45*cm, f"Page {doc.page}")
    canvas.restoreState()

def on_first_page(canvas, doc):
    canvas.saveState()
    w, h = A4
    canvas.setFillColor(DARK_BLUE)
    canvas.rect(0, 0, w, h, fill=1, stroke=0)
    canvas.restoreState()

# ── Build PDF ────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=2*cm, rightMargin=2*cm,
    topMargin=2.2*cm, bottomMargin=1.8*cm,
    title="Breast Cancer Comprehensive Reference",
    author="Bailey & Love 28th Ed. + Sabiston",
    subject="Breast Cancer Surgery"
)

story = []
story += cover_elements(A4[0], A4[1])
story += build_content()

doc.build(story, onFirstPage=on_first_page, onLaterPages=on_page)
print(f"\nPDF created: {OUTPUT}")
Running Command

cd /home/daytona/workspace/breast-cancer-pdf && python generate_pdf.py 2>&1

Editing File

~/breast-cancer-pdf/generate_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/breast-cancer-pdf/generate_pdf.py'
Running Command

cd /home/daytona/workspace/breast-cancer-pdf && python generate_pdf.py 2>&1

Editing File

~/breast-cancer-pdf/generate_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/breast-cancer-pdf/generate_pdf.py'
Running Command

cd /home/daytona/workspace/breast-cancer-pdf && python generate_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/breast-cancer-pdf/Breast_Cancer_Comprehensive_Reference.pdf

The PDF has been generated successfully (8.1 MB). Download it here:

Breast Cancer Comprehensive Reference

PDF Document · PDF


What's inside the PDF:
  • Styled cover page with source attribution and table of contents
  • 12 major sections with colour-coded section banners (dark blue header bars), sub-headings, and justified body text
  • Running header and footer on every page (title + page number)
  • 4 textbook figures embedded with captions:
    • Sabiston Fig. 68.1 - Breast anatomy cutaway diagram
    • Sabiston Fig. 68.2 - TDLU microanatomy
    • Bailey & Love Fig. 58.28 - Inflammatory carcinoma + peau d'orange (clinical photo)
    • Sabiston Fig. 68.9A - IDC histology
  • 25+ formatted tables covering risk factors, histological types, grading, molecular subtypes, TNM staging, treatment regimens, chemoprevention trials, prognosis, reconstruction, and more
  • Full coverage from both Bailey & Love 28th Ed. and Sabiston Textbook of Surgery
This is a shared conversation. Sign in to Orris to start your own chat.