Causes of blindness and symptoms of eye disorders

Reading File
Finding Sources
Finding Sources
Searching the Web

leading causes of blindness worldwide 2024 WHO

Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Finding Sources
Reading File
Reading File
Loading Image
Finding Sources
Finding Sources
I now have rich material from multiple authoritative sources. Here is a thorough, well-organized answer.

Causes of Blindness and Symptoms of Eye Disorders

Global Overview

As of 2020, approximately 33.6 million people live with blindness worldwide, and over 206 million have moderate-to-severe vision impairment. Cataract and uncorrected refractive error together account for the majority of global blindness. The leading causes differ by country and age group.

Leading Causes of Blindness

1. Cataract

Cataract (clouding of the lens) is responsible for 51% of world blindness according to the WHO and is the single most common cause globally.
Symptoms:
  • Gradual, painless blurring of vision - often worse at night
  • Increased glare and halos around lights
  • Faded or yellowed colors
  • Frequent changes in eyeglass prescription
  • Double vision in one eye
The lens opacity blocks or scatters incoming light. Cataract surgery (lens replacement) is the definitive treatment and is covered by Medicare in the US.
  • Goldman-Cecil Medicine, block 57

2. Glaucoma

Glaucoma is a group of diseases causing optic neuropathy, usually (but not always) associated with elevated intraocular pressure (IOP). It accounts for at least 10% of blindness in the US and is 4x more common in African Americans, who are 8x more likely to go blind from it. The most common form in the US is primary open-angle glaucoma (POAG).
Pathophysiology: Aqueous humor, produced in the ciliary body, normally drains through the trabecular meshwork into Schlemm's canal. When this outflow is obstructed, IOP rises and damages the optic nerve.
Glaucoma - aqueous humor flow and angle-closure mechanisms
Types and symptoms:
TypeSymptoms
Open-angle glaucomaOften silent early; gradual peripheral (tunnel) vision loss; discovered incidentally on tonometry
Angle-closure glaucoma (acute)Sudden severe eye pain, headache, nausea/vomiting, halos around lights, blurred vision, red eye
Neovascular glaucomaSecondary to diabetes/vascular disease; severe vision loss
Steroid-induced glaucomaFollows prolonged corticosteroid eye drops or systemic steroids
Congenital glaucomaEnlarged eyes (buphthalmos), tearing, light sensitivity
The damage to vision caused by glaucoma is irreversible - early detection is key. Treatment includes topical medications (beta-blockers, prostaglandin analogs), laser surgery, and trabeculectomy.
  • Robbins & Kumar Basic Pathology, p. 868-869
  • Textbook of Family Medicine 9e, p. 371-373

3. Age-Related Macular Degeneration (AMD)

AMD is the leading cause of blindness in adults aged 65+ and primarily damages the macula (the central, high-acuity part of the retina).
Types:
  • Dry AMD: Gradual accumulation of drusen (membranous debris) and geographic atrophy of the retinal pigment epithelium
  • Wet AMD: Choroidal neovascularization - fragile new vessels leak and bleed, causing rapid central vision loss
Symptoms:
  • Blurry or distorted central vision (straight lines appear wavy - "metamorphopsia")
  • Dark or empty spot in the center of vision (scotoma)
  • Colors appearing less vivid
  • Difficulty reading or recognizing faces
  • Peripheral vision is preserved - people can still navigate around but cannot see detail
Treatment options include antioxidant vitamins (AREDS formula: vitamins C, E, beta-carotene, zinc), anti-VEGF intravitreal injections (for wet AMD), and laser photocoagulation.
  • Textbook of Family Medicine 9e, pp. 371-372

4. Diabetic Retinopathy (DR)

DR is the most common cause of blindness in Americans aged 20 to 74 years. People with diabetes are at 25 times greater risk of becoming blind compared to non-diabetics.
Mechanism: Chronic hyperglycemia damages retinal blood vessels, leading to progressive leakage, hemorrhage, neovascularization, and eventual traction retinal detachment.
Symptoms (often absent until advanced):
  • Blurred or fluctuating vision
  • Dark spots or floaters
  • Impaired color vision
  • Sudden vision loss (from vitreous hemorrhage)
  • Vision loss in both eyes if advanced
Key point: Macular edema (fluid accumulation at the macula) accounts for most cases of decreased vision in DR, while proliferative DR can cause catastrophic hemorrhage.
  • Goldman-Cecil Medicine, block 57
  • Textbook of Family Medicine 9e, p. 372

5. Refractive Errors

Uncorrected refractive errors (myopia, hyperopia, astigmatism, presbyopia) are the most frequent eye problems in the US and are the second leading cause of global blindness. They are correctable with glasses, contact lenses, or surgery (LASIK, PRK).
Symptoms:
  • Blurred vision at distance (myopia) or near (hyperopia, presbyopia)
  • Eyestrain and headaches
  • Squinting

6. Retinal Vascular Occlusions

Central Retinal Artery Occlusion (CRAO):
  • Sudden, painless, complete unilateral vision loss
  • Signs: cherry-red spot at the macula, pale/edematous retina, narrowed arteries
  • Considered a "stroke of the eye" - ocular emergency
Central Retinal Vein Occlusion:
  • Sudden painless visual loss, often with "blood and thunder" fundus appearance
  • Associated with hypertension and hyperviscosity

7. Retinal Detachment

Symptoms (urgent - requires immediate referral):
  • Sudden increase in floaters
  • Flashing lights (photopsia)
  • A "veil" or "curtain" appearing across the visual field
  • Preceded by posterior vitreous detachment in many cases
Floaters alone are usually benign (from vitreous gel degeneration with aging), but their sudden increase alongside flashes is a red flag for retinal tear or detachment.
  • Textbook of Family Medicine 9e, p. 371

8. Optic Neuritis and Optic Neuropathy

  • Optic neuritis: Inflammation of the optic nerve; painful eye movement, central visual loss; ~75% of women and 34% of men develop multiple sclerosis within 15 years
  • Ischemic optic neuropathy: Sudden painless monocular vision loss; associated with temporal arteritis (GCA) - a medical emergency requiring immediate steroids

9. Infectious Causes

  • Trachoma (Chlamydia trachomatis): Leading infectious cause of blindness globally; causes scarring conjunctivitis and corneal opacity
  • Onchocerciasis ("river blindness"): Onchocerca volvulus microfilariae invade cornea causing "snowflake" keratitis
  • Herpes simplex keratitis: Recurrent infection causes corneal scarring and chronic keratitis
  • Cytomegalovirus (CMV) retinitis: Occurs in immunocompromised patients (HIV/AIDS); causes progressive necrotizing retinitis

10. Other Important Causes

CauseKey Features
Corneal disease/scarringTrauma, infection, chemical burns; corneal transplant may restore vision
Temporal arteritis (GCA)Older adults >50; headache, jaw claudication, elevated ESR/CRP; sudden vision loss
Cortical blindnessBilateral occipital lobe infarcts; can cause complete loss of conscious vision
Amaurosis fugaxTransient monocular blindness from carotid emboli; TIA equivalent - 50% risk of stroke within 1 month
Amblyopia"Lazy eye" - reduced vision from abnormal visual development in childhood
Vitamin A deficiencyCauses night blindness and xerophthalmia; major cause in developing countries
Hereditary retinal dystrophiesRetinitis pigmentosa: progressive peripheral then central loss; night blindness early
Hypertensive retinopathyChronic hypertension causes arteriolar changes; severe cases cause vision loss

Rapid Approach to Sudden Vision Loss

From the Textbook of Family Medicine, four common causes of acute/sudden vision loss follow a useful clinical pattern:
PresentationMost Likely Cause
Painful, with halos, nauseaAcute angle-closure glaucoma
Painless, sudden, monocular (cherry-red spot)Central retinal artery occlusion
Painless, flashes and curtainRetinal detachment
Painless, older adult with headache/jaw painTemporal arteritis / ischemic optic neuropathy

