attachment
attachment
attachment
attachment
attachment
attachment

Give me pdf foR 5mark on tentorium cerebelli with diagram tables Flowchart and points By Refer this & add extra points if needed

analyse_media
analyse_media
analyse_media
Reading File
Running Command

mkdir -p /tmp/workspace/tentorium-cerebelli && ls /tmp/workspace/tentorium-cerebelli/

Writing File

~/tentorium-cerebelli/make_pdf.py

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

OUTPUT = "/tmp/workspace/tentorium-cerebelli/Tentorium_Cerebelli_5mark.pdf"

# ── Colour palette ──────────────────────────────────────────────────────────
DARK_BLUE   = colors.HexColor("#1a3a5c")
MED_BLUE    = colors.HexColor("#2563a8")
LIGHT_BLUE  = colors.HexColor("#d6e8f7")
TEAL        = colors.HexColor("#0e7c7b")
TEAL_LIGHT  = colors.HexColor("#d0f0ef")
AMBER       = colors.HexColor("#e0810a")
AMBER_LIGHT = colors.HexColor("#fff3d6")
GREEN       = colors.HexColor("#1e7b34")
GREEN_LIGHT = colors.HexColor("#d4edda")
RED         = colors.HexColor("#b71c1c")
RED_LIGHT   = colors.HexColor("#fdecea")
GREY_BG     = colors.HexColor("#f5f7fa")
GREY_LINE   = colors.HexColor("#c0ccd8")
WHITE       = colors.white
BLACK       = colors.HexColor("#1a1a2e")

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=1.8*cm, rightMargin=1.8*cm,
    topMargin=1.8*cm, bottomMargin=1.8*cm,
    title="Tentorium Cerebelli – 5-Mark Notes",
    author="Anatomy Quick Notes"
)

W = A4[0] - 3.6*cm   # usable width

styles = getSampleStyleSheet()

# Custom styles
title_style = ParagraphStyle(
    "TitleStyle", parent=styles["Title"],
    fontSize=20, textColor=WHITE, alignment=TA_CENTER,
    spaceAfter=4, spaceBefore=0, fontName="Helvetica-Bold",
    leading=24
)
subtitle_style = ParagraphStyle(
    "SubTitle", parent=styles["Normal"],
    fontSize=11, textColor=colors.HexColor("#cce0f5"), alignment=TA_CENTER,
    spaceAfter=0, fontName="Helvetica-Oblique"
)
h1_style = ParagraphStyle(
    "H1", parent=styles["Heading1"],
    fontSize=13, textColor=WHITE, fontName="Helvetica-Bold",
    spaceBefore=8, spaceAfter=2, leading=16,
    backColor=DARK_BLUE, borderPad=4
)
h2_style = ParagraphStyle(
    "H2", parent=styles["Heading2"],
    fontSize=11, textColor=DARK_BLUE, fontName="Helvetica-Bold",
    spaceBefore=6, spaceAfter=2, leading=14,
    borderPad=2
)
body_style = ParagraphStyle(
    "Body", parent=styles["Normal"],
    fontSize=9.5, textColor=BLACK, fontName="Helvetica",
    spaceAfter=3, leading=14, alignment=TA_JUSTIFY
)
bullet_style = ParagraphStyle(
    "Bullet", parent=styles["Normal"],
    fontSize=9.5, textColor=BLACK, fontName="Helvetica",
    leftIndent=14, firstLineIndent=-10, spaceAfter=2, leading=13
)
small_style = ParagraphStyle(
    "Small", parent=styles["Normal"],
    fontSize=8.5, textColor=colors.HexColor("#444444"), fontName="Helvetica",
    spaceAfter=2, leading=12, alignment=TA_CENTER
)
note_style = ParagraphStyle(
    "Note", parent=styles["Normal"],
    fontSize=9, textColor=GREEN, fontName="Helvetica-Oblique",
    spaceAfter=2, leading=12, leftIndent=6
)
key_style = ParagraphStyle(
    "Key", parent=styles["Normal"],
    fontSize=9.5, textColor=RED, fontName="Helvetica-Bold",
    spaceAfter=2, leading=13
)

# ════════════════════════════════════════════════════════════════════════════
#  DIAGRAM FLOWABLES
# ════════════════════════════════════════════════════════════════════════════

class TentoriumDiagram(Flowable):
    """Schematic superior view of tentorium cerebelli."""
    def __init__(self, width=420, height=270):
        Flowable.__init__(self)
        self.width = width
        self.height = height

    def draw(self):
        c = self.canv
        w, h = self.width, self.height
        cx, cy = w/2, h/2 - 10

        # Background
        c.setFillColor(colors.HexColor("#f0f6ff"))
        c.roundRect(0, 0, w, h, 8, fill=1, stroke=0)

        # Title inside diagram
        c.setFont("Helvetica-Bold", 9)
        c.setFillColor(DARK_BLUE)
        c.drawCentredString(w/2, h - 14, "Fig. 1 — Tentorium Cerebelli (Superior View, Schematic)")

        # ── Tentorium body (crescent shape) ──────────────────────────────
        # Draw as a large trapezoid / fan shape in yellow-gold
        tent_pts = [
            cx-15, cy+30,   # top-left notch edge
            cx-80, cy+90,   # left upper
            cx-150, cy+60,  # left lateral
            cx-160, cy-10,  # left lower
            cx-120, cy-80,  # left-bottom
            cx-60,  cy-100, # bottom-left
            cx,     cy-110, # bottom-center
            cx+60,  cy-100, # bottom-right
            cx+120, cy-80,  # right-bottom
            cx+160, cy-10,  # right lower
            cx+150, cy+60,  # right lateral
            cx+80,  cy+90,  # right upper
            cx+15,  cy+30,  # top-right notch edge
        ]
        c.setFillColor(colors.HexColor("#f0d060"))
        c.setStrokeColor(colors.HexColor("#c0940a"))
        c.setLineWidth(1.5)
        path = c.beginPath()
        path.moveTo(tent_pts[0], tent_pts[1])
        for i in range(2, len(tent_pts), 2):
            path.lineTo(tent_pts[i], tent_pts[i+1])
        path.close()
        c.drawPath(path, fill=1, stroke=1)

        # ── Tentorial notch (U-shaped cutout) ────────────────────────────
        c.setFillColor(colors.HexColor("#d0e8ff"))
        c.setStrokeColor(MED_BLUE)
        c.setLineWidth(2)
        path2 = c.beginPath()
        path2.moveTo(cx-15, cy+30)
        path2.curveTo(cx-50, cy+20, cx-55, cy-25, cx, cy-40)
        path2.curveTo(cx+55, cy-25, cx+50, cy+20, cx+15, cy+30)
        c.drawPath(path2, fill=1, stroke=1)

        # ── Straight sinus (midline) ──────────────────────────────────────
        c.setStrokeColor(colors.HexColor("#1044aa"))
        c.setLineWidth(3)
        c.line(cx, cy+90, cx, cy-110)

        # ── Transverse sinuses (posterior attached margin) ────────────────
        c.setStrokeColor(colors.HexColor("#1044aa"))
        c.setLineWidth(3)
        # left transverse
        c.line(cx, cy-110, cx-120, cy-80)
        # right transverse
        c.line(cx, cy-110, cx+120, cy-80)

        # ── Superior petrosal sinuses (anterolateral attached margin) ─────
        c.setStrokeColor(colors.HexColor("#2277cc"))
        c.setLineWidth(2.5)
        c.setDash(4, 3)
        # left petrosal
        c.line(cx-15, cy+30, cx-150, cy+60)
        # right petrosal
        c.line(cx+15, cy+30, cx+150, cy+60)
        c.setDash()

        # ── Free margin (inner U) ─────────────────────────────────────────
        c.setStrokeColor(colors.HexColor("#cc2200"))
        c.setLineWidth(2)
        path3 = c.beginPath()
        path3.moveTo(cx-15, cy+30)
        path3.curveTo(cx-50, cy+18, cx-55, cy-22, cx, cy-38)
        path3.curveTo(cx+55, cy-22, cx+50, cy+18, cx+15, cy+30)
        c.drawPath(path3, fill=0, stroke=1)

        # ── Anterior clinoid processes ────────────────────────────────────
        c.setFillColor(colors.HexColor("#e8c060"))
        c.setStrokeColor(colors.HexColor("#8B6914"))
        c.setLineWidth(1)
        c.ellipse(cx-22, cy+34, cx-10, cy+44, fill=1, stroke=1)
        c.ellipse(cx+10, cy+34, cx+22, cy+44, fill=1, stroke=1)

        # ── Posterior clinoid processes ───────────────────────────────────
        c.setFillColor(colors.HexColor("#d4a020"))
        c.ellipse(cx-35, cy+12, cx-22, cy+24, fill=1, stroke=1)
        c.ellipse(cx+22, cy+12, cx+35, cy+24, fill=1, stroke=1)

        # ── Midbrain in notch ─────────────────────────────────────────────
        c.setFillColor(colors.HexColor("#f4a0a0"))
        c.setStrokeColor(RED)
        c.setLineWidth(1)
        c.ellipse(cx-16, cy-36, cx+16, cy-8, fill=1, stroke=1)
        c.setFont("Helvetica-Bold", 7)
        c.setFillColor(RED)
        c.drawCentredString(cx, cy-24, "Midbrain")

        # ── Confluence of sinuses ─────────────────────────────────────────
        c.setFillColor(colors.HexColor("#1044aa"))
        c.setStrokeColor(WHITE)
        c.setLineWidth(0.5)
        c.circle(cx, cy-110, 7, fill=1, stroke=1)

        # ── Labels ────────────────────────────────────────────────────────
        label_font = "Helvetica"
        label_size = 7.5
        c.setFont(label_font, label_size)

        def label(txt, x, y, col=DARK_BLUE, bold=False):
            c.setFillColor(col)
            if bold:
                c.setFont("Helvetica-Bold", label_size)
            else:
                c.setFont(label_font, label_size)
            c.drawString(x, y, txt)

        # Right side labels
        label("Anterior clinoid process", cx+26, cy+37, MED_BLUE)
        label("Posterior clinoid process", cx+26, cy+16, TEAL)
        label("Free margin (tentorial notch)", cx+26, cy-5, RED, bold=True)
        label("Attached margin + superior", cx+26, cy-52, colors.HexColor("#0055aa"))
        label("petrosal sinus (dashed)", cx+26, cy-62, colors.HexColor("#0055aa"))
        label("Attached margin + transverse", cx+26, cy-90, DARK_BLUE)
        label("sinus", cx+26, cy-100, DARK_BLUE)
        label("Confluence of sinuses", cx-15, cy-128, MED_BLUE, bold=True)

        # Left side labels
        label("Straight sinus", cx-130, cy+70, DARK_BLUE, bold=True)
        label("Tentorium cerebelli", cx-145, cy+40, AMBER, bold=True)
        label("Falx cerebri", cx-95, cy-10, GREEN)
        label("(attaches midline)", cx-100, cy-20, GREEN)
        label("Trigeminal ganglion", cx-160, cy-48, TEAL)
        label("(Meckel's cave)", cx-150, cy-58, TEAL)

        # Leader lines
        c.setStrokeColor(GREY_LINE)
        c.setLineWidth(0.7)
        # Straight sinus
        c.line(cx-70, cy+73, cx-2, cy+60)
        # Tentorium label to body
        c.line(cx-80, cy+43, cx-40, cy+50)
        # Trigeminal ganglion
        c.line(cx-90, cy-52, cx-70, cy+62)
        # Confluence
        c.line(cx-15, cy-124, cx-6, cy-116)
        # Attached margin superior petrosal
        c.line(cx+26, cy-47, cx+18, cy+28)
        # Attached margin transverse
        c.line(cx+85, cy-88, cx+60, cy-95)

        # Legend
        legend_x = 10
        legend_y = 14
        items = [
            (colors.HexColor("#f0d060"), "Tentorium cerebelli (body)"),
            (colors.HexColor("#1044aa"), "Venous sinuses"),
            (RED,                        "Free margin"),
            (colors.HexColor("#d0e8ff"), "Tentorial notch"),
        ]
        c.setFont("Helvetica-Bold", 7)
        c.setFillColor(DARK_BLUE)
        c.drawString(legend_x, legend_y, "Legend:")
        lx = legend_x + 45
        for col, txt in items:
            c.setFillColor(col)
            c.setStrokeColor(GREY_LINE)
            c.setLineWidth(0.5)
            c.rect(lx, legend_y - 1, 8, 8, fill=1, stroke=1)
            c.setFillColor(BLACK)
            c.setFont("Helvetica", 7)
            c.drawString(lx + 10, legend_y, txt)
            lx += 105


