Mucosal folds and middle ear ventilation

Reading File
Finding Sources
Finding Sources
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Loading Image
Reading File
Reading File
I now have comprehensive content from both Scott-Brown's and Cummings, plus the anatomy diagram. Let me compile the full answer.

Mucosal Folds and Middle Ear Ventilation

Overview

The middle ear mucosa behaves much like peritoneum - it drapes over the ossicles, ligaments, tendons, and bony walls, forming a complex series of folds and recesses. These folds are not passive linings; they actively compartmentalize the middle ear and determine how air (ventilated from the Eustachian tube) circulates through different regions.

Anatomy of the Mucosal Folds

The mucosal folds divide the tympanic cavity into distinct spaces. The key folds (described in detail by Proctor) include:
Malleal folds:
  • Anterior malleolar fold (tensor fold) - runs anteriorly from the head/neck of the malleus; forms the anterior boundary of the epitympanum diaphragm
  • Superior malleolar fold - suspends the head of the malleus superiorly
  • Lateral malleolar fold (lateral malleoincudal fold) - runs posteriorly; forms the lateral wall of Prussak's space
  • Anterior fold of von Tröltsch - anterior to the malleus handle
  • Posterior fold of von Tröltsch - posterior to the malleus handle (posterior pouch)
Incudal folds:
  • Superior incudal fold - suspends the body of incus from the tegmen
  • Medial incudal fold - connects incus to the medial wall
  • Lateral incudal fold - lateral to the incus body
  • Posterior incudal ligament - tethers the short process of incus posteriorly
Stapedial folds:
  • Plica stapedis (obturatoria stapedi) - envelops the stapes
  • Plica stapedial tendon - invests the stapedius tendon
The diagram below from Scott-Brown's (Fig. 46.15) shows these folds and the isthmi clearly:
Mucosal folds of the middle ear showing the isthmus tympani anticus and posticus, tensor tympani fold, superior malleolar fold, lateral/medial incudal folds, plica stapedis, and Prussak's space
Fig. 46.15 - The attic folds (Scott-Brown's Otorhinolaryngology)

How the Folds Compartmentalize the Middle Ear

The ossicular chain and its associated mucosal folds create an almost complete partition between the epitympanum (attic) above and the mesotympanum below. Three major folds are primarily responsible for this separation:
FoldRole
Tensor fold (anterior malleolar fold)Anterior boundary of the epitympanum diaphragm
Interosseous fold (superior incudal fold)Connects malleus head to incus body
Medial incudal foldCloses the medial aspect of the attic
After these three folds close off the attic, only two small openings remain - the isthmus tympani anticus (anterior) and the isthmus tympani posticus (posterior), seen flanking the stapes superstructure in the diagram above.

The Tympanic Isthmus and Epitympanic Ventilation

This is the physiological crux:
  • The mesotympanum receives air freely and directly from the Eustachian tube at all times - it is "flooded" with air.
  • The epitympanum, by contrast, depends entirely on the tympanic isthmus (the two small openings between the folds) for its air supply. There is no other pathway.
  • The tympanic isthmus anticus lies anterior to the stapes; the isthmus tympani posticus lies posterior to it.
  • Together, these two openings are the sole conduit for the ventilation stream from the Eustachian tube into the epitympanic space.
"The connection between the two [malleal folds] is the tympanic isthmus, which is the only conduit for a ventilation stream in the epitympanum from the Eustachian tube, unlike the mesotympanum, which is flooded by air at all times."
  • Scott-Brown's Otorhinolaryngology Head & Neck Surgery, Vol 2

Prussak's Space

A specialized compartment bounded by:
  • Laterally: pars flaccida of the tympanic membrane
  • Medially: neck of the malleus
  • Superiorly: lateral malleolar fold
Prussak's space has limited communication with the rest of the middle ear and is ventilated poorly. This restricted ventilation, combined with the negative pressure that develops when the isthmus is blocked, predisposes the pars flaccida to retraction and cholesteatoma formation.

Mucociliary Clearance Pathways

Beyond simple air circulation, the mucosa itself drives active clearance. Three mucociliary pathways run through the tympanic cavity, all converging at the Eustachian tube orifice:
  1. Epitympanic pathway
  2. Promontorial pathway
  3. Hypotympanic pathway (the largest)
Ciliated respiratory epithelium is more widespread in younger individuals; its extent diminishes with age.

Clinical Significance

1. Obstruction of the isthmus tympani:
  • Congenital defects in the folds, or inflammation from mucosal disease or cholesteatoma, can block the narrow isthmus.
  • This cuts off air supply to the epitympanum → negative pressure → progressive retraction pocket → further inflammation, creating a self-perpetuating cycle.
2. Cholesteatoma spread pathways:
  • The folds and recesses define the routes along which cholesteatoma extends.
  • Attic retraction cholesteatomas arise in Prussak's space and track posteriorly through the posterior epitympanum → aditus ad antrum → posterior mesotympanum.
  • Advanced disease crosses medially to the anterior attic; surgical removal of the incus and malleus head is therefore required to clear anterior disease.
3. Surgical implications:
  • The cog (an incomplete bony septum in the coronal plane at the anterior epitympanum) must be removed to visualize the entire supratubal recess and ensure safe disease clearance.
  • Understanding fold anatomy is essential for predicting and preventing residual cholesteatoma.
4. Otitis media with effusion:
  • Any process that impairs Eustachian tube function or narrows the isthmus impairs epitympanic ventilation disproportionately compared to the mesotympanum, explaining why effusion and retraction are first apparent in the pars flaccida/attic region.

Sources:
  • Scott-Brown's Otorhinolaryngology Head & Neck Surgery, Vol 2 - "The middle ear mucosal folds" and "The mucosa of the tympanic cavity" (describing Proctor's classification)
  • Cummings Otolaryngology Head and Neck Surgery - "Middle Ear Spaces" and Fig. 126.10 (Proctor B: The development of the middle ear spaces)

Create a visual reference guide on mucosal fold anatomy and ventilation pathways

Asking for Preferences
Reading File
Running Command

mkdir -p /home/daytona/workspace/middle-ear-guide && ls /home/daytona/workspace/…

Writing File

~/middle-ear-guide/build_guide.py

"""
Visual Reference Guide: Mucosal Fold Anatomy and Middle Ear Ventilation Pathways
Built with ReportLab - produces a multi-page, diagram-rich PDF
"""

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.graphics.shapes import (
    Drawing, Rect, Ellipse, Line, Circle, Polygon, String,
    Path, Group, PolyLine
)
from reportlab.graphics import renderPDF
from reportlab.graphics.shapes import ArcPath
import math

# ── Colour palette ──────────────────────────────────────────────────────────
TEAL       = colors.HexColor("#0D6E8A")
TEAL_LIGHT = colors.HexColor("#E0F4F8")
TEAL_MID   = colors.HexColor("#5CB8D0")
AMBER      = colors.HexColor("#E8A020")
AMBER_LIGHT= colors.HexColor("#FFF3DC")
RED        = colors.HexColor("#C0392B")
RED_LIGHT  = colors.HexColor("#FDECEA")
GREEN      = colors.HexColor("#1A7A4A")
GREEN_LIGHT= colors.HexColor("#E8F8EE")
PURPLE     = colors.HexColor("#6B3FA0")
PURPLE_LIGHT=colors.HexColor("#F2EBF9")
BONE       = colors.HexColor("#F5EFE0")
BONE_DARK  = colors.HexColor("#D4C9A8")
MUCOSA     = colors.HexColor("#F0A090")
MUCOSA_LIGHT=colors.HexColor("#FAE0DA")
DARK       = colors.HexColor("#1A2535")
GRAY_LIGHT = colors.HexColor("#F4F6F8")
GRAY_MID   = colors.HexColor("#BDC3CC")

W, H = A4  # 595 x 842 pts

# ── Styles ───────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()

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

TITLE_STYLE  = make_style("Title2", "Normal",
    fontSize=26, fontName="Helvetica-Bold", textColor=DARK,
    alignment=TA_CENTER, spaceAfter=4)