Key Points

  • Globally: Cataract (#1), uncorrected refractive error (#2), glaucoma (#3)
  • In the US (age-related): AMD, cataract, diabetic retinopathy, glaucoma
  • Working-age adults (20-64): Diabetic retinopathy is the leading cause
  • Elderly (65+): AMD is the leading cause
  • Most causes are preventable or treatable if detected early - routine eye screening is essential, especially in diabetics, hypertensives, and those with a family history of glaucoma
Sources: Textbook of Family Medicine 9e | Robbins & Kumar Basic Pathology | Goldman-Cecil Medicine | CDC Vision Health | WHO / Prevent Blindness

Create a clinical decision summary PDF for diagnosing sudden vision loss

Reading File
Reading File
Running Command

ls -la /home/daytona/workspace/ 2>/dev/null || mkdir -p /home/daytona/workspace/

Running Command

mkdir -p /home/daytona/workspace/sudden-vision-loss && python3 -c "import reportlab; print(reportlab.Version)"

Writing File

~/sudden-vision-loss/build_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon, Circle
from reportlab.graphics import renderPDF
from reportlab.graphics.charts.flowcharts import FlowChart
import os

OUTPUT = "/home/daytona/workspace/sudden-vision-loss/Sudden_Vision_Loss_Clinical_Decision_Summary.pdf"

# ── Colour palette ────────────────────────────────────────────────────────────
NAVY      = colors.HexColor("#1A3A5C")
MED_BLUE  = colors.HexColor("#2563A8")
LIGHT_BLUE= colors.HexColor("#EAF2FB")
RED       = colors.HexColor("#C0392B")
RED_BG    = colors.HexColor("#FDEDEC")
ORANGE    = colors.HexColor("#E67E22")
ORANGE_BG = colors.HexColor("#FEF5EC")
GREEN     = colors.HexColor("#1A7A4A")
GREEN_BG  = colors.HexColor("#E9F7EF")
YELLOW_BG = colors.HexColor("#FEFDE7")
GREY      = colors.HexColor("#7F8C8D")
LIGHT_GREY= colors.HexColor("#F4F6F7")
DARK_GREY = colors.HexColor("#2C3E50")
WHITE     = colors.white
BLACK     = colors.HexColor("#1A1A1A")
DIVIDER   = colors.HexColor("#D0D9E4")

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

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

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

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

SECTION_HDR = S("SectionHdr",
    fontName="Helvetica-Bold", fontSize=13, textColor=NAVY,
    leading=18, spaceBefore=10, spaceAfter=4,
    borderPad=4)

SUBSEC_HDR = S("SubsecHdr",
    fontName="Helvetica-Bold", fontSize=10, textColor=MED_BLUE,
    leading=14, spaceBefore=6, spaceAfter=2)

BODY = S("Body",
    fontName="Helvetica", fontSize=9, textColor=BLACK,
    leading=13, spaceAfter=2)

BODY_BOLD = S("BodyBold",
    fontName="Helvetica-Bold", fontSize=9, textColor=BLACK,
    leading=13, spaceAfter=2)

SMALL = S("Small",
    fontName="Helvetica", fontSize=8, textColor=GREY,
    leading=11, spaceAfter=1)

SMALL_BOLD = S("SmallBold",
    fontName="Helvetica-Bold", fontSize=8, textColor=DARK_GREY,
    leading=11)

TABLE_HDR = S("TableHdr",
    fontName="Helvetica-Bold", fontSize=9, textColor=WHITE,
    leading=12, alignment=TA_CENTER)

TABLE_CELL = S("TableCell",
    fontName="Helvetica", fontSize=8.5, textColor=BLACK,
    leading=12)

TABLE_CELL_BOLD = S("TableCellBold",
    fontName="Helvetica-Bold", fontSize=8.5, textColor=BLACK,
    leading=12)

WARNING = S("Warning",
    fontName="Helvetica-Bold", fontSize=9, textColor=RED,
    leading=13)

ALERT_HDR = S("AlertHdr",
    fontName="Helvetica-Bold", fontSize=10, textColor=RED,
    leading=14, spaceBefore=4, spaceAfter=2)

GREEN_HDR = S("GreenHdr",
    fontName="Helvetica-Bold", fontSize=10, textColor=GREEN,
    leading=14, spaceBefore=4, spaceAfter=2)

CAPTION = S("Caption",
    fontName="Helvetica-Oblique", fontSize=7.5, textColor=GREY,
    leading=10, alignment=TA_CENTER)

FOOTER_STYLE = S("Footer",
    fontName="Helvetica", fontSize=7, textColor=GREY,
    leading=10, alignment=TA_CENTER)

# ── Page setup ────────────────────────────────────────────────────────────────
PAGE_W, PAGE_H = A4
L_MARGIN = R_MARGIN = 18*mm
T_MARGIN = 15*mm
B_MARGIN = 18*mm

def header_footer(canvas, doc):
    canvas.saveState()
    # top bar
    canvas.setFillColor(NAVY)
    canvas.rect(0, PAGE_H - 12*mm, PAGE_W, 12*mm, stroke=0, fill=1)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica-Bold", 8)
    canvas.drawString(L_MARGIN, PAGE_H - 8*mm, "CLINICAL DECISION SUMMARY  |  SUDDEN VISION LOSS")
    canvas.setFont("Helvetica", 7)
    canvas.drawRightString(PAGE_W - R_MARGIN, PAGE_H - 8*mm, "For clinical reference only - not a substitute for clinical judgment")
    # bottom bar
    canvas.setFillColor(NAVY)
    canvas.rect(0, 0, PAGE_W, 10*mm, stroke=0, fill=1)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 7)
    canvas.drawString(L_MARGIN, 3.5*mm, "Sources: Textbook of Family Medicine 9e | Goldman-Cecil Medicine | Robbins & Kumar Basic Pathology | Adams & Victor Neurology")
    canvas.drawRightString(PAGE_W - R_MARGIN, 3.5*mm, f"Page {doc.page}")
    canvas.restoreState()

def first_page(canvas, doc):
    canvas.saveState()
    # full-width header banner
    canvas.setFillColor(NAVY)
    canvas.rect(0, PAGE_H - 52*mm, PAGE_W, 52*mm, stroke=0, fill=1)
    # accent stripe
    canvas.setFillColor(MED_BLUE)
    canvas.rect(0, PAGE_H - 53.5*mm, PAGE_W, 1.5*mm, stroke=0, fill=1)
    # footer
    canvas.setFillColor(NAVY)
    canvas.rect(0, 0, PAGE_W, 10*mm, stroke=0, fill=1)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 7)
    canvas.drawString(L_MARGIN, 3.5*mm, "Sources: Textbook of Family Medicine 9e | Goldman-Cecil Medicine | Robbins & Kumar Basic Pathology | Adams & Victor Neurology")
    canvas.drawRightString(PAGE_W - R_MARGIN, 3.5*mm, "Page 1")
    canvas.restoreState()

def later_pages(canvas, doc):
    header_footer(canvas, doc)

# ── Helper: coloured box ──────────────────────────────────────────────────────
def colour_box(content_rows, bg=LIGHT_BLUE, border=MED_BLUE,
               col_widths=None, hdr_row=False):
    """Wrap content in a styled single-column (or multi-column) table."""
    data = [[Paragraph(c, BODY) if isinstance(c, str) else c
             for c in (row if isinstance(row, (list, tuple)) else [row])]
            for row in content_rows]
    col_w = col_widths or [PAGE_W - L_MARGIN - R_MARGIN - 4*mm]
    t = Table(data, colWidths=col_w, hAlign="LEFT")
    style_cmds = [
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("BOX", (0,0), (-1,-1), 0.8, border),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
        ("RIGHTPADDING", (0,0), (-1,-1), 8),
        ("TOPPADDING", (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("ROWBACKGROUNDS", (0,0), (-1,-1), [bg]),
    ]
    if hdr_row:
        style_cmds += [
            ("BACKGROUND", (0,0), (-1,0), border),
            ("TEXTCOLOR", (0,0), (-1,0), WHITE),
        ]
    t.setStyle(TableStyle(style_cmds))
    return t


def section_label(text, colour=NAVY, bg=LIGHT_BLUE):
    d = Drawing(PAGE_W - L_MARGIN - R_MARGIN, 10*mm)
    d.add(Rect(0, 0, PAGE_W - L_MARGIN - R_MARGIN, 10*mm,
               fillColor=bg, strokeColor=colour, strokeWidth=0.5))
    d.add(Rect(0, 0, 4, 10*mm, fillColor=colour, strokeWidth=0))
    d.add(String(10, 3, text,
                 fontName="Helvetica-Bold", fontSize=11, fillColor=colour))
    return d


# ── Build story ───────────────────────────────────────────────────────────────
story = []
FULL_W = PAGE_W - L_MARGIN - R_MARGIN

# ════════════════════════════════════════════════════════════
# PAGE 1 HEADER (drawn by first_page callback, put text on top)
# ════════════════════════════════════════════════════════════
story.append(Spacer(1, 38*mm))   # space below banner

story.append(Paragraph("SUDDEN VISION LOSS", TITLE_STYLE))
story.append(Paragraph("Clinical Decision Summary  |  Rapid Differential Diagnosis & Management", SUBTITLE_STYLE))
story.append(Paragraph("Emergency & Primary Care Reference  |  June 2026", SUBTITLE_STYLE))
story.append(Spacer(1, 8*mm))

# ── Red flag box ─────────────────────────────────────────────
rf_data = [
    [Paragraph("<b>&#9888;  IMMEDIATE OPHTHALMOLOGY REFERRAL REQUIRED for all causes listed below</b>", WARNING)],
    [Paragraph("Sudden vision loss is a medical emergency until proven otherwise. Act within minutes to hours.", BODY)],
]
rf_tbl = Table(rf_data, colWidths=[FULL_W])
rf_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), RED_BG),
    ("BOX", (0,0), (-1,-1), 1.2, RED),
    ("LEFTPADDING", (0,0), (-1,-1), 10),
    ("RIGHTPADDING", (0,0), (-1,-1), 10),
    ("TOPPADDING", (0,0), (-1,-1), 7),
    ("BOTTOMPADDING", (0,0), (-1,-1), 7),
]))
story.append(rf_tbl)
story.append(Spacer(1, 6*mm))

