make me details note on GERD for Residency, FCPS, MRCP exam as pdf with diagram and image

Reading File
Now let me run parallel searches across the medical library, PubMed, and read the PDF skill simultaneously.
Finding Sources
Finding Sources
Searching PubMed

"gastroesophageal reflux disease"[MeSH Terms] AND management

Reading File
Good. Now let me read the main GERD sections from Yamada's Gastroenterology and Sabiston Surgery in parallel, plus search PubMed with a broader query.
Reading File
Reading File
Reading File
Searching PubMed

"gastroesophageal reflux"[MeSH Terms] AND "proton pump inhibitors"[MeSH Terms]

Now let me read the main GERD section from Yamada's Gastroenterology which is the most comprehensive gastroenterology textbook:
Finding Sources
Reading File
Searching the Web

GERD pathophysiology diagnosis management guidelines 2024 2025 MRCP residency exam

Now let me get the core GERD content from Yamada's (which will have detailed GERD chapters):
Finding Sources
Finding Sources
Reading Web Page

https://pmc.ncbi.nlm.nih.gov/articles/PMC8754510

Now let me read the comprehensive GERD section from Goldman-Cecil Medicine (excellent for MRCP) and Yamada's GERD chapter:
Finding Sources
Finding Sources
Reading File
Reading File
Excellent! I have comprehensive content. Now let me read more of the Goldman-Cecil GERD section for management details and check for images:
Reading File
Finding Sources
Reading File
Reading File
I now have comprehensive content. Let me fetch the key images and then generate the PDF:
Loading Image
Loading Image
I have all the content and images I need. Now let me update todos and generate the comprehensive PDF:
Running Command

mkdir -p /home/daytona/workspace/gerd-notes && ls /home/daytona/workspace/gerd-notes/

Writing File

~/gerd-notes/generate_gerd_pdf.py

#!/usr/bin/env python3
"""
Comprehensive GERD Notes PDF Generator
For Residency / FCPS / MRCP Exam Preparation
"""

import urllib.request
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch, cm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, PageBreak, Image, KeepTogether
)
from reportlab.platypus.flowables import Flowable
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Circle, Polygon
from reportlab.graphics import renderPDF
from reportlab.graphics.charts.barcharts import VerticalBarChart
from io import BytesIO
import os

# ── Color Palette ────────────────────────────────────────────────────────────
DARK_BLUE   = colors.HexColor("#1A3A5C")
MID_BLUE    = colors.HexColor("#2E6DA4")
LIGHT_BLUE  = colors.HexColor("#D6E8FA")
ACCENT_RED  = colors.HexColor("#C0392B")
ACCENT_GREEN= colors.HexColor("#1A7A4A")
ACCENT_ORANGE= colors.HexColor("#D35400")
YELLOW_BG   = colors.HexColor("#FFF9C4")
GREY_BG     = colors.HexColor("#F5F5F5")
WHITE       = colors.white
BLACK       = colors.black
TEAL        = colors.HexColor("#117A8B")
PURPLE      = colors.HexColor("#6C3483")

OUTPUT_PATH = "/home/daytona/workspace/gerd-notes/GERD_Exam_Notes.pdf"

# ── Custom Flowables ─────────────────────────────────────────────────────────
class ColoredBox(Flowable):
    """A colored box with text for key points."""
    def __init__(self, text, bg_color, border_color, width=None, left_bar=True):
        super().__init__()
        self.text = text
        self.bg_color = bg_color
        self.border_color = border_color
        self.box_width = width or (A4[0] - 1.8*inch)
        self.left_bar = left_bar

    def wrap(self, avail_w, avail_h):
        self.box_width = avail_w
        return (avail_w, 0.55*inch)

    def draw(self):
        c = self.canv
        w = self.box_width
        h = 0.45*inch
        if self.left_bar:
            c.setFillColor(self.bg_color)
            c.roundRect(0, 0, w, h, 4, fill=1, stroke=0)
            c.setFillColor(self.border_color)
            c.rect(0, 0, 4, h, fill=1, stroke=0)
        else:
            c.setFillColor(self.bg_color)
            c.roundRect(0, 0, w, h, 4, fill=1, stroke=0)
            c.setStrokeColor(self.border_color)
            c.setLineWidth(1.2)
            c.roundRect(0, 0, w, h, 4, fill=0, stroke=1)
        c.setFillColor(BLACK)
        c.setFont("Helvetica", 9)
        c.drawString(12, h/2 - 4, self.text)


class SectionDivider(Flowable):
    """A fancy section divider with number."""
    def __init__(self, number, title, color=DARK_BLUE):
        super().__init__()
        self.number = number
        self.title = title
        self.color = color

    def wrap(self, avail_w, avail_h):
        self.width = avail_w
        return (avail_w, 0.5*inch)

    def draw(self):
        c = self.canv
        w = self.width
        # Background bar
        c.setFillColor(self.color)
        c.roundRect(0, 2, w, 0.42*inch, 5, fill=1, stroke=0)
        # Circle with number
        c.setFillColor(WHITE)
        c.circle(0.28*inch, 0.23*inch, 0.18*inch, fill=1, stroke=0)
        c.setFillColor(self.color)
        c.setFont("Helvetica-Bold", 13)
        c.drawCentredString(0.28*inch, 0.165*inch, str(self.number))
        # Title
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 14)
        c.drawString(0.6*inch, 0.16*inch, self.title.upper())


class PathwayArrow(Flowable):
    """Simple horizontal pathway diagram."""
    def __init__(self, steps, colors_list, width=None):
        super().__init__()
        self.steps = steps
        self.colors_list = colors_list
        self.box_width = width

    def wrap(self, avail_w, avail_h):
        self.box_width = avail_w
        return (avail_w, 0.85*inch)

    def draw(self):
        c = self.canv
        n = len(self.steps)
        box_w = (self.box_width - 0.1*inch) / n - 0.08*inch
        box_h = 0.55*inch
        y = 0.12*inch
        for i, (step, col) in enumerate(zip(self.steps, self.colors_list)):
            x = i * (box_w + 0.1*inch + 0.08*inch)
            c.setFillColor(col)
            c.roundRect(x, y, box_w, box_h, 5, fill=1, stroke=0)
            c.setFillColor(WHITE)
            c.setFont("Helvetica-Bold", 7.5)
            words = step.split('\n')
            if len(words) == 1:
                c.drawCentredString(x + box_w/2, y + box_h/2 - 4, step)
            else:
                for j, word in enumerate(words):
                    c.drawCentredString(x + box_w/2, y + box_h/2 + (len(words)/2 - j - 0.5)*10, word)
            # Arrow
            if i < n - 1:
                ax = x + box_w + 2
                ay = y + box_h/2
                c.setFillColor(colors.HexColor("#555555"))
                c.setStrokeColor(colors.HexColor("#555555"))
                c.setLineWidth(1.5)
                c.line(ax, ay, ax + 8, ay)
                c.polygon([ax+8, ay+4, ax+8, ay-4, ax+14, ay], fill=1, stroke=0)


# ── Styles ───────────────────────────────────────────────────────────────────
def make_styles():
    styles = getSampleStyleSheet()

    styles.add(ParagraphStyle(
        'MainTitle',
        parent=styles['Title'],
        fontSize=26, fontName='Helvetica-Bold',
        textColor=WHITE, alignment=TA_CENTER,
        spaceAfter=4
    ))
    styles.add(ParagraphStyle(
        'Subtitle',
        fontSize=13, fontName='Helvetica',
        textColor=LIGHT_BLUE, alignment=TA_CENTER,
        spaceAfter=6
    ))
    styles.add(ParagraphStyle(
        'H2', fontSize=13, fontName='Helvetica-Bold',
        textColor=DARK_BLUE, spaceBefore=10, spaceAfter=5,
        borderPad=2
    ))
    styles.add(ParagraphStyle(
        'H3', fontSize=11, fontName='Helvetica-Bold',
        textColor=MID_BLUE, spaceBefore=7, spaceAfter=3
    ))
    styles.add(ParagraphStyle(
        'H4', fontSize=10, fontName='Helvetica-BoldOblique',
        textColor=TEAL, spaceBefore=5, spaceAfter=2
    ))
    styles.add(ParagraphStyle(
        'Body', fontSize=9.5, fontName='Helvetica',
        textColor=colors.HexColor("#222222"),
        leading=14, spaceAfter=4, alignment=TA_JUSTIFY
    ))
    styles.add(ParagraphStyle(
        'Bullet', fontSize=9.5, fontName='Helvetica',
        textColor=colors.HexColor("#222222"),
        leading=13, spaceAfter=2,
        leftIndent=12, bulletIndent=0,
        alignment=TA_LEFT
    ))
    styles.add(ParagraphStyle(
        'SubBullet', fontSize=9, fontName='Helvetica',
        textColor=colors.HexColor("#333333"),
        leading=12, spaceAfter=2,
        leftIndent=24, bulletIndent=12
    ))
    styles.add(ParagraphStyle(
        'KeyPoint', fontSize=9.5, fontName='Helvetica-Bold',
        textColor=ACCENT_RED, leading=13, spaceAfter=2,
        leftIndent=8
    ))
    styles.add(ParagraphStyle(
        'TableHeader', fontSize=9, fontName='Helvetica-Bold',
        textColor=WHITE, alignment=TA_CENTER
    ))
    styles.add(ParagraphStyle(
        'TableCell', fontSize=8.5, fontName='Helvetica',
        textColor=BLACK, leading=12
    ))
    styles.add(ParagraphStyle(
        'Caption', fontSize=8, fontName='Helvetica-Oblique',
        textColor=colors.HexColor("#555555"), alignment=TA_CENTER,
        spaceAfter=6
    ))
    styles.add(ParagraphStyle(
        'SmallNote', fontSize=8, fontName='Helvetica',
        textColor=colors.HexColor("#666666"), leading=11, spaceAfter=2
    ))
    styles.add(ParagraphStyle(
        'PageFooter', fontSize=8, fontName='Helvetica',
        textColor=colors.HexColor("#888888"), alignment=TA_CENTER
    ))
    return styles