SUBTITLE_STYLE = make_style("Sub", "Normal",
    fontSize=13, fontName="Helvetica", textColor=TEAL,
    alignment=TA_CENTER, spaceAfter=2)
CREDIT_STYLE = make_style("Credit", "Normal",
    fontSize=8, fontName="Helvetica", textColor=GRAY_MID,
    alignment=TA_CENTER)
H1_STYLE     = make_style("H1", "Normal",
    fontSize=15, fontName="Helvetica-Bold", textColor=colors.white,
    spaceBefore=0, spaceAfter=0, leftIndent=8)
H2_STYLE     = make_style("H2", "Normal",
    fontSize=12, fontName="Helvetica-Bold", textColor=TEAL,
    spaceBefore=10, spaceAfter=4)
BODY_STYLE   = make_style("Body2", "Normal",
    fontSize=9.5, fontName="Helvetica", textColor=DARK,
    spaceAfter=5, leading=14, alignment=TA_JUSTIFY)
BOLD_STYLE   = make_style("Bold2", "Normal",
    fontSize=9.5, fontName="Helvetica-Bold", textColor=DARK,
    spaceAfter=5, leading=14)
LABEL_STYLE  = make_style("Label", "Normal",
    fontSize=8, fontName="Helvetica", textColor=DARK)
CAPTION_STYLE= make_style("Caption", "Normal",
    fontSize=8, fontName="Helvetica-Oblique", textColor=colors.HexColor("#555555"),
    alignment=TA_CENTER, spaceBefore=2, spaceAfter=6)
KEY_STYLE    = make_style("Key", "Normal",
    fontSize=8.5, fontName="Helvetica", textColor=DARK, leading=13)
BOX_STYLE    = make_style("Box", "Normal",
    fontSize=9, fontName="Helvetica", textColor=DARK,
    leading=14, leftIndent=4, alignment=TA_LEFT)
SMALL_STYLE  = make_style("Small", "Normal",
    fontSize=8, fontName="Helvetica", textColor=DARK, leading=12)

# ── Helper: coloured header banner ───────────────────────────────────────────
def section_banner(text, color=TEAL, w=None):
    if w is None:
        w = W - 40*mm
    d = Drawing(w, 22)
    d.add(Rect(0, 0, w, 22, fillColor=color, strokeColor=None))
    d.add(String(8, 6, text,
                 fontName="Helvetica-Bold", fontSize=12,
                 fillColor=colors.white))
    return d

# ── Helper: small colour swatch legend row ───────────────────────────────────
def swatch_row(items):
    """items = list of (color, label)"""
    parts = []
    for col, lbl in items:
        d = Drawing(14, 10)
        d.add(Rect(0, 1, 12, 9, fillColor=col, strokeColor=colors.HexColor("#888888"), strokeWidth=0.5))
        parts.append(d)
        parts.append(Paragraph(f"<b>{lbl}</b>  ", KEY_STYLE))
    return parts