# ── Section 1: Initial Assessment ────────────────────────────
story.append(section_label("1.  INITIAL RAPID ASSESSMENT"))
story.append(Spacer(1, 3*mm))

assess_cols = [FULL_W * 0.48, FULL_W * 0.04, FULL_W * 0.48]

left_assess = [
    Paragraph("<b>History - Key Questions</b>", SUBSEC_HDR),
    Paragraph("&#8226; Onset: seconds / minutes / hours / days?", BODY),
    Paragraph("&#8226; Monocular (one eye) vs. binocular (both eyes)?", BODY),
    Paragraph("&#8226; Painless or painful?", BODY),
    Paragraph("&#8226; Complete loss or partial (quadrant, central, peripheral)?", BODY),
    Paragraph("&#8226; Preceding symptoms: flashes, floaters, curtain, halos?", BODY),
    Paragraph("&#8226; Associated: headache, jaw claudication, diplopia, weakness?", BODY),
    Paragraph("&#8226; PMH: diabetes, hypertension, AF, carotid disease, SLE, HIV?", BODY),
    Paragraph("&#8226; Medications: corticosteroids, hydroxychloroquine, ethambutol?", BODY),
    Paragraph("&#8226; Recent trauma or eye surgery?", BODY),
]

right_assess = [
    Paragraph("<b>Examination - Must-Do Steps</b>", SUBSEC_HDR),
    Paragraph("&#8226; Visual acuity (each eye separately)", BODY),
    Paragraph("&#8226; Visual field confrontation testing", BODY),
    Paragraph("&#8226; Pupillary reactions - check for RAPD (relative afferent pupillary defect)", BODY),
    Paragraph("&#8226; Intraocular pressure (tonometry) - rule out acute glaucoma", BODY),
    Paragraph("&#8226; Slit-lamp exam: anterior chamber, cornea, lens", BODY),
    Paragraph("&#8226; Dilated fundoscopy: disc, vessels, macula, retina", BODY),
    Paragraph("&#8226; Cardiovascular exam: BP, pulse, carotid bruits", BODY),
    Paragraph("&#8226; Temporal artery palpation if age &gt;50", BODY),
]

assess_tbl = Table(
    [[left_assess, Spacer(1,1), right_assess]],
    colWidths=assess_cols
)
assess_tbl.setStyle(TableStyle([
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 0),
    ("RIGHTPADDING", (0,0), (-1,-1), 0),
    ("TOPPADDING", (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(assess_tbl)
story.append(Spacer(1, 5*mm))

# RAPD note
rapd_box = Table([[Paragraph(
    "<b>RAPD (Marcus Gunn pupil):</b> Swinging flashlight test. "
    "Affected pupil dilates when light swings to it. "
    "Indicates unilateral optic nerve or severe retinal disease (optic neuritis, CRAO, ION).",
    BODY)]], colWidths=[FULL_W])
rapd_box.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), YELLOW_BG),
    ("BOX", (0,0), (-1,-1), 0.8, ORANGE),
    ("LEFTPADDING", (0,0), (-1,-1), 9),
    ("RIGHTPADDING", (0,0), (-1,-1), 9),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
]))
story.append(rapd_box)
story.append(Spacer(1, 5*mm))

# ── Section 2: Differential Diagnosis Table ───────────────────
story.append(section_label("2.  DIFFERENTIAL DIAGNOSIS BY PAIN AND LATERALITY"))
story.append(Spacer(1, 3*mm))

# header row
dd_hdr = [
    Paragraph("DIAGNOSIS", TABLE_HDR),
    Paragraph("ONSET", TABLE_HDR),
    Paragraph("PAIN?", TABLE_HDR),
    Paragraph("LATERALITY", TABLE_HDR),
    Paragraph("KEY SYMPTOMS &amp; SIGNS", TABLE_HDR),
    Paragraph("URGENCY", TABLE_HDR),
]

def urg(text, colour):
    return Paragraph(f'<font color="{colour.hexval()}"><b>{text}</b></font>', TABLE_CELL_BOLD)

dd_rows = [
    # Painful causes
    [Paragraph("<b>Acute Angle-Closure Glaucoma</b>", TABLE_CELL_BOLD),
     Paragraph("Minutes", TABLE_CELL),
     Paragraph("YES - severe", TABLE_CELL),
     Paragraph("Unilateral", TABLE_CELL),
     Paragraph("Severe eye/brow pain; N&amp;V; halos; fixed mid-dilated pupil; rock-hard eye; corneal haze; IOP often &gt;50 mmHg", TABLE_CELL),
     urg("EMERGENCY", RED)],

    [Paragraph("<b>Optic Neuritis</b>", TABLE_CELL_BOLD),
     Paragraph("Hours-days", TABLE_CELL),
     Paragraph("YES - retro-orbital, with eye movement", TABLE_CELL),
     Paragraph("Usually unilateral", TABLE_CELL),
     Paragraph("Central scotoma; RAPD present; disc swelling (papillitis) or normal disc (retrobulbar); often young woman; risk of MS", TABLE_CELL),
     urg("URGENT", ORANGE)],

    [Paragraph("<b>Uveitis / Endophthalmitis</b>", TABLE_CELL_BOLD),
     Paragraph("Hours-days", TABLE_CELL),
     Paragraph("YES", TABLE_CELL),
     Paragraph("Unilateral", TABLE_CELL),
     Paragraph("Photophobia; red eye; cells &amp; flare in anterior chamber; hypopyon if severe; vision blur", TABLE_CELL),
     urg("URGENT", ORANGE)],

    # Separator row
    [Paragraph("<b><i>--- Painless causes ---</i></b>", S("Sep", fontName="Helvetica-Oblique", fontSize=8, textColor=GREY, leading=11)),
     Paragraph("", TABLE_CELL), Paragraph("", TABLE_CELL),
     Paragraph("", TABLE_CELL), Paragraph("", TABLE_CELL), Paragraph("", TABLE_CELL)],

    [Paragraph("<b>Central Retinal Artery Occlusion (CRAO)</b>", TABLE_CELL_BOLD),
     Paragraph("Seconds", TABLE_CELL),
     Paragraph("No", TABLE_CELL),
     Paragraph("Unilateral", TABLE_CELL),
     Paragraph("Complete, sudden monocular loss; pale retina; cherry-red spot at macula; RAPD; afferent pupil defect; may follow amaurosis fugax", TABLE_CELL),
     urg("EMERGENCY", RED)],

    [Paragraph("<b>Central Retinal Vein Occlusion (CRVO)</b>", TABLE_CELL_BOLD),
     Paragraph("Hours", TABLE_CELL),
     Paragraph("No", TABLE_CELL),
     Paragraph("Unilateral", TABLE_CELL),
     Paragraph("'Blood and thunder' fundus - flame hemorrhages in all 4 quadrants; disc swelling; associated with HTN, hyperviscosity", TABLE_CELL),
     urg("URGENT", ORANGE)],

    [Paragraph("<b>Retinal Detachment</b>", TABLE_CELL_BOLD),
     Paragraph("Minutes-hours", TABLE_CELL),
     Paragraph("No", TABLE_CELL),
     Paragraph("Unilateral", TABLE_CELL),
     Paragraph("Flashing lights (photopsia); shower of floaters; curtain/shadow over vision; painless visual field loss", TABLE_CELL),
     urg("EMERGENCY", RED)],

    [Paragraph("<b>Ischemic Optic Neuropathy (ION)</b>", TABLE_CELL_BOLD),
     Paragraph("Hours (overnight)", TABLE_CELL),
     Paragraph("No", TABLE_CELL),
     Paragraph("Unilateral", TABLE_CELL),
     Paragraph("Altitudinal field defect (inferior loss); pale swollen disc; RAPD; age &gt;50; check ESR/CRP for GCA; arteritic ION can bilateralize", TABLE_CELL),
     urg("EMERGENCY*", RED)],

    [Paragraph("<b>Temporal (Giant Cell) Arteritis</b>", TABLE_CELL_BOLD),
     Paragraph("Hours-days", TABLE_CELL),
     Paragraph("Headache, jaw claudication, scalp tenderness", TABLE_CELL),
     Paragraph("Unilateral (can bilateralize)", TABLE_CELL),
     Paragraph("Age &gt;50; ESR &gt;50; CRP elevated; tender non-pulsatile temporal artery; vision can progress to bilateral if untreated", TABLE_CELL),
     urg("EMERGENCY", RED)],

    [Paragraph("<b>Vitreous Hemorrhage</b>", TABLE_CELL_BOLD),
     Paragraph("Sudden", TABLE_CELL),
     Paragraph("No", TABLE_CELL),
     Paragraph("Unilateral", TABLE_CELL),
     Paragraph("Dense floaters, cobwebs; vision may be grossly impaired; common in DR or posterior vitreous detachment; fundus view obscured", TABLE_CELL),
     urg("URGENT", ORANGE)],

    [Paragraph("<b>Wet AMD (Choroidal Neovascularization)</b>", TABLE_CELL_BOLD),
     Paragraph("Days", TABLE_CELL),
     Paragraph("No", TABLE_CELL),
     Paragraph("Usually unilateral (bilateral risk)", TABLE_CELL),
     Paragraph("Central distortion (metamorphopsia); scotoma; Amsler grid distortion; subretinal hemorrhage; usually age &gt;60", TABLE_CELL),
     urg("URGENT", ORANGE)],

    [Paragraph("<b>Cortical (Cerebral) Blindness</b>", TABLE_CELL_BOLD),
     Paragraph("Sudden", TABLE_CELL),
     Paragraph("No (headache if stroke)", TABLE_CELL),
     Paragraph("Bilateral", TABLE_CELL),
     Paragraph("Bilateral occipital lobe infarct; normal pupils &amp; fundus; Anton syndrome (denial of blindness); associated neurological deficits", TABLE_CELL),
     urg("EMERGENCY", RED)],

    [Paragraph("<b>Transient Monocular Blindness / Amaurosis Fugax</b>", TABLE_CELL_BOLD),
     Paragraph("Seconds-minutes (resolves)", TABLE_CELL),
     Paragraph("No", TABLE_CELL),
     Paragraph("Unilateral, transient", TABLE_CELL),
     Paragraph("'Shade pulled down'; resolves fully; carotid TIA equivalent; 50% risk major stroke within 1 month without treatment", TABLE_CELL),
     urg("URGENT", ORANGE)],
]