class FlowchartDiagram(Flowable):
    """Flowchart: Clinical significance of tentorial herniation."""
    def __init__(self, width=450, height=310):
        Flowable.__init__(self)
        self.width = width
        self.height = height

    def draw(self):
        c = self.canv
        w, h = self.width, self.height

        c.setFillColor(GREY_BG)
        c.roundRect(0, 0, w, h, 8, fill=1, stroke=0)

        c.setFont("Helvetica-Bold", 9)
        c.setFillColor(DARK_BLUE)
        c.drawCentredString(w/2, h-14, "Flowchart — Tentorial (Uncal) Herniation: Mechanism & Signs")

        def box(x, y, bw, bh, text, fill_col, text_col=BLACK, bold=False, radius=6):
            c.setFillColor(fill_col)
            c.setStrokeColor(colors.HexColor("#888888"))
            c.setLineWidth(1)
            c.roundRect(x, y, bw, bh, radius, fill=1, stroke=1)
            c.setFillColor(text_col)
            font = "Helvetica-Bold" if bold else "Helvetica"
            # Wrap long text
            lines = text.split("\n")
            line_h = 11
            start_y = y + bh/2 + (len(lines)-1)*line_h/2 - 3
            for i, ln in enumerate(lines):
                c.setFont(font, 8)
                c.drawCentredString(x + bw/2, start_y - i*line_h, ln)

        def arrow(x1, y1, x2, y2):
            c.setStrokeColor(colors.HexColor("#444"))
            c.setLineWidth(1.5)
            c.line(x1, y1, x2, y2)
            # Arrowhead
            dx = x2 - x1; dy = y2 - y1
            import math
            length = math.sqrt(dx*dx + dy*dy)
            if length == 0: return
            ux, uy = dx/length, dy/length
            px, py = -uy, ux
            size = 6
            ax = x2 - ux*size
            ay = y2 - uy*size
            c.setFillColor(colors.HexColor("#444"))
            path = c.beginPath()
            path.moveTo(x2, y2)
            path.lineTo(ax + px*size*0.4, ay + py*size*0.4)
            path.lineTo(ax - px*size*0.4, ay - py*size*0.4)
            path.close()
            c.drawPath(path, fill=1, stroke=0)

        # Layout: top to bottom
        bw, bh = 220, 34
        cx = w/2

        # Box 1 - Trigger
        y1 = h - 50
        box(cx-bw/2, y1-bh, bw, bh,
            "Raised Intracranial Pressure (ICP)\nor expanding supratentorial lesion",
            LIGHT_BLUE, DARK_BLUE, bold=True)
        arrow(cx, y1-bh, cx, y1-bh-12)

        # Box 2
        y2 = y1 - bh - 24
        box(cx-bw/2, y2-bh, bw, bh,
            "Uncus / medial temporal lobe\nherniated through tentorial notch",
            AMBER_LIGHT, AMBER, bold=False)
        arrow(cx, y2-bh, cx, y2-bh-12)

        # Box 3
        y3 = y2 - bh - 24
        box(cx-bw/2, y3-bh, bw, bh,
            "Compression of CN III\n(oculomotor nerve)",
            RED_LIGHT, RED, bold=False)

        # Box 4 - branch left
        bw2 = 180
        y4 = y3 - bh - 24
        box(cx - bw2 - 18, y4-bh, bw2, bh,
            "Ipsilateral CN III palsy:\nFixed dilated pupil,\nptosis, 'down-and-out' eye",
            RED_LIGHT, RED)
        # Box 5 - branch right
        box(cx + 18, y4-bh, bw2, bh,
            "Compression of midbrain RAS:\nDecreasing consciousness\n→ Coma",
            AMBER_LIGHT, AMBER)

        # Arrows from box3 to box 4 & 5
        arrow(cx - 40, y3-bh, cx - bw2/2 - 18 + bw2/2 - 40, y4)
        arrow(cx + 40, y3-bh, cx + 18 + bw2/2, y4)
        arrow(cx, y3-bh, cx, y3-bh-6)
        # horizontal split line
        c.setStrokeColor(GREY_LINE)
        c.setDash(4,3)
        c.line(cx-bw2/2-18, y3-bh-6, cx+18+bw2, y3-bh-6)
        c.setDash()

        # Box 6 - outcome
        y5 = y4 - bh - 24
        bw3 = 340
        box(cx-bw3/2, y5-bh, bw3, bh,
            "Kernohan's notch (false localising sign): contralateral CN III or\nipsilateral hemiparesis due to cerebral peduncle compression",
            colors.HexColor("#e8d0f8"), colors.HexColor("#4a0080"))

        # Arrow from branches to outcome
        arrow(cx - bw2/2 - 18 + bw2/2 - 40, y4-bh, cx, y5)
        arrow(cx + 18 + bw2/2, y4-bh, cx, y5)

        # Emergency note at bottom
        c.setFillColor(RED)
        c.setFont("Helvetica-Bold", 8)
        c.drawCentredString(w/2, 12,
            "⚠  Clinical Emergency: Herniation = neurosurgical decompression required immediately")


# ════════════════════════════════════════════════════════════════════════════
#  BUILD DOCUMENT
# ════════════════════════════════════════════════════════════════════════════
story = []

# ── TITLE BLOCK ──────────────────────────────────────────────────────────────
title_data = [[
    Paragraph("<b>TENTORIUM CEREBELLI</b>", title_style),
    Paragraph("5-Mark Anatomy Notes  |  Dura Mater Folds  |  Posterior Cranial Fossa", subtitle_style)
]]
title_table = Table(title_data, colWidths=[W])
title_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
    ("TOPPADDING", (0,0), (-1,-1), 10),
    ("BOTTOMPADDING", (0,0), (-1,-1), 10),
    ("LEFTPADDING", (0,0), (-1,-1), 14),
    ("RIGHTPADDING", (0,0), (-1,-1), 14),
    ("ROUNDEDCORNERS", (0,0), (-1,-1), [8,8,8,8]),
]))
story.append(title_table)
story.append(Spacer(1, 10))

# ── QUICK FACTS BOX ──────────────────────────────────────────────────────────
qf_data = [
    [
        Paragraph("<b>Definition</b>", ParagraphStyle("qfh", parent=styles["Normal"], fontSize=9, textColor=DARK_BLUE, fontName="Helvetica-Bold")),
        Paragraph("Tent-shaped fold of <b>dura mater</b> forming the <b>roof of posterior cranial fossa</b>", body_style)
    ],
    [
        Paragraph("<b>Latin</b>", ParagraphStyle("qfh", parent=styles["Normal"], fontSize=9, textColor=DARK_BLUE, fontName="Helvetica-Bold")),
        Paragraph("<i>Tentorium</i> = tent", body_style)
    ],
    [
        Paragraph("<b>Key Role</b>", ParagraphStyle("qfh", parent=styles["Normal"], fontSize=9, textColor=DARK_BLUE, fontName="Helvetica-Bold")),
        Paragraph("Separates cerebellum (below) from occipital lobes of cerebrum (above)", body_style)
    ],
    [
        Paragraph("<b>Compartments</b>", ParagraphStyle("qfh", parent=styles["Normal"], fontSize=9, textColor=DARK_BLUE, fontName="Helvetica-Bold")),
        Paragraph("<b>Supratentorial</b> (cerebrum) and <b>Infratentorial</b> (hindbrain + lower midbrain)", body_style)
    ],
]
qf_table = Table(qf_data, colWidths=[3.5*cm, W - 3.5*cm])
qf_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), LIGHT_BLUE),
    ("BACKGROUND", (0,0), (0,-1), MED_BLUE),
    ("TEXTCOLOR", (0,0), (0,-1), WHITE),
    ("FONTNAME", (0,0), (0,-1), "Helvetica-Bold"),
    ("FONTSIZE", (0,0), (-1,-1), 9),
    ("TOPPADDING", (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
    ("GRID", (0,0), (-1,-1), 0.5, GREY_LINE),
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [LIGHT_BLUE, colors.HexColor("#eaf4fd")]),
    ("BACKGROUND", (0,0), (0,-1), MED_BLUE),
]))
story.append(qf_table)
story.append(Spacer(1, 10))

# ── KEY POINTS ────────────────────────────────────────────────────────────────
kp_head = Table([[Paragraph("  ★  KEY POINTS AT A GLANCE", ParagraphStyle("kph", parent=styles["Normal"],
    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_LEFT))]], colWidths=[W])
kp_head.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), TEAL),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story.append(kp_head)

kp_data = [
    ["①", "Double fold of dura mater – has two layers: outer endosteal and inner meningeal."],
    ["②", "FREE (INNER) MARGIN: U-shaped, concave; ends attach to anterior clinoid processes; bounds tentorial notch."],
    ["③", "ATTACHED (OUTER) MARGIN: Convex; attached posterolaterally to transverse sulci of occipital bone, posteroinferior angle of parietal bone, superior border of petrous temporal bone, and posterior clinoid processes."],
    ["④", "Venous sinuses run along margins: transverse sinus (posterior attached margin) and superior petrosal sinus (anterolateral attached margin)."],
    ["⑤", "TENTORIAL NOTCH: occupied by midbrain + anterior superior vermis of cerebellum."],
    ["⑥", "SURFACES: Superior = convex (related to occipital lobes, falx cerebri + straight sinus attach here). Inferior = concave (fits cerebellum, falx cerebelli attaches posteriorly)."],
    ["⑦", "MECKEL'S CAVE (Trigeminal cave): evagination of inferior layer of tentorium over trigeminal impression; contains trigeminal ganglion."],
    ["⑧", "Free & attached margins CROSS near apex of petrous temporal bone → triangular area forms posterior roof of cavernous sinus; pierced by CN III and CN IV."],
]
for row in kp_data:
    story.append(
        Table([[
            Paragraph(f"<b>{row[0]}</b>", ParagraphStyle("num", parent=styles["Normal"], fontSize=10, textColor=TEAL, fontName="Helvetica-Bold", alignment=TA_CENTER)),
            Paragraph(row[1], body_style)
        ]], colWidths=[1.2*cm, W - 1.2*cm],
        style=TableStyle([
            ("VALIGN", (0,0), (-1,-1), "TOP"),
            ("TOPPADDING", (0,0), (-1,-1), 3),
            ("BOTTOMPADDING", (0,0), (-1,-1), 3),
            ("LEFTPADDING", (0,0), (-1,-1), 6),
            ("ROWBACKGROUNDS", (0,0), (-1,-1), [TEAL_LIGHT, WHITE]),
            ("BOX", (0,0), (-1,-1), 0.5, GREY_LINE),
        ]))
    )
story.append(Spacer(1, 10))