S = make_styles()

def b(text): return f"<b>{text}</b>"
def i(text): return f"<i>{text}</i>"
def color_text(text, hex_color): return f'<font color="{hex_color}">{text}</font>'

def bullet(text, style='Bullet'):
    return Paragraph(f"&#8226; {text}", S[style])

def subbullet(text):
    return Paragraph(f"&#x25E6; {text}", S['SubBullet'])

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

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


# ── Cover Page ───────────────────────────────────────────────────────────────
def cover_page():
    elems = []
    # Header background handled via custom flowable
    class CoverHeader(Flowable):
        def wrap(self, aw, ah):
            self.width = aw
            return (aw, 2.4*inch)
        def draw(self):
            c = self.canv
            w = self.width
            # Gradient-like background
            c.setFillColor(DARK_BLUE)
            c.roundRect(0, 0, w, 2.3*inch, 10, fill=1, stroke=0)
            c.setFillColor(MID_BLUE)
            c.roundRect(0, 0.05*inch, w, 0.6*inch, 10, fill=1, stroke=0)
            # GERD big title
            c.setFillColor(WHITE)
            c.setFont("Helvetica-Bold", 38)
            c.drawCentredString(w/2, 1.55*inch, "GERD")
            c.setFont("Helvetica-Bold", 15)
            c.setFillColor(LIGHT_BLUE)
            c.drawCentredString(w/2, 1.22*inch, "Gastroesophageal Reflux Disease")
            c.setFont("Helvetica", 11)
            c.setFillColor(WHITE)
            c.drawCentredString(w/2, 0.95*inch, "Comprehensive Exam Notes")
            # Badge row
            c.setFillColor(ACCENT_RED)
            bw = 1.0*inch
            bh = 0.28*inch
            badges = ["RESIDENCY", "FCPS", "MRCP"]
            total = len(badges) * bw + (len(badges)-1)*0.15*inch
            start_x = (w - total)/2
            for idx, badge in enumerate(badges):
                bx = start_x + idx*(bw + 0.15*inch)
                c.setFillColor([ACCENT_RED, ACCENT_GREEN, ACCENT_ORANGE][idx])
                c.roundRect(bx, 0.12*inch, bw, bh, 4, fill=1, stroke=0)
                c.setFillColor(WHITE)
                c.setFont("Helvetica-Bold", 8.5)
                c.drawCentredString(bx + bw/2, 0.22*inch, badge)

    elems.append(CoverHeader())
    elems.append(sp(16))

    # Info boxes
    info_data = [
        [Paragraph(b("Specialty"), S['TableHeader']),
         Paragraph(b("Target Exams"), S['TableHeader']),
         Paragraph(b("Evidence Base"), S['TableHeader']),
         Paragraph(b("Year"), S['TableHeader'])],
        [Paragraph("Gastroenterology\nGeneral Medicine", S['TableCell']),
         Paragraph("FCPS-II, MRCP Part 1/2\nResidency / USMLE", S['TableCell']),
         Paragraph("Goldman-Cecil, Yamada's\nACG/AGA Guidelines 2022-25", S['TableCell']),
         Paragraph("2025-26\nUpdated", S['TableCell'])]
    ]
    info_tbl = Table(info_data, colWidths=[1.4*inch, 1.6*inch, 2.2*inch, 1.0*inch])
    info_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
        ('BACKGROUND', (0,1), (-1,1), LIGHT_BLUE),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('ALIGN', (0,0), (-1,-1), 'CENTER'),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('GRID', (0,0), (-1,-1), 0.5, colors.white),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [LIGHT_BLUE]),
        ('ROUNDEDCORNERS', [5,5,5,5]),
        ('TOPPADDING', (0,0), (-1,-1), 6),
        ('BOTTOMPADDING', (0,0), (-1,-1), 6),
    ]))
    elems.append(info_tbl)
    elems.append(sp(14))

    # Topics covered
    elems.append(Paragraph(b("Topics Covered in This Document"), S['H2']))
    elems.append(hr())
    topics = [
        ("1", "Definition & Epidemiology", MID_BLUE),
        ("2", "Pathophysiology & Mechanisms", TEAL),
        ("3", "Clinical Features (Typical & Atypical)", ACCENT_GREEN),
        ("4", "Diagnosis & Investigations", ACCENT_ORANGE),
        ("5", "Los Angeles Classification", ACCENT_RED),
        ("6", "Complications (Barrett's, Stricture, Adenocarcinoma)", PURPLE),
        ("7", "Management (Stepwise Approach)", DARK_BLUE),
        ("8", "Surgery & Endoscopic Therapy", MID_BLUE),
        ("9", "Special Situations & High-Yield Points", TEAL),
        ("10", "Exam High-Yield Summary", ACCENT_RED),
    ]
    tdata = []
    row = []
    for idx, (num, topic, col) in enumerate(topics):
        cell_para = Paragraph(
            f'<font color="{col.hexval()}"><b>{num}.</b></font> {topic}',
            S['Bullet']
        )
        row.append(cell_para)
        if len(row) == 2:
            tdata.append(row)
            row = []
    if row:
        row.append(Paragraph("", S['Body']))
        tdata.append(row)

    tbl = Table(tdata, colWidths=[3.1*inch, 3.1*inch])
    tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), GREY_BG),
        ('GRID', (0,0), (-1,-1), 0.5, colors.white),
        ('TOPPADDING', (0,0), (-1,-1), 6),
        ('BOTTOMPADDING', (0,0), (-1,-1), 6),
        ('LEFTPADDING', (0,0), (-1,-1), 8),
    ]))
    elems.append(tbl)
    elems.append(sp(14))

    # Source note
    elems.append(Paragraph(
        f'<i>Sources: Goldman-Cecil Medicine (26e) · Yamada\'s Textbook of Gastroenterology (7e) · '
        f'Robbins &amp; Cotran Pathologic Basis of Disease · Current Surgical Therapy (14e) · '
        f'ACG Clinical Guidelines 2022 · AGA Guidelines 2022 · ASGE Guidelines 2025</i>',
        S['SmallNote']
    ))
    elems.append(PageBreak())
    return elems


# ── Section 1: Definition & Epidemiology ────────────────────────────────────
def section1():
    elems = []
    elems.append(SectionDivider(1, "Definition & Epidemiology", DARK_BLUE))
    elems.append(sp(8))

    elems.append(Paragraph(b("Definition (Montreal Consensus)"), S['H3']))
    elems.append(Paragraph(
        "GERD is defined as a condition that develops when the reflux of stomach contents into the "
        "esophagus causes <b>troublesome symptoms</b> or <b>complications</b>. Physiologic reflux "
        "occurs in everyone; GERD is diagnosed when it becomes clinically significant.",
        S['Body']
    ))
    elems.append(sp(6))

    # Epidemiology table
    elems.append(Paragraph(b("Epidemiology"), S['H3']))
    epi_data = [
        [Paragraph(b("Parameter"), S['TableHeader']),
         Paragraph(b("Data"), S['TableHeader'])],
        [Paragraph("Global Prevalence", S['TableCell']),
         Paragraph("10-20% in Western world; <5% in Asia", S['TableCell'])],
        [Paragraph("USA Prevalence", S['TableCell']),
         Paragraph("~44% ever had symptoms; ~30% in prior week", S['TableCell'])],
        [Paragraph("Gender", S['TableCell']),
         Paragraph("Equal M=F for GERD; M>F for Barrett's esophagus", S['TableCell'])],
        [Paragraph("Age", S['TableCell']),
         Paragraph("Increases with age; plateau at 7th-9th decade for Barrett's", S['TableCell'])],
        [Paragraph("Highest in", S['TableCell']),
         Paragraph("North America > Europe; Northern Europe > Southern Europe", S['TableCell'])],
    ]
    epi_tbl = Table(epi_data, colWidths=[2.0*inch, 4.2*inch])
    epi_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
        ('BACKGROUND', (0,1), (-1,1), LIGHT_BLUE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [LIGHT_BLUE, WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 8),
    ]))
    elems.append(epi_tbl)
    elems.append(sp(8))

    elems.append(Paragraph(b("Risk Factors"), S['H3']))
    rf_data = [
        [Paragraph(b("Modifiable"), S['TableHeader']),
         Paragraph(b("Non-modifiable"), S['TableHeader'])],
        [Paragraph(
            "• Obesity / central adiposity\n• High-fat diet, spicy foods, chocolate, caffeine\n"
            "• Alcohol & smoking\n• Late-night meals, large meals\n• Certain drugs (CCBs, nitrates,\n"
            "  anticholinergics, bisphosphonates)\n• Pregnancy",
            S['TableCell']),
         Paragraph(
            "• Male sex (for Barrett's esophagus)\n• Older age\n• Positive family history\n"
            "• Monozygotic twin concordance\n• White/European ethnicity\n• Hiatal hernia",
            S['TableCell'])]
    ]
    rf_tbl = Table(rf_data, colWidths=[3.1*inch, 3.1*inch])
    rf_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), TEAL),
        ('BACKGROUND', (0,1), (0,1), colors.HexColor("#E8F5E9")),
        ('BACKGROUND', (1,1), (1,1), colors.HexColor("#FFF3E0")),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 6),
        ('BOTTOMPADDING', (0,0), (-1,-1), 6),
        ('LEFTPADDING', (0,0), (-1,-1), 8),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(rf_tbl)
    elems.append(sp(8))
    return elems