col_w2 = [FULL_W*0.165, FULL_W*0.095, FULL_W*0.095, FULL_W*0.10, FULL_W*0.40, FULL_W*0.095]

dd_data = [dd_hdr] + dd_rows
dd_table = Table(dd_data, colWidths=col_w2, repeatRows=1)
dd_style = TableStyle([
    # Header
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("TEXTCOLOR", (0,0), (-1,0), WHITE),
    ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE", (0,0), (-1,0), 8.5),
    ("ALIGN", (0,0), (-1,0), "CENTER"),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    # Grid
    ("GRID", (0,0), (-1,-1), 0.4, DIVIDER),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_GREY]),
    # Separator row (row 4 = index 4)
    ("BACKGROUND", (0,4), (-1,4), colors.HexColor("#EAE8E8")),
    # Padding
    ("LEFTPADDING", (0,0), (-1,-1), 5),
    ("RIGHTPADDING", (0,0), (-1,-1), 5),
    ("TOPPADDING", (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("FONTSIZE", (0,1), (-1,-1), 8.5),
])
dd_table.setStyle(dd_style)
story.append(dd_table)
story.append(Spacer(1, 4*mm))

# ── Urgency key ──────────────────────────────────────────────
urg_data = [[
    Paragraph('<b><font color="#C0392B">EMERGENCY</font></b>  Act within minutes. Call ophthalmology NOW. Do not delay investigation.', BODY),
    Paragraph('<b><font color="#E67E22">URGENT</font></b>  Same-day ophthalmology. Do not wait for next clinic.', BODY),
]]
urg_tbl = Table(urg_data, colWidths=[FULL_W*0.52, FULL_W*0.48])
urg_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), LIGHT_GREY),
    ("BOX", (0,0), (-1,-1), 0.6, DIVIDER),
    ("LINEAFTER", (0,0), (0,-1), 0.5, DIVIDER),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
    ("RIGHTPADDING", (0,0), (-1,-1), 8),
    ("TOPPADDING", (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(urg_tbl)

# ── PAGE BREAK ───────────────────────────────────────────────
story.append(PageBreak())

# ════════════════════════════════════════════════════════════
# PAGE 2
# ════════════════════════════════════════════════════════════

# ── Section 3: Diagnostic Pathway Flowchart ───────────────────
story.append(section_label("3.  DIAGNOSTIC PATHWAY"))
story.append(Spacer(1, 3*mm))

# Draw a flowchart as a table-based diagram
def flow_box(text, bg, border, w, style=None):
    s = style or BODY
    t = Table([[Paragraph(text, s)]], colWidths=[w])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("BOX", (0,0), (-1,-1), 1, border),
        ("LEFTPADDING", (0,0), (-1,-1), 6),
        ("RIGHTPADDING", (0,0), (-1,-1), 6),
        ("TOPPADDING", (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 4),
        ("ALIGN", (0,0), (-1,-1), "CENTER"),
    ]))
    return t

ARROW = Paragraph("<b>&#9660;</b>", S("A", fontName="Helvetica-Bold", fontSize=12,
                   textColor=MED_BLUE, leading=14, alignment=TA_CENTER))
ARROW_R = Paragraph("<b>&#9658;</b>", S("AR", fontName="Helvetica-Bold", fontSize=10,
                    textColor=MED_BLUE, leading=14, alignment=TA_CENTER))

FW = FULL_W
BW = FW * 0.55  # central box width
SW = FW * 0.42  # side box width

story.append(flow_box("<b>SUDDEN VISION LOSS - Patient presents</b>", NAVY, NAVY, FW,
    S("FH", fontName="Helvetica-Bold", fontSize=10, textColor=WHITE, leading=14, alignment=TA_CENTER)))
story.append(Spacer(1, 1*mm))
story.append(ARROW)
story.append(Spacer(1, 1*mm))

story.append(flow_box(
    "<b>Step 1:</b> Is the vision loss <b>transient</b> (now recovered) or <b>persistent</b>?",
    LIGHT_BLUE, MED_BLUE, FW))
story.append(Spacer(1, 1*mm))

