Hypertension case proforma general medicine

Asking for Preferences

What format do you need the hypertension case proforma in? · What level is this proforma for?

Reading File
Reading File
Now let me search the medical library for hypertension content and check the PDF skill reference, then build the proforma.
Finding Sources
Reading File
Finding Sources
Finding Sources
Reading File
I have enough medical knowledge to build a thorough MBBS-level hypertension case proforma. Let me now create the PDF directly using ReportLab.
Running Command

ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or missing"

Writing File

~/hypertension-proforma/generate_proforma.py

#!/usr/bin/env python3
"""
Hypertension Case Proforma - General Medicine (MBBS Level)
Generates a comprehensive PDF case proforma using ReportLab.
"""

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.pdfgen import canvas

OUTPUT_PATH = "/home/daytona/workspace/hypertension-proforma/Hypertension_Case_Proforma.pdf"

W, H = A4  # 595.28 x 841.89 points

# ── Colour palette ──────────────────────────────────────────────────────────
DARK_BLUE   = colors.HexColor("#1A3A5C")
MED_BLUE    = colors.HexColor("#2E6DA4")
LIGHT_BLUE  = colors.HexColor("#D6E4F0")
ACCENT      = colors.HexColor("#C0392B")
GREY_BG     = colors.HexColor("#F2F4F6")
LINE_GREY   = colors.HexColor("#BDC3C7")
WHITE       = colors.white
BLACK       = colors.black

# ── Helper: dotted answer line ───────────────────────────────────────────────
def line(n=1, width="100%"):
    """Return a series of underline tables acting as blank fill lines."""
    rows = []
    for _ in range(n):
        t = Table([["_" * 90]], colWidths=["100%"])
        t.setStyle(TableStyle([
            ("TEXTCOLOR", (0, 0), (-1, -1), LINE_GREY),
            ("FONTSIZE",  (0, 0), (-1, -1), 7),
            ("TOPPADDING",  (0, 0), (-1, -1), 0),
            ("BOTTOMPADDING", (0, 0), (-1, -1), 2),
            ("LEFTPADDING",  (0, 0), (-1, -1), 0),
        ]))
        rows.append(t)
        rows.append(Spacer(1, 1*mm))
    return rows

def field_row(label, n_lines=1, label_width=5*cm):
    """Label + dotted line(s) as a two-column table."""
    line_str = "_" * 70
    lines_text = ("<br/>".join([line_str] * n_lines))
    data = [[label, lines_text]]
    t = Table(data, colWidths=[label_width, None])
    t.setStyle(TableStyle([
        ("VALIGN", (0, 0), (-1, -1), "BOTTOM"),
        ("FONTSIZE", (0, 0), (-1, -1), 9),
        ("TEXTCOLOR", (0, 0), (0, -1), DARK_BLUE),
        ("TEXTCOLOR", (1, 0), (1, -1), LINE_GREY),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 2),
        ("TOPPADDING",    (0, 0), (-1, -1), 4),
        ("LEFTPADDING",   (0, 0), (-1, -1), 0),
    ]))
    return t


# ── Page template with header/footer ────────────────────────────────────────
class HeaderFooterCanvas(canvas.Canvas):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._saved_page_states = []

    def showPage(self):
        self._saved_page_states.append(dict(self.__dict__))
        self._startPage()

    def save(self):
        page_count = len(self._saved_page_states)
        for state in self._saved_page_states:
            self.__dict__.update(state)
            self.draw_page(page_count)
            canvas.Canvas.showPage(self)
        canvas.Canvas.save(self)

    def draw_page(self, page_count):
        self.saveState()
        pg = self._pageNumber
        # Header bar
        self.setFillColor(DARK_BLUE)
        self.rect(0, H - 1.2*cm, W, 1.2*cm, fill=1, stroke=0)
        self.setFillColor(WHITE)
        self.setFont("Helvetica-Bold", 11)
        self.drawString(1.5*cm, H - 0.85*cm, "HYPERTENSION CASE PROFORMA")
        self.setFont("Helvetica", 8)
        self.drawRightString(W - 1.5*cm, H - 0.85*cm, "General Medicine | MBBS")
        # Footer
        self.setFillColor(DARK_BLUE)
        self.rect(0, 0, W, 0.8*cm, fill=1, stroke=0)
        self.setFillColor(WHITE)
        self.setFont("Helvetica", 7.5)
        self.drawString(1.5*cm, 0.28*cm, "Department of General Medicine")
        self.drawCentredString(W/2, 0.28*cm, "CONFIDENTIAL - For Academic Use Only")
        self.drawRightString(W - 1.5*cm, 0.28*cm, f"Page {pg} of {page_count}")
        self.restoreState()


# ── Style helpers ────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

def S(name, **kw):
    base = styles["Normal"]
    return ParagraphStyle(name, parent=base, **kw)

TITLE   = S("TITLE",  fontSize=15, textColor=DARK_BLUE, fontName="Helvetica-Bold",
             spaceAfter=2, alignment=TA_CENTER)
SEC     = S("SEC",    fontSize=10.5, textColor=WHITE,  fontName="Helvetica-Bold",
             spaceAfter=2, leading=14)
SUBSEC  = S("SUBSEC", fontSize=9.5,  textColor=DARK_BLUE, fontName="Helvetica-Bold",
             spaceBefore=4, spaceAfter=2)
BODY    = S("BODY",   fontSize=9,    textColor=BLACK, leading=13)
SMALL   = S("SMALL",  fontSize=8,    textColor=colors.HexColor("#555555"), leading=11)
NOTE    = S("NOTE",   fontSize=8,    textColor=ACCENT, fontName="Helvetica-Oblique")
LABEL   = S("LABEL",  fontSize=9,    textColor=DARK_BLUE, fontName="Helvetica-Bold")


def section_header(text):
    """Blue banner heading."""
    data = [[Paragraph(text, SEC)]]
    t = Table(data, colWidths=[W - 3*cm])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0, 0), (-1, -1), MED_BLUE),
        ("TOPPADDING",    (0, 0), (-1, -1), 5),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING",   (0, 0), (-1, -1), 8),
        ("ROUNDEDCORNERS", [3]),
    ]))
    return KeepTogether([Spacer(1, 4*mm), t, Spacer(1, 2*mm)])


def checkbox_row(items, cols=4):
    """Row of checkbox items."""
    padded = items + [""] * (cols - len(items) % cols if len(items) % cols else 0)
    rows = []
    for i in range(0, len(padded), cols):
        chunk = padded[i:i+cols]
        row_data = [["☐  " + c if c else ""] for c in chunk]
        flat = [["☐  " + c if c else "" for c in chunk]]
        rows.append(flat[0])
    t = Table(rows, colWidths=[(W - 3*cm) / cols] * cols)
    t.setStyle(TableStyle([
        ("FONTSIZE",      (0, 0), (-1, -1), 9),
        ("TEXTCOLOR",     (0, 0), (-1, -1), BLACK),
        ("TOPPADDING",    (0, 0), (-1, -1), 3),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
        ("LEFTPADDING",   (0, 0), (-1, -1), 4),
    ]))
    return t