# ── Section 2: Pathophysiology ───────────────────────────────────────────────
def section2():
    elems = []
    elems.append(SectionDivider(2, "Pathophysiology", TEAL))
    elems.append(sp(8))

    elems.append(Paragraph(b("Anti-Reflux Barrier (Normal Defense)"), S['H3']))
    elems.append(Paragraph(
        "The esophagus is protected by four overlapping mechanisms. Failure of any of these "
        "leads to pathologic reflux:", S['Body']
    ))
    defense_data = [
        [Paragraph(b("Defense Mechanism"), S['TableHeader']),
         Paragraph(b("Components"), S['TableHeader']),
         Paragraph(b("Role"), S['TableHeader'])],
        [Paragraph("1. Anti-reflux Barrier", S['TableCell']),
         Paragraph("LES + crural diaphragm + phrenoesophageal\nligament + angle of His", S['TableCell']),
         Paragraph("Primary mechanical barrier", S['TableCell'])],
        [Paragraph("2. Esophageal Clearance", S['TableCell']),
         Paragraph("Peristalsis (volume) + swallowed saliva\n(acid neutralization)", S['TableCell']),
         Paragraph("Clears refluxed material", S['TableCell'])],
        [Paragraph("3. Epithelial Defense", S['TableCell']),
         Paragraph("Mucous layer + tight junctions +\nbicarbonate secretion", S['TableCell']),
         Paragraph("Resists mucosal injury", S['TableCell'])],
        [Paragraph("4. Gastric Emptying", S['TableCell']),
         Paragraph("Normal gastric motility", S['TableCell']),
         Paragraph("Reduces gastric volume available to reflux", S['TableCell'])],
    ]
    def_tbl = Table(defense_data, colWidths=[1.6*inch, 2.6*inch, 1.9*inch])
    def_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), TEAL),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [LIGHT_BLUE, WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(def_tbl)
    elems.append(sp(8))

    # Pathophysiology diagram
    elems.append(Paragraph(b("Mechanisms of GERD (Stepwise Pathway)"), S['H3']))
    elems.append(PathwayArrow(
        ["tLESR\n(most common)", "Low LES\nPressure", "Hiatal\nHernia", "Impaired\nClearance", "Mucosal\nDamage"],
        [MID_BLUE, TEAL, ACCENT_ORANGE, PURPLE, ACCENT_RED]
    ))
    elems.append(sp(4))

    elems.append(Paragraph(b("Key Pathophysiologic Mechanisms"), S['H3']))

    mechs = [
        ("Transient LES Relaxations (tLESRs) - MOST COMMON",
         "Vagally-mediated reflex triggered by gastric distension. LES relaxes WITHOUT a swallow. "
         "This is the dominant mechanism in GERD patients. GABA-B receptor agonists (baclofen) and "
         "mGluR5 antagonists can reduce tLESRs."),
        ("Low Resting LES Pressure",
         "Normal LES pressure: 10-35 mmHg. A pressure <6 mmHg = free reflux. "
         "Associated with: scleroderma, certain drugs (CCBs, nitrates, theophylline, "
         "anticholinergics), foods (fat, chocolate, peppermint, alcohol)."),
        ("Hiatal Hernia",
         "Displaces LES above the diaphragm, separating LES from crural diaphragm. "
         "Creates a 'trap' (hernia sac) for gastric contents that can reflux during LES relaxation. "
         "Displaces the acid pocket (unbuffered acid in gastric cardia) into the hernia, "
         "worsening postprandial reflux. The larger the hernia, the worse the GERD."),
        ("Obesity",
         "Central fat increases intra-abdominal pressure → increases gastroesophageal pressure gradient "
         "→ promotes tLESRs. Also increases hiatal hernia incidence and disturbs GEJ anatomy."),
        ("Impaired Esophageal Clearance",
         "Reduced peristaltic amplitude or frequency fails to clear refluxed material. "
         "Saliva production reduced during sleep, explaining nocturnal GERD severity."),
        ("Delayed Gastric Emptying",
         "Increased gastric volume → more material available to reflux. Relevant in diabetic gastroparesis."),
        ("Acid Pocket",
         "Unbuffered acid accumulates just below GEJ post-prandially. In GERD patients, this pocket is "
         "larger and more proximal, and may extend into a hiatal hernia sac."),
    ]
    for title, text in mechs:
        elems.append(Paragraph(f"<b>{title}</b>", S['H4']))
        elems.append(Paragraph(text, S['Body']))

    elems.append(sp(8))

    # Injurious agents table
    elems.append(Paragraph(b("Injurious Agents in Refluxate"), S['H3']))
    agents_data = [
        [Paragraph(b("Agent"), S['TableHeader']),
         Paragraph(b("Damage"), S['TableHeader']),
         Paragraph(b("Clinical Significance"), S['TableHeader'])],
        [Paragraph("Hydrochloric Acid", S['TableCell']),
         Paragraph("Denatures proteins, disrupts tight junctions", S['TableCell']),
         Paragraph("Primary injurious agent; pH <4 most harmful", S['TableCell'])],
        [Paragraph("Pepsin", S['TableCell']),
         Paragraph("Proteolytic; active at pH <4", S['TableCell']),
         Paragraph("Potentiates acid injury", S['TableCell'])],
        [Paragraph("Bile Salts", S['TableCell']),
         Paragraph("Detergent effect on mucosa", S['TableCell']),
         Paragraph("Important in Barrett's development", S['TableCell'])],
        [Paragraph("Trypsin/Pancreatic enzymes", S['TableCell']),
         Paragraph("Mucosal injury at alkaline pH", S['TableCell']),
         Paragraph("Relevant in post-gastrectomy, duodenogastric reflux", S['TableCell'])],
    ]
    agents_tbl = Table(agents_data, colWidths=[1.5*inch, 2.0*inch, 2.65*inch])
    agents_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), PURPLE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor("#F3E5F5"), WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(agents_tbl)
    elems.append(sp(8))
    return elems


# ── Section 3: Clinical Features ────────────────────────────────────────────
def section3():
    elems = []
    elems.append(SectionDivider(3, "Clinical Features", ACCENT_GREEN))
    elems.append(sp(8))

    # GERD Syndrome Classification
    elems.append(Paragraph(b("Montreal Classification of GERD Syndromes"), S['H3']))
    mc_data = [
        [Paragraph(b("Esophageal Syndromes"), S['TableHeader']),
         Paragraph(b("Extra-Esophageal Syndromes"), S['TableHeader'])],
        [Paragraph(
            "<b>Symptomatic Syndromes:</b>\n"
            "• Typical reflux syndrome (heartburn + regurgitation)\n"
            "• Reflux chest pain syndrome\n\n"
            "<b>Syndromes with esophageal injury:</b>\n"
            "• Reflux esophagitis\n• Reflux stricture\n• Barrett's esophagus\n"
            "• Esophageal adenocarcinoma",
            S['TableCell']),
         Paragraph(
            "<b>Established associations:</b>\n"
            "• Reflux cough syndrome\n• Reflux laryngitis syndrome\n"
            "• Reflux asthma syndrome\n• Reflux dental erosion syndrome\n\n"
            "<b>Proposed associations:</b>\n"
            "• Sinusitis, pharyngitis, recurrent otitis media\n"
            "• Idiopathic pulmonary fibrosis\n• Recurrent aspiration pneumonia",
            S['TableCell'])]
    ]
    mc_tbl = Table(mc_data, colWidths=[3.1*inch, 3.1*inch])
    mc_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), ACCENT_GREEN),
        ('BACKGROUND', (0,1), (0,1), colors.HexColor("#E8F5E9")),
        ('BACKGROUND', (1,1), (1,1), colors.HexColor("#E3F2FD")),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 6),
        ('BOTTOMPADDING', (0,0), (-1,-1), 6),
        ('LEFTPADDING', (0,0), (-1,-1), 8),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(mc_tbl)
    elems.append(sp(8))

    elems.append(Paragraph(b("Typical Symptoms"), S['H3']))
    typical = [
        ("Heartburn", "Retrosternal burning sensation radiating upward from epigastrium to throat. "
         "Worsens after meals, when bending, or lying down. Relieved by antacids. "
         "<b>High specificity but LOW sensitivity</b> for GERD."),
        ("Regurgitation", "Effortless return of gastric contents to oropharynx/mouth with sour/bitter taste. "
         "NOT preceded by nausea. Bending/belching provokes it. "
         "<b>Distinguish from vomiting</b> (which requires effort and nausea) and "
         "<b>rumination</b> (effortless, subconscious, during meals, no heartburn)."),
        ("Water Brash", "Excessive salivation (mouth fills with saliva) - vagal reflex from esophageal acidification."),
        ("Globus", "Sensation of a lump or fullness in the throat, irrespective of swallowing."),
        ("Dysphagia", "Reported by >30% of GERD patients. Causes: peptic stricture, Schatzki ring, "
         "impaired peristalsis, or mucosal inflammation. <b>Alarm symptom</b> - needs endoscopy."),
        ("Odynophagia", "Pain on swallowing - suggests esophageal ulcer or deep erosion. <b>Alarm symptom.</b>"),
    ]
    for name, desc in typical:
        elems.append(Paragraph(f"<b>{name}:</b> {desc}", S['Bullet']))
        elems.append(sp(3))

    elems.append(sp(6))
    elems.append(Paragraph(b("Alarm Symptoms (Red Flags) - Mandate Urgent Endoscopy"), S['H3']))

    class RedFlagBox(Flowable):
        def wrap(self, aw, ah):
            self.width = aw
            return (aw, 1.1*inch)
        def draw(self):
            c = self.canv
            w = self.width
            c.setFillColor(colors.HexColor("#FFEBEE"))
            c.roundRect(0, 0, w, 1.0*inch, 6, fill=1, stroke=0)
            c.setStrokeColor(ACCENT_RED)
            c.setLineWidth(2)
            c.roundRect(0, 0, w, 1.0*inch, 6, fill=0, stroke=1)
            c.setFillColor(ACCENT_RED)
            c.setFont("Helvetica-Bold", 10)
            c.drawString(10, 0.8*inch, "RED FLAGS - REFER FOR URGENT ENDOSCOPY")
            c.setFont("Helvetica", 8.5)
            c.setFillColor(BLACK)
            flags = [
                "• Dysphagia  • Odynophagia  • Unintentional weight loss",
                "• Anemia / hematemesis / melena  • Palpable abdominal mass",
                "• Progressive symptoms despite adequate PPI therapy  • Age >55 with new-onset symptoms",
            ]
            for j, flag in enumerate(flags):
                c.drawString(10, 0.58*inch - j*0.16*inch, flag)

    elems.append(RedFlagBox())
    elems.append(sp(8))

    elems.append(Paragraph(b("Atypical (Extra-Esophageal) Symptoms"), S['H3']))
    atypical_data = [
        [Paragraph(b("System"), S['TableHeader']),
         Paragraph(b("Manifestation"), S['TableHeader']),
         Paragraph(b("Notes"), S['TableHeader'])],
        [Paragraph("Pulmonary", S['TableCell']),
         Paragraph("Chronic cough, asthma, aspiration pneumonia,\nidiopathic pulmonary fibrosis", S['TableCell']),
         Paragraph("GERD is 3rd most common cause of chronic cough\n(after rhinosinusitis, asthma). "
                   "50-75% have NO typical GERD symptoms.", S['TableCell'])],
        [Paragraph("ENT", S['TableCell']),
         Paragraph("Laryngitis, hoarseness, globus, chronic\nthroat-clearing, subglottic stenosis", S['TableCell']),
         Paragraph("Laryngopharyngeal reflux (LPR); "
                   "Reinke's edema, posterior laryngitis (cobblestoning)", S['TableCell'])],
        [Paragraph("Dental", S['TableCell']),
         Paragraph("Dental erosions (enamel erosion)", S['TableCell']),
         Paragraph("Prevalence 17-68% in GERD patients;\npalatal surface most affected", S['TableCell'])],
        [Paragraph("Cardiac", S['TableCell']),
         Paragraph("Non-cardiac chest pain (NCCP)", S['TableCell']),
         Paragraph("GERD is MOST COMMON esophageal cause of NCCP\n(more than spastic motor disorders). "
                   "Abnormal pH in 21-48% of NCCP.", S['TableCell'])],
        [Paragraph("Sleep", S['TableCell']),
         Paragraph("Nocturnal symptoms, sleep apnea", S['TableCell']),
         Paragraph("Head-of-bed elevation recommended", S['TableCell'])],
    ]
    atyp_tbl = Table(atypical_data, colWidths=[1.1*inch, 2.0*inch, 3.05*inch])
    atyp_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), ACCENT_GREEN),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor("#E8F5E9"), WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(atyp_tbl)
    elems.append(sp(8))
    return elems