branch1_data = [[
    flow_box("<b>TRANSIENT</b> (fully resolved)<br/>"
             "&#8226; Amaurosis fugax (monocular TIA)<br/>"
             "&#8226; Migraine with aura (bilateral)<br/>"
             "&#8226; Vertebrobasilar TIA<br/>"
             "<i>-> Urgent carotid Doppler, echo, ECG, neurology</i>",
             ORANGE_BG, ORANGE, SW),
    Paragraph("", BODY),
    flow_box("<b>PERSISTENT</b> (continues now)<br/>"
             "Continue to Step 2<br/>"
             "<i>Assume structural cause until proven otherwise</i>",
             RED_BG, RED, SW),
]]
b1 = Table(branch1_data, colWidths=[SW, FW-(2*SW), SW])
b1.setStyle(TableStyle([
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 0),
    ("RIGHTPADDING", (0,0), (-1,-1), 0),
    ("TOPPADDING", (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(b1)
story.append(Spacer(1, 1*mm))
story.append(ARROW)
story.append(Spacer(1, 1*mm))

story.append(flow_box(
    "<b>Step 2:</b> Is vision loss <b>monocular</b> (cover each eye) or <b>binocular</b>?",
    LIGHT_BLUE, MED_BLUE, FW))
story.append(Spacer(1, 1*mm))

branch2_data = [[
    flow_box("<b>MONOCULAR</b><br/>Lesion anterior to optic chiasm<br/>"
             "(eye, optic nerve, or retina)<br/>"
             "-> Check: IOP, fundus, RAPD<br/>"
             "-> Consider: CRAO, CRVO, RD,<br/>"
             "  Glaucoma, ION, vitreous hemorrhage",
             GREEN_BG, GREEN, SW),
    Paragraph("", BODY),
    flow_box("<b>BINOCULAR</b><br/>Lesion at or posterior to chiasm<br/>"
             "(chiasm, optic tract, cortex)<br/>"
             "-> Urgent MRI brain<br/>"
             "-> Consider: stroke, cortical blindness,<br/>"
             "  pituitary apoplexy, MS",
             ORANGE_BG, ORANGE, SW),
]]
b2 = Table(branch2_data, colWidths=[SW, FW-(2*SW), SW])
b2.setStyle(TableStyle([
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 0),
    ("RIGHTPADDING", (0,0), (-1,-1), 0),
    ("TOPPADDING", (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(b2)
story.append(Spacer(1, 1*mm))
story.append(ARROW)
story.append(Spacer(1, 1*mm))

story.append(flow_box(
    "<b>Step 3:</b> Is the vision loss <b>painful</b> or <b>painless</b>? (for monocular loss)",
    LIGHT_BLUE, MED_BLUE, FW))
story.append(Spacer(1, 1*mm))

branch3_data = [[
    flow_box("<b>PAINFUL (monocular)</b><br/>"
             "&#8226; Acute angle-closure glaucoma<br/>"
             "  IOP &gt;50, mid-dilated pupil, corneal haze<br/>"
             "  -> Immediate: pilocarpine, acetazolamide<br/>"
             "&#8226; Optic neuritis<br/>"
             "  Pain on eye movement, RAPD, young woman<br/>"
             "  -> IV methylprednisolone, MRI brain<br/>"
             "&#8226; Uveitis / endophthalmitis<br/>"
             "  Photophobia, cells in AC, hypopyon<br/>"
             "  -> Urgent slit-lamp, vitreous tap if endo",
             RED_BG, RED, SW),
    Paragraph("", BODY),
    flow_box("<b>PAINLESS (monocular)</b><br/>"
             "&#8226; Cherry-red spot + pale retina -> CRAO<br/>"
             "  -> O2, ocular massage, call stroke team<br/>"
             "&#8226; Curtain + floaters + flashes -> RD<br/>"
             "  -> Urgent surgical referral<br/>"
             "&#8226; Age &gt;50 + altitudinal defect -> ION<br/>"
             "  -> Check ESR/CRP; if arteritic, steroids NOW<br/>"
             "&#8226; 'Blood-thunder' fundus -> CRVO<br/>"
             "  -> Treat BP, anti-VEGF referral<br/>"
             "&#8226; Dense floaters, poor view -> Vit. hemorrhage<br/>"
             "  -> Urgent USS eye, DM/anticoag review",
             GREEN_BG, GREEN, SW),
]]
b3 = Table(branch3_data, colWidths=[SW, FW-(2*SW), SW])
b3.setStyle(TableStyle([
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 0),
    ("RIGHTPADDING", (0,0), (-1,-1), 0),
    ("TOPPADDING", (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(b3)
story.append(Spacer(1, 5*mm))

# ── Section 4: Investigations ─────────────────────────────────
story.append(section_label("4.  INVESTIGATIONS"))
story.append(Spacer(1, 3*mm))

inv_hdr = [Paragraph("INVESTIGATION", TABLE_HDR),
           Paragraph("INDICATED FOR", TABLE_HDR),
           Paragraph("KEY FINDING", TABLE_HDR)]

inv_rows = [
    [Paragraph("Intraocular pressure (tonometry)", TABLE_CELL_BOLD),
     Paragraph("All acute presentations; mandatory", TABLE_CELL),
     Paragraph(">21 mmHg abnormal; >50 mmHg = acute glaucoma", TABLE_CELL)],
    [Paragraph("Dilated fundoscopy", TABLE_CELL_BOLD),
     Paragraph("All monocular; macula, disc, vessels, periphery", TABLE_CELL),
     Paragraph("Cherry-red spot (CRAO); flame hemorrhages (CRVO); pale disc (ION); detached retina", TABLE_CELL)],
    [Paragraph("Slit-lamp examination", TABLE_CELL_BOLD),
     Paragraph("Anterior segment disease, uveitis, cornea", TABLE_CELL),
     Paragraph("Cells/flare (uveitis); corneal haze (glaucoma); keratic precipitates", TABLE_CELL)],
    [Paragraph("Visual field testing (confrontation/perimetry)", TABLE_CELL_BOLD),
     Paragraph("All presentations to localise lesion", TABLE_CELL),
     Paragraph("Central scotoma (optic neuritis, AMD); altitudinal (ION); bitemporal (chiasm); hemianopia (cortical)", TABLE_CELL)],
    [Paragraph("ESR + CRP (URGENT)", TABLE_CELL_BOLD),
     Paragraph("Age >50 with any monocular vision loss", TABLE_CELL),
     Paragraph("ESR >50 mm/hr or CRP elevated -> GCA until proven otherwise; start prednisolone immediately", TABLE_CELL)],
    [Paragraph("MRI/CT brain with diffusion", TABLE_CELL_BOLD),
     Paragraph("Binocular loss; suspected stroke; cortical blindness", TABLE_CELL),
     Paragraph("Occipital infarct; chiasmal lesion; pituitary apoplexy; demyelination (MS)", TABLE_CELL)],
    [Paragraph("Carotid Doppler ultrasound", TABLE_CELL_BOLD),
     Paragraph("Amaurosis fugax; CRAO; asymmetric retinal vascular disease", TABLE_CELL),
     Paragraph(">70% stenosis -> urgent endarterectomy/stenting referral", TABLE_CELL)],
    [Paragraph("12-lead ECG + cardiac echo", TABLE_CELL_BOLD),
     Paragraph("Embolic causes: CRAO, amaurosis fugax", TABLE_CELL),
     Paragraph("AF, valvular disease, patent foramen ovale -> anticoagulation", TABLE_CELL)],
    [Paragraph("Blood glucose + HbA1c", TABLE_CELL_BOLD),
     Paragraph("Diabetic retinopathy; vitreous hemorrhage", TABLE_CELL),
     Paragraph("Uncontrolled DM -> aggressive glycaemic control; ophthalmology follow-up", TABLE_CELL)],
    [Paragraph("FBC, platelets, coagulation screen", TABLE_CELL_BOLD),
     Paragraph("Vitreous/retinal hemorrhage; hyperviscosity (CRVO)", TABLE_CELL),
     Paragraph("Polycythaemia, thrombocytopenia, coagulopathy; consider haematology review", TABLE_CELL)],
    [Paragraph("Ocular ultrasound (B-scan)", TABLE_CELL_BOLD),
     Paragraph("Vitreous hemorrhage (fundus not visible)", TABLE_CELL),
     Paragraph("Retinal detachment or vitreous hemorrhage visible behind opaque media", TABLE_CELL)],
    [Paragraph("Fluorescein angiography", TABLE_CELL_BOLD),
     Paragraph("CRVO, CRAO, AMD, diabetic retinopathy", TABLE_CELL),
     Paragraph("Vascular filling defects; choroidal neovascularisation; leakage patterns", TABLE_CELL)],
    [Paragraph("Temporal artery biopsy", TABLE_CELL_BOLD),
     Paragraph("Suspected GCA after ESR/CRP elevated", TABLE_CELL),
     Paragraph("Granulomatous inflammation; giant cells. Do NOT delay steroids pending biopsy", TABLE_CELL)],
    [Paragraph("Optical coherence tomography (OCT)", TABLE_CELL_BOLD),
     Paragraph("Macular pathology; AMD; macular oedema; RD", TABLE_CELL),
     Paragraph("Drusen (dry AMD); subretinal fluid (wet AMD); macular oedema; inner retinal thinning (CRAO)", TABLE_CELL)],
]

inv_col_w = [FULL_W*0.25, FULL_W*0.32, FULL_W*0.43]
inv_table = Table([inv_hdr] + inv_rows, colWidths=inv_col_w, repeatRows=1)
inv_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_GREY]),
    ("GRID", (0,0), (-1,-1), 0.4, DIVIDER),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 5),
    ("RIGHTPADDING", (0,0), (-1,-1), 5),
    ("TOPPADDING", (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
]))
story.append(inv_table)

story.append(PageBreak())

# ════════════════════════════════════════════════════════════
# PAGE 3
# ════════════════════════════════════════════════════════════

# ── Section 5: Condition-specific management ───────────────────
story.append(section_label("5.  CONDITION-SPECIFIC EMERGENCY MANAGEMENT"))
story.append(Spacer(1, 3*mm))

def mgmt_block(title, colour, bg, items):
    rows = [[Paragraph(f"<b>{title}</b>",
                       S("MH", fontName="Helvetica-Bold", fontSize=9.5,
                         textColor=WHITE, leading=13))]] + \
           [[Paragraph(f"&#8226; {i}", TABLE_CELL)] for i in items]
    t = Table(rows, colWidths=[(FULL_W - 6*mm)/2])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,0), colour),
        ("BACKGROUND", (0,1), (-1,-1), bg),
        ("BOX", (0,0), (-1,-1), 0.8, colour),
        ("INNERGRID", (0,0), (-1,-1), 0.3, colors.HexColor("#D0D0D0")),
        ("LEFTPADDING", (0,0), (-1,-1), 7),
        ("RIGHTPADDING", (0,0), (-1,-1), 7),
        ("TOPPADDING", (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 4),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
    ]))
    return t

col_half = (FULL_W - 4*mm) / 2

m1 = mgmt_block("Acute Angle-Closure Glaucoma", RED, RED_BG, [
    "Immediate ophthalmology - this is a sight emergency",
    "Reduce IOP: oral glycerin 1 mL/kg + IM acetazolamide 500 mg",
    "Topical pilocarpine 2-4% every 15 min (miotic to open angle)",
    "Topical beta-blocker (timolol 0.5%) + alpha agonist (apraclonidine)",
    "IV mannitol 1-2 g/kg if medical Rx fails",
    "Definitive: laser peripheral iridotomy",
    "Treat fellow eye prophylactically",
])

m2 = mgmt_block("Central Retinal Artery Occlusion (CRAO)", RED, RED_BG, [
    "Act within 90 minutes for any chance of visual recovery",
    "Ocular massage: digital massage 10-15s on/5s off x 15 min",
    "Reduce IOP: acetazolamide 500 mg IV or anterior chamber paracentesis",
    "Re-breathe into paper bag or carbogen (95% O2/5% CO2) to dilate arteries",
    "Urgent stroke protocol: CT/MRI brain, carotid Doppler, ECG, echo",
    "Antiplatelet therapy; consider thrombolysis if within 4.5 hrs",
    "Do NOT use thrombolytics for ocular CRAO alone (no evidence)",
])

m3 = mgmt_block("Temporal Arteritis / Arteritic ION", RED, RED_BG, [
    "DO NOT wait for biopsy - start steroids NOW",
    "IV methylprednisolone 1 g/day x 3 days (if vision already lost)",
    "Oral prednisolone 1 mg/kg/day (max 80 mg) if vision not yet affected",
    "Aspirin 75 mg daily to reduce stroke/vision loss risk",
    "Urgent temporal artery biopsy within 1-2 weeks (steroids do not affect for 2 wks)",
    "Monitor ESR/CRP response; taper steroids very slowly over months",
    "GI protection: PPI + bisphosphonate for long-term steroid use",
])

m4 = mgmt_block("Retinal Detachment", ORANGE, ORANGE_BG, [
    "NPO (nil by mouth) - surgical emergency",
    "Urgent ophthalmology surgical referral same day",
    "Avoid head movement that may extend detachment",
    "Macula-on RD: surgery within hours for best prognosis",
    "Macula-off RD: surgery within 24 hrs; visual prognosis worse",
    "Options: pneumatic retinopexy, scleral buckle, pars plana vitrectomy",
    "Follow-up fellow eye for prophylactic treatment",
])

m5 = mgmt_block("Optic Neuritis", ORANGE, ORANGE_BG, [
    "IV methylprednisolone 1 g/day x 3 days (speeds recovery, not final acuity)",
    "MRI brain: high T2 lesions suggest MS (McDonald criteria)",
    "Neurology referral for MS risk assessment and DMT discussion",
    "75% of women / 34% men develop MS within 15 years",
    "Visual acuity usually recovers 4-12 weeks with or without treatment",
    "Avoid overheating (Uhthoff's phenomenon may worsen acuity transiently)",
])

m6 = mgmt_block("Wet AMD - Choroidal Neovascularization", ORANGE, ORANGE_BG, [
    "Urgent ophthalmology - anti-VEGF injection within days",
    "Anti-VEGF: ranibizumab, bevacizumab, or aflibercept intravitreal",
    "Amsler grid self-monitoring for fellow eye",
    "AREDS2 supplements for intermediate AMD: vitamins C, E, beta-carotene, zinc",
    "Laser photocoagulation for extrafoveal lesions only",
    "No smoking - major modifiable risk factor for AMD progression",
])

mgmt_grid = Table([
    [m1, Spacer(4,1), m2],
    [Spacer(1,4*mm), Spacer(1,4*mm), Spacer(1,4*mm)],
    [m3, Spacer(4,1), m4],
    [Spacer(1,4*mm), Spacer(1,4*mm), Spacer(1,4*mm)],
    [m5, Spacer(4,1), m6],
], colWidths=[col_half, 4*mm, col_half])
mgmt_grid.setStyle(TableStyle([
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 0),
    ("RIGHTPADDING", (0,0), (-1,-1), 0),
    ("TOPPADDING", (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(mgmt_grid)
story.append(Spacer(1, 5*mm))

# ── Section 6: Visual Field Patterns ─────────────────────────
story.append(section_label("6.  VISUAL FIELD DEFECT LOCALISATION"))
story.append(Spacer(1, 3*mm))

vf_hdr = [Paragraph("FIELD DEFECT", TABLE_HDR),
          Paragraph("LOCATION OF LESION", TABLE_HDR),
          Paragraph("LIKELY DIAGNOSIS", TABLE_HDR)]
vf_rows = [
    [Paragraph("Central scotoma (one eye)", TABLE_CELL_BOLD),
     Paragraph("Macula or optic nerve (pre-chiasm)", TABLE_CELL),
     Paragraph("Optic neuritis, CRAO (macular), AMD, toxic optic neuropathy", TABLE_CELL)],
    [Paragraph("Monocular total visual loss", TABLE_CELL_BOLD),
     Paragraph("Optic nerve or globe (unilateral, pre-chiasm)", TABLE_CELL),
     Paragraph("CRAO, severe optic neuritis, globe trauma, arteritic ION", TABLE_CELL)],
    [Paragraph("Altitudinal defect (upper or lower half)", TABLE_CELL_BOLD),
     Paragraph("Optic nerve (usually inferior fibres)", TABLE_CELL),
     Paragraph("Ischemic optic neuropathy (ION) - inferior altitudinal most common", TABLE_CELL)],
    [Paragraph("Bitemporal hemianopia", TABLE_CELL_BOLD),
     Paragraph("Optic chiasm (crossing nasal fibres)", TABLE_CELL),
     Paragraph("Pituitary tumour / apoplexy, craniopharyngioma, chiasmal compression", TABLE_CELL)],
    [Paragraph("Homonymous hemianopia", TABLE_CELL_BOLD),
     Paragraph("Optic tract, lateral geniculate, or optic radiation", TABLE_CELL),
     Paragraph("Stroke, tumour, abscess; side of defect opposite to lesion", TABLE_CELL)],
    [Paragraph("Homonymous quadrantanopia", TABLE_CELL_BOLD),
     Paragraph("Optic radiation (parietal = inferior; temporal = superior)", TABLE_CELL),
     Paragraph("'Pie in the sky' (temporal lobe); 'Pie on the floor' (parietal lobe)", TABLE_CELL)],
    [Paragraph("Peripheral (tunnel) vision", TABLE_CELL_BOLD),
     Paragraph("Retinal periphery bilaterally", TABLE_CELL),
     Paragraph("Retinitis pigmentosa (hereditary); advanced glaucoma; panretinal photocoagulation", TABLE_CELL)],
    [Paragraph("Complete bilateral visual loss (normal pupils)", TABLE_CELL_BOLD),
     Paragraph("Bilateral occipital cortex", TABLE_CELL),
     Paragraph("Cortical blindness (stroke, hypoxia); Anton syndrome; may have pupil-sparing", TABLE_CELL)],
]
vf_col_w = [FULL_W*0.27, FULL_W*0.33, FULL_W*0.40]
vf_table = Table([vf_hdr] + vf_rows, colWidths=vf_col_w, repeatRows=1)
vf_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_GREY]),
    ("GRID", (0,0), (-1,-1), 0.4, DIVIDER),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 5),
    ("RIGHTPADDING", (0,0), (-1,-1), 5),
    ("TOPPADDING", (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
]))
story.append(vf_table)
story.append(Spacer(1, 5*mm))

# ── Section 7: Key Fundoscopic Signs ─────────────────────────
story.append(section_label("7.  KEY FUNDOSCOPIC FINDINGS"))
story.append(Spacer(1, 3*mm))

fund_hdr = [Paragraph("FUNDOSCOPIC SIGN", TABLE_HDR),
            Paragraph("APPEARANCE", TABLE_HDR),
            Paragraph("DIAGNOSIS", TABLE_HDR)]
fund_rows = [
    [Paragraph("Cherry-red spot", TABLE_CELL_BOLD),
     Paragraph("Pale (ischaemic) retina with bright red spot at fovea (choroidal supply preserved)", TABLE_CELL),
     Paragraph("CRAO; rarely Niemann-Pick, Tay-Sachs (bilateral)", TABLE_CELL)],
    [Paragraph("Blood and thunder fundus", TABLE_CELL_BOLD),
     Paragraph("Flame-shaped haemorrhages in all 4 quadrants; dilated tortuous veins; disc oedema", TABLE_CELL),
     Paragraph("Central Retinal Vein Occlusion (CRVO)", TABLE_CELL)],
    [Paragraph("Pale/swollen optic disc", TABLE_CELL_BOLD),
     Paragraph("Disc swelling + pallor; may have haemorrhages at disc margin", TABLE_CELL),
     Paragraph("Arteritic or non-arteritic ION; papilloedema (if bilateral)", TABLE_CELL)],
    [Paragraph("Drusen", TABLE_CELL_BOLD),
     Paragraph("Yellow-white spots at macula; hard (small) or soft (large, confluent)", TABLE_CELL),
     Paragraph("Age-related macular degeneration (AMD) - dry type early sign", TABLE_CELL)],
    [Paragraph("Subretinal haemorrhage / grey-green membrane", TABLE_CELL_BOLD),
     Paragraph("Dark subretinal blood; grey-green choroidal neovascular membrane at macula", TABLE_CELL),
     Paragraph("Wet AMD with choroidal neovascularisation", TABLE_CELL)],
    [Paragraph("Microaneurysms + haemorrhages (dot-blot)", TABLE_CELL_BOLD),
     Paragraph("Dot and blot haemorrhages; microaneurysms; hard exudates; cotton-wool spots", TABLE_CELL),
     Paragraph("Diabetic retinopathy (non-proliferative)", TABLE_CELL)],
    [Paragraph("New vessels (NVD/NVE)", TABLE_CELL_BOLD),
     Paragraph("Abnormal frond-like vessels at disc (NVD) or elsewhere (NVE); may bleed into vitreous", TABLE_CELL),
     Paragraph("Proliferative diabetic retinopathy; retinal vein occlusion", TABLE_CELL)],
    [Paragraph("Bone-spicule pigmentation", TABLE_CELL_BOLD),
     Paragraph("Peripheral retinal pigment clumping in bone-spicule pattern; attenuated vessels", TABLE_CELL),
     Paragraph("Retinitis pigmentosa (hereditary; starts with night blindness)", TABLE_CELL)],
    [Paragraph("Optic cup enlargement (C:D ratio >0.6)", TABLE_CELL_BOLD),
     Paragraph("Enlarged cup-to-disc ratio; notching of neuroretinal rim; bayonetting of vessels", TABLE_CELL),
     Paragraph("Glaucoma (chronic open-angle; often bilateral)", TABLE_CELL)],
    [Paragraph("Silver/copper wiring + AV nipping", TABLE_CELL_BOLD),
     Paragraph("Increased arteriolar light reflex; venous compression at arteriovenous crossings", TABLE_CELL),
     Paragraph("Hypertensive retinopathy; chronic hypertension", TABLE_CELL)],
]
fund_col_w = [FULL_W*0.25, FULL_W*0.42, FULL_W*0.33]
fund_table = Table([fund_hdr] + fund_rows, colWidths=fund_col_w, repeatRows=1)
fund_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_GREY]),
    ("GRID", (0,0), (-1,-1), 0.4, DIVIDER),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 5),
    ("RIGHTPADDING", (0,0), (-1,-1), 5),
    ("TOPPADDING", (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
]))
story.append(fund_table)