# ═══════════════════════════════════════════════════════════════════════════
# PAGE 1 DIAGRAM – Coronal cross-section of the middle ear
# ═══════════════════════════════════════════════════════════════════════════
def draw_coronal_section():
    """
    Schematic coronal cross-section showing:
    - Epitympanum (attic) vs. mesotympanum
    - Malleus, incus, stapes
    - Key mucosal folds
    - Isthmus anticus and posticus
    - Prussak's space
    - Eustachian tube opening
    - Ventilation arrows
    """
    DW, DH = 480, 370
    d = Drawing(DW, DH)

    # ── Background bony walls ───────────────────────────────────────────────
    # Outer bony shell
    d.add(Rect(10, 10, DW-20, DH-20,
               fillColor=BONE, strokeColor=BONE_DARK, strokeWidth=2, rx=8, ry=8))

    # ── Middle ear cavity ──────────────────────────────────────────────────
    # Mesotympanum (lower, freely ventilated)
    d.add(Rect(60, 55, 360, 130,
               fillColor=colors.HexColor("#D6EEF7"),
               strokeColor=TEAL_MID, strokeWidth=1.2))

    # Epitympanum / attic (upper, only via isthmus)
    d.add(Rect(60, 185, 360, 130,
               fillColor=colors.HexColor("#C8E6C9"),
               strokeColor=GREEN, strokeWidth=1.2))

    # Labels for spaces
    d.add(String(65, 125, "MESOTYMPANUM", fontName="Helvetica-Bold",
                 fontSize=9, fillColor=TEAL))
    d.add(String(65, 112, "(freely ventilated via ET)", fontName="Helvetica",
                 fontSize=7.5, fillColor=TEAL))

    d.add(String(65, 295, "EPITYMPANUM  /  ATTIC", fontName="Helvetica-Bold",
                 fontSize=9, fillColor=GREEN))
    d.add(String(65, 282, "(ventilated only via isthmus)", fontName="Helvetica",
                 fontSize=7.5, fillColor=GREEN))

    # ── Eustachian tube (bottom-left) ──────────────────────────────────────
    et_x, et_y = 60, 55
    d.add(Rect(et_x-40, et_y-30, 60, 28,
               fillColor=colors.HexColor("#BFD8F0"),
               strokeColor=TEAL, strokeWidth=1.2))
    d.add(String(et_x-38, et_y-20, "Eustachian", fontName="Helvetica-Bold",
                 fontSize=7, fillColor=TEAL))
    d.add(String(et_x-35, et_y-30, "Tube", fontName="Helvetica-Bold",
                 fontSize=7, fillColor=TEAL))
    # ET arrow into mesotympanum
    d.add(Line(et_x+18, et_y-16, et_x+60, et_y+20,
               strokeColor=TEAL, strokeWidth=1.5))
    d.add(Polygon([et_x+60, et_y+20, et_x+54, et_y+14, et_x+66, et_y+14],
                  fillColor=TEAL, strokeColor=TEAL))

    # ── OSSICLES ────────────────────────────────────────────────────────────
    # Malleus (handle descends, head in attic)
    # Head of malleus (attic)
    d.add(Ellipse(230, 270, 28, 22,
                  fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1.5))
    d.add(String(218, 262, "Head of", fontName="Helvetica", fontSize=7, fillColor=DARK))
    d.add(String(216, 253, "Malleus", fontName="Helvetica-Bold", fontSize=7, fillColor=DARK))
    # Neck of malleus
    d.add(Rect(225, 180, 10, 80, fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1))
    # Handle of malleus (mesotympanum, angles laterally)
    d.add(Line(230, 180, 215, 90, strokeColor=BONE_DARK, strokeWidth=8))
    d.add(Line(230, 180, 215, 90, strokeColor=DARK, strokeWidth=1.2))
    d.add(String(175, 82, "Handle of Malleus", fontName="Helvetica", fontSize=7, fillColor=DARK))

    # Incus body (attic, articulates with malleus head)
    d.add(Ellipse(295, 265, 25, 18,
                  fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1.5))
    d.add(String(285, 258, "Body of", fontName="Helvetica", fontSize=7, fillColor=DARK))
    d.add(String(285, 249, "Incus", fontName="Helvetica-Bold", fontSize=7, fillColor=DARK))
    # Long process of incus (descending into mesotympanum)
    d.add(Line(290, 248, 290, 145, strokeColor=BONE_DARK, strokeWidth=7))
    d.add(Line(290, 248, 290, 145, strokeColor=DARK, strokeWidth=1.2))

    # Stapes (mesotympanum, head at bottom of incus long process)
    d.add(Ellipse(290, 138, 18, 10,
                  fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1.2))
    d.add(String(297, 133, "Stapes", fontName="Helvetica-Bold", fontSize=7, fillColor=DARK))
    # Crura
    d.add(Line(278, 133, 268, 108, strokeColor=BONE_DARK, strokeWidth=4))
    d.add(Line(278, 133, 268, 108, strokeColor=DARK, strokeWidth=0.8))
    d.add(Line(302, 133, 312, 108, strokeColor=BONE_DARK, strokeWidth=4))
    d.add(Line(302, 133, 312, 108, strokeColor=DARK, strokeWidth=0.8))
    d.add(Line(268, 108, 312, 108, strokeColor=BONE_DARK, strokeWidth=5))
    d.add(Line(268, 108, 312, 108, strokeColor=DARK, strokeWidth=1))
    d.add(String(315, 104, "Footplate", fontName="Helvetica", fontSize=7, fillColor=DARK))

    # ── MUCOSAL FOLDS ───────────────────────────────────────────────────────
    # Tensor fold (anterior - separates attic from meso anteriorly)
    fold_y = 185  # diaphragm level
    d.add(Line(60, fold_y, 220, fold_y,   # anterior tensor fold
               strokeColor=MUCOSA, strokeWidth=3))
    d.add(Line(245, fold_y, 285, fold_y,  # gap = isthmus anticus
               strokeColor=colors.HexColor("#AAAAAA"), strokeWidth=0.5,
               strokeDashArray=[3,3]))
    d.add(Line(295, fold_y, 360, fold_y,  # interosseous / medial incudal fold
               strokeColor=MUCOSA, strokeWidth=3))
    d.add(Line(360, fold_y, 420, fold_y,  # posterior fold
               strokeColor=MUCOSA, strokeWidth=3))

    # Second gap = isthmus posticus (posterior to stapes)
    # already shown implicitly between 295-360 band

    # Lateral malleolar fold (lateral wall of Prussak's space)
    d.add(Line(220, fold_y, 220, 315, strokeColor=RED, strokeWidth=2))
    d.add(String(140, 320, "Lat. Malleolar", fontName="Helvetica", fontSize=7.5, fillColor=RED))
    d.add(String(140, 311, "Fold", fontName="Helvetica-Bold", fontSize=7.5, fillColor=RED))

    # Superior malleolar fold (top, horizontal)
    d.add(Line(200, 310, 250, 310, strokeColor=AMBER, strokeWidth=2))
    d.add(String(155, 324, "Sup. Malleolar Fold", fontName="Helvetica", fontSize=7, fillColor=AMBER))

    # Superior incudal fold (connects incus to tegmen)
    d.add(Line(285, 295, 285, 315, strokeColor=PURPLE, strokeWidth=2))
    d.add(String(325, 320, "Sup. Incudal Fold", fontName="Helvetica", fontSize=7, fillColor=PURPLE))

    # Posterior incudal ligament (incus to fossa incudis)
    d.add(Line(310, 255, 360, 260, strokeColor=PURPLE, strokeWidth=2,
               strokeDashArray=[4,2]))
    d.add(String(365, 258, "Post. Incudal Lig.", fontName="Helvetica", fontSize=7, fillColor=PURPLE))

    # Anterior malleolar fold label
    d.add(String(63, 192, "Anterior Malleolar / Tensor Fold", fontName="Helvetica-Bold",
                 fontSize=7.5, fillColor=MUCOSA))

    # Medial incudal fold label
    d.add(String(300, 192, "Medial Incudal Fold", fontName="Helvetica-Bold",
                 fontSize=7.5, fillColor=MUCOSA))

    # Plica stapedis (around stapes)
    d.add(Ellipse(290, 128, 28, 14, fillColor=None,
                  strokeColor=AMBER, strokeWidth=1.5, strokeDashArray=[3,2]))
    d.add(String(318, 122, "Plica Stapedis", fontName="Helvetica", fontSize=7, fillColor=AMBER))

    # ── ISTHMUS labels & arrows ──────────────────────────────────────────────
    # Isthmus anticus (between tensor fold end and stapes)
    d.add(Rect(220, 178, 28, 14,
               fillColor=colors.HexColor("#FFE0B2"),
               strokeColor=AMBER, strokeWidth=1.2))
    d.add(String(222, 182, "Isthmus", fontName="Helvetica-Bold", fontSize=6.5, fillColor=AMBER))
    d.add(String(222, 174, "Anticus", fontName="Helvetica-Bold", fontSize=6.5, fillColor=AMBER))

    # Isthmus posticus (posterior to stapes footplate area)
    d.add(Rect(358, 178, 28, 14,
               fillColor=colors.HexColor("#FFE0B2"),
               strokeColor=AMBER, strokeWidth=1.2))
    d.add(String(360, 182, "Isthmus", fontName="Helvetica-Bold", fontSize=6.5, fillColor=AMBER))
    d.add(String(360, 174, "Posticus", fontName="Helvetica-Bold", fontSize=6.5, fillColor=AMBER))

    # ── PRUSSAK'S SPACE ──────────────────────────────────────────────────────
    d.add(Rect(165, 190, 52, 110,
               fillColor=colors.HexColor("#FFD6D6"),
               strokeColor=RED, strokeWidth=1.5, strokeDashArray=[4,2]))
    d.add(String(168, 280, "Prussak's", fontName="Helvetica-Bold", fontSize=8, fillColor=RED))
    d.add(String(174, 270, "Space", fontName="Helvetica-Bold", fontSize=8, fillColor=RED))

    # Pars flaccida (lateral wall of Prussak's)
    d.add(Rect(145, 190, 18, 110,
               fillColor=colors.HexColor("#FFB5B5"),
               strokeColor=RED, strokeWidth=1.2))
    d.add(String(108, 242, "Pars", fontName="Helvetica-Bold", fontSize=7, fillColor=RED))
    d.add(String(103, 233, "Flaccida", fontName="Helvetica-Bold", fontSize=7, fillColor=RED))

    # ── VENTILATION ARROWS ───────────────────────────────────────────────────
    # Big blue arrow in mesotympanum = free air flow from ET
    d.add(Line(110, 100, 380, 100, strokeColor=TEAL, strokeWidth=2))
    d.add(Polygon([380, 100, 373, 95, 373, 105],
                  fillColor=TEAL, strokeColor=TEAL))
    d.add(String(220, 90, "Free airflow in mesotympanum", fontName="Helvetica-Oblique",
                 fontSize=7.5, fillColor=TEAL))

    # Upward arrows through isthmi into attic
    # Through isthmus anticus
    d.add(Line(234, 185, 234, 230, strokeColor=AMBER, strokeWidth=1.8))
    d.add(Polygon([234, 230, 229, 222, 239, 222],
                  fillColor=AMBER, strokeColor=AMBER))

    # Through isthmus posticus
    d.add(Line(372, 185, 372, 230, strokeColor=AMBER, strokeWidth=1.8))
    d.add(Polygon([372, 230, 367, 222, 377, 222],
                  fillColor=AMBER, strokeColor=AMBER))

    # Blocked isthmus indicator (cholesteatoma scenario) - small X on anticus
    # Not needed for base diagram

    # ── TEGMEN (top bony wall) ────────────────────────────────────────────────
    d.add(Rect(60, 315, 360, 20,
               fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1))
    d.add(String(215, 321, "TEGMEN", fontName="Helvetica-Bold", fontSize=8, fillColor=DARK))

    # ── TYMPANIC MEMBRANE indicator ──────────────────────────────────────────
    d.add(Line(60, 55, 60, 315, strokeColor=colors.HexColor("#8B6914"), strokeWidth=3))
    d.add(String(20, 180, "TM", fontName="Helvetica-Bold", fontSize=8, fillColor=colors.HexColor("#8B6914")))

    # ── PROMONTORY (medial wall) ──────────────────────────────────────────────
    d.add(Rect(415, 70, 15, 120,
               fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1))
    d.add(String(430, 128, "Promontory", fontName="Helvetica", fontSize=7, fillColor=DARK))

    # ── Oval window ──────────────────────────────────────────────────────────
    d.add(Ellipse(420, 118, 10, 7,
                  fillColor=colors.HexColor("#D0E8F0"), strokeColor=DARK, strokeWidth=1))
    d.add(String(430, 115, "Oval W.", fontName="Helvetica", fontSize=7, fillColor=DARK))

    # Round window
    d.add(Circle(420, 85, 6,
                 fillColor=colors.HexColor("#D0E8F0"), strokeColor=DARK, strokeWidth=1))
    d.add(String(430, 82, "Round W.", fontName="Helvetica", fontSize=7, fillColor=DARK))

    # ── Mucociliary pathways (dashed curved arrows) ──────────────────────────
    # Promontorial pathway
    d.add(Line(400, 80, 120, 80, strokeColor=colors.HexColor("#50A060"),
               strokeWidth=1.2, strokeDashArray=[5,3]))
    d.add(Polygon([120, 80, 128, 75, 128, 85],
                  fillColor=GREEN, strokeColor=GREEN))
    d.add(String(220, 68, "Promontorial mucociliary pathway", fontName="Helvetica-Oblique",
                 fontSize=6.5, fillColor=GREEN))

    # ── Border decoration ────────────────────────────────────────────────────
    d.add(Rect(2, 2, DW-4, DH-4,
               fillColor=None, strokeColor=TEAL_MID, strokeWidth=1.5, rx=6, ry=6))

    return d