# ── Section 4: Diagnosis ─────────────────────────────────────────────────────
def section4():
    elems = []
    elems.append(SectionDivider(4, "Diagnosis & Investigations", ACCENT_ORANGE))
    elems.append(sp(8))

    # Diagnostic algorithm
    elems.append(Paragraph(b("Diagnostic Algorithm (ACG/AGA 2022 Guidelines)"), S['H3']))
    algo_data = [
        [Paragraph(b("Step"), S['TableHeader']),
         Paragraph(b("Action"), S['TableHeader']),
         Paragraph(b("Recommendation"), S['TableHeader'])],
        [Paragraph("Step 1", S['TableCell']),
         Paragraph("Classic symptoms (heartburn + regurgitation)\nNO alarm features", S['TableCell']),
         Paragraph("Empiric 8-week PPI trial (once daily before meal)\n"
                   "[Strong recommendation, moderate evidence - ACG 2022]", S['TableCell'])],
        [Paragraph("Step 2a", S['TableCell']),
         Paragraph("Symptoms respond to PPI trial", S['TableCell']),
         Paragraph("Attempt PPI discontinuation. If recurrence → long-term PPI\n"
                   "(on-demand or continuous)", S['TableCell'])],
        [Paragraph("Step 2b", S['TableCell']),
         Paragraph("Symptoms do NOT respond adequately\nOR symptoms recur on stopping PPI", S['TableCell']),
         Paragraph("Upper endoscopy (after stopping PPI for 2-4 weeks ideally)\n"
                   "[Strong recommendation]", S['TableCell'])],
        [Paragraph("Step 3a", S['TableCell']),
         Paragraph("Endoscopy shows LA Grade C/D esophagitis,\nlong-segment Barrett's, or peptic stricture", S['TableCell']),
         Paragraph("GERD confirmed. No need for reflux monitoring off therapy.\n"
                   "Initiate aggressive management.", S['TableCell'])],
        [Paragraph("Step 3b", S['TableCell']),
         Paragraph("Endoscopy normal / LA Grade A or B only", S['TableCell']),
         Paragraph("Reflux monitoring OFF therapy (pH or impedance-pH)\n"
                   "to confirm diagnosis [Strong recommendation]", S['TableCell'])],
        [Paragraph("Step 4", S['TableCell']),
         Paragraph("Extraesophageal symptoms WITHOUT\ntypical GERD symptoms", S['TableCell']),
         Paragraph("Reflux testing before PPI therapy (to establish GERD)\n"
                   "then treat concurrent esophageal GERD syndrome", S['TableCell'])],
    ]
    algo_tbl = Table(algo_data, colWidths=[0.85*inch, 2.3*inch, 3.0*inch])
    algo_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), ACCENT_ORANGE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor("#FFF3E0"), WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(algo_tbl)
    elems.append(sp(8))

    elems.append(Paragraph(b("Investigations in Detail"), S['H3']))

    inv_data = [
        [Paragraph(b("Investigation"), S['TableHeader']),
         Paragraph(b("Indication / Use"), S['TableHeader']),
         Paragraph(b("Key Facts"), S['TableHeader'])],
        [Paragraph("Upper GI Endoscopy\n(OGD/EGD)", S['TableCell']),
         Paragraph("• Alarm symptoms\n• Failure of empiric PPI\n• Confirm GERD\n"
                   "• Surveillance (Barrett's)", S['TableCell']),
         Paragraph("LA Grade C/D or Barrett's = definitive GERD.\n"
                   "Ideally off PPI 2-4 weeks before. Biopsy for "
                   "Barrett's/dysplasia.", S['TableCell'])],
        [Paragraph("Ambulatory 24-hr\npH Monitoring", S['TableCell']),
         Paragraph("• Gold standard for diagnosing GERD\n• Must be OFF PPI (7 days)\n"
                   "• Correlating symptoms with reflux", S['TableCell']),
         Paragraph("DeMeester score >14.72 OR\n"
                   "Acid exposure time (AET) >6% = pathologic.\n"
                   "Wireless capsule: 48-96 hrs, more comfortable.", S['TableCell'])],
        [Paragraph("Impedance-pH\nMonitoring", S['TableCell']),
         Paragraph("• Detects non-acid reflux\n• Persistent symptoms on PPI\n"
                   "• Preferred for extraesophageal GERD", S['TableCell']),
         Paragraph("Can detect weakly acid and non-acid reflux.\n"
                   "Symptom Index (SI) >50% significant.\n"
                   "Symptom Association Probability (SAP) >95% significant.", S['TableCell'])],
        [Paragraph("Esophageal\nManometry (HRM)", S['TableCell']),
         Paragraph("• Pre-surgical workup\n• Rule out achalasia\n"
                   "• Determine type of fundoplication\n• NOT for primary GERD diagnosis", S['TableCell']),
         Paragraph("High-resolution manometry not recommended as\ndiagnostic test for GERD alone. "
                   "Chicago Classification v4.0 for motility disorders.", S['TableCell'])],
        [Paragraph("Barium Esophagram", S['TableCell']),
         Paragraph("• Detect hiatal hernia\n• Evaluate dysphagia\n"
                   "• Assess strictures pre-dilation", S['TableCell']),
         Paragraph("Higher sensitivity than endoscopy for subtle\nstrictures (use solid challenge - barium pill). "
                   "Not sensitive for mild GERD.", S['TableCell'])],
        [Paragraph("Mucosal Impedance\n(new)", S['TableCell']),
         Paragraph("• Adjunct to endoscopy\n• Differentiate GERD from EoE", S['TableCell']),
         Paragraph("Catheter-based balloon sensor during endoscopy.\n"
                   "Promising - detects mucosal integrity changes. ASGE 2025.", S['TableCell'])],
    ]
    inv_tbl = Table(inv_data, colWidths=[1.4*inch, 2.0*inch, 2.75*inch])
    inv_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [LIGHT_BLUE, WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(inv_tbl)
    elems.append(sp(8))
    return elems


# ── Section 5: Los Angeles Classification (with image) ──────────────────────
def section5():
    elems = []
    elems.append(SectionDivider(5, "Los Angeles Classification of Esophagitis", ACCENT_RED))
    elems.append(sp(8))

    la_data = [
        [Paragraph(b("Grade"), S['TableHeader']),
         Paragraph(b("Endoscopic Finding"), S['TableHeader']),
         Paragraph(b("Clinical Significance"), S['TableHeader'])],
        [Paragraph("A", S['TableCell']),
         Paragraph("One or more mucosal breaks <5 mm long,\nnot extending between tops of 2 mucosal folds", S['TableCell']),
         Paragraph("Mild esophagitis; PPI for 4-8 weeks. May not confirm GERD diagnosis alone.", S['TableCell'])],
        [Paragraph("B", S['TableCell']),
         Paragraph("One or more mucosal breaks >5 mm long,\nnot extending between tops of 2 mucosal folds", S['TableCell']),
         Paragraph("Moderate; 8 weeks PPI, re-endoscope to confirm healing.", S['TableCell'])],
        [Paragraph("C", S['TableCell']),
         Paragraph("Mucosal break continuous between tops of\n≥2 folds but <75% of circumference", S['TableCell']),
         Paragraph("Severe; CONFIRMS GERD diagnosis. 8-12 weeks high-dose PPI.\n"
                   "No need for pH monitoring to confirm diagnosis.", S['TableCell'])],
        [Paragraph("D", S['TableCell']),
         Paragraph("Mucosal break involving ≥75% of\nesophageal circumference", S['TableCell']),
         Paragraph("Very severe; CONFIRMS GERD. Consider early surgery referral.\n"
                   "High risk for stricture / Barrett's.", S['TableCell'])],
    ]
    la_tbl = Table(la_data, colWidths=[0.6*inch, 2.5*inch, 3.05*inch])
    la_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), ACCENT_RED),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor("#FFEBEE"), WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 6),
        ('BOTTOMPADDING', (0,0), (-1,-1), 6),
        ('LEFTPADDING', (0,0), (-1,-1), 8),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(la_tbl)
    elems.append(sp(8))

    # Try to include the LA classification image
    img_url = "https://cdn.orris.care/cdss_images/f94e730e08c384d7bb094a78cdb91d45929bbb7a711a437b276f749072dc6c07.png"
    img_path = "/home/daytona/workspace/gerd-notes/la_classification.png"
    try:
        urllib.request.urlretrieve(img_url, img_path)
        if os.path.exists(img_path) and os.path.getsize(img_path) > 1000:
            elems.append(Paragraph(b("Endoscopic Images - Los Angeles Classification"), S['H3']))
            img = Image(img_path, width=5.5*inch, height=2.8*inch)
            img.hAlign = 'CENTER'
            elems.append(img)
            elems.append(Paragraph(
                "Fig. 1: Los Angeles Classification of reflux esophagitis (Grades A-D). "
                "Grade A: small isolated mucosal break. Grade B: larger break. "
                "Grade C: confluent breaks <75% circumference. Grade D: circumferential involvement. "
                "(Source: Current Surgical Therapy 14e / Nayar & Vaezi, 2004)",
                S['Caption']
            ))
    except Exception as e:
        elems.append(Paragraph(f"[Image: LA Classification diagram - {str(e)[:50]}]", S['Caption']))

    elems.append(sp(8))

    elems.append(Paragraph(b("Key Exam Point on LA Classification"), S['H3']))
    elems.append(Paragraph(
        "LA Grade C or D = definitive confirmation of GERD diagnosis (no need for pH monitoring). "
        "LA Grade A or B = insufficient to confirm GERD (may be seen in healthy subjects); "
        "if diagnosis uncertain, proceed to reflux monitoring off PPI therapy. "
        "Note: up to 30% of LA Grade A lesions may be normal variants.",
        S['Body']
    ))
    elems.append(sp(8))
    return elems