story.append(PageBreak())

# ════════════════════════════════════════════════════════════
# PAGE 4
# ════════════════════════════════════════════════════════════

# ── Section 8: Drugs implicated ──────────────────────────────
story.append(section_label("8.  DRUG-INDUCED VISUAL LOSS"))
story.append(Spacer(1, 3*mm))

drug_hdr = [Paragraph("DRUG", TABLE_HDR),
            Paragraph("MECHANISM", TABLE_HDR),
            Paragraph("VISUAL EFFECT", TABLE_HDR),
            Paragraph("ACTION", TABLE_HDR)]
drug_rows = [
    [Paragraph("Ethambutol", TABLE_CELL_BOLD),
     Paragraph("Optic nerve toxicity", TABLE_CELL),
     Paragraph("Central / centrocaecal scotoma; colour vision loss (red-green)", TABLE_CELL),
     Paragraph("Stop drug; monitor monthly if TB treatment required", TABLE_CELL)],
    [Paragraph("Hydroxychloroquine (HCQ)", TABLE_CELL_BOLD),
     Paragraph("Retinal toxicity - 'bull's eye' maculopathy", TABLE_CELL),
     Paragraph("Peripheral visual field loss; irreversible; dose-related", TABLE_CELL),
     Paragraph("Annual OCT screening; stop if maculopathy detected", TABLE_CELL)],
    [Paragraph("Amiodarone", TABLE_CELL_BOLD),
     Paragraph("Corneal microdeposits; optic neuropathy", TABLE_CELL),
     Paragraph("Halos; blurred vision; rarely optic neuritis", TABLE_CELL),
     Paragraph("Often reversible on dose reduction; ophthalmology review", TABLE_CELL)],
    [Paragraph("Corticosteroids (topical/systemic)", TABLE_CELL_BOLD),
     Paragraph("Raises IOP; lens opacity", TABLE_CELL),
     Paragraph("Steroid glaucoma; posterior subcapsular cataract", TABLE_CELL),
     Paragraph("Monitor IOP; taper dose; switch to steroid-sparing agent", TABLE_CELL)],
    [Paragraph("Vigabatrin", TABLE_CELL_BOLD),
     Paragraph("Retinal GABAergic toxicity", TABLE_CELL),
     Paragraph("Irreversible bilateral peripheral visual field constriction", TABLE_CELL),
     Paragraph("Annual visual field testing; consider drug withdrawal", TABLE_CELL)],
    [Paragraph("Sildenafil / PDE5 inhibitors", TABLE_CELL_BOLD),
     Paragraph("Non-arteritic ION risk (controversial); colour vision disturbance", TABLE_CELL),
     Paragraph("Blue-tinged vision; acute ION in rare cases", TABLE_CELL),
     Paragraph("Avoid in high ION risk patients; stop if vision change occurs", TABLE_CELL)],
    [Paragraph("Digoxin toxicity", TABLE_CELL_BOLD),
     Paragraph("Retinal photoreceptor toxicity", TABLE_CELL),
     Paragraph("Yellow/green halos; central scotoma; colour vision changes", TABLE_CELL),
     Paragraph("Check digoxin levels; dose reduction", TABLE_CELL)],
    [Paragraph("Isotretinoin", TABLE_CELL_BOLD),
     Paragraph("Raised intracranial pressure (pseudotumour cerebri)", TABLE_CELL),
     Paragraph("Papilloedema; visual field defects", TABLE_CELL),
     Paragraph("Stop drug; ophthalmology + neurology referral", TABLE_CELL)],
    [Paragraph("Topiramate", TABLE_CELL_BOLD),
     Paragraph("Idiosyncratic uveal effusion causing angle-closure", TABLE_CELL),
     Paragraph("Acute angle-closure glaucoma", TABLE_CELL),
     Paragraph("Stop topiramate; treat acute glaucoma; do NOT use pilocarpine", TABLE_CELL)],
]
drug_col_w = [FULL_W*0.18, FULL_W*0.24, FULL_W*0.32, FULL_W*0.26]
drug_table = Table([drug_hdr] + drug_rows, colWidths=drug_col_w, repeatRows=1)
drug_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_GREY]),
    ("GRID", (0,0), (-1,-1), 0.4, DIVIDER),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 5),
    ("RIGHTPADDING", (0,0), (-1,-1), 5),
    ("TOPPADDING", (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
]))
story.append(drug_table)
story.append(Spacer(1, 5*mm))