# ── DIAGRAM ───────────────────────────────────────────────────────────────────
diag_head = Table([[Paragraph("  ✦  ANATOMICAL DIAGRAM", ParagraphStyle("dh", parent=styles["Normal"],
    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
diag_head.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), MED_BLUE),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story.append(diag_head)
story.append(Spacer(1, 4))
story.append(TentoriumDiagram(width=W, height=270))
story.append(Spacer(1, 2))
story.append(Paragraph(
    "<i>Colour code: Gold = tentorium body; Blue fill = tentorial notch; Red outline = free margin; Blue lines = venous sinuses (solid = transverse/straight; dashed = superior petrosal); Pink oval = midbrain.</i>",
    small_style
))
story.append(Spacer(1, 10))

# ── MARGINS TABLE ─────────────────────────────────────────────────────────────
margins_head = Table([[Paragraph("  ▶  TABLE 1 — MARGINS OF TENTORIUM CEREBELLI", ParagraphStyle("mh", parent=styles["Normal"],
    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
margins_head.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), AMBER),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story.append(margins_head)

col1 = 3.5*cm; col2 = 3.5*cm; col3 = W - col1 - col2
margin_table_data = [
    [
        Paragraph("<b>Feature</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Free (Inner) Margin</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Attached (Outer) Margin</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
    ],
    ["Shape", "U-shaped, concave", "Convex"],
    ["Anterior attachment", "Anterior clinoid processes", "Posterior clinoid processes"],
    ["Posterior/lateral attachment", "—", "Transverse sulci of occipital bone;\nposteroinferior angle of parietal bone"],
    ["Anterolateral attachment", "—", "Superior border of petrous temporal bone"],
    ["Associated sinus", "—", "Transverse sinus (posterior);\nSuperior petrosal sinus (anterolateral)"],
    ["Bounds", "Tentorial notch (occupied by midbrain + superior vermis)", "Posterior cranial fossa"],
    ["Special feature", "Ends of 'U' pierce dura of posterior clinoid process", "Free & attached margins cross at apex of petrous temporal bone"],
]
mt = Table(margin_table_data, colWidths=[col1, col2, col3])
mt.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
    ("TEXTCOLOR", (0,0), (-1,0), WHITE),
    ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE", (0,0), (-1,-1), 8.5),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, AMBER_LIGHT]),
    ("GRID", (0,0), (-1,-1), 0.5, GREY_LINE),
    ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
    ("TOPPADDING", (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 5),
    ("ALIGN", (0,0), (0,-1), "LEFT"),
    ("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
    ("TEXTCOLOR", (0,1), (0,-1), DARK_BLUE),
]))
story.append(mt)
story.append(Spacer(1, 10))

# ── ATTACHMENTS TABLE ─────────────────────────────────────────────────────────
att_head = Table([[Paragraph("  ▶  TABLE 2 — ATTACHMENTS OF TENTORIUM CEREBELLI", ParagraphStyle("ah", parent=styles["Normal"],
    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
att_head.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), TEAL),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story.append(att_head)

att_data = [
    [
        Paragraph("<b>Region</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Bone/Structure</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Specific Point</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Associated Sinus</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
    ],
    ["Posterior", "Occipital bone", "Lips of transverse sulci", "Transverse sinus"],
    ["Posterolateral", "Parietal bone", "Posteroinferior angle", "—"],
    ["Anterolateral", "Petrous temporal bone", "Superior border", "Superior petrosal sinus"],
    ["Anterior", "Sphenoid", "Posterior clinoid processes", "—"],
    ["Anterior (free margin)", "Sphenoid", "Anterior clinoid processes", "—"],
]
at = Table(att_data, colWidths=[3*cm, 3.5*cm, 4.5*cm, W-11*cm])
at.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), TEAL),
    ("TEXTCOLOR", (0,0), (-1,0), WHITE),
    ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE", (0,0), (-1,-1), 8.5),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, TEAL_LIGHT]),
    ("GRID", (0,0), (-1,-1), 0.5, GREY_LINE),
    ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
    ("TOPPADDING", (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(at)
story.append(Spacer(1, 10))

# ── SURFACES TABLE ────────────────────────────────────────────────────────────
surf_head = Table([[Paragraph("  ▶  TABLE 3 — SURFACES OF TENTORIUM CEREBELLI", ParagraphStyle("sh", parent=styles["Normal"],
    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
surf_head.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), RED),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story.append(surf_head)

surf_data = [
    [
        Paragraph("<b>Feature</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
        Paragraph("<b>Superior Surface</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Inferior Surface</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
    ],
    ["Shape", "Convex; slopes to each side from median plane", "Concave"],
    ["Brain relation", "Related to occipital lobes of cerebrum", "Fits the convex superior surface of cerebellum"],
    ["Falx attachment", "Falx cerebri attaches in midline", "Falx cerebelli attaches posteriorly"],
    ["Sinus", "Straight sinus along line of falx cerebri attachment", "—"],
]
st = Table(surf_data, colWidths=[3.5*cm, (W-3.5*cm)/2, (W-3.5*cm)/2])
st.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), RED),
    ("TEXTCOLOR", (0,0), (-1,0), WHITE),
    ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE", (0,0), (-1,-1), 8.5),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, RED_LIGHT]),
    ("GRID", (0,0), (-1,-1), 0.5, GREY_LINE),
    ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
    ("TOPPADDING", (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 5),
    ("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
    ("TEXTCOLOR", (0,1), (0,-1), DARK_BLUE),
]))
story.append(st)
story.append(Spacer(1, 10))

# ── MECKEL'S CAVE BOX ─────────────────────────────────────────────────────────
meckel_data = [[
    Paragraph(
        "<b>Meckel's Cave (Trigeminal Cave)</b><br/>"
        "• A recess of dura mater related to the attached margin of the tentorium.<br/>"
        "• Formed by evagination of the <b>inferior layer of the tentorium</b> over the <b>trigeminal impression</b> on the petrous temporal bone.<br/>"
        "• Contains: <b>trigeminal ganglion</b> + proximal sensory root of CN V.<br/>"
        "• Clinical: Site of percutaneous procedures (e.g., balloon compression) for trigeminal neuralgia.",
        body_style
    )
]]
meckel_table = Table(meckel_data, colWidths=[W])
meckel_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#ede0f8")),
    ("TOPPADDING", (0,0), (-1,-1), 8),
    ("BOTTOMPADDING", (0,0), (-1,-1), 8),
    ("LEFTPADDING", (0,0), (-1,-1), 10),
    ("BOX", (0,0), (-1,-1), 1.5, colors.HexColor("#7b2fa8")),
    ("ROUNDEDCORNERS", (0,0), (-1,-1), [6,6,6,6]),
]))
story.append(KeepTogether([
    Table([[Paragraph("  ✦  MECKEL'S CAVE", ParagraphStyle("mh", parent=styles["Normal"],
        fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W],
        style=TableStyle([
            ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#7b2fa8")),
            ("TOPPADDING", (0,0), (-1,-1), 6),
            ("BOTTOMPADDING", (0,0), (-1,-1), 6),
            ("LEFTPADDING", (0,0), (-1,-1), 8),
        ])),
    meckel_table,
    Spacer(1, 10),
]))

# ── RELATED STRUCTURES TABLE ──────────────────────────────────────────────────
rel_head = Table([[Paragraph("  ▶  TABLE 4 — NERVES & STRUCTURES RELATED TO TENTORIUM", ParagraphStyle("rh", parent=styles["Normal"],
    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
rel_head.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story.append(rel_head)

rel_data = [
    [
        Paragraph("<b>Structure</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Relationship to Tentorium</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Clinical Note</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
    ],
    ["CN III (Oculomotor)", "Passes through triangular area (crosses margins); runs in lateral wall of cavernous sinus", "First nerve compressed in uncal herniation → fixed dilated pupil"],
    ["CN IV (Trochlear)", "Arises dorsal to midbrain; pierces tentorium at its free margin to enter cavernous sinus", "Uniquely originates from dorsal brainstem"],
    ["CN V (Trigeminal)", "Sensory root + ganglion in Meckel's cave under tentorium", "Trigeminal neuralgia; percutaneous procedures via Meckel's cave"],
    ["Midbrain", "Occupies tentorial notch (encircled by free margin)", "Compressed in transtentorial herniation → coma"],
    ["Straight sinus", "Runs midline along superior surface (junction of falx cerebri and tentorium)", "Drains great cerebral vein (of Galen)"],
    ["Great cerebral vein\n(of Galen)", "Drains into straight sinus at junction with tentorium", "Thrombosis → haemorrhagic infarction"],
    ["Transverse sinus", "Along posterior attached margin", "Major venous drainage of brain"],
    ["Superior petrosal sinus", "Along anterolateral attached margin", "Connects cavernous sinus to transverse sinus"],
]
rt = Table(rel_data, colWidths=[3.5*cm, 7*cm, W-10.5*cm])
rt.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
    ("TEXTCOLOR", (0,0), (-1,0), WHITE),
    ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE", (0,0), (-1,-1), 8.5),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_BLUE]),
    ("GRID", (0,0), (-1,-1), 0.5, GREY_LINE),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("TOPPADDING", (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 5),
    ("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
    ("TEXTCOLOR", (0,1), (0,-1), DARK_BLUE),
    ("BACKGROUND", (2,1), (2,-1), colors.HexColor("#fef9e7")),
]))
story.append(rt)
story.append(Spacer(1, 10))

# ── FLOWCHART ─────────────────────────────────────────────────────────────────
flow_head = Table([[Paragraph("  ▶  FLOWCHART — UNCAL/TENTORIAL HERNIATION (Clinical Significance)", ParagraphStyle("fh", parent=styles["Normal"],
    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
flow_head.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), RED),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story.append(flow_head)
story.append(Spacer(1, 4))
story.append(FlowchartDiagram(width=W, height=310))
story.append(Spacer(1, 10))

# ── COMPARISON TABLE: DURAL FOLDS ─────────────────────────────────────────────
comp_head = Table([[Paragraph("  ▶  TABLE 5 — COMPARISON OF DURAL FOLDS", ParagraphStyle("ch", parent=styles["Normal"],
    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
comp_head.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), GREEN),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story.append(comp_head)

comp_data = [
    [
        Paragraph("<b>Dural Fold</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Position</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Separates</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph("<b>Sinus</b>", ParagraphStyle("th", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
    ],
    ["Falx cerebri", "Vertical; sagittal plane", "Right & left cerebral hemispheres", "Superior & inferior sagittal sinuses; straight sinus"],
    ["Tentorium cerebelli", "Horizontal-oblique", "Cerebrum (above) from cerebellum (below)", "Transverse, superior petrosal, straight sinuses"],
    ["Falx cerebelli", "Vertical; below tentorium", "Right & left cerebellar hemispheres", "Occipital sinus"],
    ["Diaphragma sellae", "Horizontal; roof of sella turcica", "Covers hypophyseal fossa", "Circular sinus"],
]
ct = Table(comp_data, colWidths=[3.5*cm, 3.5*cm, 4*cm, W-11*cm])
ct.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), GREEN),
    ("TEXTCOLOR", (0,0), (-1,0), WHITE),
    ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE", (0,0), (-1,-1), 8.5),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREEN_LIGHT]),
    ("GRID", (0,0), (-1,-1), 0.5, GREY_LINE),
    ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
    ("TOPPADDING", (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 5),
    ("FONTNAME", (0,2), (0,2), "Helvetica-Bold"),
    ("BACKGROUND", (0,2), (-1,2), colors.HexColor("#c8f0c8")),
    ("TEXTCOLOR", (0,2), (0,2), TEAL),
    ("FONTNAME", (0,2), (0,2), "Helvetica-Bold"),
]))
story.append(ct)
story.append(Spacer(1, 10))

# ── EXAM MEMORY AID ──────────────────────────────────────────────────────────
exam_data = [[
    Paragraph(
        "<b>📝 EXAM MEMORY AIDS</b><br/><br/>"
        "<b>Mnemonic — TANS</b> for attachments:<br/>"
        "• <b>T</b>ransverse sulci of occipital bone (posterior)<br/>"
        "• <b>A</b>nterior &amp; posterior clinoid processes (sphenoid)<br/>"
        "• <b>N</b>eck of petrous temporal (superior border — anterolateral)<br/>"
        "• <b>S</b>uperior sagittal = straight sinus (along midline superior surface)<br/><br/>"
        "<b>Sinuses along tentorium margins:</b> "
        "Straight sinus (midline) → Confluence of sinuses → Transverse sinuses (posterior) → Sigmoid sinuses → Internal jugular veins<br/><br/>"
        "<b>Tentorial notch contents (MASVV):</b> Midbrain, Anterior superior vermis of cerebellum; remember CN III and IV pass through the triangular area.",
        ParagraphStyle("exm", parent=styles["Normal"], fontSize=9.5, textColor=DARK_BLUE, fontName="Helvetica",
                       leading=15, spaceAfter=2)
    )
]]
exam_table = Table(exam_data, colWidths=[W])
exam_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), AMBER_LIGHT),
    ("TOPPADDING", (0,0), (-1,-1), 10),
    ("BOTTOMPADDING", (0,0), (-1,-1), 10),
    ("LEFTPADDING", (0,0), (-1,-1), 12),
    ("BOX", (0,0), (-1,-1), 1.5, AMBER),
]))
story.append(exam_table)
story.append(Spacer(1, 10))

# ── CLINICAL CORRELATIONS ─────────────────────────────────────────────────────
clin_head = Table([[Paragraph("  ▶  CLINICAL CORRELATIONS", ParagraphStyle("clh", parent=styles["Normal"],
    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
clin_head.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#7b2fa8")),
    ("TOPPADDING", (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story.append(clin_head)

clin_items = [
    ("Transtentorial (Uncal) Herniation",
     "Raised ICP pushes uncus/medial temporal lobe through tentorial notch → compresses CN III (ipsilateral fixed dilated pupil) and midbrain → coma. Kernohan's notch: contra-lateral cerebral peduncle compression → ipsilateral hemiplegia (false localising sign)."),
    ("Central Herniation",
     "Both hemispheres herniate symmetrically through notch → bilateral midbrain compression → 'pinpoint' pupils, Cheyne-Stokes breathing, decerebrate posturing."),
    ("Straight Sinus Thrombosis",
     "Thrombosis at junction of falx cerebri and tentorium → haemorrhagic infarction of deep structures (basal ganglia, thalami)."),
    ("Posterior Fossa Tumours",
     "Infratentorial mass (e.g., medulloblastoma, cerebellar metastasis) → upward herniation through tentorial notch."),
    ("Trigeminal Neuralgia Treatment",
     "Balloon microcompression and glycerol rhizolysis performed via Meckel's cave under fluoroscopic guidance."),
    ("Subdural Haematoma",
     "Blood collects between dura and arachnoid layers; tentorium marks boundary between supratentorial and infratentorial subdurals."),
]

clin_data = [[
    Paragraph(f"<b>{title}</b>", body_style),
    Paragraph(desc, body_style)
] for title, desc in clin_items]

clin_table = Table(clin_data, colWidths=[4.5*cm, W-4.5*cm])
clin_table.setStyle(TableStyle([
    ("FONTSIZE", (0,0), (-1,-1), 8.5),
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [colors.HexColor("#f5eeff"), WHITE]),
    ("GRID", (0,0), (-1,-1), 0.5, GREY_LINE),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("TOPPADDING", (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 6),
    ("BACKGROUND", (0,0), (0,-1), colors.HexColor("#ede0f8")),
    ("FONTNAME", (0,0), (0,-1), "Helvetica-Bold"),
    ("TEXTCOLOR", (0,0), (0,-1), colors.HexColor("#4a0080")),
]))
story.append(clin_table)
story.append(Spacer(1, 10))

# ── QUICK REVISION FLOWCHART (text-based) ─────────────────────────────────────
rev_head = Table([[Paragraph("  ▶  QUICK REVISION — VENOUS DRAINAGE PATHWAY THROUGH TENTORIUM", ParagraphStyle("rvh", parent=styles["Normal"],
    fontSize=10, textColor=WHITE, fontName="Helvetica-Bold"))]], colWidths=[W])
rev_head.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), MED_BLUE),
    ("TOPPADDING", (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story.append(rev_head)

sinus_chain = [
    "Superior sagittal sinus",
    "↓",
    "Confluence of sinuses (Torcular Herophili)",
    "↓",
    "Transverse sinuses\n(along posterior attached margin of tentorium)",
    "↓",
    "Sigmoid sinuses",
    "↓",
    "Internal jugular veins",
]
sinus_styles = []
sin_data = []
for item in sinus_chain:
    if item == "↓":
        sin_data.append([Paragraph("<b>↓</b>", ParagraphStyle("arr", parent=styles["Normal"], fontSize=14, textColor=MED_BLUE, alignment=TA_CENTER))])
        sinus_styles.append(("BACKGROUND", (0, len(sin_data)-1), (-1, len(sin_data)-1), WHITE))
    else:
        sin_data.append([Paragraph(item, ParagraphStyle("sn", parent=styles["Normal"], fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER))])
        sinus_styles.append(("BACKGROUND", (0, len(sin_data)-1), (-1, len(sin_data)-1), MED_BLUE))

sin_table = Table(sin_data, colWidths=[W])
ts_list = [
    ("TOPPADDING", (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("ALIGN", (0,0), (-1,-1), "CENTER"),
    ("FONTSIZE", (0,0), (-1,-1), 9),
]
for s in sinus_styles:
    ts_list.append(s)
sin_table.setStyle(TableStyle(ts_list))
story.append(sin_table)
story.append(Spacer(1, 10))

# ── ALSO REMEMBER BOX ────────────────────────────────────────────────────────
also_data = [[
    Paragraph(
        "<b>ALSO REMEMBER (Extra Points):</b><br/>"
        "• The tentorium contains two layers of dura (endosteal outer + meningeal inner layer).<br/>"
        "• The free margin of the tentorium is C-shaped when viewed from below (concave anteriorly).<br/>"
        "• The tentorial notch is also called the <b>incisura tentorii</b>.<br/>"
        "• The trochlear nerve (CN IV) is the only cranial nerve to arise from the <b>dorsal</b> aspect of the brainstem; it winds around the brainstem and pierces the <b>free margin</b> of the tentorium.<br/>"
        "• The tentorium is the most common site of <b>epidural haematoma</b> in the posterior fossa.<br/>"
        "• During spinal anaesthesia, the tentorium does NOT provide a barrier to CSF spread.<br/>"
        "• <b>Kernohan-Woltman notch phenomenon</b>: False localising sign where compression of contralateral cerebral peduncle against tentorium causes ipsilateral hemiplegia.",
        ParagraphStyle("also", parent=styles["Normal"], fontSize=9.5, textColor=BLACK, fontName="Helvetica",
                       leading=15, spaceAfter=2)
    )
]]
also_table = Table(also_data, colWidths=[W])
also_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), GREEN_LIGHT),
    ("TOPPADDING", (0,0), (-1,-1), 10),
    ("BOTTOMPADDING", (0,0), (-1,-1), 10),
    ("LEFTPADDING", (0,0), (-1,-1), 12),
    ("BOX", (0,0), (-1,-1), 1.5, GREEN),
]))
story.append(also_table)
story.append(Spacer(1, 8))

# ── FOOTER ────────────────────────────────────────────────────────────────────
story.append(HRFlowable(width=W, thickness=1, color=GREY_LINE))
story.append(Paragraph(
    "Ref: Chaurasia's Human Anatomy (Regional &amp; Applied) — Dura Mater, Tentorium Cerebelli  |  "
    "Notes compiled for 5-mark anatomy exam preparation",
    small_style
))

# ── BUILD ─────────────────────────────────────────────────────────────────────
def on_page(canvas, doc):
    canvas.saveState()
    canvas.setFont("Helvetica", 7)
    canvas.setFillColor(colors.HexColor("#888888"))
    page_num = doc.page
    canvas.drawRightString(A4[0] - 1.8*cm, 1*cm, f"Page {page_num}")
    canvas.drawString(1.8*cm, 1*cm, "Tentorium Cerebelli — Anatomy 5-Mark Notes")
    canvas.restoreState()

doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print("PDF created:", OUTPUT)
Running Command

cd /tmp/workspace/tentorium-cerebelli && python make_pdf.py 2>&1

PDF generated successfully! Here's your download:

Tentorium Cerebelli 5mark

PDF Document · PDF


Here's a summary of everything included in the PDF:

What's Inside

Title block with subject tag and 5-mark context

★ Key Points (8 numbered points)

  1. Double fold of dura mater (endosteal + meningeal layers)
  2. Free margin - U-shaped, attaches to anterior clinoid processes, bounds tentorial notch
  3. Attached margin - convex, attaches to occipital, parietal, petrous temporal bones and posterior clinoid processes
  4. Venous sinuses along margins (transverse + superior petrosal)
  5. Tentorial notch - contains midbrain + anterior superior vermis
  6. Superior & inferior surfaces with falx attachments
  7. Meckel's cave - trigeminal ganglion location
  8. Crossing of margins - triangular area pierced by CN III & CN IV

✦ Anatomical Diagram (custom-drawn)

  • Superior view schematic with colour-coded structures
  • Labels: clinoid processes, free margin, attached margins, straight/transverse sinuses, confluence, midbrain in notch

5 Tables

TableContent
1Margins (Free vs. Attached)
2Attachments by region
3Superior vs. Inferior surfaces
4Nerves & structures related to tentorium
5Comparison of all 4 dural folds

▶ Flowchart

Uncal/tentorial herniation pathway: Raised ICP → Uncus herniates through notch → CN III compression → Fixed dilated pupil + coma → Kernohan's notch phenomenon

Bonus Sections

  • Meckel's Cave dedicated box
  • Venous drainage pathway chain flowchart
  • Clinical correlations (herniation, sinus thrombosis, trigeminal neuralgia, posterior fossa tumours)
  • Exam mnemonics (TANS for attachments)
  • Extra points (CN IV origin, false localising signs, Kernohan-Woltman phenomenon)

Give me pdf foR 5mark on Brain stem - all cranial nerve nuclei & Cranial Nerve exit from nuclei with diagram tables Flowchart and points By Refer BD Chaurasia's Human Anatomy for dental Students 5ᵗʰ edition & add extra Points if needed

Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Loading Image
Running Command

mkdir -p /tmp/workspace/brainstem-cn && ls /tmp/workspace/brainstem-cn/

Writing File

~/brainstem-cn/make_brainstem_pdf.py

"""
Brainstem - Cranial Nerve Nuclei & Exit Points
5-Mark Anatomy Notes PDF
Ref: BD Chaurasia's Human Anatomy for Dental Students (5th Ed)
     + Neuroanatomy through Clinical Cases (Blumenfeld)
"""
import urllib.request, os, math
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.platypus.flowables import Flowable
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY, TA_RIGHT

OUTPUT = "/tmp/workspace/brainstem-cn/Brainstem_CN_Nuclei_5mark.pdf"

# ── colour palette ──────────────────────────────────────────────────────────
NAVY      = colors.HexColor("#0d2b52")
BLUE      = colors.HexColor("#1a5276")
LBLUE     = colors.HexColor("#d6eaf8")
TEAL      = colors.HexColor("#0e6655")
LTEAL     = colors.HexColor("#d0f0eb")
ORANGE    = colors.HexColor("#b94a00")
LORANGE   = colors.HexColor("#fde8d8")
RED       = colors.HexColor("#922b21")
LRED      = colors.HexColor("#fadbd8")
PURPLE    = colors.HexColor("#6c3483")
LPURPLE   = colors.HexColor("#e8daef")
GREEN     = colors.HexColor("#1e6b25")
LGREEN    = colors.HexColor("#d5f5e3")
AMBER     = colors.HexColor("#9a6200")
LAMBER    = colors.HexColor("#fef9e7")
GREY      = colors.HexColor("#f2f3f4")
GLINE     = colors.HexColor("#bdc3c7")
BLACK     = colors.HexColor("#1c2833")
WHITE     = colors.white

# Functional column colours (matching the textbook diagram)
COL_GSE   = colors.HexColor("#f0a000")   # somatic motor
COL_GVE   = colors.HexColor("#e8d800")   # parasympathetic
COL_SVE   = colors.HexColor("#e06010")   # branchial motor
COL_SVA   = colors.HexColor("#30a050")   # special visceral sensory
COL_GVA   = colors.HexColor("#50c878")   # general visceral sensory
COL_GSA   = colors.HexColor("#3090d0")   # general somatic sensory
COL_SSA   = colors.HexColor("#c060c0")   # special somatic sensory

doc = SimpleDocTemplate(
    OUTPUT, pagesize=A4,
    leftMargin=1.8*cm, rightMargin=1.8*cm,
    topMargin=1.8*cm, bottomMargin=1.8*cm,
    title="Brainstem – Cranial Nerve Nuclei",
    author="Anatomy 5-Mark Notes"
)
W = A4[0] - 3.6*cm

styles = getSampleStyleSheet()

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

title_s  = ps("T", fontSize=19, textColor=WHITE, alignment=TA_CENTER,
              fontName="Helvetica-Bold", leading=23, spaceAfter=3)
sub_s    = ps("Sub", fontSize=10, textColor=colors.HexColor("#cce0f5"),
              alignment=TA_CENTER, fontName="Helvetica-Oblique")
body_s   = ps("Bd", fontSize=9.2, textColor=BLACK, fontName="Helvetica",
              leading=14, spaceAfter=2, alignment=TA_JUSTIFY)
bul_s    = ps("Bl", fontSize=9.2, textColor=BLACK, fontName="Helvetica",
              leading=13, spaceAfter=2, leftIndent=14, firstLineIndent=-10)
small_s  = ps("Sm", fontSize=8, textColor=colors.HexColor("#555555"),
              fontName="Helvetica", alignment=TA_CENTER, leading=11)
key_s    = ps("Ky", fontSize=9.5, textColor=RED, fontName="Helvetica-Bold",
              leading=13, spaceAfter=2)

def section_head(text, bg=NAVY):
    t = Table([[Paragraph(f"  {text}", ps("sh",
        fontSize=11, textColor=WHITE, fontName="Helvetica-Bold",
        leading=14))]], colWidths=[W])
    t.setStyle(TableStyle([
        ("BACKGROUND",(0,0),(-1,-1),bg),
        ("TOPPADDING",(0,0),(-1,-1),6),
        ("BOTTOMPADDING",(0,0),(-1,-1),6),
        ("LEFTPADDING",(0,0),(-1,-1),8),
    ]))
    return t

# ════════════════════════════════════════════════════════════════════════════
#  DIAGRAM 1 — Brainstem lateral view with CN exit points
# ════════════════════════════════════════════════════════════════════════════
class BrainstemDiagram(Flowable):
    def __init__(self, width=480, height=380):
        Flowable.__init__(self)
        self.width = width
        self.height = height

    def draw(self):
        c = self.canv
        w, h = self.width, self.height

        # Background
        c.setFillColor(colors.HexColor("#f8fbff"))
        c.roundRect(0, 0, w, h, 8, fill=1, stroke=0)

        # Title
        c.setFont("Helvetica-Bold", 9)
        c.setFillColor(NAVY)
        c.drawCentredString(w/2, h-13, "Fig. 1 — Brainstem (Anterior View): Cranial Nerve Exit Points")

        # ── Draw brainstem outline ─────────────────────────────────────
        # Midbrain (top)
        mid_x, mid_y = w/2, h-45
        mid_w, mid_h = 80, 50
        c.setFillColor(colors.HexColor("#fde8d8"))
        c.setStrokeColor(ORANGE)
        c.setLineWidth(1.5)
        c.roundRect(mid_x-mid_w/2, mid_y-mid_h, mid_w, mid_h, 8, fill=1, stroke=1)

        # Pons (middle)
        pons_x, pons_y = w/2, mid_y-mid_h-2
        pons_w, pons_h = 100, 70
        c.setFillColor(colors.HexColor("#d6eaf8"))
        c.setStrokeColor(BLUE)
        c.roundRect(pons_x-pons_w/2, pons_y-pons_h, pons_w, pons_h, 8, fill=1, stroke=1)

        # Medulla (bottom)
        med_x, med_y = w/2, pons_y-pons_h-2
        med_w, med_h = 80, 90
        c.setFillColor(colors.HexColor("#d5f5e3"))
        c.setStrokeColor(TEAL)
        c.roundRect(med_x-med_w/2, med_y-med_h, med_w, med_h, 10, fill=1, stroke=1)

        # Spinal cord (below medulla)
        sc_y = med_y-med_h-2
        c.setFillColor(colors.HexColor("#eafaf1"))
        c.setStrokeColor(TEAL)
        c.setLineWidth(1)
        c.rect(w/2-25, sc_y-30, 50, 30, fill=1, stroke=1)

        # Labels inside structures
        c.setFont("Helvetica-Bold", 9)
        c.setFillColor(ORANGE)
        c.drawCentredString(mid_x, mid_y-mid_h/2+3, "MIDBRAIN")

        c.setFillColor(BLUE)
        c.drawCentredString(pons_x, pons_y-pons_h/2+3, "PONS")
        c.setFont("Helvetica", 8)
        c.drawCentredString(pons_x, pons_y-pons_h/2-9, "(+ Middle")
        c.drawCentredString(pons_x, pons_y-pons_h/2-19, "Cerebellar")
        c.drawCentredString(pons_x, pons_y-pons_h/2-29, "Peduncle)")

        c.setFont("Helvetica-Bold", 9)
        c.setFillColor(TEAL)
        c.drawCentredString(med_x, med_y-med_h/2+5, "MEDULLA")
        c.setFont("Helvetica", 8)
        c.drawCentredString(med_x, med_y-med_h/2-7, "OBLONGATA")

        c.setFont("Helvetica-Bold", 8)
        c.setFillColor(TEAL)
        c.drawCentredString(w/2, sc_y-15, "Spinal Cord")

        # ── CN exit points (LEFT side = numbers, RIGHT = names) ─────────
        # Format: (y_position, cn_label, colour, name_text, structure)
        cn_exits = [
            # (y relative to mid_y top of midbrain, CN#, col, description)
            (mid_y-10,      "III",  RED,    "CN III – Oculomotor",       "Emerges from interpeduncular fossa (medial surface, crus cerebri)"),
            (mid_y-mid_h-5, "IV",   PURPLE, "CN IV – Trochlear",         "Only CN to exit DORSAL surface of brainstem; winds round"),
            (pons_y-10,     "V",    BLUE,   "CN V – Trigeminal",         "Exits lateral pons (larger sensory + smaller motor root)"),
            (pons_y-28,     "VI",   ORANGE, "CN VI – Abducens",          "Exits pontomedullary junction (medially)"),
            (pons_y-45,     "VII",  GREEN,  "CN VII – Facial",           "Exits pontomedullary junction (laterally)"),
            (pons_y-55,     "VIII", TEAL,   "CN VIII – Vestibulocochlear","Exits pontomedullary junction (lateral to VII)"),
            (med_y-12,      "IX",   RED,    "CN IX – Glossopharyngeal",  "Exits lateral medulla (groove dorsal to olive)"),
            (med_y-28,      "X",    BLUE,   "CN X – Vagus",              "Exits lateral medulla (below IX)"),
            (med_y-44,      "XI",   PURPLE, "CN XI – Accessory",         "Spinal roots: C1-C5; cranial root from lateral medulla"),
            (med_y-62,      "XII",  ORANGE, "CN XII – Hypoglossal",      "Exits ventral medulla (groove between pyramid + olive)"),
        ]

        for (cy2, num, col, name, desc) in cn_exits:
            # Circle with CN number on left
            lx = w/2 - pons_w/2 - 15
            c.setFillColor(col)
            c.setStrokeColor(WHITE)
            c.setLineWidth(0.8)
            c.circle(lx, cy2, 10, fill=1, stroke=1)
            c.setFont("Helvetica-Bold", 7.5)
            c.setFillColor(WHITE)
            offset = -3 if len(num) > 2 else -3
            c.drawCentredString(lx, cy2+offset, num)

            # Dotted line to right side
            c.setStrokeColor(col)
            c.setLineWidth(0.8)
            c.setDash(3, 3)
            rx = w/2 + pons_w/2 + 8
            c.line(lx+11, cy2, rx, cy2)
            c.setDash()

            # Name on right
            c.setFillColor(col)
            c.setFont("Helvetica-Bold", 7.5)
            c.drawString(rx+2, cy2+2, name)
            c.setFillColor(BLACK)
            c.setFont("Helvetica", 6.5)
            c.drawString(rx+2, cy2-8, desc)

        # CN I & II note at top
        c.setFillColor(colors.HexColor("#888888"))
        c.setFont("Helvetica-Oblique", 7.5)
        c.drawString(18, h-30, "CN I (Olfactory) → Forebrain/Olfactory bulb")
        c.drawString(18, h-40, "CN II (Optic) → Diencephalon (NOT brainstem)")

        # Legend: structure colours
        legend_items = [
            (colors.HexColor("#fde8d8"), ORANGE, "Midbrain"),
            (colors.HexColor("#d6eaf8"), BLUE,   "Pons"),
            (colors.HexColor("#d5f5e3"), TEAL,   "Medulla"),
        ]
        lx2 = 12
        c.setFont("Helvetica-Bold", 7.5)
        c.setFillColor(NAVY)
        c.drawString(lx2, 12, "Structure:")
        lx2 += 55
        for fill, stroke, lbl in legend_items:
            c.setFillColor(fill); c.setStrokeColor(stroke); c.setLineWidth(1)
            c.roundRect(lx2, 8, 14, 10, 2, fill=1, stroke=1)
            c.setFillColor(BLACK); c.setFont("Helvetica", 7.5)
            c.drawString(lx2+16, 12, lbl)
            lx2 += 60


# ════════════════════════════════════════════════════════════════════════════
#  DIAGRAM 2 — Functional columns of CN nuclei (schematic cross-section style)
# ════════════════════════════════════════════════════════════════════════════
class ColumnDiagram(Flowable):
    def __init__(self, width=480, height=220):
        Flowable.__init__(self)
        self.width = width
        self.height = height

    def draw(self):
        c = self.canv
        w, h = self.width, self.height

        c.setFillColor(colors.HexColor("#f5f8ff"))
        c.roundRect(0, 0, w, h, 8, fill=1, stroke=0)

        c.setFont("Helvetica-Bold", 9)
        c.setFillColor(NAVY)
        c.drawCentredString(w/2, h-13, "Fig. 2 — Functional Columns of Cranial Nerve Nuclei (Cross-Sectional Schema)")

        # Central axis (representing midline sulcus)
        cx = w/2
        c.setStrokeColor(GLINE)
        c.setLineWidth(1.5)
        c.setDash(5, 3)
        c.line(cx, h-25, cx, 20)
        c.setDash()

        # Labels: MOTOR (left) and SENSORY (right)
        c.setFont("Helvetica-Bold", 10)
        c.setFillColor(NAVY)
        c.drawRightString(cx-8, h-28, "◀ MOTOR NUCLEI")
        c.drawString(cx+8, h-28, "SENSORY NUCLEI ▶")

        # Column bars — left = motor, right = sensory
        # Each column: (x, y_top, height, label, abbrev, colour)
        bar_w = 60
        top = h-45

        motor_cols = [
            (cx-80,  top, 140, "Somatic Motor\n(GSE)", "GSE", COL_GSE,
             "CN III,IV,\nVI, XII"),
            (cx-150, top, 130, "Parasympathetic\n(GVE)", "GVE", COL_GVE,
             "CN III,VII,\nIX, X"),
            (cx-220, top, 120, "Branchial Motor\n(SVE)", "SVE", COL_SVE,
             "CN V,VII,\nIX,X,XI"),
        ]
        sensory_cols = [
            (cx+20,  top, 100, "Visceral Sensory\n(GVA/SVA)", "GVA\nSVA", COL_SVA,
             "CN VII,IX,\nX (Solitarius)"),
            (cx+90,  top, 130, "General Somatic\nSensory (GSA)", "GSA", COL_GSA,
             "CN V,VII,\nIX,X (Trigeminal\nnuclei)"),
            (cx+160, top, 110, "Special Somatic\nSensory (SSA)", "SSA", COL_SSA,
             "CN VIII\n(Cochlear &\nVestibular nuclei)"),
        ]

        def draw_column(x, y_top, col_h, label, abbrev, fill, nerves):
            c.setFillColor(fill)
            c.setStrokeColor(colors.HexColor("#444444"))
            c.setLineWidth(1)
            c.roundRect(x, y_top-col_h, bar_w, col_h, 5, fill=1, stroke=1)
            # Abbreviation inside bar
            c.setFillColor(WHITE)
            c.setFont("Helvetica-Bold", 8)
            for i, ln in enumerate(abbrev.split("\n")):
                c.drawCentredString(x+bar_w/2, y_top-col_h/2+4-i*10, ln)
            # Label below bar
            c.setFillColor(BLACK)
            c.setFont("Helvetica", 7)
            label_y = y_top - col_h - 14
            for i, ln in enumerate(label.split("\n")):
                c.drawCentredString(x+bar_w/2, label_y - i*9, ln)
            # Nerves below label
            c.setFillColor(fill)
            c.setFont("Helvetica-Bold", 7)
            nerve_y = label_y - len(label.split("\n"))*9 - 10
            for i, ln in enumerate(nerves.split("\n")):
                c.drawCentredString(x+bar_w/2, nerve_y - i*9, ln)

        for args in motor_cols:
            draw_column(*args)
        for args in sensory_cols:
            draw_column(*args)

        # Sulcus limitans label
        c.setFillColor(colors.HexColor("#888888"))
        c.setFont("Helvetica-Oblique", 7)
        c.drawCentredString(cx, 15, "— Sulcus limitans (separates motor from sensory columns) —")

        # Medial label
        c.setFont("Helvetica", 7)
        c.setFillColor(NAVY)
        c.drawCentredString(cx-110, top+8, "← Medial")
        c.drawCentredString(cx+110, top+8, "Lateral →")


# ════════════════════════════════════════════════════════════════════════════
#  DIAGRAM 3 — Per-level cross-section nuclei positions
# ════════════════════════════════════════════════════════════════════════════
class CrossSectionDiagram(Flowable):
    def __init__(self, width=480, height=320):
        Flowable.__init__(self)
        self.width = width
        self.height = height

    def draw(self):
        c = self.canv
        w, h = self.width, self.height

        c.setFillColor(colors.HexColor("#fafbff"))
        c.roundRect(0, 0, w, h, 8, fill=1, stroke=0)
        c.setFont("Helvetica-Bold", 9)
        c.setFillColor(NAVY)
        c.drawCentredString(w/2, h-13, "Fig. 3 — Nuclei at Each Level of Brainstem (Schematic Cross-Sections)")

        def cross_section(x, y, radius, title, title_col, nuclei):
            """nuclei = list of (angle_deg, label, col)"""
            # Outer circle
            c.setFillColor(colors.HexColor("#f0f4ff"))
            c.setStrokeColor(title_col)
            c.setLineWidth(1.5)
            c.circle(x, y, radius, fill=1, stroke=1)
            # Central canal dot
            c.setFillColor(title_col)
            c.circle(x, y, 5, fill=1, stroke=0)
            # Title above
            c.setFont("Helvetica-Bold", 8.5)
            c.setFillColor(title_col)
            c.drawCentredString(x, y+radius+8, title)
            # Plot nuclei
            for angle, label, ncol in nuclei:
                rad = math.radians(angle)
                nx = x + (radius*0.6) * math.cos(rad)
                ny = y + (radius*0.6) * math.sin(rad)
                c.setFillColor(ncol)
                c.setStrokeColor(WHITE)
                c.setLineWidth(0.5)
                c.circle(nx, ny, 7, fill=1, stroke=1)
                # Leader line + label
                lx2 = x + (radius+12) * math.cos(rad)
                ly2 = y + (radius+12) * math.sin(rad)
                c.setStrokeColor(ncol)
                c.setLineWidth(0.7)
                c.line(nx + 7*math.cos(rad), ny + 7*math.sin(rad), lx2, ly2)
                c.setFont("Helvetica", 6.5)
                c.setFillColor(BLACK)
                # Adjust label placement
                if math.cos(rad) > 0.3:
                    c.drawString(lx2+2, ly2-3, label)
                elif math.cos(rad) < -0.3:
                    tw = c.stringWidth(label, "Helvetica", 6.5)
                    c.drawString(lx2-tw-2, ly2-3, label)
                else:
                    tw = c.stringWidth(label, "Helvetica", 6.5)
                    if math.sin(rad) > 0:
                        c.drawCentredString(lx2, ly2+4, label)
                    else:
                        c.drawCentredString(lx2, ly2-10, label)

        # MIDBRAIN
        cross_section(100, h-90, 52, "MIDBRAIN", ORANGE, [
            (90,   "EW\n(CN III)",    RED),
            (0,    "III Motor",       RED),
            (180,  "IV\n(Trochlear)", PURPLE),
            (270,  "Mes. V",          BLUE),
        ])

        # PONS
        cross_section(270, h-90, 58, "UPPER PONS", BLUE, [
            (90,   "Mot V",           COL_SVE),
            (45,   "Chief\nSens V",   COL_GSA),
            (135,  "Mes V",           COL_GSA),
            (270,  "IV (exit\ndorsal)",PURPLE),
        ])

        # LOWER PONS
        cross_section(450, h-90, 58, "LOWER PONS", BLUE, [
            (90,   "AbdN VI",         COL_GSE),
            (30,   "Facial\nVII",     COL_SVE),
            (150,  "Sup Sal\nVII",    COL_GVE),
            (270,  "Sp V\n(descend)", COL_GSA),
            (210,  "Vest VIII",       COL_SSA),
            (330,  "Coch VIII",       COL_SSA),
        ])

        # UPPER MEDULLA
        cross_section(130, 85, 55, "UPPER MEDULLA", TEAL, [
            (90,   "Sol Nuc\n(IX,X)",  COL_SVA),
            (30,   "Dors Mot X",       COL_GVE),
            (150,  "Inf Sal IX",       COL_GVE),
            (270,  "Sp V cont.",       COL_GSA),
            (0,    "N.Ambig\nIX,X",   COL_SVE),
        ])

        # LOWER MEDULLA
        cross_section(370, 85, 55, "LOWER MEDULLA", TEAL, [
            (90,   "XII\nHypogl",      COL_GSE),
            (30,   "Acc XI\n(cranial)", COL_SVE),
            (150,  "Sp V end",         COL_GSA),
            (270,  "Sol caud\n(GVA)",   COL_GVA),
            (210,  "N.Ambig\n(cont)",   COL_SVE),
        ])

        # Key
        key_items = [
            (COL_GSE, "GSE = Somatic Motor"), (COL_SVE, "SVE = Branchial Motor"),
            (COL_GVE, "GVE = Parasympathetic"), (COL_SVA, "SVA = Sp.Visceral Sensory"),
            (COL_GVA, "GVA = Gen.Visceral Sensory"), (COL_GSA, "GSA = Gen.Somatic Sensory"),
            (COL_SSA, "SSA = Sp.Somatic Sensory"),
        ]
        kx = 8
        c.setFont("Helvetica-Bold", 7)
        c.setFillColor(NAVY)
        c.drawString(kx, 14, "Key:")
        kx += 30
        for col, lbl in key_items:
            c.setFillColor(col); c.setStrokeColor(GLINE); c.setLineWidth(0.5)
            c.circle(kx+4, 16, 4, fill=1, stroke=1)
            c.setFillColor(BLACK); c.setFont("Helvetica", 6.5)
            c.drawString(kx+10, 13, lbl)
            kx += c.stringWidth(lbl, "Helvetica", 6.5) + 20


# ════════════════════════════════════════════════════════════════════════════
#  FLOWCHART — CN Lesion localization
# ════════════════════════════════════════════════════════════════════════════
class LesionFlowchart(Flowable):
    def __init__(self, width=480, height=350):
        Flowable.__init__(self)
        self.width = width
        self.height = height

    def draw(self):
        c = self.canv
        w, h = self.width, self.height

        c.setFillColor(colors.HexColor("#f8fffe"))
        c.roundRect(0, 0, w, h, 8, fill=1, stroke=0)

        c.setFont("Helvetica-Bold", 9)
        c.setFillColor(NAVY)
        c.drawCentredString(w/2, h-13, "Flowchart — Clinical Localization of Brainstem CN Lesions")

        def box(x, y, bw, bh, lines, fill, tc=BLACK, bold=False, radius=6):
            c.setFillColor(fill)
            c.setStrokeColor(GLINE)
            c.setLineWidth(1)
            c.roundRect(x, y-bh, bw, bh, radius, fill=1, stroke=1)
            fnt = "Helvetica-Bold" if bold else "Helvetica"
            lh = 10
            n = len(lines)
            sy = y - bh/2 + (n-1)*lh/2
            for i, ln in enumerate(lines):
                c.setFont(fnt, 8)
                c.setFillColor(tc)
                c.drawCentredString(x+bw/2, sy - i*lh, ln)

        def arrow(x1, y1, x2, y2, col=GLINE):
            c.setStrokeColor(col)
            c.setLineWidth(1.5)
            c.line(x1, y1, x2, y2)
            dx = x2-x1; dy = y2-y1
            L = math.sqrt(dx*dx+dy*dy)
            if L == 0: return
            ux, uy = dx/L, dy/L
            px, py = -uy, ux
            sz = 5
            ax, ay = x2-ux*sz, y2-uy*sz
            c.setFillColor(col)
            path = c.beginPath()
            path.moveTo(x2, y2)
            path.lineTo(ax+px*sz*0.4, ay+py*sz*0.4)
            path.lineTo(ax-px*sz*0.4, ay-py*sz*0.4)
            path.close()
            c.drawPath(path, fill=1, stroke=0)

        def label_line(x, y, text, col=BLACK):
            c.setFont("Helvetica-Oblique", 7.5)
            c.setFillColor(col)
            c.drawCentredString(x, y, text)

        cx = w/2
        # Top: clinical sign
        y0 = h-30
        bw0 = 260; bh0 = 30
        box(cx-bw0/2, y0, bw0, bh0, ["Cranial Nerve Deficit Identified",
            "on Clinical Examination"], LBLUE, NAVY, bold=True)
        arrow(cx, y0-bh0, cx, y0-bh0-14, NAVY)

        # Decision: multiple or single?
        y1 = y0-bh0-24; bw1=240; bh1=28
        box(cx-bw1/2, y1, bw1, bh1, ["Multiple CN affected?"], LAMBER, AMBER, bold=True)
        arrow(cx-bw1/2, y1-bh1/2, cx-bw1/2-30, y1-bh1/2-40, AMBER)
        label_line(cx-bw1/2-55, y1-bh1/2-44, "YES", AMBER)
        arrow(cx+bw1/2, y1-bh1/2, cx+bw1/2+30, y1-bh1/2-40, BLUE)
        label_line(cx+bw1/2+50, y1-bh1/2-44, "NO", BLUE)

        # Left branch (multiple CN)
        yL = y1-bh1-50; bwL=160; bhL=50
        box(cx-bw1/2-30-bwL/2, yL, bwL, bhL, [
            "BRAINSTEM lesion", "(intraaxial)", "Crossed signs:",
            "ipsi CN + contra hemiplegia"], colors.HexColor("#fff3d6"), AMBER)

        # Right branch (single CN)
        yR = y1-bh1-50; bwR=160; bhR=38
        box(cx+bw1/2+30+bwR/2-bwR, yR, bwR, bhR, [
            "Peripheral CN lesion",
            "(skull foramen / cistern)"], colors.HexColor("#dff0fb"), BLUE)

        # Below brainstem box -> which level?
        yL2 = yL - bhL - 12
        bwL2 = 160; bhL2 = 28
        box(cx-bw1/2-30-bwL/2, yL2, bwL2, bhL2,
            ["Which brainstem level?"], LRED, RED, bold=True)
        arrow(cx-bw1/2-30-bwL/2+bwL/2, yL-bhL,
              cx-bw1/2-30-bwL/2+bwL/2, yL2, RED)

        # Three sub-boxes for level
        yL3 = yL2 - bhL2 - 12
        bw3 = 115; bh3 = 65
        sx = cx-bw1/2-30-bwL/2+bwL/2  # centre x

        # Midbrain
        msx = sx - bw3 - 10
        box(msx-bw3/2, yL3, bw3, bh3, [
            "MIDBRAIN", "CN III, IV affected",
            "Weber: CN III +",
            "contralateral", "hemiplegia",
            "(Cerebral peduncle)"], LORANGE, ORANGE)
        arrow(sx - bw3/2, yL2-bhL2, msx, yL3, ORANGE)
        label_line(msx-20, yL2-bhL2-6, "III/IV", ORANGE)

        # Pons
        box(sx-bw3/2, yL3, bw3, bh3, [
            "PONS", "CN V,VI,VII,VIII",
            "Millard-Gubler:",
            "CN VI,VII +",
            "contra hemiplegia",
            "(PPRF, MLF)"], LBLUE, BLUE)
        arrow(sx, yL2-bhL2, sx, yL3, BLUE)
        label_line(sx, yL2-bhL2-6, "V–VIII", BLUE)

        # Medulla
        mdsx = sx + bw3 + 10
        box(mdsx-bw3/2, yL3, bw3, bh3, [
            "MEDULLA", "CN IX,X,XI,XII",
            "Wallenberg (PICA):",
            "IX,X,XI deficit +",
            "ipsi face pain-loss,",
            "Horner's"], LTEAL, TEAL)
        arrow(sx + bw3/2, yL2-bhL2, mdsx, yL3, TEAL)
        label_line(mdsx+20, yL2-bhL2-6, "IX–XII", TEAL)

        # Bottom note
        c.setFont("Helvetica-Oblique", 8)
        c.setFillColor(RED)
        c.drawCentredString(w/2, 10, "⚠  Crossed signs = pathognomonic of INTRAAXIAL (brainstem) lesion")


# ════════════════════════════════════════════════════════════════════════════
#  BUILD DOCUMENT
# ════════════════════════════════════════════════════════════════════════════
story = []

# ── TITLE ────────────────────────────────────────────────────────────────────
title_data = [[
    Paragraph("<b>BRAINSTEM — CRANIAL NERVE NUCLEI &amp; EXITS</b>", title_s),
    Paragraph("5-Mark Anatomy Notes  |  BD Chaurasia Dental Anatomy (5th Ed)  |  Cranial Nerves III–XII", sub_s),
]]
title_tbl = Table(title_data, colWidths=[W])
title_tbl.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(-1,-1),NAVY),
    ("TOPPADDING",(0,0),(-1,-1),10),
    ("BOTTOMPADDING",(0,0),(-1,-1),10),
    ("LEFTPADDING",(0,0),(-1,-1),10),
    ("RIGHTPADDING",(0,0),(-1,-1),10),
]))
story.append(title_tbl)
story.append(Spacer(1,8))

# ── QUICK FACTS ───────────────────────────────────────────────────────────────
qf_data = [
    [Paragraph("<b>Brainstem Parts</b>",ps("qh",fontSize=9,textColor=WHITE,fontName="Helvetica-Bold")),
     Paragraph("Midbrain (mesencephalon) → Pons (metencephalon) → Medulla oblongata (myelencephalon)",body_s)],
    [Paragraph("<b>CN I &amp; II</b>",ps("qh",fontSize=9,textColor=WHITE,fontName="Helvetica-Bold")),
     Paragraph("NOT true brainstem CNs — CN I from forebrain (olfactory bulb), CN II from diencephalon (thalamus)",body_s)],
    [Paragraph("<b>CN III–XII</b>",ps("qh",fontSize=9,textColor=WHITE,fontName="Helvetica-Bold")),
     Paragraph("Arise from brainstem nuclei in roughly rostral→caudal order (III→IV midbrain; V–VIII pons; IX–XII medulla)",body_s)],
    [Paragraph("<b>Columns</b>",ps("qh",fontSize=9,textColor=WHITE,fontName="Helvetica-Bold")),
     Paragraph("3 Motor columns (GSE, GVE, SVE) + 3 Sensory columns (GVA/SVA, GSA, SSA) run along brainstem",body_s)],
    [Paragraph("<b>SAT mnemonic</b>",ps("qh",fontSize=9,textColor=WHITE,fontName="Helvetica-Bold")),
     Paragraph("3 nuclei receiving >1 CN: <b>S</b>olitarius (VII,IX,X) + <b>A</b>mbiguus (IX,X,XI) + <b>T</b>rigeminal nuclei (V,VII,IX,X)",body_s)],
]
qf_tbl = Table(qf_data, colWidths=[3.5*cm, W-3.5*cm])
qf_tbl.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(0,-1),BLUE),
    ("TEXTCOLOR",(0,0),(0,-1),WHITE),
    ("ROWBACKGROUNDS",(0,0),(-1,-1),[LBLUE,colors.HexColor("#eaf4fd")]),
    ("BACKGROUND",(0,0),(0,-1),BLUE),
    ("GRID",(0,0),(-1,-1),0.5,GLINE),
    ("VALIGN",(0,0),(-1,-1),"TOP"),
    ("TOPPADDING",(0,0),(-1,-1),4),
    ("BOTTOMPADDING",(0,0),(-1,-1),4),
    ("LEFTPADDING",(0,0),(-1,-1),6),
    ("FONTSIZE",(0,0),(-1,-1),9),
]))
story.append(qf_tbl)
story.append(Spacer(1,8))

# ── KEY POINTS ────────────────────────────────────────────────────────────────
story.append(section_head("★  KEY POINTS — BRAINSTEM CN NUCLEI", NAVY))
kp_items = [
    ("①", "The brainstem contains nuclei for CN III through XII (10 pairs). CN I and II are not brainstem nerves."),
    ("②", "MOTOR nuclei: Somatic motor (GSE) → most medial; Parasympathetic (GVE) → intermediate; Branchial motor (SVE) → lateral. Separated by sulcus limitans."),
    ("③", "SENSORY nuclei: Visceral sensory (GVA/SVA) → medial; General somatic sensory (GSA) → intermediate; Special somatic sensory (SSA) → most lateral."),
    ("④", "Only CN IV (trochlear) exits from the DORSAL surface of the brainstem — all others exit ventrally or laterally."),
    ("⑤", "CN III and IV exit at the level of the midbrain; CN V,VI,VII,VIII from the pons; CN IX,X,XI,XII from the medulla."),
    ("⑥", "The Edinger-Westphal nucleus (GVE) is the parasympathetic nucleus of CN III — pupillary constriction and accommodation."),
    ("⑦", "The Trigeminal sensory nucleus is the longest in the brainstem — extends from mid-pons to C2 spinal cord (mesencephalic, chief sensory, spinal nucleus)."),
    ("⑧", "Nucleus ambiguus (SVE) is shared by CN IX, X, and cranial root of XI — innervates pharyngeal/laryngeal muscles."),
    ("⑨", "Nucleus solitarius (SVA/GVA) is shared by CN VII (taste anterior 2/3 tongue), IX (taste posterior 1/3), and X (visceral sensory)."),
    ("⑩", "CN XI (accessory): spinal root from C1-C5 anterior horn cells; cranial root from nucleus ambiguus — joins X briefly, then separates."),
]
for num, text in kp_items:
    t = Table([[
        Paragraph(f"<b>{num}</b>", ps("n", fontSize=11, textColor=BLUE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph(text, body_s)
    ]], colWidths=[1.2*cm, W-1.2*cm])
    t.setStyle(TableStyle([
        ("VALIGN",(0,0),(-1,-1),"TOP"),
        ("TOPPADDING",(0,0),(-1,-1),3),
        ("BOTTOMPADDING",(0,0),(-1,-1),3),
        ("LEFTPADDING",(0,0),(-1,-1),5),
        ("BOX",(0,0),(-1,-1),0.5,GLINE),
        ("ROWBACKGROUNDS",(0,0),(-1,-1),[LTEAL, WHITE]),
    ]))
    story.append(t)
story.append(Spacer(1,8))

# ── DIAGRAM 1 ─────────────────────────────────────────────────────────────────
story.append(section_head("✦  DIAGRAM 1 — Brainstem Anterior View: CN Exit Points", BLUE))
story.append(Spacer(1,4))
story.append(BrainstemDiagram(width=W, height=380))
story.append(Spacer(1,4))
story.append(Paragraph(
    "<i>Note: CN IV (trochlear) is the only CN to exit from the dorsal surface; it then wraps around the brainstem. "
    "CN I & II are NOT brainstem nerves.</i>", small_s))
story.append(Spacer(1,8))

# ── TABLE 1 — Master CN Nuclei Table ─────────────────────────────────────────
story.append(section_head("▶  TABLE 1 — MASTER TABLE: ALL CN NUCLEI, LOCATION & FUNCTION", NAVY))
story.append(Spacer(1,2))

col_w = [0.6*cm, 2.2*cm, 2.8*cm, 2.4*cm, W-8*cm]

def cn_row(num, name, nucleus, location, func, bg=WHITE):
    return [
        Paragraph(f"<b>{num}</b>", ps("cn", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph(f"<b>{name}</b>", ps("cn2", fontSize=8.5, textColor=NAVY, fontName="Helvetica-Bold")),
        Paragraph(nucleus, ps("cn3", fontSize=8, textColor=BLACK, fontName="Helvetica", leading=11)),
        Paragraph(location, ps("cn4", fontSize=8, textColor=BLUE, fontName="Helvetica-Bold", leading=11)),
        Paragraph(func, ps("cn5", fontSize=8, textColor=BLACK, fontName="Helvetica", leading=11)),
    ]

header_row = [
    Paragraph("<b>CN</b>", ps("h", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
    Paragraph("<b>Name</b>", ps("h", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
    Paragraph("<b>Nucleus/Nuclei</b>", ps("h", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
    Paragraph("<b>Brainstem Level</b>", ps("h", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
    Paragraph("<b>Function(s)</b>", ps("h", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
]

cn_data = [header_row,
    cn_row("I",   "Olfactory",       "Olfactory bulb (anterior brain)", "Forebrain\n(not brainstem)", "Special sensory: Smell"),
    cn_row("II",  "Optic",           "Lateral geniculate nucleus\n(thalamus)", "Diencephalon\n(not brainstem)", "Special sensory: Vision"),
    cn_row("III", "Oculomotor",      "Oculomotor nucleus (GSE)\nEdinger-Westphal nucleus (GVE)",
           "Midbrain\n(superior colliculus level)",
           "Motor: 4 extraocular muscles (SR,IR,MR,IO) + levator palpebrae\nParasympathetic: pupil constriction (sphincter pupillae) + ciliary muscle (accommodation)"),
    cn_row("IV",  "Trochlear",       "Trochlear nucleus (GSE)",
           "Midbrain\n(inferior colliculus level)\n★ Exits DORSAL",
           "Motor: Superior oblique muscle\n(depresses, intorts, abducts eye)\nOnly CN with dorsal exit + longest intracranial course"),
    cn_row("V",   "Trigeminal",      "Motor nucleus of V (SVE)\nChief (principal) sensory nucleus (GSA)\nSpinal nucleus of V (GSA: pain/temp)\nMesencephalic nucleus of V (GSA: proprioception)",
           "Pons (motor + chief sensory\nat mid-pons level;\nspinal nucleus extends\nto C2 spinal cord;\nmesencephalic up to midbrain)",
           "Motor: muscles of mastication (temporalis, masseter, pterygoids), tensor tympani, tensor veli palatini, mylohyoid, ant. belly digastric\nSensory: face, scalp, teeth, gums, sinuses, meninges, ant. 2/3 tongue (general sensation), cornea"),
    cn_row("VI",  "Abducens",        "Abducens nucleus (GSE)",
           "Pons\n(pontomedullary junction\n— medial)",
           "Motor: Lateral rectus (abducts eye)\nLong intracranial course → injured in raised ICP (false localising)"),
    cn_row("VII", "Facial",          "Facial nucleus (SVE)\nSuperior salivatory nucleus (GVE)\nNucleus solitarius — rostral (SVA)",
           "Pons\n(pontomedullary junction\n— lateral to VI)",
           "Motor: muscles of facial expression, stapedius, stylohyoid, post. belly digastric\nParasympathetic: lacrimal, submandibular, sublingual glands\nTaste: anterior 2/3 tongue (chorda tympani via NTS)\nSensory: small area around ear (GSA)"),
    cn_row("VIII","Vestibulocochlear","Cochlear nuclei (SSA):\n  • Dorsal cochlear nucleus\n  • Ventral cochlear nucleus\nVestibular nuclei (SSA):\n  • Superior (Bechterew)\n  • Inferior (Roller)\n  • Medial (Schwalbe)\n  • Lateral (Deiters)",
           "Pons\n(pontomedullary junction\nlateral to VII)",
           "Cochlear: Hearing\nVestibular: Balance, spatial orientation, vestibulo-ocular reflex (VOR)\n★ Purely sensory nerve"),
    cn_row("IX",  "Glossopharyngeal","Nucleus ambiguus (SVE)\nInferior salivatory nucleus (GVE)\nNucleus solitarius (SVA + GVA)",
           "Medulla\n(upper: exits lateral\ndorsal to olive)",
           "Motor: stylopharyngeus\nParasympathetic: parotid gland (via otic ganglion)\nTaste: posterior 1/3 tongue\nSensory: posterior 1/3 tongue, tonsil, pharynx, middle ear, carotid body/sinus (chemoreceptor + baroreceptor)\nGag reflex (afferent)"),
    cn_row("X",   "Vagus",           "Dorsal motor nucleus of X (GVE)\nNucleus ambiguus (SVE)\nNucleus solitarius (GVA + SVA)\nSpinal nucleus of V (GSA)",
           "Medulla\n(exits lateral medulla\nbelow IX)",
           "Parasympathetic: thoracic + abdominal viscera (to splenic flexure)\nMotor: pharynx, larynx, palate (recurrent + superior laryngeal nerves)\nVisceral sensory: thoracic/abdominal organs\nTaste: epiglottis, base of tongue\nSomatic: small ear/EAC area"),
    cn_row("XI",  "Accessory",       "Spinal accessory nucleus (SVE)\n  C1–C5 anterior horn cells\nCranial root:\n  Nucleus ambiguus (SVE)",
           "Medulla + C1–C5\nspinal cord\n(roots ascend through\nforamen magnum)",
           "Spinal root: sternocleidomastoid + upper trapezius\nCranial root: joins vagus → laryngeal/pharyngeal muscles (some authorities)\n★ Only CN with spinal cord origin"),
    cn_row("XII", "Hypoglossal",     "Hypoglossal nucleus (GSE)",
           "Medulla\n(exits ventral medulla\nbetween pyramid + olive)",
           "Motor: ALL intrinsic + extrinsic tongue muscles EXCEPT palatoglossus (CN X)\nProtrusion: genioglossus\n★ LMN lesion → tongue deviates TOWARD the side of lesion"),
]

cn_tbl = Table(cn_data, colWidths=col_w)
ts_cn = [
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("TEXTCOLOR", (0,0), (-1,0), WHITE),
    ("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE", (0,0), (-1,-1), 8),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("GRID", (0,0), (-1,-1), 0.4, GLINE),
    ("TOPPADDING", (0,0), (-1,-1), 3),
    ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ("LEFTPADDING", (0,0), (-1,-1), 4),
    # Row background colours by level
    ("BACKGROUND", (0,1), (-1,2), colors.HexColor("#f9f9f9")),   # I, II
    ("BACKGROUND", (0,3), (-1,4), LORANGE),  # III, IV (midbrain)
    ("BACKGROUND", (0,5), (-1,8), LBLUE),    # V-VIII (pons)
    ("BACKGROUND", (0,9), (-1,12), LTEAL),   # IX-XII (medulla)
    # CN number background
    ("BACKGROUND", (0,1), (0,2), GREY),
    ("BACKGROUND", (0,3), (0,4), ORANGE),
    ("BACKGROUND", (0,5), (0,8), BLUE),
    ("BACKGROUND", (0,9), (0,12), TEAL),
    ("TEXTCOLOR", (0,3), (0,4), WHITE),
    ("TEXTCOLOR", (0,5), (0,8), WHITE),
    ("TEXTCOLOR", (0,9), (0,12), WHITE),
    ("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
]
cn_tbl.setStyle(TableStyle(ts_cn))
story.append(cn_tbl)
story.append(Spacer(1,4))
story.append(Paragraph(
    "<i>Colour key: Orange rows = Midbrain (III–IV) | Blue rows = Pons (V–VIII) | Teal rows = Medulla (IX–XII)</i>",
    small_s))
story.append(Spacer(1,8))

# ── DIAGRAM 2 — Functional Columns ────────────────────────────────────────────
story.append(section_head("✦  DIAGRAM 2 — Functional Columns of CN Nuclei", BLUE))
story.append(Spacer(1,4))
story.append(ColumnDiagram(width=W, height=220))
story.append(Spacer(1,4))
story.append(Paragraph(
    "<i>Motor nuclei lie medial to the sulcus limitans; sensory nuclei lie lateral. "
    "GSE = general somatic efferent | GVE = general visceral efferent | SVE = special visceral efferent | "
    "GVA/SVA = general/special visceral afferent | GSA = general somatic afferent | SSA = special somatic afferent.</i>",
    small_s))
story.append(Spacer(1,8))

# ── TABLE 2 — Functional Column Classification ───────────────────────────────
story.append(section_head("▶  TABLE 2 — FUNCTIONAL COLUMN CLASSIFICATION OF CN NUCLEI", TEAL))

col2_w = [3*cm, 3.5*cm, 3.5*cm, W-10*cm]
col2_header = [
    Paragraph("<b>Column</b>", ps("h2", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
    Paragraph("<b>Nuclei</b>", ps("h2", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
    Paragraph("<b>Cranial Nerves</b>", ps("h2", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
    Paragraph("<b>Function</b>", ps("h2", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
]
col2_data = [col2_header,
    [Paragraph("<b>Somatic Motor\n(GSE)</b>", ps("c1", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("Oculomotor nucleus\nTrochlear nucleus\nAbducens nucleus\nHypoglossal nucleus", ps("c2", fontSize=8)),
     Paragraph("CN III, IV, VI, XII", ps("c3", fontSize=8.5, fontName="Helvetica-Bold", textColor=NAVY)),
     Paragraph("Extraocular muscles (III,IV,VI)\nAll tongue muscles (XII)", ps("c4", fontSize=8))],
    [Paragraph("<b>Parasympathetic\n(GVE)</b>", ps("c1", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("Edinger-Westphal (EW)\nSuperior salivatory\nInferior salivatory\nDorsal motor nucleus of X", ps("c2", fontSize=8)),
     Paragraph("CN III\nCN VII\nCN IX\nCN X", ps("c3", fontSize=8.5, fontName="Helvetica-Bold", textColor=NAVY)),
     Paragraph("Pupil constriction + accommodation (EW)\nLacrimal, submandibular, sublingual (Sup sal)\nParotid gland (Inf sal)\nThoracoabdominal viscera (Dors motor X)", ps("c4", fontSize=8))],
    [Paragraph("<b>Branchial Motor\n(SVE)</b>", ps("c1", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("Motor nucleus of V\nFacial nucleus\nNucleus ambiguus\nSpinal accessory nucleus", ps("c2", fontSize=8)),
     Paragraph("CN V\nCN VII\nCN IX, X, (XI)\nCN XI", ps("c3", fontSize=8.5, fontName="Helvetica-Bold", textColor=NAVY)),
     Paragraph("Muscles of mastication\nFacial expression, stapedius\nPharynx/larynx/palate muscles\nSCM + upper trapezius", ps("c4", fontSize=8))],
    [Paragraph("<b>Visceral Sensory\n(GVA + SVA)</b>", ps("c1", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("Nucleus solitarius\n  • Rostral = SVA\n  • Caudal = GVA", ps("c2", fontSize=8)),
     Paragraph("CN VII (taste ant.2/3)\nCN IX (taste post.1/3)\nCN X (visceral + taste)", ps("c3", fontSize=8.5, fontName="Helvetica-Bold", textColor=NAVY)),
     Paragraph("Taste (SVA) from tongue, epiglottis\nVisceral afferents from thoracoabdominal organs (GVA)", ps("c4", fontSize=8))],
    [Paragraph("<b>General Somatic\nSensory (GSA)</b>", ps("c1", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("Mesencephalic nucleus of V\nChief (principal) sensory nucleus of V\nSpinal nucleus of V", ps("c2", fontSize=8)),
     Paragraph("CN V (main)\nAlso: VII, IX, X\n(small somatic areas)", ps("c3", fontSize=8.5, fontName="Helvetica-Bold", textColor=NAVY)),
     Paragraph("Proprioception (Mes. V)\nTactile/discriminative touch (Chief V)\nPain & temperature from face (Spinal V – pars caudalis)", ps("c4", fontSize=8))],
    [Paragraph("<b>Special Somatic\nSensory (SSA)</b>", ps("c1", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("Cochlear nuclei (dorsal + ventral)\nVestibular nuclei (4: superior, inferior, medial, lateral)", ps("c2", fontSize=8)),
     Paragraph("CN VIII", ps("c3", fontSize=8.5, fontName="Helvetica-Bold", textColor=NAVY)),
     Paragraph("Hearing (cochlear nuclei)\nBalance/vestibular reflexes/VOR (vestibular nuclei)\nLateral (Deiters) nucleus → lateral vestibulospinal tract", ps("c4", fontSize=8))],
]
col2_tbl = Table(col2_data, colWidths=col2_w)
col2_tbl.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(-1,0), TEAL),
    ("TEXTCOLOR",(0,0),(-1,0), WHITE),
    ("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
    ("GRID",(0,0),(-1,-1),0.4, GLINE),
    ("VALIGN",(0,0),(-1,-1),"TOP"),
    ("TOPPADDING",(0,0),(-1,-1),4),
    ("BOTTOMPADDING",(0,0),(-1,-1),4),
    ("LEFTPADDING",(0,0),(-1,-1),5),
    # Column 0 background: alternate
    ("BACKGROUND",(0,1),(0,1), COL_GSE),
    ("BACKGROUND",(0,2),(0,2), COL_GVE),
    ("BACKGROUND",(0,3),(0,3), COL_SVE),
    ("BACKGROUND",(0,4),(0,4), COL_SVA),
    ("BACKGROUND",(0,5),(0,5), COL_GSA),
    ("BACKGROUND",(0,6),(0,6), COL_SSA),
    # Row backgrounds
    ("ROWBACKGROUNDS",(1,1),(-1,-1),[WHITE, GREY]),
]))
story.append(col2_tbl)
story.append(Spacer(1,8))

# ── DIAGRAM 3 — Cross-sections ────────────────────────────────────────────────
story.append(section_head("✦  DIAGRAM 3 — Nuclei at Each Brainstem Level (Cross-Section Schematics)", ORANGE))
story.append(Spacer(1,4))
story.append(CrossSectionDiagram(width=W, height=320))
story.append(Spacer(1,4))
story.append(Paragraph(
    "<i>Abbreviations: EW = Edinger-Westphal; Mes = Mesencephalic; Mot = Motor; Sens = Sensory; "
    "AbdN = Abducens; Sol Nuc = Nucleus solitarius; Dors Mot = Dorsal motor; "
    "N.Ambig = Nucleus ambiguus; Acc = Accessory; Vest = Vestibular; Coch = Cochlear; "
    "Sup Sal = Superior salivatory; Inf Sal = Inferior salivatory.</i>",
    small_s))
story.append(Spacer(1,8))

# ── TABLE 3 — Skull exit foramina ─────────────────────────────────────────────
story.append(section_head("▶  TABLE 3 — SKULL EXIT FORAMINA OF CRANIAL NERVES", PURPLE))

for_data = [
    [Paragraph("<b>CN</b>", ps("fh", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("<b>Name</b>", ps("fh", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("<b>Foramen</b>", ps("fh", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("<b>Clinical Relevance</b>", ps("fh", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold"))],
    ["I", "Olfactory", "Cribriform plate (ethmoid)", "Anosmia in anterior fossa fractures"],
    ["II", "Optic", "Optic canal (sphenoid)", "Visual loss; papilloedema in raised ICP"],
    ["III", "Oculomotor", "Superior orbital fissure (SOF)", "Palsy → ptosis, fixed dilated pupil, 'down-and-out' eye"],
    ["IV", "Trochlear", "SOF (smallest cranial nerve)", "Weakness of downward gaze → patient tilts head (head tilt test)"],
    ["V1", "Ophthalmic", "SOF", "Loss of corneal reflex"],
    ["V2", "Maxillary", "Foramen rotundum", "Loss of cheek/upper lip sensation; dental anaesthesia"],
    ["V3", "Mandibular", "Foramen ovale", "Loss of lower face sensation + jaw deviation toward lesion"],
    ["VI", "Abducens", "SOF", "Medial squint; false localising sign in raised ICP (Gradenigo syndrome)"],
    ["VII", "Facial", "Internal acoustic meatus → stylomastoid foramen", "Bell's palsy; taste loss (chorda tympani); hyperacusis (stapedius)"],
    ["VIII", "Vestibulocochlear", "Internal acoustic meatus", "Sensorineural deafness; vertigo; acoustic neuroma (CPA angle)"],
    ["IX", "Glossopharyngeal", "Jugular foramen", "Loss of gag reflex afferent; parotid hyposecretion; carotid body loss"],
    ["X", "Vagus", "Jugular foramen", "Hoarseness; dysphagia; absent gag efferent; autonomic dysfunction"],
    ["XI", "Accessory", "Jugular foramen", "Winging of scapula (trapezius); cannot turn head (SCM)"],
    ["XII", "Hypoglossal", "Hypoglossal canal (occipital bone)", "Tongue deviation + wasting toward lesion (LMN)"],
]
for_tbl = Table(for_data, colWidths=[0.8*cm, 2.5*cm, 4*cm, W-7.3*cm])
for_tbl.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(-1,0), PURPLE),
    ("TEXTCOLOR",(0,0),(-1,0), WHITE),
    ("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
    ("FONTSIZE",(0,0),(-1,-1),8.3),
    ("GRID",(0,0),(-1,-1),0.4, GLINE),
    ("VALIGN",(0,0),(-1,-1),"TOP"),
    ("TOPPADDING",(0,0),(-1,-1),3),
    ("BOTTOMPADDING",(0,0),(-1,-1),3),
    ("LEFTPADDING",(0,0),(-1,-1),4),
    ("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, LPURPLE]),
    ("FONTNAME",(0,1),(0,-1),"Helvetica-Bold"),
    ("TEXTCOLOR",(0,1),(0,-1), PURPLE),
    ("BACKGROUND",(2,8),(2,8), colors.HexColor("#fff0d0")),
]))
story.append(for_tbl)
story.append(Spacer(1,8))

# ── FLOWCHART ─────────────────────────────────────────────────────────────────
story.append(section_head("▶  FLOWCHART — Clinical Localization of Brainstem CN Lesions", RED))
story.append(Spacer(1,4))
story.append(LesionFlowchart(width=W, height=350))
story.append(Spacer(1,8))

# ── TABLE 4 — Classic Brainstem Syndromes ─────────────────────────────────────
story.append(section_head("▶  TABLE 4 — CLASSIC BRAINSTEM SYNDROMES (Dental/Clinical Exam)", RED))

syn_data = [
    [Paragraph("<b>Syndrome</b>", ps("sh", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("<b>Level</b>", ps("sh", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("<b>Structure Injured</b>", ps("sh", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold")),
     Paragraph("<b>Signs</b>", ps("sh", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold"))],
    ["Weber's syndrome", "Midbrain (base)", "CN III nucleus + cerebral peduncle (CST)",
     "Ipsilateral CN III palsy (ptosis, fixed dilated pupil, 'down-and-out') + contralateral hemiplegia"],
    ["Benedikt's syndrome", "Midbrain (tegmentum)", "CN III + red nucleus + medial lemniscus",
     "Ipsilateral CN III palsy + contralateral tremor/ataxia + contralateral hemisensory loss"],
    ["Parinaud's syndrome", "Dorsal midbrain (Sylvian aqueduct)", "Pretectal area",
     "Loss of upward gaze; light-near dissociation; convergence retraction nystagmus"],
    ["Millard-Gubler syndrome", "Caudal pons", "CN VI + CN VII + CST",
     "Ipsilateral CN VI and VII palsy + contralateral hemiplegia"],
    ["Foville's syndrome", "Caudal pons (tegmentum)", "CN VI + CN VII + PPRF + MLF",
     "Ipsilateral gaze palsy + CN VII palsy + contralateral hemiplegia"],
    ["Lateral Medullary (Wallenberg's)", "Lateral medulla (PICA)", "CN IX,X,XI; spinothalamic; sympathetics; inferior cerebellar peduncle",
     "Ipsilateral: CN IX/X (dysphagia, hoarseness), Horner's, facial pain-temp loss, ataxia\nContralateral: limb pain-temp loss"],
    ["Medial Medullary (Dejerine)", "Medial medulla (ASA)", "CN XII + CST + medial lemniscus",
     "Ipsilateral tongue deviation + contralateral hemiplegia + contralateral touch/proprioception loss"],
]
syn_tbl = Table(syn_data, colWidths=[3*cm, 2.5*cm, 3.5*cm, W-9*cm])
syn_tbl.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(-1,0), RED),
    ("TEXTCOLOR",(0,0),(-1,0), WHITE),
    ("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
    ("FONTSIZE",(0,0),(-1,-1),8),
    ("GRID",(0,0),(-1,-1),0.4, GLINE),
    ("VALIGN",(0,0),(-1,-1),"TOP"),
    ("TOPPADDING",(0,0),(-1,-1),3),
    ("BOTTOMPADDING",(0,0),(-1,-1),3),
    ("LEFTPADDING",(0,0),(-1,-1),4),
    ("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, LRED]),
    ("FONTNAME",(0,1),(0,-1),"Helvetica-Bold"),
    ("TEXTCOLOR",(0,1),(0,-1), RED),
]))
story.append(syn_tbl)
story.append(Spacer(1,8))

# ── DENTAL RELEVANCE BOX ──────────────────────────────────────────────────────
dent_data = [[
    Paragraph(
        "<b>🦷 DENTAL RELEVANCE — Cranial Nerve Nuclei</b><br/><br/>"
        "<b>CN V (Trigeminal) — Most important for Dentistry:</b><br/>"
        "• Chief sensory nucleus (pons): discriminative touch from teeth, gums, palate<br/>"
        "• Spinal nucleus (pars caudalis, medulla/C2): pain &amp; temperature from teeth/face → target of trigeminal neuralgia procedures<br/>"
        "• Motor nucleus (pons): muscles of mastication (masseter, temporalis, pterygoids) → bruxism, TMJ dysfunction<br/>"
        "• Mesencephalic nucleus: proprioception from PDL, jaw-closing muscles → jaw reflexes<br/><br/>"
        "<b>CN VII (Facial):</b> Chorda tympani (taste ant. 2/3 tongue) from NTS; superior salivatory → submandibular + sublingual salivary glands<br/>"
        "<b>CN IX (Glossopharyngeal):</b> Inferior salivatory nucleus → parotid gland; taste posterior 1/3 tongue via NTS<br/>"
        "<b>CN XII (Hypoglossal):</b> All tongue movements → critical for chewing, swallowing, speech articulation<br/>"
        "<b>CN XI (Accessory):</b> Head position for dental procedures (SCM, trapezius)",
        ps("dent", fontSize=9, textColor=BLACK, fontName="Helvetica", leading=14, spaceAfter=2)
    )
]]
dent_tbl = Table(dent_data, colWidths=[W])
dent_tbl.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(-1,-1), colors.HexColor("#fff8e1")),
    ("TOPPADDING",(0,0),(-1,-1),10),
    ("BOTTOMPADDING",(0,0),(-1,-1),10),
    ("LEFTPADDING",(0,0),(-1,-1),12),
    ("BOX",(0,0),(-1,-1),2, AMBER),
]))
story.append(dent_tbl)
story.append(Spacer(1,8))

# ── MEMORY AIDS ───────────────────────────────────────────────────────────────
story.append(section_head("✦  EXAM MEMORY AIDS & MNEMONICS", GREEN))
mem_data = [[
    Paragraph(
        "<b>CN in order:</b> Oh Oh Oh To Touch And Feel Very Good Velvet — Ah Heaven!<br/>"
        "(Olfactory, Optic, Oculomotor, Trochlear, Trigeminal, Abducens, Facial, Vestibulocochlear, Glossopharyngeal, Vagus, Accessory, Hypoglossal)<br/><br/>"
        "<b>Sensory/Motor:</b> Some Say Marry Money But My Brother Says Big Brains Matter More<br/>"
        "(S=sensory, M=motor, B=both for CN I–XII)<br/><br/>"
        "<b>Motor columns (medial→lateral):</b> G-G-S = GSE (somatic motor) → GVE (parasympathetic) → SVE (branchial motor)<br/>"
        "<b>Sensory columns (medial→lateral):</b> G-G-S = GVA/SVA (visceral) → GSA (somatic) → SSA (special somatic)<br/><br/>"
        "<b>SAT nuclei</b> (receive >1 CN): <b>S</b>olitarius · <b>A</b>mbiguus · <b>T</b>rigeminal<br/>"
        "<b>SOF contents:</b> CN III, IV, V1, VI + ophthalmic veins + sympathetics (mnemonic: 'Three IV V1 VI')<br/>"
        "<b>Jugular foramen:</b> CN IX, X, XI + sigmoid sinus + inferior petrosal sinus<br/><br/>"
        "<b>LMN vs UMN for CN VII:</b> LMN = ALL face ipsilateral (forehead + lower); "
        "UMN = LOWER face only (upper face spared due to bilateral cortical representation)<br/>"
        "<b>Hypoglossal:</b> Tongue deviates TOWARD the side of lesion (LMN); AWAY from lesion (UMN = uncommon)<br/>"
        "<b>Dorsal exit:</b> Only CN IV exits dorsal surface — crosses contralateral before exiting!",
        ps("mem", fontSize=9, textColor=BLACK, fontName="Helvetica", leading=14)
    )
]]
mem_tbl = Table(mem_data, colWidths=[W])
mem_tbl.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(-1,-1), LGREEN),
    ("TOPPADDING",(0,0),(-1,-1),10),
    ("BOTTOMPADDING",(0,0),(-1,-1),10),
    ("LEFTPADDING",(0,0),(-1,-1),12),
    ("BOX",(0,0),(-1,-1),2, GREEN),
]))
story.append(mem_tbl)
story.append(Spacer(1,8))

# ── EXTRA POINTS BOX ─────────────────────────────────────────────────────────
story.append(section_head("▶  EXTRA POINTS (High-Yield for Exams)", NAVY))
extra_items = [
    "The facial nucleus has TWO subdivisions: dorsal (innervates upper face — forehead, frontalis) receives BILATERAL cortical input; ventral (lower face) receives CONTRALATERAL cortical input only — explains UMN vs LMN VII palsy.",
    "The abducens nucleus contains two cell types: motor neurons (→ CN VI, lateral rectus) and interneurons (→ contralateral oculomotor nucleus via MLF → medial rectus). So abducens nucleus lesion causes IPSILATERAL GAZE PALSY (not just lateral rectus palsy).",
    "Edinger-Westphal nucleus: parasympathetic pre-ganglionic fibres travel with CN III → ciliary ganglion → short ciliary nerves → sphincter pupillae + ciliary muscle. Compression of CN III (e.g., uncal herniation, PCA aneurysm) first affects pupillomotor fibres on the outside of the nerve.",
    "The mesencephalic nucleus of CN V is unique — it is the ONLY primary sensory nucleus located WITHIN the CNS (all other 1st order sensory neurons are in peripheral ganglia). It conveys proprioception from jaw muscles and PDL.",
    "Nucleus solitarius: the rostral portion receives special visceral afferent (taste: CN VII, IX, X); the caudal portion receives general visceral afferent (cardiorespiratory, gastrointestinal via CN IX, X).",
    "CN VI has the longest intracranial course of all CNs → most commonly injured in raised ICP (false localising sign) as it gets stretched over the petrous ridge.",
    "The recurrent laryngeal nerve (branch of CN X vagus): left side loops around aortic arch (longer) → more commonly injured in thoracic/mediastinal disease; right side loops around subclavian artery.",
    "Auerbach's plexus (myenteric) and Meissner's plexus (submucosal) in gut wall receive parasympathetic fibres from the dorsal motor nucleus of X.",
    "CN XI spinal accessory nucleus: located in ventral horn of C1-C5 — the only cranial nerve with a nucleus outside the brainstem.",
    "Internuclear ophthalmoplegia (INO): lesion of MLF between abducens and oculomotor nuclei → failure of adduction ipsilateral to lesion + nystagmus of contralateral abducting eye. Bilateral INO in young patients = multiple sclerosis.",
]
for i, item in enumerate(extra_items):
    t = Table([[
        Paragraph(f"<b>{'★' if i < 5 else '•'}</b>", ps("e", fontSize=12, textColor=AMBER, fontName="Helvetica-Bold", alignment=TA_CENTER)),
        Paragraph(item, body_s)
    ]], colWidths=[0.8*cm, W-0.8*cm])
    t.setStyle(TableStyle([
        ("VALIGN",(0,0),(-1,-1),"TOP"),
        ("TOPPADDING",(0,0),(-1,-1),3),
        ("BOTTOMPADDING",(0,0),(-1,-1),3),
        ("LEFTPADDING",(0,0),(-1,-1),5),
        ("BOX",(0,0),(-1,-1),0.4, GLINE),
        ("ROWBACKGROUNDS",(0,0),(-1,-1),[LAMBER, WHITE]),
    ]))
    story.append(t)
story.append(Spacer(1,8))

# ── FOOTER ────────────────────────────────────────────────────────────────────
story.append(HRFlowable(width=W, thickness=1, color=GLINE))
story.append(Paragraph(
    "Ref: BD Chaurasia's Human Anatomy for Dental Students, 5th Edition — Brainstem, Cranial Nerve Nuclei &amp; Exits  |  "
    "Neuroanatomy through Clinical Cases (Blumenfeld) — Table 12.3, 12.4  |  "
    "Gray's Anatomy for Students  |  Notes compiled for 5-mark anatomy exam preparation",
    small_s))

# ── BUILD ─────────────────────────────────────────────────────────────────────
def on_page(canvas, doc):
    canvas.saveState()
    canvas.setFont("Helvetica", 7)
    canvas.setFillColor(colors.HexColor("#888888"))
    canvas.drawRightString(A4[0]-1.8*cm, 0.9*cm, f"Page {doc.page}")
    canvas.drawString(1.8*cm, 0.9*cm, "Brainstem — Cranial Nerve Nuclei & Exits | 5-Mark Anatomy Notes")
    canvas.restoreState()

doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print("✓ PDF created:", OUTPUT)
Running Command

cd /tmp/workspace/brainstem-cn && python make_brainstem_pdf.py 2>&1

Your PDF is ready! Download it here:

Brainstem CN Nuclei 5mark

PDF Document · PDF


What's Inside the PDF

★ 10 Key Points

From CN I-II (NOT brainstem) through columnar organization, SAT mnemonic, dorsal exit of CN IV, and LMN tongue deviation rules.

✦ Diagram 1 — Brainstem Anterior View

Custom schematic showing all CN exit points (III-XII) with:
  • Midbrain (orange), Pons (blue), Medulla (green) colour-coded
  • Each CN labeled with level and exit description
  • CN IV specially marked as dorsal exit

▶ Table 1 — MASTER CN Nuclei Table (All 12 CNs)

ColumnWhat it shows
CN #Colour-coded by brainstem level
Nucleus/NucleiAll nuclei per CN (e.g. CN VII has 3 nuclei)
Brainstem LevelExact location
FunctionFull motor + sensory + parasympathetic breakdown
Orange rows = Midbrain | Blue rows = Pons | Teal rows = Medulla

✦ Diagram 2 — Functional Columns Schema

Visual bar chart showing all 6 longitudinal columns (3 motor + 3 sensory) with which CNs belong to each.

▶ Table 2 — Functional Column Classification (GSE, GVE, SVE, GVA, SVA, GSA, SSA)

Full breakdown with nuclei, nerves, and functions for each column.

✦ Diagram 3 — Cross-Section Schematics

Five circular cross-sections (Midbrain / Upper Pons / Lower Pons / Upper Medulla / Lower Medulla) showing where each nucleus sits.

▶ Table 3 — Skull Exit Foramina

All 14 CN exits (including V1/V2/V3) with foramen and clinical relevance.

▶ Flowchart — Clinical Localization

Raised ICP → Multiple/Single CN → Brainstem vs peripheral → Level (Midbrain/Pons/Medulla) → Specific syndrome (Weber's, Millard-Gubler, Wallenberg's).

▶ Table 4 — Classic Brainstem Syndromes

7 syndromes: Weber, Benedikt, Parinaud, Millard-Gubler, Foville, Wallenberg, Dejerine with level + structure + signs.

🦷 Dental Relevance Box

CN V (all 4 nuclei for dentistry), CN VII (salivary), CN IX (parotid), CN XII (tongue), CN XI (head position).

✦ Memory Aids & 10 Extra High-Yield Points

Including the abducens interneuron explanation, mesencephalic V uniqueness, INO/MLF, false localising CN VI, and UMN vs LMN facial palsy.
This is a shared conversation. Sign in to Orris to start your own chat.