# ── Section 6: Complications ─────────────────────────────────────────────────
def section6():
    elems = []
    elems.append(SectionDivider(6, "Complications of GERD", PURPLE))
    elems.append(sp(8))

    # Complications overview
    elems.append(PathwayArrow(
        ["Esophagitis\n(erosive)", "Peptic\nUlcer", "Stricture\n(peptic)", "Barrett's\nEsophagus", "Adeno-\ncarcinoma"],
        [MID_BLUE, TEAL, ACCENT_ORANGE, PURPLE, ACCENT_RED]
    ))
    elems.append(sp(4))

    elems.append(Paragraph(b("1. Erosive Esophagitis"), S['H3']))
    elems.append(Paragraph(
        "Mucosal breaks (erosions/ulcerations) in the distal esophagus. Classified by LA system. "
        "Heals with 8-12 weeks PPI therapy. Recurrence common if PPI stopped. "
        "Complications: bleeding (hematemesis/anemia), stricture.",
        S['Body']
    ))

    elems.append(Paragraph(b("2. Peptic Stricture"), S['H3']))
    elems.append(Paragraph(
        "Fibrous narrowing from chronic acid injury and healing. Presents as <b>progressive "
        "dysphagia to solids</b>. Diagnosed on barium esophagram (higher sensitivity) or endoscopy. "
        "Treatment: endoscopic dilation (gradual, to ≥13 mm) + long-term PPI. "
        "For recalcitrant strictures: intralesional triamcinolone injection.",
        S['Body']
    ))

    elems.append(Paragraph(b("3. Barrett's Esophagus"), S['H3']))
    elems.append(Paragraph(
        "Intestinal metaplasia replaces normal squamous epithelium of distal esophagus. "
        "The most important complication due to its association with esophageal adenocarcinoma.",
        S['Body']
    ))

    be_data = [
        [Paragraph(b("Feature"), S['TableHeader']),
         Paragraph(b("Details"), S['TableHeader'])],
        [Paragraph("Prevalence", S['TableCell']),
         Paragraph("5-15% of endoscopy patients with GERD symptoms; 1.3-1.6% general population", S['TableCell'])],
        [Paragraph("Demographics", S['TableCell']),
         Paragraph("Middle-aged White men; ~25% are women or <50 yrs; 45% have NO reflux symptoms", S['TableCell'])],
        [Paragraph("Risk Factors", S['TableCell']),
         Paragraph("Long-standing reflux, smoking, male sex, older age, central obesity, White ethnicity", S['TableCell'])],
        [Paragraph("Endoscopic Appearance", S['TableCell']),
         Paragraph("Tongues of red, velvety mucosa extending upward from GEJ\n"
                   "(salmon-colored mucosa above Z-line)", S['TableCell'])],
        [Paragraph("Classification", S['TableCell']),
         Paragraph("Long-segment: ≥3 cm | Short-segment: <3 cm (lower cancer risk)", S['TableCell'])],
        [Paragraph("Histology (MUST KNOW)", S['TableCell']),
         Paragraph("Intestinal-type metaplasia with GOBLET CELLS (wine goblet shape, alcian-blue positive).\n"
                   "Goblet cells are DIAGNOSTIC of Barrett's.", S['TableCell'])],
        [Paragraph("Cancer Risk", S['TableCell']),
         Paragraph("Annual cancer risk ~0.1-0.3% per year overall; higher with dysplasia and long-segment.\n"
                   "CDX2 transcription factor promotes columnar metaplasia.", S['TableCell'])],
        [Paragraph("Dysplasia Grades", S['TableCell']),
         Paragraph("No dysplasia → Low-grade dysplasia (LGD) → High-grade dysplasia (HGD) → "
                   "Adenocarcinoma\nAtypical mitoses, nuclear hyperchromasia, increased N:C ratio", S['TableCell'])],
    ]
    be_tbl = Table(be_data, colWidths=[1.6*inch, 4.6*inch])
    be_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), PURPLE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor("#F3E5F5"), WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(be_tbl)
    elems.append(sp(8))

    # Barrett's image
    img_url2 = "https://cdn.orris.care/cdss_images/854a9069e076aef6407662efaf7ced76b5083d57a1275c30a53c50192f11de0c.png"
    img_path2 = "/home/daytona/workspace/gerd-notes/barretts.png"

    # Barrett's surveillance table
    elems.append(Paragraph(b("Barrett's Esophagus - Surveillance & Management"), S['H3']))
    surv_data = [
        [Paragraph(b("Histology"), S['TableHeader']),
         Paragraph(b("Surveillance Interval"), S['TableHeader']),
         Paragraph(b("Management"), S['TableHeader'])],
        [Paragraph("No dysplasia", S['TableCell']),
         Paragraph("Every 3-5 years", S['TableCell']),
         Paragraph("Continue PPI. Lifestyle modification.", S['TableCell'])],
        [Paragraph("Indefinite for dysplasia", S['TableCell']),
         Paragraph("Repeat endoscopy in 3-6 months", S['TableCell']),
         Paragraph("Optimize PPI therapy.", S['TableCell'])],
        [Paragraph("Low-grade dysplasia (LGD)", S['TableCell']),
         Paragraph("Every 6 months × 2, then annually", S['TableCell']),
         Paragraph("Endoscopic eradication (RFA, EMR) preferred.\nCan survey if patient declines ablation.", S['TableCell'])],
        [Paragraph("High-grade dysplasia (HGD)", S['TableCell']),
         Paragraph("N/A - treat immediately", S['TableCell']),
         Paragraph("Endoscopic eradication therapy (RFA or EMR).\nEsophagectomy if endoscopic therapy unavailable.", S['TableCell'])],
        [Paragraph("Intramucosal adenocarcinoma\n(T1a)", S['TableCell']),
         Paragraph("N/A - treat immediately", S['TableCell']),
         Paragraph("EMR + RFA if no lymphovascular invasion.", S['TableCell'])],
    ]
    surv_tbl = Table(surv_data, colWidths=[1.6*inch, 1.6*inch, 3.0*inch])
    surv_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), PURPLE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor("#F3E5F5"), WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(surv_tbl)
    elems.append(sp(8))
    return elems