# ═══════════════════════════════════════════════════════════════════════════
# PAGE 2 DIAGRAM – Superior view (attic diaphragm)
# ═══════════════════════════════════════════════════════════════════════════
def draw_attic_diaphragm():
    """
    Superior view of the epitympanum showing the diaphragm:
    tensor fold + interosseous fold + medial incudal fold
    with the two isthmus openings.
    """
    DW, DH = 420, 280
    d = Drawing(DW, DH)

    # Background
    d.add(Rect(0, 0, DW, DH, fillColor=BONE, strokeColor=BONE_DARK, strokeWidth=1.5, rx=6, ry=6))

    # Attic floor/diaphragm overall outline
    d.add(Ellipse(210, 140, 175, 110,
                  fillColor=colors.HexColor("#E8F5E9"),
                  strokeColor=GREEN, strokeWidth=2))

    # Malleus head
    d.add(Ellipse(175, 155, 35, 28,
                  fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1.5))
    d.add(String(156, 150, "Malleus Head", fontName="Helvetica-Bold", fontSize=8, fillColor=DARK))

    # Incus body
    d.add(Ellipse(240, 150, 32, 25,
                  fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1.5))
    d.add(String(226, 144, "Incus Body", fontName="Helvetica-Bold", fontSize=8, fillColor=DARK))

    # Tensor fold (anterior - from lateral wall to malleus neck, runs anteriorly)
    d.add(Line(70, 155, 140, 155, strokeColor=MUCOSA, strokeWidth=4))
    d.add(String(72, 162, "Tensor Fold (Anterior Malleolar Fold)", fontName="Helvetica-Bold",
                 fontSize=7.5, fillColor=MUCOSA))

    # Interosseous fold (between malleus and incus)
    d.add(Line(208, 150, 210, 150, strokeColor=PURPLE, strokeWidth=4))  # tiny gap visualised
    d.add(String(190, 130, "Interosseous fold", fontName="Helvetica", fontSize=7.5, fillColor=PURPLE))

    # Medial incudal fold (incus to medial wall)
    d.add(Line(272, 152, 340, 152, strokeColor=MUCOSA, strokeWidth=4))
    d.add(String(278, 162, "Medial Incudal Fold", fontName="Helvetica-Bold",
                 fontSize=7.5, fillColor=MUCOSA))

    # Isthmus anticus (gap - anterior)
    d.add(Rect(140, 143, 33, 22,
               fillColor=AMBER_LIGHT, strokeColor=AMBER, strokeWidth=1.5))
    d.add(String(142, 155, "Isthmus", fontName="Helvetica-Bold", fontSize=7, fillColor=AMBER))
    d.add(String(142, 146, "Anticus", fontName="Helvetica-Bold", fontSize=7, fillColor=AMBER))

    # Isthmus posticus (gap - posterior)
    d.add(Rect(275, 143, 33, 22,
               fillColor=AMBER_LIGHT, strokeColor=AMBER, strokeWidth=1.5))
    d.add(String(277, 155, "Isthmus", fontName="Helvetica-Bold", fontSize=7, fillColor=AMBER))
    d.add(String(277, 146, "Posticus", fontName="Helvetica-Bold", fontSize=7, fillColor=AMBER))

    # Arrows through isthmi (ventilation from below = upward in coronal; here = inward)
    d.add(Line(157, 130, 157, 143, strokeColor=AMBER, strokeWidth=2))
    d.add(Polygon([157, 143, 153, 137, 161, 137], fillColor=AMBER, strokeColor=AMBER))

    d.add(Line(291, 130, 291, 143, strokeColor=AMBER, strokeWidth=2))
    d.add(Polygon([291, 143, 287, 137, 295, 137], fillColor=AMBER, strokeColor=AMBER))

    d.add(String(125, 118, "Air enters via isthmi", fontName="Helvetica-Oblique",
                 fontSize=8, fillColor=AMBER))

    # Superior malleolar fold (lateral to malleus head)
    d.add(Line(148, 183, 170, 183, strokeColor=AMBER, strokeWidth=2.5))
    d.add(String(95, 188, "Sup. Malleolar Fold", fontName="Helvetica", fontSize=7.5, fillColor=AMBER))

    # Posterior incudal ligament
    d.add(Line(270, 155, 320, 175, strokeColor=PURPLE, strokeWidth=2,
               strokeDashArray=[4,2]))
    d.add(String(295, 180, "Post. Incudal Lig.", fontName="Helvetica", fontSize=7, fillColor=PURPLE))

    # Anterior (ant.epitympanum) label
    d.add(String(88, 230, "ANTERIOR", fontName="Helvetica-Bold", fontSize=9, fillColor=DARK))
    d.add(Line(135, 233, 180, 233, strokeColor=DARK, strokeWidth=0.8))

    # Posterior label
    d.add(String(285, 230, "POSTERIOR", fontName="Helvetica-Bold", fontSize=9, fillColor=DARK))
    d.add(Line(265, 233, 285, 233, strokeColor=DARK, strokeWidth=0.8))

    # Lateral label
    d.add(String(60, 55, "LATERAL", fontName="Helvetica-Bold", fontSize=9, fillColor=DARK))
    # Medial label
    d.add(String(335, 55, "MEDIAL", fontName="Helvetica-Bold", fontSize=9, fillColor=DARK))

    # COG bony septum
    d.add(Line(175, 185, 175, 220, strokeColor=DARK, strokeWidth=2))
    d.add(String(150, 222, "Cog (bony septum)", fontName="Helvetica-Oblique",
                 fontSize=7, fillColor=DARK))

    # Title
    d.add(String(95, 260, "Superior View: Attic Diaphragm and Isthmus Tympani",
                 fontName="Helvetica-Bold", fontSize=10, fillColor=DARK))

    d.add(Rect(1, 1, DW-2, DH-2,
               fillColor=None, strokeColor=TEAL_MID, strokeWidth=1.5, rx=6, ry=6))
    return d