def two_col_checklist(left_items, right_items, header_left="", header_right=""):
    """Two-column checklist table."""
    max_len = max(len(left_items), len(right_items))
    left_items  = left_items  + [""] * (max_len - len(left_items))
    right_items = right_items + [""] * (max_len - len(right_items))
    data = []
    if header_left or header_right:
        data.append([
            Paragraph(header_left, SUBSEC),
            Paragraph(header_right, SUBSEC)
        ])
    for l, r in zip(left_items, right_items):
        data.append([
            ("☐  " + l) if l else "",
            ("☐  " + r) if r else ""
        ])
    half = (W - 3*cm) / 2
    t = Table(data, colWidths=[half, half])
    t.setStyle(TableStyle([
        ("FONTSIZE",      (0, 0), (-1, -1), 9),
        ("TOPPADDING",    (0, 0), (-1, -1), 3),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 3),
        ("LEFTPADDING",   (0, 0), (-1, -1), 4),
        ("LINEAFTER",     (0, 0), (0, -1), 0.5, LINE_GREY),
        ("FONTNAME",      (0, 0), (-1, 0), "Helvetica-Bold") if (header_left or header_right) else ("FONTSIZE", (0,0), (-1,-1), 9),
    ]))
    return t


def bp_table():
    """JNC 8 / ACC/AHA 2017 BP classification table."""
    headers = ["Category", "Systolic (mmHg)", "", "Diastolic (mmHg)"]
    data = [
        headers,
        ["Normal",              "< 120",       "AND", "< 80"],
        ["Elevated",            "120-129",     "AND", "< 80"],
        ["Stage 1 HTN",         "130-139",     "OR",  "80-89"],
        ["Stage 2 HTN",         "≥ 140",       "OR",  "≥ 90"],
        ["Hypertensive Crisis", "≥ 180",       "AND/OR", "≥ 120"],
    ]
    col_w = [(W - 3*cm) * f for f in [0.35, 0.25, 0.1, 0.30]]
    t = Table(data, colWidths=col_w)
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0, 0), (-1, 0), DARK_BLUE),
        ("TEXTCOLOR",     (0, 0), (-1, 0), WHITE),
        ("FONTNAME",      (0, 0), (-1, 0), "Helvetica-Bold"),
        ("FONTSIZE",      (0, 0), (-1, -1), 8.5),
        ("ROWBACKGROUNDS",(0, 1), (-1, -1), [WHITE, GREY_BG]),
        ("GRID",          (0, 0), (-1, -1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
        ("LEFTPADDING",   (0, 0), (-1, -1), 6),
        ("ALIGN",         (1, 0), (-1, -1), "CENTER"),
        ("VALIGN",        (0, 0), (-1, -1), "MIDDLE"),
        # Highlight hypertensive crisis row
        ("BACKGROUND",    (0, 5), (-1, 5), colors.HexColor("#FDECEA")),
        ("TEXTCOLOR",     (0, 5), (-1, 5), ACCENT),
        ("FONTNAME",      (0, 5), (-1, 5), "Helvetica-Bold"),
    ]))
    return t