# ── Section 7: Management ────────────────────────────────────────────────────
def section7():
    elems = []
    elems.append(SectionDivider(7, "Management of GERD", DARK_BLUE))
    elems.append(sp(8))

    elems.append(Paragraph(b("Step 1: Lifestyle Modifications (All Patients)"), S['H3']))
    lifestyle_data = [
        [Paragraph(b("Recommendation"), S['TableHeader']),
         Paragraph(b("Evidence"), S['TableHeader']),
         Paragraph(b("Notes"), S['TableHeader'])],
        [Paragraph("Weight loss (if overweight/obese)", S['TableCell']),
         Paragraph("Strong (RCT evidence)", S['TableCell']),
         Paragraph("Most effective single lifestyle intervention; reduces tLESRs", S['TableCell'])],
        [Paragraph("Head-of-bed elevation (15-20 cm)", S['TableCell']),
         Paragraph("Good (RCTs)", S['TableCell']),
         Paragraph("For nocturnal symptoms; use bed wedge, not extra pillows", S['TableCell'])],
        [Paragraph("Avoid meals 2-3 hrs before bedtime", S['TableCell']),
         Paragraph("Conditional", S['TableCell']),
         Paragraph("Reduces supine reflux risk", S['TableCell'])],
        [Paragraph("Avoid trigger foods", S['TableCell']),
         Paragraph("Conditional (limited data)", S['TableCell']),
         Paragraph("Fat, chocolate, peppermint, spicy foods, citrus, tomatoes, caffeine, alcohol", S['TableCell'])],
        [Paragraph("Stop smoking", S['TableCell']),
         Paragraph("Conditional", S['TableCell']),
         Paragraph("Smoking reduces LES pressure", S['TableCell'])],
        [Paragraph("Avoid tight clothing", S['TableCell']),
         Paragraph("Expert opinion", S['TableCell']),
         Paragraph("Reduces intra-abdominal pressure", S['TableCell'])],
        [Paragraph("Left lateral decubitus sleeping position", S['TableCell']),
         Paragraph("Good", S['TableCell']),
         Paragraph("Reduces nocturnal acid exposure", S['TableCell'])],
    ]
    ls_tbl = Table(lifestyle_data, colWidths=[1.8*inch, 1.3*inch, 3.1*inch])
    ls_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), MID_BLUE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [LIGHT_BLUE, WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(ls_tbl)
    elems.append(sp(8))

    elems.append(Paragraph(b("Step 2: Pharmacological Management"), S['H3']))

    elems.append(Paragraph(b("A. Antacids & Alginates"), S['H4']))
    elems.append(bullet("Magnesium/aluminum hydroxide - rapid symptom relief, short-acting"))
    elems.append(bullet("Sodium alginate forms a viscous 'raft' on top of gastric contents, reducing reflux"))
    elems.append(bullet("Suitable for mild, intermittent symptoms. No healing effect on esophagitis."))
    elems.append(sp(4))

    elems.append(Paragraph(b("B. H2-Receptor Antagonists (H2RAs)"), S['H4']))
    elems.append(bullet("Ranitidine (withdrawn - NDMA contamination), Famotidine, Cimetidine, Nizatidine"))
    elems.append(bullet("Competitive reversible histamine H2 receptor blockade on parietal cells"))
    elems.append(bullet("Effective for mild-moderate GERD; tolerance (tachyphylaxis) develops within 2 weeks"))
    elems.append(bullet("Useful as add-on nighttime dose with PPI for nocturnal acid breakthrough"))
    elems.append(sp(4))

    elems.append(Paragraph(b("C. Proton Pump Inhibitors (PPIs) - FIRST-LINE TREATMENT"), S['H4']))

    ppi_data = [
        [Paragraph(b("PPI"), S['TableHeader']),
         Paragraph(b("Dose"), S['TableHeader']),
         Paragraph(b("Notes"), S['TableHeader'])],
        [Paragraph("Omeprazole", S['TableCell']),
         Paragraph("20-40 mg OD/BD", S['TableCell']),
         Paragraph("First PPI; best studied; substrate of CYP2C19 (genetic polymorphism affects efficacy)", S['TableCell'])],
        [Paragraph("Lansoprazole", S['TableCell']),
         Paragraph("15-30 mg OD", S['TableCell']),
         Paragraph("Once daily adequate for GERD maintenance", S['TableCell'])],
        [Paragraph("Pantoprazole", S['TableCell']),
         Paragraph("20-40 mg OD", S['TableCell']),
         Paragraph("Fewest drug interactions; preferred in polypharmacy patients", S['TableCell'])],
        [Paragraph("Rabeprazole", S['TableCell']),
         Paragraph("10-20 mg OD", S['TableCell']),
         Paragraph("Least dependent on CYP2C19; more consistent suppression", S['TableCell'])],
        [Paragraph("Esomeprazole", S['TableCell']),
         Paragraph("20-40 mg OD", S['TableCell']),
         Paragraph("S-isomer of omeprazole; marginally superior healing rates in LA Grade C/D", S['TableCell'])],
        [Paragraph("Dexlansoprazole", S['TableCell']),
         Paragraph("30-60 mg OD", S['TableCell']),
         Paragraph("Dual delayed-release; can be taken without regard to meals (MRCP point)", S['TableCell'])],
    ]
    ppi_tbl = Table(ppi_data, colWidths=[1.3*inch, 1.3*inch, 3.6*inch])
    ppi_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [LIGHT_BLUE, WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(ppi_tbl)
    elems.append(sp(6))

    # PPI key points
    ppi_keys = [
        ("TIMING", "Take 30-60 minutes BEFORE the first meal of the day (activates the H+/K+-ATPase)"),
        ("MECHANISM", "Irreversibly block H+/K+-ATPase (proton pump) on parietal cell canalicular membrane. "
         "Bind covalently as active sulfenamide after acid activation."),
        ("EFFICACY", "Heal 80-95% of erosive esophagitis in 8 weeks. Superior to H2RAs."),
        ("ADVERSE EFFECTS", "Short-term: headache, diarrhea, nausea. Long-term: hypomagnesemia, "
         "C. difficile infection, community-acquired pneumonia, bone fractures (prolonged), "
         "vitamin B12 deficiency, renal interstitial nephritis, SIBO"),
        ("REBOUND ACID", "Hypersecretion on stopping PPI; taper gradually in long-term users"),
        ("CYP2C19", "Omeprazole/esomeprazole inhibit CYP2C19 → may reduce clopidogrel efficacy "
         "(IMPORTANT drug interaction for cardiology MRCP questions)"),
    ]
    for key, val in ppi_keys:
        elems.append(Paragraph(f'<font color="{MID_BLUE.hexval()}"><b>{key}:</b></font> {val}', S['Bullet']))
        elems.append(sp(2))

    elems.append(sp(6))
    elems.append(Paragraph(b("D. Potassium-Competitive Acid Blockers (P-CABs) - Vonoprazan"), S['H4']))
    elems.append(Paragraph(
        "Vonoprazan reversibly blocks K+ binding site on H+/K+-ATPase. "
        "Unlike PPIs, does NOT require acid activation → works faster, more consistent suppression. "
        "Meta-analysis (Simadibrata 2024, PMID 38263507) shows superior efficacy vs PPIs in "
        "PPI-resistant GERD. Network meta-analysis (Zhuang 2024, PMID 38345252) shows P-CABs "
        "superior to PPIs for Grade C/D esophagitis healing. Approved in Japan/USA; gaining "
        "adoption in UK/South Asia.",
        S['Body']
    ))
    elems.append(sp(6))

    elems.append(Paragraph(b("E. Other Agents"), S['H4']))
    elems.append(bullet("Sucralfate: cytoprotective; useful in pregnancy (limited systemic absorption)"))
    elems.append(bullet("Prokinetics (metoclopramide, domperidone): limited evidence; used for gastroparesis-related GERD"))
    elems.append(bullet("Baclofen (GABA-B agonist): reduces tLESRs; used in refractory GERD; "
                        "side effects limit use (sedation, confusion) - NOT recommended without objective GERD evidence (ACG)"))
    elems.append(bullet("TCAs / SSRIs: for functional heartburn / visceral hypersensitivity component"))
    elems.append(sp(8))
    return elems


# ── Section 8: Surgery & Endoscopic Therapy ──────────────────────────────────
def section8():
    elems = []
    elems.append(SectionDivider(8, "Surgery & Endoscopic Therapy", MID_BLUE))
    elems.append(sp(8))

    elems.append(Paragraph(b("Indications for Surgical/Endoscopic Referral"), S['H3']))
    ind_items = [
        "Medically refractory GERD (failure of twice-daily PPI for ≥8 weeks)",
        "Patient preference / unwilling to take lifelong medication",
        "Significant PPI side effects or intolerance",
        "Large hiatal hernia with mechanical symptoms",
        "Objective GERD (pH-proven) with persistent symptoms",
        "High-grade dysplasia / early adenocarcinoma in Barrett's esophagus",
        "Esophageal injury (esophagitis, Barrett's) despite adequate medical therapy",
    ]
    for item in ind_items:
        elems.append(bullet(item))

    elems.append(sp(8))
    elems.append(Paragraph(b("Surgical Options"), S['H3']))

    surg_data = [
        [Paragraph(b("Procedure"), S['TableHeader']),
         Paragraph(b("Description"), S['TableHeader']),
         Paragraph(b("Indication / Notes"), S['TableHeader'])],
        [Paragraph("Laparoscopic Nissen\nFundoplication (LNF)\n360° wrap", S['TableCell']),
         Paragraph("Complete 360° posterior wrap of gastric fundus\naround lower esophagus", S['TableCell']),
         Paragraph("Gold standard for normal esophageal motility.\n"
                   "Meta-analysis (Li 2023, PMID 36998190): Nissen vs Toupet - Nissen has lower "
                   "GERD recurrence; Toupet has lower dysphagia rate.", S['TableCell'])],
        [Paragraph("Laparoscopic Toupet\nFundoplication\n270° wrap", S['TableCell']),
         Paragraph("Partial 270° posterior wrap", S['TableCell']),
         Paragraph("Preferred in ineffective esophageal motility (Chicago\nClassification v4.0) "
                   "to prevent post-op dysphagia.", S['TableCell'])],
        [Paragraph("Laparoscopic Dor\n180° anterior wrap", S['TableCell']),
         Paragraph("Anterior partial wrap", S['TableCell']),
         Paragraph("After Heller myotomy for achalasia.\nSometimes used in poor motility.", S['TableCell'])],
        [Paragraph("Magnetic Sphincter\nAugmentation (MSA)\nLINX device", S['TableCell']),
         Paragraph("Ring of magnetic titanium beads placed\naround LES laparoscopically", S['TableCell']),
         Paragraph("Minimally invasive alternative to fundoplication.\nPreserves ability to belch/vomit. "
                   "Requires normal esophageal motility.\nContraindicated: metal allergy, MRI needs.", S['TableCell'])],
        [Paragraph("Roux-en-Y gastric bypass", S['TableCell']),
         Paragraph("Bariatric surgery creating Roux limb", S['TableCell']),
         Paragraph("Excellent anti-reflux effect; preferred in morbid\nobesity with GERD.", S['TableCell'])],
    ]
    surg_tbl = Table(surg_data, colWidths=[1.4*inch, 2.1*inch, 2.65*inch])
    surg_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), MID_BLUE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [LIGHT_BLUE, WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(surg_tbl)
    elems.append(sp(8))

    elems.append(Paragraph(b("Endoscopic Therapies for Barrett's Esophagus"), S['H3']))
    endo_data = [
        [Paragraph(b("Technique"), S['TableHeader']),
         Paragraph(b("Mechanism"), S['TableHeader']),
         Paragraph(b("Use"), S['TableHeader'])],
        [Paragraph("RFA (Radiofrequency\nAblation)", S['TableCell']),
         Paragraph("Thermal energy delivered via balloon/focal\ncatheter ablates metaplastic mucosa", S['TableCell']),
         Paragraph("First-line for flat Barrett's + dysplasia.\n~80-90% complete eradication of dysplasia.", S['TableCell'])],
        [Paragraph("EMR (Endoscopic\nMucosal Resection)", S['TableCell']),
         Paragraph("Injection + snare resection of visible nodules\nor dysplastic areas", S['TableCell']),
         Paragraph("Staging + treatment of HGD/early T1a adenocarcinoma.\nShould precede RFA for nodular disease.", S['TableCell'])],
        [Paragraph("ESD (Endoscopic\nSubmucosal Dissection)", S['TableCell']),
         Paragraph("En-bloc submucosal dissection using\nspecialized knives", S['TableCell']),
         Paragraph("For larger lesions or those needing en-bloc\nresection; more technically demanding.", S['TableCell'])],
        [Paragraph("Cryotherapy", S['TableCell']),
         Paragraph("Liquid nitrogen or CO2 freezes tissue", S['TableCell']),
         Paragraph("Alternative when RFA fails or not available.", S['TableCell'])],
    ]
    endo_tbl = Table(endo_data, colWidths=[1.4*inch, 2.1*inch, 2.65*inch])
    endo_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), PURPLE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor("#F3E5F5"), WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(endo_tbl)
    elems.append(sp(8))
    return elems


# ── Section 9: Special Situations ────────────────────────────────────────────
def section9():
    elems = []
    elems.append(SectionDivider(9, "Special Situations", TEAL))
    elems.append(sp(8))

    special = [
        ("GERD in Pregnancy",
         "Very common (30-80%); due to progesterone-mediated LES relaxation + uterine pressure. "
         "Treatment ladder: lifestyle → antacids/alginates → H2RAs (famotidine - Category B) → "
         "PPIs (Category B: all PPIs except omeprazole Category C in some guidelines). "
         "Sucralfate: safe (not absorbed). Resolve post-partum in most."),
        ("GERD in Scleroderma",
         "Severely impaired LES + absent/weak peristalsis. Aggressive PPI therapy required. "
         "Surgery CONTRAINDICATED (absent peristalsis - fundoplication causes dysphagia). "
         "High Barrett's risk."),
        ("Nocturnal GERD",
         "Most acid suppression occurs at night. Add H2RA at bedtime ('nocturnal acid breakthrough') "
         "to PPI therapy. Head-of-bed elevation and left lateral position. Avoid food within 3 hrs."),
        ("Laryngopharyngeal Reflux (LPR)",
         "Posterior laryngitis, hoarseness, chronic cough, throat clearing. "
         "Only 40% have typical GERD symptoms. Diagnosis: laryngoscopy (cobblestoning, erythema, "
         "pseudosulcus). Requires TWICE-daily PPI for minimum 3 months. "
         "Poor symptom-acid correlation; do not start PPI without objective confirmation."),
        ("GERD and Asthma",
         "Bidirectional relationship: GERD triggers asthma (micro-aspiration, vagal reflex); "
         "asthma drugs (beta-agonists, theophylline) worsen GERD (reduce LES pressure). "
         "If asthma poorly controlled + typical GERD symptoms: treat GERD. "
         "If asthma + NO typical GERD: pH/impedance testing before PPI."),
        ("PPI-Refractory GERD",
         "Definition: failure of twice-daily PPI therapy. Differential: non-compliance, "
         "incorrect timing, functional heartburn, weakly acidic reflux, esophageal hypersensitivity, "
         "EoE, or bile reflux. Investigations: impedance-pH ON therapy. "
         "Treatment options: optimize PPI timing, switch PPI, vonoprazan, baclofen, TCA/SSRI, "
         "surgical referral."),
    ]
    for title, text in special:
        elems.append(Paragraph(f"<b>{title}</b>", S['H3']))
        elems.append(Paragraph(text, S['Body']))
        elems.append(sp(4))

    return elems


# ── Section 10: High-Yield Summary ───────────────────────────────────────────
def section10():
    elems = []
    elems.append(SectionDivider(10, "High-Yield Exam Summary", ACCENT_RED))
    elems.append(sp(8))

    elems.append(Paragraph(b("Must-Know Facts for FCPS / MRCP / Residency"), S['H3']))

    class HighYieldBox(Flowable):
        def __init__(self, items, col_header, bg, border):
            super().__init__()
            self.items = items
            self.col_header = col_header
            self.bg = bg
            self.border = border
        def wrap(self, aw, ah):
            self.width = aw
            h = 0.35*inch + len(self.items) * 0.18*inch
            self.height = h
            return (aw, h)
        def draw(self):
            c = self.canv
            w = self.width
            h = self.height
            c.setFillColor(self.bg)
            c.roundRect(0, 0, w, h, 5, fill=1, stroke=0)
            c.setStrokeColor(self.border)
            c.setLineWidth(1.5)
            c.roundRect(0, 0, w, h, 5, fill=0, stroke=1)
            c.setFillColor(self.border)
            c.setFont("Helvetica-Bold", 9.5)
            c.drawString(8, h - 0.25*inch, self.col_header)
            c.setFillColor(BLACK)
            c.setFont("Helvetica", 8.5)
            for j, item in enumerate(self.items):
                c.drawString(14, h - 0.38*inch - j*0.18*inch, f"• {item}")

    hy_groups = [
        ("DEFINITION & EPIDEMIOLOGY", DARK_BLUE, colors.HexColor("#E3F2FD"), [
            "Montreal definition: troublesome symptoms OR complications from esophageal reflux",
            "Prevalence: 10-20% Western; <5% Asia; USA up to 44%",
            "Risk factors: obesity (most modifiable), hiatal hernia, smoking, genetics",
            "Physiologic reflux occurs normally - GERD = pathologic amount",
        ]),
        ("PATHOPHYSIOLOGY KEY POINTS", TEAL, colors.HexColor("#E0F2F1"), [
            "Most common mechanism = Transient LES Relaxations (tLESRs)",
            "Vagally mediated, triggered by gastric distension",
            "Hiatal hernia: separates LES from crural diaphragm, creates acid pocket",
            "Acid pocket: unbuffered acid below GEJ, source of postprandial reflux",
            "Obesity: increases intra-abdominal pressure → more tLESRs",
        ]),
        ("CLINICAL FEATURES", ACCENT_GREEN, colors.HexColor("#E8F5E9"), [
            "Heartburn + regurgitation: HIGH specificity, LOW sensitivity for GERD",
            "GERD is MOST COMMON esophageal cause of non-cardiac chest pain",
            "Chronic cough: GERD is 3rd commonest cause; 50-75% no typical GERD symptoms",
            "Rumination ≠ regurgitation (rumination: subconscious, no heartburn, post-meal)",
            "Alarm symptoms: dysphagia, weight loss, anemia, hematemesis, odynophagia",
        ]),
        ("INVESTIGATIONS", ACCENT_ORANGE, colors.HexColor("#FFF3E0"), [
            "Classic symptoms + no alarms → empiric 8-week PPI (no endoscopy needed first)",
            "Gold standard for GERD: 24-hr pH monitoring (DeMeester score >14.72, AET >6%)",
            "LA Grade C/D = confirms GERD; no pH monitoring needed",
            "LA Grade A/B alone = does NOT confirm GERD diagnosis",
            "Manometry: NOT for GERD diagnosis; use for pre-surgical workup only",
            "pH monitoring: must be OFF PPI for 7 days",
        ]),
        ("MANAGEMENT", MID_BLUE, colors.HexColor("#E3F2FD"), [
            "PPIs: take 30-60 min BEFORE first meal (not at bedtime)",
            "Dexlansoprazole: only PPI taken WITHOUT regard to meals",
            "Omeprazole/esomeprazole inhibit CYP2C19 → reduce clopidogrel efficacy",
            "Vonoprazan (P-CAB): superior to PPI in resistant GERD and Grade C/D esophagitis",
            "Nissen fundoplication: 360° wrap; gold standard for surgical GERD",
            "Toupet (270°): preferred in poor esophageal motility",
            "Surgery contraindicated in scleroderma (no peristalsis)",
        ]),
        ("BARRETT'S ESOPHAGUS", PURPLE, colors.HexColor("#F3E5F5"), [
            "Goblet cells (intestinal metaplasia) = DIAGNOSTIC of Barrett's",
            "Only 10% of symptomatic GERD → Barrett's; 45% Barrett's have NO reflux symptoms",
            "Cancer risk ~0.1-0.3%/yr; higher with LGD, HGD, long-segment, male, obesity",
            "HGD/early adenocarcinoma → EMR then RFA",
            "Long-segment Barrett's = ≥3 cm; short-segment <3 cm",
            "CDX2 transcription factor promotes columnar metaplasia",
            "Surveillance: no dysplasia → 3-5 years; LGD → 6 months; HGD → treat immediately",
        ]),
        ("LA CLASSIFICATION (MUST MEMORIZE)", ACCENT_RED, colors.HexColor("#FFEBEE"), [
            "Grade A: mucosal break <5 mm, not crossing fold tops",
            "Grade B: mucosal break >5 mm, not crossing fold tops",
            "Grade C: mucosal break crossing fold tops, <75% circumference",
            "Grade D: mucosal break ≥75% circumference (circumferential)",
            "Only LA Grade C/D confirms GERD diagnosis on endoscopy",
        ]),
    ]

    for header, border_col, bg_col, items in hy_groups:
        elems.append(KeepTogether([
            HighYieldBox(items, header, bg_col, border_col),
            sp(8)
        ]))

    # Differentials table
    elems.append(Paragraph(b("GERD - Key Differentials"), S['H3']))
    diff_data = [
        [Paragraph(b("Condition"), S['TableHeader']),
         Paragraph(b("Distinguishing Features"), S['TableHeader'])],
        [Paragraph("Functional Heartburn", S['TableCell']),
         Paragraph("Normal pH/impedance testing; no acid-symptom correlation; "
                   "responds to neuromodulators (TCAs/SSRIs), not PPIs", S['TableCell'])],
        [Paragraph("Eosinophilic Esophagitis (EoE)", S['TableCell']),
         Paragraph("Young atopic males; dysphagia/food impaction dominant; "
                   "eosinophils >15/HPF on biopsy; furrows/rings on endoscopy; "
                   "responds to PPI or swallowed budesonide", S['TableCell'])],
        [Paragraph("Achalasia", S['TableCell']),
         Paragraph("Dysphagia to solids AND liquids; regurgitation of undigested food; "
                   "bird-beak on barium; absent peristalsis + aperistalsis on manometry", S['TableCell'])],
        [Paragraph("Rumination Syndrome", S['TableCell']),
         Paragraph("Effortless regurgitation during meals; no heartburn; "
                   "subconscious; resolves with behavioral therapy/diaphragmatic breathing", S['TableCell'])],
        [Paragraph("Peptic Ulcer Disease", S['TableCell']),
         Paragraph("Epigastric pain; relieved by food (DU) or worsened by food (GU); "
                   "H. pylori testing; endoscopy shows ulcer", S['TableCell'])],
        [Paragraph("Cardiac Chest Pain", S['TableCell']),
         Paragraph("Exertional, radiation to arm/jaw, diaphoresis, ECG changes; "
                   "MUST EXCLUDE before esophageal workup", S['TableCell'])],
    ]
    diff_tbl = Table(diff_data, colWidths=[1.6*inch, 4.6*inch])
    diff_tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), DARK_BLUE),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [LIGHT_BLUE, WHITE]),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
        ('FONTSIZE', (0,0), (-1,-1), 8.5),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    elems.append(diff_tbl)
    elems.append(sp(8))

    # Recent evidence
    elems.append(Paragraph(b("Recent Evidence (2023-2025)"), S['H3']))
    recent_ev = [
        ("PMID 38263507 (J Gastroenterol Hepatol 2024)",
         "Vonoprazan (P-CAB) superior to PPIs for PPI-resistant GERD - systematic review & meta-analysis"),
        ("PMID 38345252 (Am J Gastroenterol 2024)",
         "P-CABs superior to PPIs for Grade C/D esophagitis healing - network meta-analysis"),
        ("PMID 36998190 (Surg Innov 2023)",
         "Nissen vs Toupet fundoplication: Nissen = lower GERD recurrence; Toupet = lower dysphagia"),
        ("ASGE 2025",
         "New mucosal impedance testing (catheter-based balloon) during endoscopy - differentiates GERD from EoE"),
        ("ACG 2022",
         "Empiric 8-week PPI recommended for classic symptoms without alarms (before endoscopy)"),
    ]
    for ref, text in recent_ev:
        elems.append(Paragraph(
            f'<font color="{MID_BLUE.hexval()}"><b>{ref}:</b></font> {text}',
            S['Bullet']
        ))
        elems.append(sp(2))

    elems.append(sp(8))

    # Final footer
    elems.append(hr(DARK_BLUE, 1))
    elems.append(Paragraph(
        "Prepared for Residency / FCPS / MRCP Examination Preparation | May 2026 | "
        "Sources: Goldman-Cecil Medicine (26e), Yamada's Gastroenterology (7e), Robbins Pathology, "
        "Current Surgical Therapy (14e), ACG/AGA/ASGE Guidelines",
        S['Caption']
    ))
    return elems