# ═══════════════════════════════════════════════════════════════════════════
# PAGE 3 DIAGRAM – Cholesteatoma spread via folds
# ═══════════════════════════════════════════════════════════════════════════
def draw_cholesteatoma_spread():
    DW, DH = 450, 300
    d = Drawing(DW, DH)

    d.add(Rect(0, 0, DW, DH, fillColor=BONE, strokeColor=BONE_DARK, strokeWidth=1.5, rx=6, ry=6))

    # Cavities
    # Mesotympanum
    d.add(Rect(60, 30, 330, 100, fillColor=colors.HexColor("#D6EEF7"),
               strokeColor=TEAL_MID, strokeWidth=1.2))
    d.add(String(68, 50, "MESOTYMPANUM", fontName="Helvetica-Bold", fontSize=8, fillColor=TEAL))

    # Epitympanum
    d.add(Rect(60, 130, 330, 80, fillColor=colors.HexColor("#C8E6C9"),
               strokeColor=GREEN, strokeWidth=1.2))
    d.add(String(68, 195, "EPITYMPANUM", fontName="Helvetica-Bold", fontSize=8, fillColor=GREEN))

    # Prussak's space (left side)
    d.add(Rect(60, 130, 70, 80, fillColor=RED_LIGHT, strokeColor=RED, strokeWidth=1.5,
               strokeDashArray=[4,2]))
    d.add(String(63, 185, "Prussak's", fontName="Helvetica-Bold", fontSize=7.5, fillColor=RED))
    d.add(String(66, 175, "Space", fontName="Helvetica-Bold", fontSize=7.5, fillColor=RED))

    # Mastoid antrum
    d.add(Rect(390, 100, 55, 130, fillColor=colors.HexColor("#FFF9C4"),
               strokeColor=colors.HexColor("#F9A825"), strokeWidth=1.2))
    d.add(String(393, 165, "Mastoid", fontName="Helvetica-Bold", fontSize=7.5,
                 fillColor=colors.HexColor("#F57F17")))
    d.add(String(393, 155, "Antrum", fontName="Helvetica-Bold", fontSize=7.5,
                 fillColor=colors.HexColor("#F57F17")))

    # Aditus ad antrum
    d.add(Rect(390, 130, 10, 50, fillColor=colors.HexColor("#FFF9C4"),
               strokeColor=colors.HexColor("#F9A825"), strokeWidth=1))
    d.add(String(355, 157, "Aditus", fontName="Helvetica", fontSize=7,
                 fillColor=colors.HexColor("#F57F17")))

    # Cholesteatoma spread arrows (numbered steps)
    arrow_col = colors.HexColor("#C62828")

    # 1: Pars flaccida retraction → Prussak's
    d.add(String(18, 170, "①", fontName="Helvetica-Bold", fontSize=11, fillColor=arrow_col))
    d.add(Line(48, 170, 60, 170, strokeColor=arrow_col, strokeWidth=2))
    d.add(Polygon([60, 170, 54, 166, 54, 174], fillColor=arrow_col, strokeColor=arrow_col))

    # 2: Prussak's → posterior epitympanum
    d.add(String(138, 185, "②", fontName="Helvetica-Bold", fontSize=11, fillColor=arrow_col))
    d.add(Line(148, 170, 200, 170, strokeColor=arrow_col, strokeWidth=2))
    d.add(Polygon([200, 170, 194, 166, 194, 174], fillColor=arrow_col, strokeColor=arrow_col))

    # 3: Post epitympanum → antrum via aditus
    d.add(String(330, 185, "③", fontName="Helvetica-Bold", fontSize=11, fillColor=arrow_col))
    d.add(Line(370, 170, 390, 170, strokeColor=arrow_col, strokeWidth=2))
    d.add(Polygon([390, 170, 384, 166, 384, 174], fillColor=arrow_col, strokeColor=arrow_col))

    # 4: Down to posterior mesotympanum
    d.add(String(310, 155, "④", fontName="Helvetica-Bold", fontSize=11, fillColor=arrow_col))
    d.add(Line(330, 145, 330, 130, strokeColor=arrow_col, strokeWidth=2))
    d.add(Polygon([330, 130, 326, 137, 334, 137], fillColor=arrow_col, strokeColor=arrow_col))

    # Ossicles (schematic)
    # Malleus
    d.add(Ellipse(195, 175, 20, 16, fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1.2))
    d.add(String(183, 169, "Malleus", fontName="Helvetica", fontSize=6.5, fillColor=DARK))
    # Incus
    d.add(Ellipse(245, 172, 18, 14, fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1.2))
    d.add(String(237, 166, "Incus", fontName="Helvetica", fontSize=6.5, fillColor=DARK))

    # Fold diaphragm line
    d.add(Line(130, 130, 390, 130, strokeColor=MUCOSA, strokeWidth=3))
    d.add(String(155, 118, "Mucosal fold diaphragm (tensor + interosseous + medial incudal)",
                 fontName="Helvetica-Oblique", fontSize=7, fillColor=MUCOSA))

    # Blocked isthmus marker
    d.add(Rect(150, 124, 22, 12, fillColor=colors.HexColor("#FF8F00"),
               strokeColor=AMBER, strokeWidth=1))
    d.add(String(153, 127, "Isthmus", fontName="Helvetica-Bold", fontSize=6, fillColor=DARK))
    d.add(String(156, 120, "⚠ Risk", fontName="Helvetica-Bold", fontSize=6, fillColor=DARK))

    # Pars flaccida
    d.add(Rect(40, 130, 18, 80, fillColor=colors.HexColor("#FFCCBC"),
               strokeColor=colors.HexColor("#BF360C"), strokeWidth=1.5))
    d.add(String(8, 168, "Pars", fontName="Helvetica-Bold", fontSize=7,
                 fillColor=colors.HexColor("#BF360C")))
    d.add(String(5, 159, "Flaccida", fontName="Helvetica-Bold", fontSize=7,
                 fillColor=colors.HexColor("#BF360C")))

    # ET opening bottom left
    d.add(Rect(60, 12, 50, 18, fillColor=colors.HexColor("#BFD8F0"),
               strokeColor=TEAL, strokeWidth=1))
    d.add(String(62, 18, "Eustachian Tube", fontName="Helvetica", fontSize=7, fillColor=TEAL))

    d.add(String(80, 276, "Cholesteatoma Spread Pathways via Mucosal Fold Compartments",
                 fontName="Helvetica-Bold", fontSize=10, fillColor=DARK))

    d.add(Rect(1, 1, DW-2, DH-2,
               fillColor=None, strokeColor=RED, strokeWidth=1.5, rx=6, ry=6))
    return d


# ═══════════════════════════════════════════════════════════════════════════
# MUCOCILIARY PATHWAYS DIAGRAM
# ═══════════════════════════════════════════════════════════════════════════
def draw_mucociliary():
    DW, DH = 420, 220
    d = Drawing(DW, DH)

    d.add(Rect(0, 0, DW, DH, fillColor=GRAY_LIGHT, strokeColor=GRAY_MID, strokeWidth=1.5, rx=6, ry=6))

    # Middle ear outline
    d.add(Rect(40, 30, 340, 155, fillColor=colors.HexColor("#E8F4F8"),
               strokeColor=TEAL, strokeWidth=1.5, rx=4, ry=4))

    # Eustachian tube (right)
    d.add(Rect(380, 65, 38, 30, fillColor=colors.HexColor("#BFD8F0"),
               strokeColor=TEAL, strokeWidth=1.2))
    d.add(String(382, 78, "Eust.", fontName="Helvetica-Bold", fontSize=7.5, fillColor=TEAL))
    d.add(String(382, 69, "Tube", fontName="Helvetica-Bold", fontSize=7.5, fillColor=TEAL))

    # Promontory (medial wall - left)
    d.add(Rect(25, 60, 15, 80, fillColor=BONE_DARK, strokeColor=DARK, strokeWidth=1))
    d.add(String(10, 97, "Prom.", fontName="Helvetica", fontSize=7, fillColor=DARK))

    # ── Three mucociliary pathways ───────────────────────────────────────────
    # 1. Epitympanic (top, green)
    epi_y = 165
    for x in range(60, 370, 18):
        d.add(Line(x, epi_y, x+12, epi_y, strokeColor=GREEN, strokeWidth=2))
        d.add(Polygon([x+12, epi_y, x+7, epi_y+3, x+7, epi_y-3],
                      fillColor=GREEN, strokeColor=GREEN))
    d.add(String(50, 175, "Epitympanic pathway", fontName="Helvetica-Bold",
                 fontSize=8, fillColor=GREEN))

    # 2. Promontorial (middle, blue)
    prom_y = 110
    for x in range(60, 370, 18):
        d.add(Line(x, prom_y, x+12, prom_y, strokeColor=TEAL, strokeWidth=2))
        d.add(Polygon([x+12, prom_y, x+7, prom_y+3, x+7, prom_y-3],
                      fillColor=TEAL, strokeColor=TEAL))
    d.add(String(50, 120, "Promontorial pathway", fontName="Helvetica-Bold",
                 fontSize=8, fillColor=TEAL))

    # 3. Hypotympanic (bottom, amber - LARGEST)
    hypo_y = 50
    for x in range(60, 370, 18):
        d.add(Line(x, hypo_y, x+12, hypo_y, strokeColor=AMBER, strokeWidth=2.5))
        d.add(Polygon([x+12, hypo_y, x+7, hypo_y+3, x+7, hypo_y-3],
                      fillColor=AMBER, strokeColor=AMBER))
    d.add(String(50, 40, "Hypotympanic pathway (largest)", fontName="Helvetica-Bold",
                 fontSize=8, fillColor=AMBER))

    # All converge at ET
    d.add(Line(370, 165, 380, 80, strokeColor=GREEN, strokeWidth=1.5))
    d.add(Line(370, 110, 380, 80, strokeColor=TEAL, strokeWidth=1.5))
    d.add(Line(370, 50, 380, 80, strokeColor=AMBER, strokeWidth=2))

    d.add(String(70, 200, "Three Mucociliary Pathways - All converge at the ET orifice",
                 fontName="Helvetica-Bold", fontSize=9.5, fillColor=DARK))

    d.add(Rect(1, 1, DW-2, DH-2, fillColor=None, strokeColor=TEAL_MID,
               strokeWidth=1.2, rx=6, ry=6))
    return d