# ── Section 9: Special Populations ───────────────────────────
story.append(section_label("9.  SPECIAL POPULATIONS"))
story.append(Spacer(1, 3*mm))

sp_left = [
    Paragraph("<b>Paediatric / Young Adult</b>", SUBSEC_HDR),
    Paragraph("&#8226; <b>Optic neuritis</b>: often bilateral in children; high MS risk in adults", BODY),
    Paragraph("&#8226; <b>Retinoblastoma</b>: leukocoria (white pupil reflex), strabismus", BODY),
    Paragraph("&#8226; <b>Juvenile glaucoma</b>: buphthalmos, photophobia, tearing", BODY),
    Paragraph("&#8226; <b>Non-accidental injury</b>: bilateral retinal haemorrhages in infants - mandatory safeguarding referral", BODY),
    Paragraph("&#8226; <b>Myopia progression</b>: rapid change, risk of retinal detachment", BODY),
    Spacer(1, 3*mm),
    Paragraph("<b>Pregnancy</b>", SUBSEC_HDR),
    Paragraph("&#8226; Visual disturbance + HTN -> pre-eclampsia / HELLP; emergency obstetric review", BODY),
    Paragraph("&#8226; Hypertensive retinopathy may worsen in pre-eclampsia", BODY),
    Paragraph("&#8226; Central serous retinopathy: more common in 3rd trimester", BODY),
    Paragraph("&#8226; Pituitary adenoma may expand -> bitemporal hemianopia", BODY),
]