# ── BUILD DOCUMENT ───────────────────────────────────────────────────────────
def build():
    doc = SimpleDocTemplate(
        OUTPUT_PATH,
        pagesize=A4,
        leftMargin=1.5*cm, rightMargin=1.5*cm,
        topMargin=1.6*cm,  bottomMargin=1.2*cm,
        title="Hypertension Case Proforma",
        author="Department of General Medicine",
    )

    story = []

    # ── TITLE BLOCK ──────────────────────────────────────────────────────────
    story.append(Spacer(1, 4*mm))
    title_data = [[
        Paragraph("HYPERTENSION", S("t1", fontSize=18, fontName="Helvetica-Bold",
                                    textColor=DARK_BLUE, alignment=TA_CENTER)),
    ],[
        Paragraph("CASE PROFORMA — General Medicine (MBBS)", S("t2", fontSize=11,
                  fontName="Helvetica", textColor=MED_BLUE, alignment=TA_CENTER)),
    ]]
    tb = Table(title_data, colWidths=[W - 3*cm])
    tb.setStyle(TableStyle([
        ("BACKGROUND",    (0, 0), (-1, -1), LIGHT_BLUE),
        ("TOPPADDING",    (0, 0), (-1, -1), 8),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 8),
        ("ROUNDEDCORNERS", [4]),
    ]))
    story.append(tb)
    story.append(Spacer(1, 6*mm))

    # ── SECTION 1: PATIENT PARTICULARS ──────────────────────────────────────
    story.append(section_header("SECTION 1 : PATIENT PARTICULARS"))

    demo_data = [
        ["Name:", "_" * 35, "IP/OP No.:", "_" * 15],
        ["Age:", "_" * 12, "Sex:", "☐ Male   ☐ Female   ☐ Other"],
        ["Date of Admission:", "_" * 18, "Date of Examination:", "_" * 18],
        ["Ward / Bed No.:", "_" * 18, "Unit:", "_" * 18],
        ["Occupation:", "_" * 22, "Socioeconomic Status:", "☐ Upper  ☐ Middle  ☐ Lower"],
        ["Address:", "_" * 35, "Religion:", "_" * 15],
        ["Informant:", "_" * 22, "Reliability:", "☐ Good  ☐ Fair  ☐ Poor"],
    ]
    cw = [(W-3*cm)*f for f in [0.14, 0.36, 0.18, 0.32]]
    dt = Table(demo_data, colWidths=cw)
    dt.setStyle(TableStyle([
        ("FONTSIZE",      (0, 0), (-1, -1), 9),
        ("FONTNAME",      (0, 0), (0, -1), "Helvetica-Bold"),
        ("FONTNAME",      (0, 0), (2, -1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0, 0), (0, -1), DARK_BLUE),
        ("TEXTCOLOR",     (2, 0), (2, -1), DARK_BLUE),
        ("TEXTCOLOR",     (1, 0), (1, -1), LINE_GREY),
        ("TOPPADDING",    (0, 0), (-1, -1), 5),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING",   (0, 0), (-1, -1), 3),
        ("BACKGROUND",    (0, 0), (-1, -1), GREY_BG),
        ("ROWBACKGROUNDS",(0, 0), (-1, -1), [WHITE, GREY_BG]),
    ]))
    story.append(dt)
    story.append(Spacer(1, 4*mm))

    # ── SECTION 2: CHIEF COMPLAINTS ─────────────────────────────────────────
    story.append(section_header("SECTION 2 : CHIEF COMPLAINTS"))
    story.append(Paragraph(
        "List complaints in chronological order with duration:", SMALL))
    story.append(Spacer(1, 2*mm))

    cc_data = [["No.", "Complaint", "Duration"]]
    for i in range(1, 7):
        cc_data.append([str(i), "_" * 45, "_" * 15])
    cct = Table(cc_data, colWidths=[(W-3*cm)*f for f in [0.07, 0.72, 0.21]])
    cct.setStyle(TableStyle([
        ("BACKGROUND",    (0, 0), (-1, 0), DARK_BLUE),
        ("TEXTCOLOR",     (0, 0), (-1, 0), WHITE),
        ("FONTNAME",      (0, 0), (-1, 0), "Helvetica-Bold"),
        ("FONTSIZE",      (0, 0), (-1, -1), 9),
        ("ROWBACKGROUNDS",(0, 1), (-1, -1), [WHITE, GREY_BG]),
        ("GRID",          (0, 0), (-1, -1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0, 0), (-1, -1), 5),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING",   (0, 0), (-1, -1), 6),
        ("ALIGN",         (0, 0), (0, -1), "CENTER"),
        ("TEXTCOLOR",     (1, 1), (1, -1), LINE_GREY),
        ("TEXTCOLOR",     (2, 1), (2, -1), LINE_GREY),
    ]))
    story.append(cct)
    story.append(Spacer(1, 4*mm))

    # ── SECTION 3: HISTORY OF PRESENT ILLNESS ───────────────────────────────
    story.append(section_header("SECTION 3 : HISTORY OF PRESENT ILLNESS"))

    story.append(Paragraph(
        "<b>A. Onset of Hypertension</b>", SUBSEC))
    hpi1 = [
        ["Age at diagnosis:", "_" * 20, "Known HTN since:", "_" * 18],
        ["Incidental finding (asymptomatic):", "☐ Yes  ☐ No",
         "Symptomatic at diagnosis:", "☐ Yes  ☐ No"],
    ]
    cw4 = [(W-3*cm)*f for f in [0.22, 0.28, 0.22, 0.28]]
    t1 = Table(hpi1, colWidths=cw4)
    t1.setStyle(TableStyle([
        ("FONTSIZE",  (0,0),(-1,-1), 9),
        ("FONTNAME",  (0,0),(0,-1), "Helvetica-Bold"),
        ("FONTNAME",  (2,0),(2,-1), "Helvetica-Bold"),
        ("TEXTCOLOR", (0,0),(0,-1), DARK_BLUE),
        ("TEXTCOLOR", (2,0),(2,-1), DARK_BLUE),
        ("TEXTCOLOR", (1,0),(1,-1), LINE_GREY),
        ("TOPPADDING",(0,0),(-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
        ("ROWBACKGROUNDS",(0,0),(-1,-1),[WHITE, GREY_BG]),
    ]))
    story.append(t1)
    story.append(Spacer(1, 3*mm))

    story.append(Paragraph("<b>B. Current Symptoms - Tick all that apply</b>", SUBSEC))
    sym_data = [
        ["Headache (occipital)", "Blurred vision / Visual disturbance",
         "Chest pain / Angina", "Palpitations"],
        ["Breathlessness (grade:", "Dizziness / Giddiness",
         "Epistaxis", "Facial flushing"],
        ["Nocturia / Polyuria", "Leg swelling / Oedema",
         "Weakness / Fatigue", "Tinnitus"],
        ["Haematuria", "Decreased urine output", "Claudication (leg pain on walking)",
         "Facial / limb numbness"],
        ["Seizures", "Altered consciousness", "Neck stiffness", "Vomiting"],
    ]
    sym_flat = [item for row in sym_data for item in row]
    story.append(checkbox_row(sym_flat, cols=4))
    story.append(Spacer(1, 2*mm))
    story.append(field_row("Duration of current episode:", 1))
    story.append(Spacer(1, 2*mm))
    story.append(Paragraph("<b>Additional details of presenting complaint:</b>", SUBSEC))
    for _ in range(3):
        story.append(field_row("", 1, label_width=0.5*cm))
    story.append(Spacer(1, 4*mm))

    story.append(Paragraph("<b>C. Drug History (current antihypertensives)</b>", SUBSEC))
    drug_data = [["Drug Name", "Dose", "Frequency", "Duration", "Compliance"]]
    for _ in range(5):
        drug_data.append(["_"*20, "_"*10, "_"*12, "_"*10, "☐ Regular  ☐ Irregular"])
    cwd = [(W-3*cm)*f for f in [0.27, 0.13, 0.17, 0.13, 0.30]]
    dt2 = Table(drug_data, colWidths=cwd)
    dt2.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), DARK_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 5),
        ("BOTTOMPADDING", (0,0),(-1,-1), 5),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("TEXTCOLOR",     (0,1),(-1,-1), LINE_GREY),
    ]))
    story.append(dt2)
    story.append(Spacer(1, 2*mm))
    story.append(field_row("Other medications (NSAIDs / OCP / steroids / decongestants):", 1, label_width=9*cm))
    story.append(Spacer(1, 4*mm))

    # ── SECTION 4: PAST HISTORY ──────────────────────────────────────────────
    story.append(section_header("SECTION 4 : PAST HISTORY"))

    past_items_l = [
        "Diabetes Mellitus       Type: _____  Since: ___",
        "Coronary Artery Disease  Since: ______",
        "Previous MI / Stent / CABG",
        "Stroke / TIA  When: ____________",
        "CKD / Renal Disease  Stage: _____",
        "Hyperlipidaemia",
        "Thyroid Disorder",
        "Sleep Apnoea",
    ]
    past_items_r = [
        "Peripheral Arterial Disease",
        "Atrial Fibrillation",
        "Heart Failure  (HFrEF / HFpEF)",
        "Aortic Aneurysm",
        "Pheochromocytoma / Conn's",
        "Previous surgery",
        "Hospitalisation (reason): ________",
        "Retinopathy Grade: ___________",
    ]
    story.append(two_col_checklist(past_items_l, past_items_r,
                                   "Cardiovascular / Metabolic", "Other Comorbidities"))
    story.append(Spacer(1, 4*mm))

    # ── SECTION 5: FAMILY HISTORY ────────────────────────────────────────────
    story.append(section_header("SECTION 5 : FAMILY HISTORY"))
    fam = [
        ["Condition", "Father", "Mother", "Sibling(s)", "Maternal Grand", "Paternal Grand"],
        ["Hypertension",     "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No"],
        ["Diabetes Mellitus","☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No"],
        ["Heart Disease",    "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No"],
        ["Stroke / CVA",     "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No"],
        ["Renal Disease",    "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No", "☐ Yes  ☐ No"],
    ]
    cwf = [(W-3*cm)*f for f in [0.22, 0.155, 0.155, 0.155, 0.155, 0.16]]
    ft = Table(fam, colWidths=cwf)
    ft.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), DARK_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("ALIGN",         (1,0),(-1,-1), "CENTER"),
    ]))
    story.append(ft)
    story.append(Spacer(1, 2*mm))
    story.append(field_row("Family history of early CVD (men <55 y, women <65 y):", 1, label_width=9*cm))
    story.append(Spacer(1, 4*mm))

    # ── SECTION 6: PERSONAL / SOCIAL HISTORY ────────────────────────────────
    story.append(section_header("SECTION 6 : PERSONAL / SOCIAL HISTORY"))

    social_data = [
        ["Smoking:", "☐ Never   ☐ Current   ☐ Ex-smoker",
         "Pack-years:", "_________"],
        ["Alcohol:", "☐ Never   ☐ Occasional   ☐ Regular   ☐ Binge",
         "Units/week:", "_________"],
        ["Tobacco (chewing):", "☐ Never   ☐ Current   ☐ Former",
         "Duration:", "_________"],
        ["Diet:", "☐ Vegetarian   ☐ Non-vegetarian",
         "Salt intake:", "☐ High  ☐ Normal  ☐ Restricted"],
        ["Physical activity:", "☐ Sedentary   ☐ Moderate   ☐ Active",
         "BMI category:", "☐ Normal  ☐ Overweight  ☐ Obese"],
        ["Stress level:", "☐ Low   ☐ Moderate   ☐ High",
         "Sleep (hrs/night):", "_________"],
    ]
    soc_t = Table(social_data, colWidths=[(W-3*cm)*f for f in [0.18, 0.40, 0.14, 0.28]])
    soc_t.setStyle(TableStyle([
        ("FONTSIZE",      (0,0),(-1,-1), 9),
        ("FONTNAME",      (0,0),(0,-1), "Helvetica-Bold"),
        ("FONTNAME",      (2,0),(2,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,0),(0,-1), DARK_BLUE),
        ("TEXTCOLOR",     (2,0),(2,-1), DARK_BLUE),
        ("TOPPADDING",    (0,0),(-1,-1), 5),
        ("BOTTOMPADDING", (0,0),(-1,-1), 5),
        ("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.3, LINE_GREY),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
    ]))
    story.append(soc_t)
    story.append(Spacer(1, 4*mm))

    # ── SECTION 7: GENERAL PHYSICAL EXAMINATION ─────────────────────────────
    story.append(section_header("SECTION 7 : GENERAL PHYSICAL EXAMINATION"))

    story.append(Paragraph("<b>A. Vital Signs</b>", SUBSEC))
    vs_data = [
        ["Blood Pressure", "Right Arm (Sitting):", "____/____  mmHg",
         "Left Arm (Sitting):", "____/____  mmHg"],
        ["", "Right Arm (Standing):", "____/____  mmHg",
         "Right Arm (Supine):", "____/____  mmHg"],
        ["", "Pulse Pressure:", "_____  mmHg",
         "Mean Arterial Pressure:", "_____  mmHg"],
        ["Pulse Rate", "Rate:", "_____ bpm",
         "Rhythm:", "☐ Regular  ☐ Irregular"],
        ["", "Character:", "____________________",
         "Volume:", "☐ Normal  ☐ Raised  ☐ Reduced"],
        ["Respiratory Rate", "_____ /min", "",
         "Temperature:", "_____°F / °C"],
        ["SpO2", "_____%  (Room air / O2)", "",
         "Height:", "_____ cm"],
        ["Weight", "_____ kg",  "",
         "BMI:", "_____ kg/m²"],
        ["Waist Circumference", "_____ cm", "",
         "Waist-Hip Ratio:", "_____"],
    ]
    vs_t = Table(vs_data, colWidths=[(W-3*cm)*f for f in [0.19, 0.22, 0.22, 0.2, 0.17]])
    vs_t.setStyle(TableStyle([
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("FONTNAME",      (0,0),(0,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,0),(0,-1), DARK_BLUE),
        ("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.3, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("TEXTCOLOR",     (2,0),(-1,-1), LINE_GREY),
        ("SPAN",          (0,0),(0,2)),  # BP spans 3 rows
        ("SPAN",          (0,3),(0,4)),  # Pulse spans 2 rows
        ("VALIGN",        (0,0),(-1,-1), "MIDDLE"),
    ]))
    story.append(vs_t)
    story.append(Spacer(1, 3*mm))

    story.append(Paragraph("<b>B. General Appearance</b>", SUBSEC))
    gen_items = [
        "Conscious & oriented", "Cooperative", "Pallor", "Icterus",
        "Cyanosis (central / peripheral)", "Clubbing", "Lymphadenopathy",
        "Pedal oedema (Grade: ____)", "Raised JVP", "Xanthelasma / Xanthoma",
        "Cushingoid facies", "Acromegalic features",
    ]
    story.append(checkbox_row(gen_items, cols=4))
    story.append(Spacer(1, 2*mm))
    story.append(field_row("Other findings:", 1))
    story.append(Spacer(1, 4*mm))

    # ── SECTION 8: SYSTEMIC EXAMINATION ─────────────────────────────────────
    story.append(section_header("SECTION 8 : SYSTEMIC EXAMINATION"))

    # Cardiovascular
    story.append(Paragraph("<b>A. Cardiovascular System</b>", SUBSEC))
    cvs_data = [
        ["Apex Beat:", "Position: ____________", "Character: ____________",
         "Forceful: ☐ Yes  ☐ No"],
        ["Heart Sounds:", "S1: ☐ N  ☐ Loud  ☐ Soft",
         "S2: ☐ N  ☐ A2>P2  ☐ P2>A2", "S3/S4: ☐ Present  ☐ Absent"],
        ["Murmurs:", "☐ Absent", "☐ Present - Site: _________",
         "Grade: ___  Radiation: _________"],
        ["Peripheral Pulses:", "Radial: ☐ Present  ☐ Absent",
         "Femoral: ☐ Present  ☐ Absent", "Dorsalis pedis: ☐ P  ☐ A"],
        ["Radio-femoral delay:", "☐ Present  ☐ Absent", "Bruit:", "☐ Carotid  ☐ Renal  ☐ None"],
    ]
    cvs_t = Table(cvs_data, colWidths=[(W-3*cm)*f for f in [0.19, 0.27, 0.27, 0.27]])
    cvs_t.setStyle(TableStyle([
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("FONTNAME",      (0,0),(0,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,0),(0,-1), DARK_BLUE),
        ("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.3, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
    ]))
    story.append(cvs_t)
    story.append(Spacer(1, 3*mm))

    # Respiratory
    story.append(Paragraph("<b>B. Respiratory System</b>", SUBSEC))
    story.append(checkbox_row([
        "Air entry equal bilaterally", "Wheeze", "Crepitations",
        "Pleural effusion (R / L)", "Normal vesicular breath sounds", "Rhonchi"], cols=3))
    story.append(field_row("Additional findings:", 1))
    story.append(Spacer(1, 3*mm))

    # Abdomen
    story.append(Paragraph("<b>C. Abdomen</b>", SUBSEC))
    abd_items = [
        "Liver: palpable ___ cm / not palpable",
        "Spleen: palpable / not palpable",
        "Kidneys: ballotable (R / L) / not palpable",
        "Renal bruit: ☐ Present  ☐ Absent",
        "Ascites: ☐ Present  ☐ Absent",
        "Abdominal aortic pulsation: ☐ Normal  ☐ Expansile",
    ]
    story.append(checkbox_row(abd_items, cols=2))
    story.append(Spacer(1, 3*mm))

    # Neurological
    story.append(Paragraph("<b>D. Neurological System</b>", SUBSEC))
    neuro_data = [
        ["Higher functions:", "☐ Normal  ☐ Impaired",
         "Speech:", "☐ Normal  ☐ Dysarthria  ☐ Aphasia"],
        ["Cranial nerves:", "☐ Intact  ☐ Deficit (specify: _______)",
         "Pupils:", "☐ Equal  ☐ Unequal  ☐ Reacting"],
        ["Power (UL):", "R: ___/5  L: ___/5",
         "Power (LL):", "R: ___/5  L: ___/5"],
        ["Reflexes:", "☐ Normal  ☐ Brisk  ☐ Absent",
         "Plantar:", "☐ Flexor  ☐ Extensor  ☐ Equivocal"],
        ["Sensory:", "☐ Normal  ☐ Reduced", "Coordination:", "☐ Normal  ☐ Ataxia"],
        ["Fundoscopy:", "☐ Normal  Grade: ___  ☐ Papilloedema  ☐ Flame haemorrhages  ☐ Exudates  ☐ AV nipping", "", ""],
    ]
    neuro_t = Table(neuro_data, colWidths=[(W-3*cm)*f for f in [0.15, 0.35, 0.15, 0.35]])
    neuro_t.setStyle(TableStyle([
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("FONTNAME",      (0,0),(0,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,0),(0,-1), DARK_BLUE),
        ("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.3, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("SPAN",          (1,5),(3,5)),
    ]))
    story.append(neuro_t)
    story.append(Spacer(1, 4*mm))

    # ── SECTION 9: INVESTIGATIONS ────────────────────────────────────────────
    story.append(section_header("SECTION 9 : INVESTIGATIONS"))

    # Routine
    story.append(Paragraph("<b>A. Routine / Baseline Investigations</b>", SUBSEC))
    inv_data = [
        ["Investigation", "Result", "Normal Range", "Interpretation"],
        ["Haemoglobin (g/dL)", "", "M: 13-17  F: 12-15", ""],
        ["Total WBC (cells/µL)", "", "4,000-11,000", ""],
        ["Platelet Count (lakh/µL)", "", "1.5-4.5", ""],
        ["Fasting Blood Glucose (mg/dL)", "", "70-100", ""],
        ["HbA1c (%)", "", "< 5.7 normal", ""],
        ["Serum Creatinine (mg/dL)", "", "M:0.7-1.3  F:0.5-1.1", ""],
        ["eGFR (mL/min/1.73m²)", "", "> 60 normal", ""],
        ["Blood Urea (mg/dL)", "", "7-20", ""],
        ["Serum Sodium (mEq/L)", "", "135-145", ""],
        ["Serum Potassium (mEq/L)", "", "3.5-5.0", ""],
        ["Serum Calcium (mg/dL)", "", "8.5-10.5", ""],
        ["Uric Acid (mg/dL)", "", "M:3.5-7.2  F:2.6-6.0", ""],
        ["Total Cholesterol (mg/dL)", "", "< 200 desirable", ""],
        ["LDL (mg/dL)", "", "< 100 optimal", ""],
        ["HDL (mg/dL)", "", "M:> 40  F:> 50", ""],
        ["Triglycerides (mg/dL)", "", "< 150", ""],
        ["TSH (mIU/L)", "", "0.5-4.5", ""],
        ["Urine Albumin-Creatinine Ratio", "", "< 30 normal", ""],
        ["Urine Routine & Microscopy", "", "No RBC/protein/casts", ""],
    ]
    cw_inv = [(W-3*cm)*f for f in [0.35, 0.22, 0.23, 0.20]]
    inv_t = Table(inv_data, colWidths=cw_inv)
    inv_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), DARK_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("ALIGN",         (2,0),(-1,-1), "CENTER"),
    ]))
    story.append(inv_t)
    story.append(Spacer(1, 3*mm))

    # Special investigations
    story.append(Paragraph("<b>B. Cardiac & Imaging Investigations</b>", SUBSEC))
    card_inv = [
        ["ECG findings:", "____________________________________________________________________"],
        ["Chest X-ray:", "☐ Cardiomegaly  ☐ Pulmonary oedema  ☐ Rib notching  ☐ Normal"],
        ["2D Echo findings:", "____________________________________________________________________"],
        ["LV mass index:", "_______  g/m²  (Normal: M<115, F<95)"],
        ["EF (%):", "_______  ☐ Normal (>55%)  ☐ Reduced  ☐ Preserved"],
        ["Renal USG:", "R kidney: ___cm  L kidney: ___cm  Cortical thickness: ___cm"],
        ["Renal Doppler:", "☐ Normal  ☐ Renal artery stenosis  ☐ Increased RI"],
        ["CT / MRI Brain:", "☐ Normal  ☐ Lacunar infarcts  ☐ Haemorrhage  ☐ WMC"],
        ["24-hr Ambulatory BP:", "Daytime avg: ____/____  Night avg: ____/____  Dipping: ☐ Yes  ☐ No"],
    ]
    cw_c = [(W-3*cm)*f for f in [0.25, 0.75]]
    card_t = Table(card_inv, colWidths=cw_c)
    card_t.setStyle(TableStyle([
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("FONTNAME",      (0,0),(0,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,0),(0,-1), DARK_BLUE),
        ("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.3, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("TEXTCOLOR",     (1,0),(-1,-1), LINE_GREY),
    ]))
    story.append(card_t)
    story.append(Spacer(1, 3*mm))

    # Secondary HTN workup
    story.append(Paragraph("<b>C. Secondary Hypertension Workup (if indicated)</b>", SUBSEC))
    sec_inv = [
        ["Plasma renin activity:", "_____________",
         "Serum aldosterone:", "_____________"],
        ["Aldosterone/Renin ratio:", "_____________",
         "24-hr urine catecholamines:", "_____________"],
        ["24-hr urine VMA:", "_____________",
         "Plasma metanephrines:", "_____________"],
        ["Serum cortisol (AM):", "_____________",
         "Overnight dex. suppression:", "_____________"],
        ["CT Adrenals:", "__________________________",
         "MRI Pituitary:", "__________________________"],
        ["Sleep study (AHI):", "_____________",
         "Thyroid function:", "_____________"],
        ["MIBG scan:", "_____________",
         "Renal artery angiogram:", "_____________"],
    ]
    sec_t = Table(sec_inv, colWidths=[(W-3*cm)*f for f in [0.22, 0.28, 0.22, 0.28]])
    sec_t.setStyle(TableStyle([
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("FONTNAME",      (0,0),(0,-1), "Helvetica-Bold"),
        ("FONTNAME",      (2,0),(2,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,0),(0,-1), DARK_BLUE),
        ("TEXTCOLOR",     (2,0),(2,-1), DARK_BLUE),
        ("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.3, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("TEXTCOLOR",     (1,0),(1,-1), LINE_GREY),
        ("TEXTCOLOR",     (3,0),(3,-1), LINE_GREY),
    ]))
    story.append(sec_t)
    story.append(Spacer(1, 4*mm))

    # ── SECTION 10: BP CLASSIFICATION ───────────────────────────────────────
    story.append(section_header("SECTION 10 : BP CLASSIFICATION (ACC/AHA 2017)"))
    story.append(bp_table())
    story.append(Spacer(1, 2*mm))
    story.append(Paragraph(
        "<b>Patient's BP stage:</b> ☐ Normal   ☐ Elevated   ☐ Stage 1 HTN   "
        "☐ Stage 2 HTN   ☐ Hypertensive Urgency   ☐ Hypertensive Emergency",
        BODY))
    story.append(Spacer(1, 2*mm))
    story.append(Paragraph(
        "<b>Type:</b> ☐ Primary (Essential)   ☐ Secondary (cause: ___________________)   "
        "☐ Isolated Systolic   ☐ Isolated Diastolic   ☐ White-coat HTN",
        BODY))
    story.append(Spacer(1, 4*mm))

    # ── SECTION 11: TARGET ORGAN DAMAGE ─────────────────────────────────────
    story.append(section_header("SECTION 11 : TARGET ORGAN DAMAGE ASSESSMENT"))

    tod_data = [
        ["Organ", "Evidence of Damage", "Severity"],
        ["Heart",
         "☐ LVH on ECG/Echo  ☐ HF  ☐ CAD  ☐ AF  ☐ None",
         "☐ Mild  ☐ Mod  ☐ Severe"],
        ["Brain",
         "☐ Stroke/TIA  ☐ Lacunar infarcts  ☐ Cognitive impairment  ☐ None",
         "☐ Mild  ☐ Mod  ☐ Severe"],
        ["Kidney",
         "☐ Microalbuminuria  ☐ Proteinuria  ☐ CKD  ☐ None",
         "☐ Mild  ☐ Mod  ☐ Severe"],
        ["Eye",
         "☐ Grade I  ☐ Grade II  ☐ Grade III  ☐ Grade IV retinopathy  ☐ None",
         "☐ Mild  ☐ Mod  ☐ Severe"],
        ["Peripheral Vessels",
         "☐ PAD  ☐ Aortic aneurysm  ☐ Carotid plaque  ☐ None",
         "☐ Mild  ☐ Mod  ☐ Severe"],
    ]
    tod_cw = [(W-3*cm)*f for f in [0.15, 0.65, 0.20]]
    tod_t = Table(tod_data, colWidths=tod_cw)
    tod_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), DARK_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 5),
        ("BOTTOMPADDING", (0,0),(-1,-1), 5),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
    ]))
    story.append(tod_t)
    story.append(Spacer(1, 4*mm))

    # ── SECTION 12: CARDIOVASCULAR RISK STRATIFICATION ──────────────────────
    story.append(section_header("SECTION 12 : CARDIOVASCULAR RISK STRATIFICATION"))

    story.append(Paragraph("<b>Risk Factors Present:</b>", SUBSEC))
    rf_items = [
        "Age ≥ 55 y (Male) / ≥ 65 y (Female)",
        "Smoking",
        "Dyslipidaemia (LDL > 130 or HDL low)",
        "Diabetes Mellitus",
        "Family history of premature CVD",
        "Obesity (BMI ≥ 30)",
        "Sedentary lifestyle",
        "hs-CRP > 2 mg/L",
        "Metabolic syndrome",
        "Microalbuminuria / CKD Stage G3+",
    ]
    story.append(checkbox_row(rf_items, cols=2))
    story.append(Spacer(1, 2*mm))

    risk_strat = [
        ["Risk Category", "Definition", "Patient Qualifies?"],
        ["Low",           "No TOD, no RF, Stage 1 HTN",          "☐"],
        ["Moderate",      "1-2 RF, no TOD, Stage 1-2 HTN",       "☐"],
        ["High",          "≥ 3 RF OR 1 TOD, Stage 1-2 HTN",      "☐"],
        ["Very High",     "Known CVD / DM with TOD / Stage 3 HTN","☐"],
    ]
    rs_t = Table(risk_strat, colWidths=[(W-3*cm)*f for f in [0.18, 0.62, 0.20]])
    rs_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), DARK_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 9),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 5),
        ("BOTTOMPADDING", (0,0),(-1,-1), 5),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("ALIGN",         (2,0),(-1,-1), "CENTER"),
    ]))
    story.append(rs_t)
    story.append(Spacer(1, 4*mm))

    # ── SECTION 13: DIAGNOSIS ────────────────────────────────────────────────
    story.append(section_header("SECTION 13 : DIAGNOSIS"))

    dx_data = [
        ["Primary Diagnosis:", "_______________________________________________"],
        ["Secondary Diagnosis 1:", "_______________________________________________"],
        ["Secondary Diagnosis 2:", "_______________________________________________"],
        ["Complications:", "_______________________________________________"],
        ["Hypertensive Emergency:", "☐ Yes   ☐ No   If yes, type: _____________________"],
    ]
    dx_t = Table(dx_data, colWidths=[(W-3*cm)*f for f in [0.26, 0.74]])
    dx_t.setStyle(TableStyle([
        ("FONTSIZE",      (0,0),(-1,-1), 9),
        ("FONTNAME",      (0,0),(0,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,0),(0,-1), DARK_BLUE),
        ("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.3, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 6),
        ("BOTTOMPADDING", (0,0),(-1,-1), 6),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("TEXTCOLOR",     (1,0),(-1,-1), LINE_GREY),
    ]))
    story.append(dx_t)
    story.append(Spacer(1, 4*mm))

    # ── SECTION 14: MANAGEMENT PLAN ─────────────────────────────────────────
    story.append(section_header("SECTION 14 : MANAGEMENT PLAN"))

    story.append(Paragraph("<b>A. Non-Pharmacological (Lifestyle Modifications)</b>", SUBSEC))
    nlm_items = [
        "Weight reduction (target BMI < 25 kg/m²)",
        "DASH diet / reduce saturated fat",
        "Restrict sodium (< 2.3 g/day NaCl)",
        "Increase potassium intake (diet)",
        "Regular aerobic exercise (150 min/week)",
        "Stop smoking / cessation counselling",
        "Reduce alcohol (< 2 units/day)",
        "Stress reduction / relaxation",
        "Sleep hygiene (target 7-8 hrs)",
        "Home BP monitoring education",
    ]
    story.append(checkbox_row(nlm_items, cols=2))
    story.append(Spacer(1, 3*mm))

    story.append(Paragraph("<b>B. Pharmacological Treatment</b>", SUBSEC))
    story.append(Paragraph(
        "<i>First-line agents: ACE inhibitors, ARBs, CCBs, Thiazide diuretics. "
        "Beta-blockers for specific indications (CHF, post-MI, AF rate control).</i>", SMALL))
    story.append(Spacer(1, 2*mm))

    rx_data = [["Drug", "Class", "Dose", "Frequency", "Indication / Rationale", "Precaution"]]
    for _ in range(6):
        rx_data.append(["", "", "", "", "", ""])
    rx_cw = [(W-3*cm)*f for f in [0.18, 0.15, 0.12, 0.12, 0.27, 0.16]]
    rx_t = Table(rx_data, colWidths=rx_cw)
    rx_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), DARK_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 10),
        ("BOTTOMPADDING", (0,0),(-1,-1), 10),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
    ]))
    story.append(rx_t)
    story.append(Spacer(1, 3*mm))

    story.append(Paragraph("<b>C. Target BP Goals</b>", SUBSEC))
    goal_data = [
        ["Patient Profile", "Target BP", "Evidence Base"],
        ["General HTN (< 65 y)", "< 130/80 mmHg", "ACC/AHA 2017"],
        ["Elderly (≥ 65 y)", "< 130/80 mmHg (SBP)", "SPRINT trial"],
        ["HTN + Diabetes", "< 130/80 mmHg", "ADA Standards 2024"],
        ["HTN + CKD (non-DM)", "< 130/80 mmHg", "KDIGO 2021"],
        ["HTN + CKD + Proteinuria", "< 130/80 mmHg (ACE/ARB preferred)", "KDIGO 2021"],
        ["HTN + CAD / Post-MI", "< 130/80 mmHg", "ACC/AHA 2017"],
        ["Hypertensive Emergency", "Reduce MAP by 25% in 1 hr, then 160/100 over 2-6 hr", "ESC 2018"],
    ]
    goal_cw = [(W-3*cm)*f for f in [0.37, 0.30, 0.33]]
    goal_t = Table(goal_data, colWidths=goal_cw)
    goal_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), MED_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
    ]))
    story.append(goal_t)
    story.append(Spacer(1, 4*mm))

    # ── SECTION 15: PROGRESS NOTES ──────────────────────────────────────────
    story.append(section_header("SECTION 15 : DAILY PROGRESS NOTES"))
    prog_data = [["Date", "BP (mmHg)", "PR (/min)", "Symptoms", "Assessment", "Plan / Changes"]]
    for _ in range(6):
        prog_data.append(["", "", "", "", "", ""])
    prog_cw = [(W-3*cm)*f for f in [0.13, 0.15, 0.12, 0.20, 0.20, 0.20]]
    prog_t = Table(prog_data, colWidths=prog_cw)
    prog_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), DARK_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 18),
        ("BOTTOMPADDING", (0,0),(-1,-1), 18),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
    ]))
    story.append(prog_t)
    story.append(Spacer(1, 4*mm))

    # ── SECTION 16: DISCHARGE SUMMARY ───────────────────────────────────────
    story.append(section_header("SECTION 16 : DISCHARGE SUMMARY"))

    disc_data = [
        ["Date of Admission:", "_____________", "Date of Discharge:", "_____________"],
        ["Duration of Stay:", "_____________", "Condition at Discharge:",
         "☐ Improved  ☐ Stable  ☐ Same  ☐ DAMA"],
        ["Discharge BP:", "____/____  mmHg", "Discharge HR:", "_____ bpm"],
        ["Final Diagnosis:", "_____________________________",
         "ICD-10 Code:", "___________"],
    ]
    disc_t = Table(disc_data, colWidths=[(W-3*cm)*f for f in [0.20, 0.30, 0.22, 0.28]])
    disc_t.setStyle(TableStyle([
        ("FONTSIZE",      (0,0),(-1,-1), 9),
        ("FONTNAME",      (0,0),(0,-1), "Helvetica-Bold"),
        ("FONTNAME",      (2,0),(2,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,0),(0,-1), DARK_BLUE),
        ("TEXTCOLOR",     (2,0),(2,-1), DARK_BLUE),
        ("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.3, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 5),
        ("BOTTOMPADDING", (0,0),(-1,-1), 5),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("TEXTCOLOR",     (1,0),(-1,-1), LINE_GREY),
    ]))
    story.append(disc_t)
    story.append(Spacer(1, 3*mm))

    story.append(Paragraph("<b>Discharge Medications:</b>", SUBSEC))
    disc_rx = [["Drug", "Dose", "Frequency", "Duration", "Special Instructions"]]
    for _ in range(5):
        disc_rx.append(["", "", "", "", ""])
    disc_rx_cw = [(W-3*cm)*f for f in [0.25, 0.15, 0.15, 0.15, 0.30]]
    disc_rx_t = Table(disc_rx, colWidths=disc_rx_cw)
    disc_rx_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), DARK_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 10),
        ("BOTTOMPADDING", (0,0),(-1,-1), 10),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
    ]))
    story.append(disc_rx_t)
    story.append(Spacer(1, 3*mm))

    story.append(Paragraph("<b>Follow-up Instructions:</b>", SUBSEC))
    fu_items = [
        "Review in OPD in _____ days / weeks",
        "Repeat BP check in _____ days",
        "Repeat labs: ______________________",
        "Ambulatory BP monitoring",
        "Ophthalmology review",
        "Nephrology referral",
        "Cardiology referral",
        "ECHO review in _____ months",
    ]
    story.append(checkbox_row(fu_items, cols=2))
    story.append(Spacer(1, 3*mm))
    story.append(field_row("Patient education given on:", 1))
    story.append(Spacer(1, 4*mm))

    # ── SECTION 17: SIGNATURES ───────────────────────────────────────────────
    story.append(section_header("SECTION 17 : SIGNATURES"))

    sig_data = [
        ["Student Name:", "_________________________",
         "Roll No.:", "_____________"],
        ["Signature:", "_________________________",
         "Date:", "_____________"],
        ["", "", "", ""],
        ["Resident / PG Signature:", "_________________________",
         "Date:", "_____________"],
        ["Consultant Signature:", "_________________________",
         "Date:", "_____________"],
        ["Unit Chief / HOD Signature:", "_________________________",
         "Stamp:", "_____________"],
    ]
    sig_t = Table(sig_data, colWidths=[(W-3*cm)*f for f in [0.25, 0.35, 0.14, 0.26]])
    sig_t.setStyle(TableStyle([
        ("FONTSIZE",      (0,0),(-1,-1), 9),
        ("FONTNAME",      (0,0),(0,-1), "Helvetica-Bold"),
        ("FONTNAME",      (2,0),(2,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,0),(0,-1), DARK_BLUE),
        ("TEXTCOLOR",     (2,0),(2,-1), DARK_BLUE),
        ("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, GREY_BG]),
        ("TOPPADDING",    (0,0),(-1,-1), 8),
        ("BOTTOMPADDING", (0,0),(-1,-1), 8),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("TEXTCOLOR",     (1,0),(-1,-1), LINE_GREY),
        ("LINEBELOW",     (0,-1),(-1,-1), 0.5, LINE_GREY),
    ]))
    story.append(sig_t)
    story.append(Spacer(1, 4*mm))

    # ── APPENDIX: HYPERTENSION QUICK REFERENCE ──────────────────────────────
    story.append(section_header("APPENDIX : QUICK REFERENCE - ANTIHYPERTENSIVE DRUG CLASSES"))

    drug_ref = [
        ["Class", "Prototype Drug(s)", "Compelling Indications", "Contraindications / Cautions"],
        ["ACE Inhibitors\n(ACEi)", "Enalapril, Ramipril,\nLisinopril",
         "DM, CKD proteinuria,\nHF, post-MI, LVD",
         "Bilateral RAS, Pregnancy,\nHyperkalaemia, Angioedema Hx"],
        ["ARBs", "Losartan, Valsartan,\nTelmisartan",
         "ACEi intolerant, DM,\nCKD, HF",
         "Bilateral RAS, Pregnancy,\nHyperkalaemia"],
        ["CCBs\n(Dihydropyridine)", "Amlodipine, Nifedipine",
         "Elderly ISH, Angina,\nAfro-Caribbean patients",
         "Severe aortic stenosis\n(caution)"],
        ["CCBs\n(Non-DHP)", "Diltiazem, Verapamil",
         "Angina, AF rate control,\nSVT",
         "Heart failure (EF reduced),\nAV block, Bradycardia"],
        ["Thiazide Diuretics", "Hydrochlorothiazide,\nChlorthalidone, Indapamide",
         "Elderly, ISH,\nOsteoporosis",
         "Gout, Hypokalaemia,\nGlucose intolerance"],
        ["Beta-Blockers", "Atenolol, Metoprolol,\nCarvedilol, Bisoprolol",
         "Post-MI, Angina, HF,\nAF rate control, Pregnancy (labetalol)",
         "Asthma, AV block,\nPeripheral arterial disease"],
        ["Aldosterone Antag.", "Spironolactone,\nEplerenone",
         "Resistant HTN, HF,\nConn's syndrome",
         "Hyperkalaemia, CKD\n(severe), renal failure"],
        ["Alpha-Blockers", "Prazosin, Doxazosin",
         "Resistant HTN,\nBPH, Phaeochromocytoma",
         "Postural hypotension,\n1st dose effect"],
        ["Central Agents", "Methyldopa, Clonidine",
         "Pregnancy (methyldopa)\nRefractory HTN",
         "Depression, Rebound HTN\non withdrawal (clonidine)"],
    ]
    drug_ref_cw = [(W-3*cm)*f for f in [0.18, 0.22, 0.28, 0.32]]
    drug_ref_t = Table(drug_ref, colWidths=drug_ref_cw)
    drug_ref_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), DARK_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 8),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
        ("FONTNAME",      (0,1),(0,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,1),(0,-1), MED_BLUE),
    ]))
    story.append(drug_ref_t)
    story.append(Spacer(1, 3*mm))

    # Keith-Wagener-Barker Fundoscopy grading
    story.append(Paragraph("<b>Keith-Wagener-Barker Fundoscopy Grading:</b>", SUBSEC))
    kwb = [
        ["Grade", "Features"],
        ["Grade I",  "Mild narrowing / tortuosity of arteries, increased light reflex (copper wire)"],
        ["Grade II", "More severe narrowing, A-V nipping (Gunn's sign), silver wire appearance"],
        ["Grade III","Flame haemorrhages, dot & blot haemorrhages, cotton wool spots (soft exudates)"],
        ["Grade IV", "Grade III features + Papilloedema (bilateral disc oedema)"],
    ]
    kwb_cw = [(W-3*cm)*f for f in [0.10, 0.90]]
    kwb_t = Table(kwb, colWidths=kwb_cw)
    kwb_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), MED_BLUE),
        ("TEXTCOLOR",     (0,0),(-1,0), WHITE),
        ("FONTNAME",      (0,0),(-1,0), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,-1), 8.5),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_BG]),
        ("GRID",          (0,0),(-1,-1), 0.4, LINE_GREY),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
        ("LEFTPADDING",   (0,0),(-1,-1), 5),
        ("FONTNAME",      (0,1),(0,-1), "Helvetica-Bold"),
        ("TEXTCOLOR",     (0,1),(0,-1), ACCENT),
    ]))
    story.append(kwb_t)
    story.append(Spacer(1, 3*mm))

    story.append(Paragraph(
        "<b>References:</b> ACC/AHA 2017 Hypertension Guidelines | "
        "ESC/ESH 2018 HTN Guidelines | JNC 8 | WHO/ISH 2020 | "
        "KDIGO 2021 BP in CKD | ADA Standards of Medical Care 2024",
        SMALL))
    story.append(Spacer(1, 3*mm))
    story.append(HRFlowable(width="100%", thickness=0.5, color=LINE_GREY))
    story.append(Spacer(1, 2*mm))
    story.append(Paragraph(
        "This proforma is intended for academic/educational use. "
        "Clinical decisions must be guided by current institutional protocols and attending physician judgement.",
        NOTE))

    # Build
    doc.build(story, canvasmaker=HeaderFooterCanvas)
    print(f"PDF generated: {OUTPUT_PATH}")