# ═══════════════════════════════════════════════════════════════════════════
# BUILD THE PDF
# ═══════════════════════════════════════════════════════════════════════════
def build_pdf(out_path):
    doc = SimpleDocTemplate(
        out_path,
        pagesize=A4,
        leftMargin=18*mm, rightMargin=18*mm,
        topMargin=16*mm, bottomMargin=16*mm,
        title="Middle Ear Mucosal Fold Anatomy & Ventilation Pathways",
        author="Orris Medical Reference"
    )

    story = []

    # ── COVER BANNER ─────────────────────────────────────────────────────────
    cover = Drawing(W - 36*mm, 60)
    cover.add(Rect(0, 0, W - 36*mm, 60, fillColor=TEAL, strokeColor=None, rx=6, ry=6))
    cover.add(String(18, 32, "MIDDLE EAR MUCOSAL FOLD ANATOMY",
                     fontName="Helvetica-Bold", fontSize=19, fillColor=colors.white))
    cover.add(String(18, 14, "AND VENTILATION PATHWAYS  |  Visual Reference Guide",
                     fontName="Helvetica", fontSize=12, fillColor=colors.HexColor("#B2EBF2")))
    story.append(cover)
    story.append(Spacer(1, 6*mm))

    # ── Introductory text ────────────────────────────────────────────────────
    story.append(Paragraph(
        "The middle ear mucosa behaves like peritoneum - it drapes over ossicles, ligaments, tendons and bony walls "
        "to form a series of folds and recesses. These folds compartmentalise the tympanic cavity and directly govern "
        "airflow between the mesotympanum, epitympanum and mastoid system. "
        "Understanding their anatomy is essential for explaining otitis media, cholesteatoma formation and surgical planning.",
        BODY_STYLE))
    story.append(Spacer(1, 3*mm))

    # ══════════════════════════════════════════════════════════════════════════
    # SECTION 1 - Coronal Cross-section
    # ══════════════════════════════════════════════════════════════════════════
    story.append(section_banner("SECTION 1 — Coronal Cross-Section: Key Folds and Spaces"))
    story.append(Spacer(1, 3*mm))

    story.append(draw_coronal_section())
    story.append(Paragraph(
        "Fig 1. Schematic coronal cross-section of the right middle ear. "
        "The mucosal fold diaphragm (tensor fold + medial incudal fold) separates the epitympanum (green) from "
        "the mesotympanum (blue). The isthmus tympani anticus and posticus are the sole air conduits into the attic. "
        "Prussak's space (pink) lies lateral to the malleus neck and medial to the pars flaccida.",
        CAPTION_STYLE))

    story.append(Spacer(1, 4*mm))

    # ── Legend ──────────────────────────────────────────────────────────────
    story.append(section_banner("COLOUR KEY", color=colors.HexColor("#455A64"), w=W - 36*mm))
    story.append(Spacer(1, 2*mm))

    key_data = [
        [colors.HexColor("#D6EEF7"), "Mesotympanum (freely ventilated)"],
        [colors.HexColor("#C8E6C9"), "Epitympanum / Attic (isthmus-dependent)"],
        [RED_LIGHT,                  "Prussak's space"],
        [AMBER_LIGHT,                "Isthmus tympani anticus / posticus"],
        [MUCOSA,                     "Mucosal folds (tensor, interosseous, medial incudal)"],
        [AMBER,                      "Plica stapedis / superior malleolar fold"],
        [PURPLE,                     "Incudal folds / posterior incudal ligament"],
        [BONE_DARK,                  "Ossicles (malleus, incus, stapes)"],
        [TEAL,                       "Airflow / ventilation direction"],
    ]
    for col, label in key_data:
        kd = Drawing(12, 10)
        kd.add(Rect(0, 1, 11, 9, fillColor=col,
                    strokeColor=colors.HexColor("#777777"), strokeWidth=0.5))
        row_tbl = Table([[kd, Paragraph(label, KEY_STYLE)]], colWidths=[16, 130*mm])
        row_tbl.setStyle(TableStyle([("VALIGN", (0,0), (-1,-1), "MIDDLE"),
                                     ("LEFTPADDING",(0,0),(-1,-1),2),
                                     ("TOPPADDING",(0,0),(-1,-1),1),
                                     ("BOTTOMPADDING",(0,0),(-1,-1),1)]))
        story.append(row_tbl)

    story.append(PageBreak())

    # ══════════════════════════════════════════════════════════════════════════
    # SECTION 2 – Named Folds Reference Table
    # ══════════════════════════════════════════════════════════════════════════
    story.append(section_banner("SECTION 2 — Named Mucosal Folds: Anatomy and Function"))
    story.append(Spacer(1, 4*mm))

    header_style = ParagraphStyle("TH", parent=base["Normal"],
        fontSize=9, fontName="Helvetica-Bold", textColor=colors.white, alignment=TA_CENTER)
    cell_style   = ParagraphStyle("TC", parent=base["Normal"],
        fontSize=8.5, fontName="Helvetica", textColor=DARK, alignment=TA_LEFT, leading=13)

    def th(txt): return Paragraph(txt, header_style)
    def td(txt): return Paragraph(txt, cell_style)

    table_data = [
        [th("Fold / Structure"), th("Location"), th("Boundaries / Attachments"), th("Ventilation Role")],
        [td("<b>Tensor fold</b>\n(Ant. malleolar fold)"),
         td("Anterior attic diaphragm"),
         td("Tensor tympani tendon → lateral malleolar fold"),
         td("Forms the anterior limb of the epitympanum diaphragm; closes off attic anteriorly")],
        [td("<b>Lateral malleolar fold</b>"),
         td("Lateral wall of Prussak's space"),
         td("Runs from notch of Rivinus to malleus neck"),
         td("Defines Prussak's space; restricts lateral attic ventilation")],
        [td("<b>Superior malleolar fold</b>"),
         td("Superior, over malleus head"),
         td("Tegmen → malleus head / neck"),
         td("Suspends malleus; part of attic roof lining")],
        [td("<b>Interosseous fold</b>"),
         td("Between malleus head and incus body"),
         td("Malleus head → incus body"),
         td("Central component of the diaphragm; partially closes the attic floor")],
        [td("<b>Medial incudal fold</b>"),
         td("Medial to incus body"),
         td("Incus body → medial attic wall"),
         td("Closes off medial attic; with tensor and interosseous folds creates complete diaphragm")],
        [td("<b>Superior incudal fold</b>"),
         td("Superior to incus body"),
         td("Incus → tegmen tympani"),
         td("Suspends incus; carries blood supply")],
        [td("<b>Posterior incudal ligament</b>"),
         td("Posterior to short process of incus"),
         td("Short process of incus → fossa incudis"),
         td("Tethers incus; not a major airflow determinant")],
        [td("<b>Plica stapedis</b>\n(Obturatoria stapedi)"),
         td("Around stapes"),
         td("Envelops stapes superstructure and stapedius tendon"),
         td("Wraps stapes; lies between the two isthmi")],
        [td("<b>Anterior fold of von Tröltsch</b>"),
         td("Anterior to malleus handle"),
         td("Between anterior canal wall and malleus handle"),
         td("Bounds the anterior recess (pouch); may retain squamous debris")],
        [td("<b>Posterior fold of von Tröltsch</b>"),
         td("Posterior to malleus handle"),
         td("Posterior canal wall → malleus handle"),
         td("Bounds the posterior recess; cholesteatoma can originate here")],
    ]

    col_ws = [42*mm, 30*mm, 62*mm, 64*mm]
    tbl = Table(table_data, colWidths=col_ws, repeatRows=1)
    tbl.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,0), TEAL),
        ("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.white, TEAL_LIGHT]),
        ("GRID",          (0,0), (-1,-1), 0.5, GRAY_MID),
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
        ("TOPPADDING",    (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 4),
        ("LEFTPADDING",   (0,0), (-1,-1), 5),
        ("RIGHTPADDING",  (0,0), (-1,-1), 5),
        ("LINEBELOW",     (0,0), (-1,0), 1.5, TEAL),
    ]))
    story.append(tbl)

    story.append(Spacer(1, 6*mm))

    # ── Attic diaphragm diagram ──────────────────────────────────────────────
    story.append(section_banner("Attic Diaphragm — Superior View", color=GREEN))
    story.append(Spacer(1, 3*mm))
    story.append(draw_attic_diaphragm())
    story.append(Paragraph(
        "Fig 2. Superior (axial) view of the epitympanum. The tensor fold (anteriorly), interosseous fold "
        "(centrally) and medial incudal fold (posteriorly) together form the attic diaphragm. "
        "The only openings in this diaphragm are the isthmus tympani anticus (anterior to stapes) "
        "and the isthmus tympani posticus (posterior to stapes).",
        CAPTION_STYLE))

    story.append(PageBreak())

    # ══════════════════════════════════════════════════════════════════════════
    # SECTION 3 – Ventilation Pathways
    # ══════════════════════════════════════════════════════════════════════════
    story.append(section_banner("SECTION 3 — Ventilation Pathways: Mesotympanum vs. Epitympanum"))
    story.append(Spacer(1, 4*mm))

    # Two-column layout: mesotympanum vs. epitympanum
    meso_text = [
        Paragraph("<b>Mesotympanum</b>", H2_STYLE),
        Paragraph(
            "Directly receives air from the Eustachian tube opening. "
            "Air floods the mesotympanum freely during each swallowing act that opens the ET. "
            "This space is therefore well-ventilated under normal conditions.",
            BODY_STYLE),
        Paragraph("<b>Key features:</b>", BOLD_STYLE),
        Paragraph("- Bounded by TM laterally, promontory medially", BODY_STYLE),
        Paragraph("- Contains oval window, round window, stapes footplate", BODY_STYLE),
        Paragraph("- Sinus tympani: posterior recess that may harbor occult cholesteatoma", BODY_STYLE),
        Paragraph("- ET orifice is the direct air source", BODY_STYLE),
    ]

    epi_text = [
        Paragraph("<b>Epitympanum (Attic)</b>", H2_STYLE),
        Paragraph(
            "Does <b>not</b> receive air directly from the ET. "
            "Its only air supply is through the two tympanic isthmi - narrow openings in the mucosal fold diaphragm. "
            "Any process blocking the isthmus cuts off epitympanic ventilation.",
            BODY_STYLE),
        Paragraph("<b>Subdivisions:</b>", BOLD_STYLE),
        Paragraph("- Prussak's space (lateral, between pars flaccida and malleus neck)", BODY_STYLE),
        Paragraph("- Anterior epitympanum (supratubal recess, anterior to cog)", BODY_STYLE),
        Paragraph("- Posterior epitympanum (communicates with aditus ad antrum)", BODY_STYLE),
        Paragraph("- Isthmus anticus: anterior to stapes superstructure", BODY_STYLE),
        Paragraph("- Isthmus posticus: posterior to stapes superstructure", BODY_STYLE),
    ]

    meso_inner = [[p] for p in meso_text]
    epi_inner  = [[p] for p in epi_text]

    from reportlab.platypus import FrameBreak

    col_w = (W - 36*mm - 8*mm) / 2
    meso_tbl = Table([[p] for p in meso_text], colWidths=[col_w])
    meso_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#E8F4FB")),
        ("BOX", (0,0), (-1,-1), 1, TEAL),
        ("TOPPADDING", (0,0), (-1,-1), 3),
        ("BOTTOMPADDING", (0,0), (-1,-1), 3),
        ("LEFTPADDING", (0,0), (-1,-1), 6),
    ]))

    epi_tbl = Table([[p] for p in epi_text], colWidths=[col_w])
    epi_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#E8F5E9")),
        ("BOX", (0,0), (-1,-1), 1, GREEN),
        ("TOPPADDING", (0,0), (-1,-1), 3),
        ("BOTTOMPADDING", (0,0), (-1,-1), 3),
        ("LEFTPADDING", (0,0), (-1,-1), 6),
    ]))

    side_by_side = Table([[meso_tbl, epi_tbl]], colWidths=[col_w + 4*mm, col_w + 4*mm])
    side_by_side.setStyle(TableStyle([
        ("VALIGN", (0,0), (-1,-1), "TOP"),
        ("LEFTPADDING", (0,0), (-1,-1), 0),
        ("RIGHTPADDING", (0,0), (-1,-1), 4),
    ]))
    story.append(side_by_side)

    story.append(Spacer(1, 5*mm))

    # Mucociliary diagram
    story.append(section_banner("Mucociliary Clearance Pathways", color=GREEN))
    story.append(Spacer(1, 3*mm))
    story.append(draw_mucociliary())
    story.append(Paragraph(
        "Fig 3. Three mucociliary clearance pathways within the tympanic cavity. "
        "All three converge at the Eustachian tube tympanic orifice. "
        "The hypotympanic pathway is the largest and most important. "
        "Ciliated epithelium is more widespread in younger individuals.",
        CAPTION_STYLE))

    story.append(Spacer(1, 4*mm))

    # ── Isthmus box ──────────────────────────────────────────────────────────
    isthmus_data = [
        [Paragraph("<b>THE TYMPANIC ISTHMUS — Summary</b>", ParagraphStyle("IH",parent=base["Normal"],
            fontSize=10, fontName="Helvetica-Bold", textColor=colors.white))],
        [Paragraph(
            "<b>Isthmus tympani anticus:</b>  Located anterior to the stapes superstructure, "
            "between the end of the tensor fold and the plica stapedis.<br/><br/>"
            "<b>Isthmus tympani posticus:</b>  Located posterior to the stapes superstructure, "
            "between the medial incudal fold and the posterior mesotympanic wall.<br/><br/>"
            "Together these two openings are the <b>sole route</b> for air to enter the epitympanum "
            "from the Eustachian tube. The mesotympanum acts as an antechamber; air rises "
            "through the isthmi into the attic by the pressure gradient created with each ET opening.<br/><br/>"
            "<b>Normal dimensions:</b>  Both isthmi are narrow (approximately 1–2 mm). "
            "Even small amounts of mucosal oedema or granulation tissue can block them entirely.",
            BOX_STYLE)],
    ]
    isthmus_tbl = Table(isthmus_data, colWidths=[W - 36*mm])
    isthmus_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (0,0), AMBER),
        ("BACKGROUND", (0,1), (0,1), AMBER_LIGHT),
        ("BOX", (0,0), (-1,-1), 1.5, AMBER),
        ("INNERGRID", (0,0), (-1,-1), 0.5, AMBER),
        ("TOPPADDING", (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
    ]))
    story.append(isthmus_tbl)

    story.append(PageBreak())

    # ══════════════════════════════════════════════════════════════════════════
    # SECTION 4 – Cholesteatoma and Pathology
    # ══════════════════════════════════════════════════════════════════════════
    story.append(section_banner("SECTION 4 — Pathology: Isthmus Obstruction and Cholesteatoma",
                                color=RED))
    story.append(Spacer(1, 4*mm))

    story.append(draw_cholesteatoma_spread())
    story.append(Paragraph(
        "Fig 4. Cholesteatoma spread pathways defined by mucosal fold compartments. "
        "① Pars flaccida retraction enters Prussak's space. "
        "② Keratin migrates posteriorly through the posterior epitympanum. "
        "③ Extension into the mastoid antrum via the aditus ad antrum. "
        "④ Inferior spread to the posterior mesotympanum. "
        "Obstruction of the isthmus tympani (⚠) perpetuates negative pressure and drives retraction.",
        CAPTION_STYLE))

    story.append(Spacer(1, 4*mm))

    # Pathology table
    story.append(section_banner("Clinical Consequences of Fold/Isthmus Pathology", color=RED))
    story.append(Spacer(1, 3*mm))

    path_data = [
        [th("Pathology"), th("Mechanism"), th("Result"), th("Clinical Correlate")],
        [td("<b>Isthmus obstruction</b>"),
         td("Mucosal oedema, granulation, fold fibrosis, or cholesteatoma mass blocks one or both isthmi"),
         td("Loss of epitympanic air; negative pressure builds in attic"),
         td("Attic retraction pocket, pars flaccida cholesteatoma")],
        [td("<b>Congenital fold defects</b>"),
         td("Incomplete development of tensor or interosseous fold during embryogenesis"),
         td("Abnormal airflow compartmentalisation from birth"),
         td("Recurrent otitis media, persistent effusion in attic")],
        [td("<b>Mucosal inflammation\n(OME/CSOM)</b>"),
         td("Subepithelial oedema and fibrous thickening of folds reduces isthmus cross-section"),
         td("Progressive epitympanic under-ventilation"),
         td("Chronic glue ear; bimodal effusion in meso- and epitympanum")],
        [td("<b>Prussak's space\nretraction</b>"),
         td("Lateral malleolar fold weakness + chronic negative pressure allows pars flaccida to retract medially"),
         td("Keratin accumulates, expands via fold-defined pathways"),
         td("Attic cholesteatoma; scutum erosion on CT; ossicular destruction")],
        [td("<b>Cholesteatoma\nblocking aditus</b>"),
         td("Expanding matrix in posterior epitympanum obstructs aditus ad antrum"),
         td("Mastoid ventilation fails; closed mastoid air cell system"),
         td("Coalescent mastoid disease; epidural/lateral sinus involvement")],
    ]
    path_tbl = Table(path_data, colWidths=[36*mm, 50*mm, 46*mm, 66*mm], repeatRows=1)
    path_tbl.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,0), RED),
        ("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.white, RED_LIGHT]),
        ("GRID",          (0,0), (-1,-1), 0.5, GRAY_MID),
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
        ("TOPPADDING",    (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 4),
        ("LEFTPADDING",   (0,0), (-1,-1), 5),
        ("RIGHTPADDING",  (0,0), (-1,-1), 5),
        ("LINEBELOW",     (0,0), (-1,0), 1.5, RED),
    ]))
    story.append(path_tbl)

    story.append(PageBreak())

    # ══════════════════════════════════════════════════════════════════════════
    # SECTION 5 – Quick-reference summary card
    # ══════════════════════════════════════════════════════════════════════════
    story.append(section_banner("SECTION 5 — Surgical Anatomy Quick-Reference", color=PURPLE))
    story.append(Spacer(1, 4*mm))

    # Surgical pearls
    pearls = [
        ("<b>The isthmus anticus</b> lies anterior to the stapes superstructure, "
         "between the tensor fold edge and the plica stapedis."),
        ("<b>The isthmus posticus</b> lies posterior to the stapes, between "
         "the medial incudal fold and the posterior tympanic wall."),
        ("<b>The cog</b> is a bony spur from the tegmen in the coronal plane; "
         "it divides the anterior from posterior epitympanum and must be removed "
         "to fully visualise the supratubal recess."),
        ("<b>Prussak's space</b>: medial to pars flaccida, lateral to malleus neck, "
         "inferior to the lateral malleolar fold. The origin of most attic cholesteatomas."),
        ("<b>Removal of incus + malleus head</b> is required in attic cholesteatoma surgery "
         "to access and clear disease in the anterior epitympanum."),
        ("<b>The posterior pouch of von Tröltsch</b> (posterior to malleus handle, "
         "anterior to chorda tympani) is a starting point for pars tensa retractions."),
        ("<b>Mucociliary flow</b> runs in three streams (epitympanic, promontorial, hypotympanic), "
         "all converging at the ET tympanic orifice. The hypotympanic stream is the largest."),
        ("<b>Bony dehiscence</b> of the facial nerve is most common above the oval window "
         "(tympanic segment, 55%) — the nerve runs just superior to the cochleariform process "
         "as a reliable landmark for its mid-portion."),
    ]

    for i, pearl in enumerate(pearls, 1):
        p_tbl = Table([[
            Paragraph(f"{i}", ParagraphStyle("Num", parent=base["Normal"],
                fontSize=14, fontName="Helvetica-Bold",
                textColor=colors.white, alignment=TA_CENTER)),
            Paragraph(pearl, BOX_STYLE)
        ]], colWidths=[12*mm, W - 36*mm - 16*mm])
        p_tbl.setStyle(TableStyle([
            ("BACKGROUND", (0,0), (0,0), PURPLE),
            ("BACKGROUND", (1,0), (1,0), PURPLE_LIGHT),
            ("BOX", (0,0), (-1,-1), 0.8, PURPLE),
            ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
            ("TOPPADDING", (0,0), (-1,-1), 5),
            ("BOTTOMPADDING", (0,0), (-1,-1), 5),
            ("LEFTPADDING", (0,0), (-1,-1), 6),
            ("RIGHTPADDING", (0,0), (-1,-1), 6),
        ]))
        story.append(p_tbl)
        story.append(Spacer(1, 2*mm))

    story.append(Spacer(1, 4*mm))

    # Embryology note
    story.append(section_banner("Embryological Note", color=colors.HexColor("#455A64")))
    story.append(Spacer(1, 3*mm))
    story.append(Paragraph(
        "The future Eustachian tube lumen and middle ear spaces are formed by 8 months' gestation. "
        "The ossicles and their associated muscles, tendons and ligaments form from the first and second "
        "branchial arch mesenchyme, generating the complex series of mucosal folds as the endodermal "
        "epithelium of the tubotympanic recess envelopes each structure in turn. "
        "The epitympanum and mastoid antrum are the last spaces to pneumatise. "
        "Congenital anomalies of the folds - particularly incomplete formation of the tensor fold - "
        "can predispose to inadequate epitympanic ventilation from birth.",
        BODY_STYLE))

    story.append(Spacer(1, 5*mm))

    # Source attribution
    story.append(HRFlowable(width="100%", thickness=0.5, color=GRAY_MID))
    story.append(Spacer(1, 2*mm))
    story.append(Paragraph(
        "<b>Sources:</b>  Scott-Brown's Otorhinolaryngology Head &amp; Neck Surgery, 8th ed. (Vol 2) — "
        "Sections: 'The middle ear mucosal folds', 'The mucosa of the tympanic cavity', "
        "'Derivatives of the first and second branchial arches'.  |  "
        "Cummings Otolaryngology Head and Neck Surgery — Chapters 126 (Endoscopic Ear Anatomy, "
        "Middle Ear Spaces, Fig. 126.10) and 128.  |  "
        "Proctor B: The development of the middle ear spaces and their surgical significance (1964).",
        CREDIT_STYLE))

    doc.build(story)
    print(f"PDF saved to: {out_path}")


if __name__ == "__main__":
    out = "/home/daytona/workspace/middle-ear-guide/Mucosal_Fold_Ventilation_Guide.pdf"
    build_pdf(out)
Your credits are exhausted. You can purchase a top-up or subscribe to a plan to continue using Orris. If you're already subscribed, your daily credits will reset tomorrow.
This is a shared conversation. Sign in to Orris to start your own chat.