# ── Page Template (Header + Footer) ─────────────────────────────────────────
def add_header_footer(canvas, doc):
    canvas.saveState()
    page_width = A4[0]
    # Header bar
    canvas.setFillColor(DARK_BLUE)
    canvas.rect(0, A4[1] - 0.45*inch, page_width, 0.45*inch, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica-Bold", 10)
    canvas.drawString(0.4*inch, A4[1] - 0.3*inch, "GERD - Comprehensive Exam Notes")
    canvas.setFont("Helvetica", 8)
    canvas.drawRightString(page_width - 0.4*inch, A4[1] - 0.3*inch, "Residency | FCPS | MRCP")
    # Footer
    canvas.setFillColor(DARK_BLUE)
    canvas.rect(0, 0, page_width, 0.35*inch, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 8)
    canvas.drawCentredString(page_width/2, 0.12*inch,
        f"Page {doc.page} | Goldman-Cecil · Yamada's · ACG/AGA Guidelines 2022-25")
    canvas.restoreState()


def first_page(canvas, doc):
    canvas.saveState()
    # Full dark blue background for cover
    canvas.setFillColor(DARK_BLUE)
    canvas.rect(0, A4[1]-0.4*inch, A4[0], 0.4*inch, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 7)
    canvas.drawCentredString(A4[0]/2, A4[1]-0.27*inch, "GASTROENTEROLOGY | EXAM PREPARATION")
    canvas.restoreState()


# ── Main build ───────────────────────────────────────────────────────────────
def build_pdf():
    doc = SimpleDocTemplate(
        OUTPUT_PATH,
        pagesize=A4,
        leftMargin=0.9*inch,
        rightMargin=0.9*inch,
        topMargin=0.65*inch,
        bottomMargin=0.55*inch,
        title="GERD Comprehensive Exam Notes",
        author="Medical AI Assistant",
        subject="GERD - Residency/FCPS/MRCP"
    )

    story = []
    story += cover_page()
    story += section1()
    story.append(PageBreak())
    story += section2()
    story.append(PageBreak())
    story += section3()
    story.append(PageBreak())
    story += section4()
    story.append(PageBreak())
    story += section5()
    story.append(PageBreak())
    story += section6()
    story.append(PageBreak())
    story += section7()
    story.append(PageBreak())
    story += section8()
    story.append(PageBreak())
    story += section9()
    story.append(PageBreak())
    story += section10()

    doc.build(
        story,
        onFirstPage=first_page,
        onLaterPages=add_header_footer
    )
    print(f"PDF generated: {OUTPUT_PATH}")
    import os
    size = os.path.getsize(OUTPUT_PATH)
    print(f"File size: {size/1024:.1f} KB")

if __name__ == "__main__":
    build_pdf()
Running Command

cd /home/daytona/workspace/gerd-notes && python generate_gerd_pdf.py 2>&1

Editing File

~/gerd-notes/generate_gerd_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/gerd-notes/generate_gerd_pdf.py'
Running Command

cd /home/daytona/workspace/gerd-notes && sed -i "s/style='Bullet'/style='BulletItem'/g; s/S\['Bullet'\]/S['BulletItem']/g" generate_gerd_pdf.py && python generate_gerd_pdf.py 2>&1

Running Command

cd /home/daytona/workspace/gerd-notes && python -c " content = open('generate_gerd_pdf.py').read() content = content.replace(\"style='Bullet'\", \"style='BulletItem'\") content = content.replace(\"S['Bullet']\", \"S['BulletItem']\") open('generate_gerd_pdf.py','w').write(content) print('done') " && python generate_gerd_pdf.py 2>&1

Running Command

cd /home/daytona/workspace/gerd-notes && python -c " content = open('generate_gerd_pdf.py').read() # Fix polygon -> path drawing old = 'c.polygon([ax+8, ay+4, ax+8, ay-4, ax+14, ay], fill=1, stroke=0)' new = '''p = c.beginPath() p.moveTo(ax+8, ay+4) p.lineTo(ax+8, ay-4) p.lineTo(ax+14, ay) p.close() c.drawPath(p, fill=1, stroke=0)''' content = content.replace(old, new) open('generate_gerd_pdf.py','w').write(content) print('fixed') " && python generate_gerd_pdf.py 2>&1

Model call limits exceeded: run limit (20/20)
This is a shared conversation. Sign in to Orris to start your own chat.