if __name__ == "__main__":
    import os
    os.makedirs("/home/daytona/workspace/hypertension-proforma", exist_ok=True)
    build()
Running Command

cd /home/daytona/workspace/hypertension-proforma && python3 generate_proforma.py 2>&1

Running Command

ls -lh /home/daytona/workspace/hypertension-proforma/Hypertension_Case_Proforma.pdf

Your Hypertension Case Proforma PDF is ready:

Hypertension Case Proforma

PDF Document · PDF


Here is what the proforma covers across 17 sections + Appendix:
SectionContent
1Patient Particulars (demographics, IP/OP No., socioeconomic status)
2Chief Complaints (tabulated with duration)
3History of Present Illness - onset, symptoms checklist, drug history, compliance
4Past History (DM, CAD, MI, stroke, CKD, phaeochromocytoma, etc.)
5Family History (6-generation table for HTN, DM, heart disease, stroke, renal)
6Personal / Social History (smoking, alcohol, diet, exercise, stress)
7General Physical Examination - vital signs (both arms BP), BMI, waist-hip ratio
8Systemic Examination - CVS, respiratory, abdomen, full neurological, fundoscopy
9Investigations - baseline labs (20 parameters), cardiac/imaging, secondary HTN workup
10BP Classification table (ACC/AHA 2017 - Normal to Hypertensive Crisis)
11Target Organ Damage (heart, brain, kidney, eye, peripheral vessels)
12CV Risk Stratification (Low / Moderate / High / Very High)
13Diagnosis block with ICD-10 space
14Management - lifestyle modifications, drug table, target BP goals by comorbidity
15Daily Progress Notes table
16Discharge Summary + discharge medications + follow-up plan
17Signatures (student, resident, consultant, unit chief)
AppendixAntihypertensive drug class quick reference + Keith-Wagener-Barker grading
Guidelines referenced: ACC/AHA 2017, ESC/ESH 2018, KDIGO 2021, ADA 2024, JNC 8, WHO/ISH 2020.
This is a shared conversation. Sign in to Orris to start your own chat.