sp_right = [
    Paragraph("<b>Elderly (&gt;60 years)</b>", SUBSEC_HDR),
    Paragraph("&#8226; AMD is leading cause of vision loss in this group", BODY),
    Paragraph("&#8226; Always check ESR/CRP in >50 with monocular loss (rule out GCA)", BODY),
    Paragraph("&#8226; Falls risk from visual impairment -> safety review", BODY),
    Paragraph("&#8226; Glaucoma more prevalent; screen at least every 3 years from age 50", BODY),
    Spacer(1, 3*mm),
    Paragraph("<b>Diabetic Patients</b>", SUBSEC_HDR),
    Paragraph("&#8226; Diabetic retinopathy leading cause of blindness age 20-74 in USA", BODY),
    Paragraph("&#8226; Annual dilated fundoscopy mandatory for all diabetics", BODY),
    Paragraph("&#8226; HbA1c < 53 mmol/mol (7%) target to slow progression", BODY),
    Paragraph("&#8226; Macular oedema: anti-VEGF injections (first line)", BODY),
    Paragraph("&#8226; Proliferative DR: panretinal photocoagulation; vitrectomy if vitreous haemorrhage", BODY),
    Spacer(1, 3*mm),
    Paragraph("<b>HIV / Immunocompromised</b>", SUBSEC_HDR),
    Paragraph("&#8226; CMV retinitis: CD4 < 50; painless progressive loss; 'tomato sauce' fundus", BODY),
    Paragraph("&#8226; Toxoplasma chorioretinitis: headlights in fog appearance", BODY),
    Paragraph("&#8226; Treatment: IV ganciclovir; antiretroviral therapy for IRIS management", BODY),
]

sp_tbl = Table([[sp_left, Spacer(4,1), sp_right]],
               colWidths=[col_half, 4*mm, col_half])
sp_tbl.setStyle(TableStyle([
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 0),
    ("RIGHTPADDING", (0,0), (-1,-1), 0),
    ("TOPPADDING", (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(sp_tbl)
story.append(Spacer(1, 5*mm))

# ── Section 10: Disposition Summary ──────────────────────────
story.append(section_label("10.  DISPOSITION & FOLLOW-UP SUMMARY"))
story.append(Spacer(1, 3*mm))

disp_data = [
    [Paragraph("<b>ADMIT / CALL OPHTHALMOLOGY NOW</b>", S("DH",
        fontName="Helvetica-Bold", fontSize=9, textColor=WHITE, leading=13)),
     Paragraph("<b>SAME-DAY URGENT REFERRAL</b>", S("DH2",
        fontName="Helvetica-Bold", fontSize=9, textColor=WHITE, leading=13)),
     Paragraph("<b>ROUTINE / SCHEDULED FOLLOW-UP</b>", S("DH3",
        fontName="Helvetica-Bold", fontSize=9, textColor=WHITE, leading=13))],
    [Paragraph(
        "&#8226; Acute angle-closure glaucoma<br/>"
        "&#8226; CRAO (within 90 minutes!)<br/>"
        "&#8226; Retinal detachment (macula-on)<br/>"
        "&#8226; GCA / arteritic ION (give steroids first)<br/>"
        "&#8226; Cortical blindness (stroke team)<br/>"
        "&#8226; Endophthalmitis<br/>"
        "&#8226; Bilateral vision loss",
        TABLE_CELL),
     Paragraph(
        "&#8226; CRVO<br/>"
        "&#8226; Wet AMD (new onset)<br/>"
        "&#8226; Vitreous haemorrhage<br/>"
        "&#8226; Optic neuritis<br/>"
        "&#8226; Non-arteritic ION<br/>"
        "&#8226; Amaurosis fugax (neurovascular workup)<br/>"
        "&#8226; Retinal detachment (macula-off, stable)",
        TABLE_CELL),
     Paragraph(
        "&#8226; Stable dry AMD<br/>"
        "&#8226; Controlled glaucoma (review every 6-12 months)<br/>"
        "&#8226; Refractive error correction<br/>"
        "&#8226; Diabetic retinopathy screening (annual)<br/>"
        "&#8226; Post-optic neuritis MRI follow-up<br/>"
        "&#8226; Cataract (if vision not severely impaired)<br/>"
        "&#8226; Hydroxychloroquine monitoring (annual OCT)",
        TABLE_CELL)],
]
disp_col_w = [FULL_W/3, FULL_W/3, FULL_W/3]
disp_tbl = Table(disp_data, colWidths=disp_col_w)
disp_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (0,0), RED),
    ("BACKGROUND", (1,0), (1,0), ORANGE),
    ("BACKGROUND", (2,0), (2,0), GREEN),
    ("BACKGROUND", (0,1), (0,1), RED_BG),
    ("BACKGROUND", (1,1), (1,1), ORANGE_BG),
    ("BACKGROUND", (2,1), (2,1), GREEN_BG),
    ("BOX", (0,0), (-1,-1), 0.8, DIVIDER),
    ("INNERGRID", (0,0), (-1,-1), 0.5, DIVIDER),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 7),
    ("RIGHTPADDING", (0,0), (-1,-1), 7),
    ("TOPPADDING", (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
]))
story.append(disp_tbl)
story.append(Spacer(1, 5*mm))

# ── Disclaimer ───────────────────────────────────────────────
disclaimer_data = [[Paragraph(
    "<b>DISCLAIMER:</b> This clinical decision summary is intended as a quick-reference educational aid for healthcare professionals. "
    "It does not replace clinical judgment, institutional protocols, or specialist consultation. "
    "Drug doses and management steps should be verified against current formularies and guidelines before use. "
    "Always consult ophthalmology for definitive diagnosis and management of acute vision loss.",
    SMALL)]]
disc_tbl = Table(disclaimer_data, colWidths=[FULL_W])
disc_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), LIGHT_GREY),
    ("BOX", (0,0), (-1,-1), 0.5, GREY),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
    ("RIGHTPADDING", (0,0), (-1,-1), 8),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
]))
story.append(disc_tbl)

# ── Build ────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=L_MARGIN,
    rightMargin=R_MARGIN,
    topMargin=55*mm,   # space for header banner on p1
    bottomMargin=B_MARGIN,
)

# First page has taller top margin for the big banner
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate

class MyDoc(BaseDocTemplate):
    def __init__(self, filename, **kw):
        super().__init__(filename, **kw)
        frame_p1 = Frame(L_MARGIN, B_MARGIN,
                         PAGE_W - L_MARGIN - R_MARGIN,
                         PAGE_H - 55*mm - B_MARGIN,
                         id="p1")
        frame_rest = Frame(L_MARGIN, B_MARGIN,
                           PAGE_W - L_MARGIN - R_MARGIN,
                           PAGE_H - 15*mm - B_MARGIN,
                           id="rest")
        self.addPageTemplates([
            PageTemplate(id="First", frames=[frame_p1], onPage=first_page),
            PageTemplate(id="Later", frames=[frame_rest], onPage=later_pages),
        ])

    def handle_pageBegin(self):
        if self.page == 1:
            self._handle_pageBegin()
        else:
            self._handle_pageBegin()

doc2 = MyDoc(OUTPUT)
# Force page template switch after page 1
from reportlab.platypus import NextPageTemplate
story.insert(0, NextPageTemplate("First"))

# Insert template switch before first page break
# Find position of first PageBreak
for i, elem in enumerate(story):
    if isinstance(elem, PageBreak):
        story.insert(i, NextPageTemplate("Later"))
        break

doc2.build(story)
print(f"PDF created: {OUTPUT}")
Running Command

cd /home/daytona/workspace/sudden-vision-loss && python3 build_pdf.py 2>&1

Editing File

~/sudden-vision-loss/build_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/sudden-vision-loss/build_pdf.py'
Running Command

cd /home/daytona/workspace/sudden-vision-loss && python3 build_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/sudden-vision-loss/Sudden_Vision_Loss_Clinical_Decision_Summary.pdf

The PDF has been generated successfully. Here's your download link:

Sudden Vision Loss Clinical Decision Summary

PDF Document · PDF


Here's what's included across the 4 pages:
Page 1 - Assessment & Differential Diagnosis
  • Red-flag emergency banner
  • Initial rapid assessment checklist (history + examination, including RAPD test)
  • Full differential diagnosis table (13 conditions) organized by pain/laterality with urgency coding (EMERGENCY / URGENT)
Page 2 - Diagnostic Pathway & Investigations
  • Step-by-step decision flowchart: transient vs. persistent → monocular vs. binocular → painful vs. painless - each branch with specific diagnoses and first actions
  • Investigations table (14 tests): tonometry, fundoscopy, ESR/CRP, MRI, carotid Doppler, OCT, fluorescein angiography, etc. with key expected findings
Page 3 - Management & Fundoscopy
  • Condition-specific emergency management for 6 major causes (acute glaucoma, CRAO, GCA/ION, retinal detachment, optic neuritis, wet AMD) with specific drug doses and timelines
  • Visual field defect localization table (8 patterns matched to anatomical lesion)
  • Key fundoscopic signs table (10 signs with appearances and diagnoses)
Page 4 - Special Populations & Disposition
  • Drug-induced visual loss (9 drugs: ethambutol, HCQ, amiodarone, topiramate, etc.)
  • Special population considerations: paediatric, pregnancy, elderly, diabetics, HIV/immunocompromised
  • Three-column disposition guide: admit now / same-day referral / routine follow-up
  • Disclaimer
This is a shared conversation. Sign in to Orris to start your own chat.