Physiological changes during pregnancy & make a detailed summary downloadable photo or pdf for better visual memory

Reading File
Now let me search the medical library for pregnancy physiology content in parallel.
Finding Sources
Finding Sources
Found the key section. Let me read it now along with more content from that block.
Reading File
Excellent - I have very rich content. Now let me read the remaining sections (GI, renal, hepatic changes) and also check the pptx skill to create a visual PDF.
Reading File
Reading File
I have all the content I need. Now let me create a detailed, visually rich PDF using Python with reportlab.
Running Command

mkdir -p /home/daytona/workspace/pregnancy-physiology && ls /home/daytona/workspace/pregnancy-physiology/

Writing File

~/pregnancy-physiology/make_pdf.py

#!/usr/bin/env python3
"""
Physiological Changes During Pregnancy - Visual Summary PDF
Based on Morgan & Mikhail's Clinical Anesthesiology, 7e
"""

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame
from reportlab.lib.colors import HexColor
import reportlab.lib.colors as rcolors

# ── Color Palette ──────────────────────────────────────────────────────────
DARK_BG      = HexColor('#0D1B2A')   # deep navy
HEADER_BG    = HexColor('#1B4F72')   # dark teal-blue
ACCENT_PINK  = HexColor('#E91E8C')   # hot pink accent
ACCENT_CYAN  = HexColor('#00BCD4')   # cyan accent
ACCENT_GOLD  = HexColor('#FFD600')   # golden yellow
ACCENT_GREEN = HexColor('#4CAF50')   # green
ACCENT_ORG   = HexColor('#FF6F00')   # orange
LIGHT_TEXT   = HexColor('#ECEFF1')   # near white
CARD_BG_1    = HexColor('#112233')   # card dark navy
CARD_BG_2    = HexColor('#0A2540')
ROW_ALT      = HexColor('#1A3555')
TABLE_HDR    = HexColor('#1565C0')
WHITE        = colors.white
BLACK        = colors.black

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

title_style = ParagraphStyle(
    'TitleStyle',
    fontName='Helvetica-Bold',
    fontSize=26,
    textColor=WHITE,
    alignment=TA_CENTER,
    spaceAfter=4,
    leading=30,
)
subtitle_style = ParagraphStyle(
    'SubtitleStyle',
    fontName='Helvetica',
    fontSize=12,
    textColor=ACCENT_CYAN,
    alignment=TA_CENTER,
    spaceAfter=2,
)
source_style = ParagraphStyle(
    'SourceStyle',
    fontName='Helvetica-Oblique',
    fontSize=9,
    textColor=HexColor('#90A4AE'),
    alignment=TA_CENTER,
    spaceAfter=6,
)
section_title_style = ParagraphStyle(
    'SectionTitle',
    fontName='Helvetica-Bold',
    fontSize=13,
    textColor=WHITE,
    alignment=TA_CENTER,
    spaceAfter=2,
    leading=16,
)
body_style = ParagraphStyle(
    'BodyStyle',
    fontName='Helvetica',
    fontSize=9,
    textColor=LIGHT_TEXT,
    alignment=TA_JUSTIFY,
    spaceAfter=4,
    leading=13,
)
bullet_style = ParagraphStyle(
    'BulletStyle',
    fontName='Helvetica',
    fontSize=8.5,
    textColor=LIGHT_TEXT,
    alignment=TA_LEFT,
    leftIndent=10,
    bulletIndent=2,
    spaceAfter=2,
    leading=12,
)
small_bold = ParagraphStyle(
    'SmallBold',
    fontName='Helvetica-Bold',
    fontSize=8,
    textColor=ACCENT_GOLD,
    alignment=TA_CENTER,
)
footnote_style = ParagraphStyle(
    'Footnote',
    fontName='Helvetica-Oblique',
    fontSize=7.5,
    textColor=HexColor('#78909C'),
    alignment=TA_CENTER,
)
card_header_style = ParagraphStyle(
    'CardHeader',
    fontName='Helvetica-Bold',
    fontSize=10,
    textColor=WHITE,
    alignment=TA_CENTER,
    leading=13,
)
card_body_style = ParagraphStyle(
    'CardBody',
    fontName='Helvetica',
    fontSize=8,
    textColor=LIGHT_TEXT,
    alignment=TA_LEFT,
    leading=11,
)
arrow_style = ParagraphStyle(
    'ArrowStyle',
    fontName='Helvetica-Bold',
    fontSize=9,
    textColor=ACCENT_GOLD,
    alignment=TA_CENTER,
)

# ── Helper to make a colored section banner ────────────────────────────────
def section_banner(title, icon, bg_color):
    data = [[Paragraph(f'{icon}  {title}', section_title_style)]]
    t = Table(data, colWidths=[17*cm])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), bg_color),
        ('ROUNDEDCORNERS', [8]),
        ('TOPPADDING', (0,0), (-1,-1), 8),
        ('BOTTOMPADDING', (0,0), (-1,-1), 8),
        ('LEFTPADDING', (0,0), (-1,-1), 12),
    ]))
    return t

def make_change_table(rows, accent):
    """rows: list of (Parameter, Change, Clinical Note)"""
    header = [
        Paragraph('Parameter', ParagraphStyle('th', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
        Paragraph('Change', ParagraphStyle('th', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
        Paragraph('Clinical Significance', ParagraphStyle('th', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
    ]
    table_data = [header]
    for i, (param, change, note) in enumerate(rows):
        bg = ROW_ALT if i % 2 == 0 else CARD_BG_1
        # Determine change color
        if '+' in str(change):
            chg_color = HexColor('#69F0AE')  # green for increase
        elif '-' in str(change):
            chg_color = HexColor('#FF5252')  # red for decrease
        else:
            chg_color = ACCENT_GOLD
        row = [
            Paragraph(param, ParagraphStyle('td', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT, alignment=TA_LEFT)),
            Paragraph(f'<b>{change}</b>', ParagraphStyle('chg', fontName='Helvetica-Bold', fontSize=9, textColor=chg_color, alignment=TA_CENTER)),
            Paragraph(note, ParagraphStyle('note', fontName='Helvetica', fontSize=8, textColor=HexColor('#B0BEC5'), alignment=TA_LEFT)),
        ]
        table_data.append(row)
    t = Table(table_data, colWidths=[5.5*cm, 2.5*cm, 9*cm])
    style = [
        ('BACKGROUND', (0,0), (-1,0), accent),
        ('GRID', (0,0), (-1,-1), 0.3, HexColor('#2C3E50')),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('RIGHTPADDING', (0,0), (-1,-1), 6),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [ROW_ALT, CARD_BG_1]),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ]
    t.setStyle(TableStyle(style))
    return t

# ── Document setup ─────────────────────────────────────────────────────────
OUTPUT = '/home/daytona/workspace/pregnancy-physiology/Physiological_Changes_During_Pregnancy.pdf'

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=1.8*cm,
    leftMargin=1.8*cm,
    topMargin=1.5*cm,
    bottomMargin=1.5*cm,
)

story = []

# ══════════════════════════════════════════════════════════════════════════════
# HEADER BLOCK
# ══════════════════════════════════════════════════════════════════════════════
header_data = [[
    Paragraph('PHYSIOLOGICAL CHANGES<br/>DURING PREGNANCY', title_style),
]]
header_table = Table(header_data, colWidths=[17*cm])
header_table.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,-1), DARK_BG),
    ('TOPPADDING', (0,0), (-1,-1), 18),
    ('BOTTOMPADDING', (0,0), (-1,-1), 8),
    ('ROUNDEDCORNERS', [10]),
]))
story.append(header_table)

story.append(Paragraph('A Visual Medical Summary for Students & Clinicians', subtitle_style))
story.append(Paragraph('Source: Morgan & Mikhail\'s Clinical Anesthesiology, 7e | p. 1572–1586', source_style))
story.append(Spacer(1, 5*mm))

# ══════════════════════════════════════════════════════════════════════════════
# QUICK REFERENCE NUMBERS TABLE
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_banner('QUICK REFERENCE: KEY NUMBERS AT A GLANCE', '📊', TABLE_HDR))
story.append(Spacer(1, 2*mm))

qr_data = [
    [Paragraph('System', small_bold), Paragraph('Parameter', small_bold),
     Paragraph('Change', small_bold), Paragraph('System', small_bold),
     Paragraph('Parameter', small_bold), Paragraph('Change', small_bold)],
    # col 1                                        col 2
    ['Neuro', 'MAC', Paragraph('<b><font color="#FF5252">-40%</font></b>', arrow_style),
     'CVS', 'Blood Volume', Paragraph('<b><font color="#69F0AE">+35%</font></b>', arrow_style)],
    ['Resp', 'O₂ Consumption', Paragraph('<b><font color="#69F0AE">+20-50%</font></b>', arrow_style),
     'CVS', 'Plasma Volume', Paragraph('<b><font color="#69F0AE">+55%</font></b>', arrow_style)],
    ['Resp', 'FRC', Paragraph('<b><font color="#FF5252">-20%</font></b>', arrow_style),
     'CVS', 'Cardiac Output', Paragraph('<b><font color="#69F0AE">+40%</font></b>', arrow_style)],
    ['Resp', 'Minute Ventilation', Paragraph('<b><font color="#69F0AE">+50%</font></b>', arrow_style),
     'CVS', 'Heart Rate', Paragraph('<b><font color="#69F0AE">+20%</font></b>', arrow_style)],
    ['Resp', 'Tidal Volume', Paragraph('<b><font color="#69F0AE">+40%</font></b>', arrow_style),
     'CVS', 'Stroke Volume', Paragraph('<b><font color="#69F0AE">+30%</font></b>', arrow_style)],
    ['Resp', 'PaCO₂', Paragraph('<b><font color="#FF5252">-15%</font></b>', arrow_style),
     'CVS', 'DBP', Paragraph('<b><font color="#FF5252">-15%</font></b>', arrow_style)],
    ['Resp', 'Airway Resistance', Paragraph('<b><font color="#FF5252">-35%</font></b>', arrow_style),
     'Haem', 'Hemoglobin', Paragraph('<b><font color="#FF5252">-20%</font></b>', arrow_style)],
    ['Renal', 'GFR', Paragraph('<b><font color="#69F0AE">+50%</font></b>', arrow_style),
     'Haem', 'Clotting Factors', Paragraph('<b><font color="#69F0AE">+30-250%</font></b>', arrow_style)],
]

cell_style = ParagraphStyle('cs', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT, alignment=TA_LEFT)
qr_table = Table(qr_data, colWidths=[2.2*cm, 4*cm, 2.3*cm, 2.2*cm, 4*cm, 2.3*cm])
qr_style = TableStyle([
    ('BACKGROUND', (0,0), (-1,0), HexColor('#1565C0')),
    ('TEXTCOLOR', (0,0), (-1,0), WHITE),
    ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
    ('FONTSIZE', (0,0), (-1,0), 8),
    ('ROWBACKGROUNDS', (0,1), (-1,-1), [CARD_BG_1, ROW_ALT]),
    ('GRID', (0,0), (-1,-1), 0.3, HexColor('#2C3E50')),
    ('TOPPADDING', (0,0), (-1,-1), 4),
    ('BOTTOMPADDING', (0,0), (-1,-1), 4),
    ('LEFTPADDING', (0,0), (-1,-1), 5),
    ('RIGHTPADDING', (0,0), (-1,-1), 5),
    ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ('FONTNAME', (0,1), (0,-1), 'Helvetica-Bold'),
    ('FONTNAME', (3,1), (3,-1), 'Helvetica-Bold'),
    ('TEXTCOLOR', (0,1), (0,-1), ACCENT_CYAN),
    ('TEXTCOLOR', (3,1), (3,-1), ACCENT_CYAN),
    ('ALIGN', (2,0), (2,-1), 'CENTER'),
    ('ALIGN', (5,0), (5,-1), 'CENTER'),
])
qr_table.setStyle(qr_style)
story.append(qr_table)
story.append(Spacer(1, 5*mm))

# ══════════════════════════════════════════════════════════════════════════════
# 1. NEUROLOGICAL
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('1. NEUROLOGICAL / CNS CHANGES', '🧠', HexColor('#4A148C')),
    Spacer(1, 2*mm),
    make_change_table([
        ('MAC (Min. Alveolar Conc.)', '-40%', 'Reduced anesthetic requirement at term; MAC returns to normal by day 3 post-delivery'),
        ('Sensitivity to local anesthetics', 'Increased', 'Neural blockade at lower concentrations due to progesterone & engorgement of epidural veins'),
        ('Epidural space volume', 'Decreased', 'Engorged epidural veins -> smaller epidural/intrathecal volume -> wider block spread'),
    ], HexColor('#6A1B9A')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Mechanism:</b> Progesterone (up to 20x normal at term) increases sedation. '
        'β-endorphin surge during labor contributes. Enhanced sensitivity to local anesthetics '
        'is partly neuronal (progesterone effect) and partly mechanical (engorged epidural veins '
        'reduce volume of epidural/subarachnoid space).',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 2. RESPIRATORY
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('2. RESPIRATORY CHANGES', '🫁', HexColor('#01579B')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Oxygen Consumption', '+20 to 50%', 'Meets increased metabolic demands of fetus, uterus, and maternal tissue'),
        ('Minute Ventilation', '+50%', 'Mainly via ↑ tidal volume (progesterone-driven); PaCO₂ drops to ~32 mmHg'),
        ('Tidal Volume', '+40%', 'Primary driver of hyperventilation; progesterone stimulates respiratory centers'),
        ('Respiratory Rate', '+15%', 'Minor contributor to increased minute ventilation'),
        ('Functional Residual Capacity (FRC)', '-20%', 'Elevated diaphragm from gravid uterus; makes mother prone to rapid desaturation'),
        ('Airway Resistance', '-35%', 'Progesterone-mediated bronchodilation'),
        ('PaO₂', '+10%', 'Rises to ~106 mmHg near sea level; hyperventilation effect'),
        ('PaCO₂', '-15%', 'Drops to ~32 mmHg; compensatory metabolic acidosis (HCO₃⁻ drops to ~20 mEq/L)'),
        ('HCO₃⁻', '-15%', 'Renal compensation for respiratory alkalosis; normal pH ~7.44'),
        ('P50 (Hb-O₂ curve)', '+27→30 mmHg', 'Right shift facilitates O₂ offloading to fetus'),
    ], HexColor('#0277BD')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Key clinical points:</b> The ↓ FRC combined with ↑ O₂ consumption means that apnea '
        '(e.g., during intubation) leads to much faster O₂ desaturation than in non-pregnant patients - '
        'pre-oxygenation is critical. Airway edema (progesterone/estrogen) can make intubation difficult; '
        'a smaller ETT (6.0-7.0 mm) is often recommended. The physiological respiratory alkalosis '
        '(PaCO₂ ~32 mmHg) is the normal state; a "normal" PaCO₂ of 40 mmHg in pregnancy suggests '
        'impending respiratory failure.',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 3. CARDIOVASCULAR
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('3. CARDIOVASCULAR CHANGES', '❤️', HexColor('#B71C1C')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Blood Volume', '+35%', 'Starts rising in 1st trimester; peaks at 28-32 weeks; helps offset blood loss at delivery'),
        ('Plasma Volume', '+55%', 'Exceeds RBC expansion -> physiological "dilutional" anemia of pregnancy'),
        ('Cardiac Output', '+40%', 'Rises by 8-10 weeks; peaks near end of 2nd trimester; further increases during labor'),
        ('Stroke Volume', '+30%', 'Due to increased preload and decreased afterload'),
        ('Heart Rate', '+20%', 'Rises by ~15-20 bpm; tachycardia >100 bpm is normal in late pregnancy'),
        ('Systolic BP', '-5%', 'Slight decrease; drops most in 2nd trimester, rises back to baseline at term'),
        ('Diastolic BP', '-15%', 'More pronounced drop; nadirs around 24-28 weeks'),
        ('Peripheral Vascular Resistance', '-15%', 'Progesterone + placental arteriovenous shunt + vasodilation mediators'),
        ('Pulmonary Vascular Resistance', '-30%', 'Reduces RV afterload; important in pulmonary hypertension management'),
    ], HexColor('#C62828')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Aortocaval compression:</b> After 18-20 weeks, the gravid uterus can compress the '
        'inferior vena cava and abdominal aorta when supine, reducing venous return by up to 40% '
        '("supine hypotension syndrome"). Left uterine displacement (LUD) is standard of care during '
        'labor and all obstetric procedures. Cardiac output further increases during labor '
        '(+10-25% in first stage, up to +45% in second stage) due to autotransfusion from uterine '
        'contractions, pain, and anxiety.',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 4. HEMATOLOGICAL
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('4. HEMATOLOGICAL CHANGES', '🩸', HexColor('#E65100')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Hemoglobin', '-20%', 'Physiological dilutional anemia; Hgb <11 g/dL in 1st trimester or <10.5 g/dL in 2nd trimester is pathological'),
        ('Hematocrit', 'Decreases', 'Falls from ~40% to ~34%; nadirs at ~30-34 weeks'),
        ('Platelets', '-10%', 'Mild thrombocytopenia is normal; <70,000 warrants investigation'),
        ('WBC', 'Increased', 'Leukocytosis up to 12,000/μL; during labor may reach 20,000-30,000/μL'),
        ('Fibrinogen', 'Doubles', 'Rises from ~300 to 600 mg/dL; ESR increases markedly'),
        ('Clotting Factors (II,VII,VIII,X,XII)', '+30 to 250%', 'Pregnancy is a hypercoagulable state; risk of DVT/PE increases 4-5x'),
        ('Protein C & S', 'Decreased', 'Further tilts balance toward thrombosis; fibrinolytic activity decreased'),
        ('Serum albumin', 'Decreased', 'From ~4.0 to ~3.0 g/dL; affects protein-bound drug pharmacokinetics'),
    ], HexColor('#E64A19')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Coagulation implications:</b> The hypercoagulable state protects against hemorrhage at delivery '
        'but increases thromboembolism risk 4-5 fold. Virchow\'s triad is complete in pregnancy: '
        'hypercoagulability (clotting factor excess), venous stasis (uterine compression), and '
        'endothelial injury (delivery). VTE prophylaxis should be considered in high-risk patients.',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 5. RENAL
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('5. RENAL & METABOLIC CHANGES', '🫘', HexColor('#1B5E20')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Glomerular Filtration Rate (GFR)', '+50%', 'Starts rising in 1st trimester; renal plasma flow increases 70%; kidneys enlarge ~1 cm'),
        ('Serum Creatinine', 'Decreased', 'Normal creatinine 0.5-0.8 mg/dL in pregnancy; "normal" 1.0 mg/dL suggests renal impairment'),
        ('Serum BUN', 'Decreased', 'Lower due to increased GFR; normal ~8-9 mg/dL'),
        ('Serum Uric Acid', 'Decreased early', 'Rises in 3rd trimester; elevated uric acid is a marker of preeclampsia'),
        ('Glucosuria', 'May be present', 'Tubular reabsorption of glucose does not increase proportionally with GFR'),
        ('Urinary protein', 'Up to 300 mg/day', 'Normal upper limit doubles; >300 mg/24h suggests preeclampsia'),
        ('Sodium retention', 'Increased', 'Despite elevated GFR; estrogen/aldosterone effect; contributes to edema'),
    ], HexColor('#2E7D32')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Drug dosing:</b> Increased renal clearance affects many drugs (penicillins, aminoglycosides, '
        'digoxin) - doses may need to be higher or more frequent. Serum creatinine and BUN are normally '
        'lower; values in the "normal" non-pregnant range may indicate significant renal dysfunction.',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 6. GASTROINTESTINAL
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('6. GASTROINTESTINAL CHANGES', '🤰', HexColor('#4E342E')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Gastric emptying', 'Delayed', 'Progesterone reduces GI motility; risk of aspiration during anesthesia (Mendelson syndrome)'),
        ('Lower esophageal sphincter tone', 'Decreased', 'Progesterone effect; combined with increased intragastric pressure -> GERD in >80%'),
        ('Intragastric pressure', 'Increased', 'Gravid uterus elevates stomach; increases aspiration risk'),
        ('Nausea & vomiting', 'Common', 'Affects 70-80%; hyperemesis gravidarum in <2%; peaks at 8-10 weeks'),
        ('Liver enzymes (ALK-P)', 'Increased', 'Placenta produces alkaline phosphatase; ALT/AST should remain normal'),
        ('Serum albumin', 'Decreased', 'Dilutional; from 4.0 -> 3.0 g/dL; affects drug binding'),
        ('Gallbladder emptying', 'Delayed', 'Bile becomes more lithogenic; cholesterol gallstones 2x more common in pregnancy'),
        ('Constipation', 'Common', 'Reduced colonic motility; water absorption; iron supplementation worsens this'),
    ], HexColor('#5D4037')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Aspiration risk:</b> All pregnant patients beyond 12-16 weeks are considered to have a '
        '"full stomach" for anesthesia purposes, regardless of fasting time. Rapid sequence '
        'induction (RSI) with cricoid pressure is the standard for general anesthesia. '
        'Antacid prophylaxis (sodium citrate, H2-blockers, PPI) is recommended.',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 7. ENDOCRINE / HORMONAL
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('7. ENDOCRINE & HORMONAL CHANGES', '⚗️', HexColor('#006064')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Progesterone', 'Up to 20x normal', 'Sedation, bronchodilation, reduced GI motility, decreased LES tone, vasodilation'),
        ('Estrogen', 'Greatly increased', 'Airway mucosal edema, clotting factor synthesis, increased binding proteins'),
        ('hCG (human chorionic gonadotropin)', 'Peaks at 8-10 wks', 'Maintains corpus luteum; basis of pregnancy tests; elevated in molar pregnancy'),
        ('hPL (human placental lactogen)', 'Increases throughout', 'Insulin antagonist; promotes lipolysis; causes gestational insulin resistance'),
        ('Insulin resistance', 'Increases', 'Peaks in 3rd trimester; gestational diabetes in ~7-10% of pregnancies'),
        ('Thyroid hormones (total T3/T4)', 'Increased', 'TBG doubles; free T3/T4 remain normal; TSH may transiently decrease in 1st trimester'),
        ('Cortisol', 'Increased', '3x normal at term; partly explains glucose intolerance and striae gravidarum'),
        ('Aldosterone', 'Increased 10x', 'Compensates for progesterone-induced Na loss; contributes to fluid retention'),
    ], HexColor('#00838F')),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 8. MUSCULOSKELETAL / OTHER
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('8. MUSCULOSKELETAL & OTHER CHANGES', '🦴', HexColor('#37474F')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Lumbar lordosis', 'Increases', 'Compensates for anterior shift in center of gravity; causes back pain in ~50%'),
        ('Relaxin hormone', 'Increased', 'Relaxes pelvic ligaments (pubic symphysis, sacroiliac joints) for delivery'),
        ('Uterus weight', '60g -> 1000g', 'Increases 20-fold; blood flow rises from 50 ml/min to 500-700 ml/min at term'),
        ('Skin changes', 'Striae, linea nigra', 'Hyperpigmentation (MSH from placenta), spider angiomata, palmar erythema'),
        ('Eye changes', 'Corneal thickening', 'Avoid new contact lens prescriptions; IOP decreases; visual changes common'),
        ('Body weight', '+11-16 kg average', 'Fetus ~3.3 kg; placenta ~0.6 kg; amniotic fluid ~0.8 kg; rest is maternal tissue'),
        ('Total body water', '+6-8 L', 'Distributed: plasma, interstitial, amniotic fluid; dependent edema in 80% is normal'),
    ], HexColor('#455A64')),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# CLINICAL PEARLS BOX
# ══════════════════════════════════════════════════════════════════════════════
pearls_data = [[
    Paragraph(
        '<b><font color="#FFD600">🏆 HIGH-YIELD CLINICAL PEARLS</font></b><br/><br/>'
        '<font color="#69F0AE"><b>1.</b></font> <font color="#ECEFF1">Rapid desaturation during apnea</font> '
        '- ↓FRC + ↑O₂ consumption = short safe apnea time. Pre-oxygenate 3-5 min before induction.<br/>'
        '<font color="#69F0AE"><b>2.</b></font> <font color="#ECEFF1">Supine hypotension</font> '
        '- IVC compression after 18-20 wks. Always use LEFT LATERAL TILT 15°.<br/>'
        '<font color="#69F0AE"><b>3.</b></font> <font color="#ECEFF1">Full stomach risk</font> '
        '- Use RSI for all GA in pregnancy >12-16 wks regardless of fasting status.<br/>'
        '<font color="#69F0AE"><b>4.</b></font> <font color="#ECEFF1">Dilutional anemia</font> '
        '- Hgb 10-11 g/dL is normal in pregnancy (not pathological if other causes excluded).<br/>'
        '<font color="#69F0AE"><b>5.</b></font> <font color="#ECEFF1">PaCO₂ "normal" = danger</font> '
        '- Normal non-pregnant PaCO₂ (40 mmHg) in pregnancy = respiratory FAILURE (normal = 32 mmHg).<br/>'
        '<font color="#69F0AE"><b>6.</b></font> <font color="#ECEFF1">Creatinine "normal" = impaired</font> '
        '- Normal creatinine in pregnancy = 0.5-0.8 mg/dL. Value of 1.0 mg/dL warrants investigation.<br/>'
        '<font color="#69F0AE"><b>7.</b></font> <font color="#ECEFF1">Hypercoagulability</font> '
        '- VTE risk 4-5x higher. Immobility + surgery = thromboprophylaxis is essential.<br/>'
        '<font color="#69F0AE"><b>8.</b></font> <font color="#ECEFF1">Reduced MAC</font> '
        '- Need 40% less volatile anesthetic; also more sensitive to IV sedatives and opioids.',
        ParagraphStyle('pearls', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT,
                       leading=14, alignment=TA_LEFT)
    )
]]
pearls_table = Table(pearls_data, colWidths=[17*cm])
pearls_table.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,-1), HexColor('#0A1628')),
    ('BOX', (0,0), (-1,-1), 1.5, ACCENT_GOLD),
    ('TOPPADDING', (0,0), (-1,-1), 12),
    ('BOTTOMPADDING', (0,0), (-1,-1), 12),
    ('LEFTPADDING', (0,0), (-1,-1), 14),
    ('RIGHTPADDING', (0,0), (-1,-1), 14),
    ('ROUNDEDCORNERS', [8]),
]))
story.append(pearls_table)
story.append(Spacer(1, 5*mm))

# ══════════════════════════════════════════════════════════════════════════════
# TRIMESTER TIMELINE
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_banner('TIMELINE: WHEN CHANGES OCCUR', '📅', HexColor('#1A237E')))
story.append(Spacer(1, 2*mm))

timeline_data = [
    [
        Paragraph('<b>1st Trimester (0-12 wks)</b>', ParagraphStyle('t1h', fontName='Helvetica-Bold', fontSize=9, textColor=ACCENT_GOLD, alignment=TA_CENTER)),
        Paragraph('<b>2nd Trimester (13-26 wks)</b>', ParagraphStyle('t2h', fontName='Helvetica-Bold', fontSize=9, textColor=ACCENT_GREEN, alignment=TA_CENTER)),
        Paragraph('<b>3rd Trimester (27-40 wks)</b>', ParagraphStyle('t3h', fontName='Helvetica-Bold', fontSize=9, textColor=ACCENT_PINK, alignment=TA_CENTER)),
    ],
    [
        Paragraph(
            '• ↑hCG peaks 8-10 wks\n• Nausea/vomiting peak\n• ↑Progesterone & estrogen\n'
            '• Plasma volume starts ↑\n• ↑Heart rate begins\n• GFR starts increasing\n'
            '• Progesterone -> ↑ventilation',
            ParagraphStyle('t1b', fontName='Helvetica', fontSize=8, textColor=LIGHT_TEXT, leading=12)
        ),
        Paragraph(
            '• BP nadir at 24-28 wks\n• Plasma volume peaks (+55%)\n• CO peaks (late 2nd trimester)\n'
            '• FRC decreases (diaphragm rises)\n• IVC compression risk begins\n'
            '• Gestational DM screening (24-28 wks)\n• Fetal movements felt',
            ParagraphStyle('t2b', fontName='Helvetica', fontSize=8, textColor=LIGHT_TEXT, leading=12)
        ),
        Paragraph(
            '• MAC -40% at term\n• Uterus 1000g; blood flow 700ml/min\n• Insulin resistance peaks\n'
            '• Clotting factors max elevation\n• BP returns near baseline\n'
            '• Lumbar lordosis maximal\n• RBC mass peaks',
            ParagraphStyle('t3b', fontName='Helvetica', fontSize=8, textColor=LIGHT_TEXT, leading=12)
        ),
    ]
]
timeline_table = Table(timeline_data, colWidths=[5.6*cm, 5.6*cm, 5.6*cm])
timeline_table.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (0,0), HexColor('#3E2700')),
    ('BACKGROUND', (1,0), (1,0), HexColor('#004D00')),
    ('BACKGROUND', (2,0), (2,0), HexColor('#4A0020')),
    ('BACKGROUND', (0,1), (0,1), CARD_BG_1),
    ('BACKGROUND', (1,1), (1,1), CARD_BG_2),
    ('BACKGROUND', (2,1), (2,1), CARD_BG_1),
    ('GRID', (0,0), (-1,-1), 0.5, HexColor('#2C3E50')),
    ('TOPPADDING', (0,0), (-1,-1), 8),
    ('BOTTOMPADDING', (0,0), (-1,-1), 8),
    ('LEFTPADDING', (0,0), (-1,-1), 8),
    ('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
story.append(timeline_table)
story.append(Spacer(1, 5*mm))

# ══════════════════════════════════════════════════════════════════════════════
# FOOTER
# ══════════════════════════════════════════════════════════════════════════════
story.append(HRFlowable(width='100%', thickness=0.5, color=HexColor('#37474F')))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
    'Source: Morgan & Mikhail\'s Clinical Anesthesiology, 7e, Chapter 40 (pp. 1572-1587) | '
    'Compiled for educational purposes | Orris Medical Summary',
    footnote_style
))

# ══════════════════════════════════════════════════════════════════════════════
# BUILD
# ══════════════════════════════════════════════════════════════════════════════

def add_background(canvas, doc):
    canvas.saveState()
    canvas.setFillColor(DARK_BG)
    canvas.rect(0, 0, A4[0], A4[1], fill=1, stroke=0)
    canvas.restoreState()

doc.build(story, onFirstPage=add_background, onLaterPages=add_background)
print(f"PDF created: {OUTPUT}")
Running Command

cd /home/daytona/workspace/pregnancy-physiology && python make_pdf.py 2>&1

The PDF was created successfully. Here is your complete visual summary:

Physiological Changes During Pregnancy

Source: Morgan & Mikhail's Clinical Anesthesiology, 7e (Chapter 40)

Download Your Visual Summary PDF:

Physiological Changes During Pregnancy

PDF Document · PDF


The PDF is dark-themed with color-coded sections for easy visual memory. Here is a text overview of what it contains:

Quick Reference Numbers

SystemParameterChange
NeuroMAC-40%
RespO₂ Consumption+20-50%
RespFRC-20%
RespMinute Ventilation+50%
CVSPlasma Volume+55%
CVSCardiac Output+40%
CVSHeart Rate+20%
RenalGFR+50%
HaemClotting Factors+30-250%

1. Neurological

  • MAC falls 40% at term - far less anesthetic needed
  • Enhanced sensitivity to local anesthetics (epidural veins engorged, volume of epidural space reduced)
  • Progesterone (up to 20x normal) is responsible; returns to normal by day 3 postpartum

2. Respiratory

  • Minute ventilation +50% (progesterone stimulates respiratory centers)
  • FRC -20% (diaphragm pushed up) + O₂ consumption +50% = rapid desaturation during apnea
  • PaCO₂ drops to ~32 mmHg (compensated by HCO₃⁻ dropping to ~20 mEq/L) - pH ~7.44
  • A "normal" PaCO₂ of 40 mmHg in pregnancy signals impending respiratory failure

3. Cardiovascular

  • Cardiac output rises by 8-10 weeks, peaks late 2nd trimester (+40%)
  • BP nadir at 24-28 weeks; rises back to near baseline at term
  • Aortocaval compression after 18-20 weeks in supine position reduces venous return up to 40% - always use left uterine displacement
  • During labor, CO rises another 10-45% via uterine autotransfusion

4. Hematological

  • Plasma volume +55% >> RBC expansion = physiological dilutional anemia (Hgb ~10-11 g/dL is normal)
  • Hypercoagulable state: clotting factors up +30-250%, protein C/S decrease = VTE risk 4-5x higher
  • Virchow's triad is complete in pregnancy

5. Renal

  • GFR +50% from 1st trimester; kidneys enlarge ~1 cm
  • "Normal" creatinine of 1.0 mg/dL in pregnancy = impaired kidneys (normal = 0.5-0.8 mg/dL)
  • Glucosuria can be physiological (tubular reabsorption doesn't scale with GFR)

6. Gastrointestinal

  • Delayed gastric emptying + reduced LES tone + elevated intragastric pressure = aspiration risk
  • All patients >12-16 weeks are "full stomach" for anesthesia purposes - RSI is mandatory
  • Gallstones 2x more common (progesterone slows gallbladder emptying)

7. Endocrine/Hormonal

  • Progesterone (up to 20x): bronchodilation, reduced GI motility, vasodilation, sedation
  • hPL acts as insulin antagonist - gestational DM in ~7-10%
  • Cortisol 3x normal; aldosterone 10x normal (fluid retention)

8. Musculoskeletal

  • Uterine blood flow 50 ml/min → 700 ml/min at term
  • Relaxin loosens pelvic ligaments
  • Total body water increases 6-8 L; weight gain 11-16 kg average

Top 8 High-Yield Clinical Pearls

  1. Pre-oxygenate before any GA induction - safe apnea time is very short
  2. Left lateral tilt 15° - always, to prevent IVC compression
  3. RSI mandatory for all GA in pregnancy >12-16 weeks
  4. Hgb 10-11 is normal - do not over-transfuse
  5. PaCO₂ 40 = failure in pregnancy (normal is 32 mmHg)
  6. Creatinine 1.0 = investigate in pregnancy (normal is 0.5-0.8)
  7. VTE prophylaxis in all high-risk obstetric patients
  8. -40% MAC - reduce volatile anesthetic dose accordingly

Can you make this pdf with more diagrams and flowchart for better visual memory

Writing File

~/pregnancy-physiology/make_pdf_v2.py

#!/usr/bin/env python3
"""
Physiological Changes During Pregnancy - ENHANCED Visual PDF v2
With bar charts, flowcharts, body diagrams, and system maps
"""

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.lib.colors import HexColor
from reportlab.graphics.shapes import (
    Drawing, Rect, String, Line, Circle, Polygon, Ellipse,
    Arrow, Group, Path
)
from reportlab.graphics import renderPDF
from reportlab.graphics.charts.barcharts import VerticalBarChart, HorizontalBarChart
from reportlab.graphics.charts.piecharts import Pie
from reportlab.platypus import Flowable
import math

# ── Palette ────────────────────────────────────────────────────────────────
DARK_BG      = HexColor('#0A0F1E')
NAVY         = HexColor('#0D1B2A')
CARD_DARK    = HexColor('#0F1F35')
CARD_MID     = HexColor('#112233')
ROW_ALT      = HexColor('#1A3555')
HEADER_BG    = HexColor('#1B4F72')
TABLE_HDR    = HexColor('#1565C0')
PINK         = HexColor('#E91E8C')
CYAN         = HexColor('#00BCD4')
GOLD         = HexColor('#FFD600')
GREEN        = HexColor('#4CAF50')
ORANGE       = HexColor('#FF6F00')
RED          = HexColor('#EF5350')
PURPLE       = HexColor('#7B1FA2')
TEAL         = HexColor('#00897B')
BLUE         = HexColor('#1E88E5')
LIME         = HexColor('#C6FF00')
WHITE        = colors.white
LIGHT_TEXT   = HexColor('#ECEFF1')
DIM_TEXT     = HexColor('#90A4AE')

W, H = A4   # 595.27 x 841.89 pts

# ── Reusable styles ────────────────────────────────────────────────────────
def S(name, **kw):
    return ParagraphStyle(name, **kw)

title_s   = S('T', fontName='Helvetica-Bold', fontSize=28, textColor=WHITE,
               alignment=TA_CENTER, leading=34, spaceAfter=4)
sub_s     = S('S', fontName='Helvetica', fontSize=11, textColor=CYAN,
               alignment=TA_CENTER, spaceAfter=2)
src_s     = S('SR', fontName='Helvetica-Oblique', fontSize=8.5, textColor=DIM_TEXT,
               alignment=TA_CENTER, spaceAfter=6)
sec_s     = S('SEC', fontName='Helvetica-Bold', fontSize=13, textColor=WHITE,
               alignment=TA_CENTER, leading=16)
body_s    = S('B', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT,
               alignment=TA_JUSTIFY, leading=13, spaceAfter=3)
bullet_s  = S('BU', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT,
               alignment=TA_LEFT, leading=12, leftIndent=10, spaceAfter=2)
small_b   = S('SB', fontName='Helvetica-Bold', fontSize=8, textColor=GOLD,
               alignment=TA_CENTER)
note_s    = S('N', fontName='Helvetica-Oblique', fontSize=7.5, textColor=DIM_TEXT,
               alignment=TA_CENTER)
lbl_s     = S('L', fontName='Helvetica-Bold', fontSize=8, textColor=WHITE,
               alignment=TA_CENTER, leading=10)
lbl_sm    = S('LS', fontName='Helvetica', fontSize=7, textColor=LIGHT_TEXT,
               alignment=TA_CENTER, leading=9)

CONTENT_W = 17 * cm

# ═══════════════════════════════════════════════════════════════════════════
# DRAWING HELPERS
# ═══════════════════════════════════════════════════════════════════════════

class DrawingFlowable(Flowable):
    def __init__(self, drawing):
        Flowable.__init__(self)
        self.drawing = drawing
        self.width = drawing.width
        self.height = drawing.height

    def draw(self):
        renderPDF.draw(self.drawing, self.canv, 0, 0)


def hex2rgb(h):
    h = h.hexval()[1:]
    return tuple(int(h[i:i+2], 16)/255 for i in (0,2,4))


def rounded_rect(d, x, y, w, h, r, fill_color, stroke_color=None, stroke_width=0.5):
    p = Path()
    p.moveTo(x+r, y)
    p.lineTo(x+w-r, y)
    p.curveTo(x+w-r, y, x+w, y, x+w, y+r)
    p.lineTo(x+w, y+h-r)
    p.curveTo(x+w, y+h-r, x+w, y+h, x+w-r, y+h)
    p.lineTo(x+r, y+h)
    p.curveTo(x+r, y+h, x, y+h, x, y+h-r)
    p.lineTo(x, y+r)
    p.curveTo(x, y+r, x, y, x+r, y)
    p.closePath()
    p.fillColor = fill_color
    p.strokeColor = stroke_color
    p.strokeWidth = stroke_width
    d.add(p)


def arrow_line(d, x1, y1, x2, y2, color=GOLD, width=1.5):
    """Draw a line with an arrowhead at (x2,y2)."""
    d.add(Line(x1, y1, x2, y2, strokeColor=color, strokeWidth=width))
    # arrowhead
    angle = math.atan2(y2-y1, x2-x1)
    size = 6
    ax1 = x2 - size*math.cos(angle-0.4)
    ay1 = y2 - size*math.sin(angle-0.4)
    ax2 = x2 - size*math.cos(angle+0.4)
    ay2 = y2 - size*math.sin(angle+0.4)
    d.add(Polygon([x2, y2, ax1, ay1, ax2, ay2],
                  fillColor=color, strokeColor=color, strokeWidth=0.3))


def text_box(d, x, y, w, h, text, bg, fg=WHITE, font='Helvetica-Bold', size=9, r=5):
    rounded_rect(d, x, y, w, h, r, bg, HexColor('#2C3E50'), 0.5)
    d.add(String(x+w/2, y+h/2-size*0.38, text,
                 textAnchor='middle', fontSize=size,
                 fontName=font, fillColor=fg))


# ═══════════════════════════════════════════════════════════════════════════
# CHART 1: Horizontal bar chart of % changes
# ═══════════════════════════════════════════════════════════════════════════
def make_bar_chart():
    DW, DH = CONTENT_W, 7.2*cm
    d = Drawing(DW, DH)

    # Background
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)

    # Title
    d.add(String(DW/2, DH-14, 'KEY PARAMETER CHANGES IN PREGNANCY  (% change from baseline)',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=GOLD))

    params = [
        ('Plasma Volume',       +55, CYAN),
        ('Min. Ventilation',    +50, BLUE),
        ('GFR',                 +50, GREEN),
        ('Cardiac Output',      +40, PINK),
        ('Tidal Volume',        +40, PINK),
        ('O₂ Consumption',      +35, ORANGE),
        ('Blood Volume',        +35, ORANGE),
        ('Heart Rate',          +20, HexColor('#FF9800')),
        ('Clotting Factors',    +30, RED),
        ('Stroke Volume',       +30, LIME),
        ('FRC',                 -20, HexColor('#FF5252')),
        ('Hemoglobin',          -20, HexColor('#FF5252')),
        ('MAC',                 -40, PURPLE),
        ('PaCO₂',               -15, HexColor('#FF7043')),
        ('Pulm Resistance',     -30, HexColor('#CE93D8')),
    ]

    bar_area_x = 130
    bar_area_w = DW - bar_area_x - 60
    zero_x = bar_area_x + bar_area_w * 0.45
    row_h = 14
    start_y = DH - 32

    max_val = 60

    for i, (name, val, clr) in enumerate(params):
        y = start_y - i * row_h
        if y < 8:
            break

        # label
        d.add(String(bar_area_x - 4, y-3, name,
                     textAnchor='end', fontSize=7, fontName='Helvetica',
                     fillColor=LIGHT_TEXT))

        # bar
        bar_len = abs(val) / max_val * bar_area_w * 0.45
        if val > 0:
            bx = zero_x
        else:
            bx = zero_x - bar_len

        r2 = Rect(bx, y-2, bar_len if val > 0 else bar_len,
                  row_h - 4, fillColor=clr, strokeColor=None)
        r2.rx = 2
        d.add(r2)

        # value text
        tx = zero_x + bar_len + 3 if val > 0 else zero_x - bar_len - 3
        anchor = 'start' if val > 0 else 'end'
        sign = '+' if val > 0 else ''
        d.add(String(tx, y-3, f'{sign}{val}%',
                     textAnchor=anchor, fontSize=7, fontName='Helvetica-Bold',
                     fillColor=clr))

    # zero line
    d.add(Line(zero_x, 12, zero_x, DH-22,
               strokeColor=HexColor('#546E7A'), strokeWidth=1, strokeDashArray=[3,2]))
    d.add(String(zero_x, 6, '0%', textAnchor='middle', fontSize=7,
                 fontName='Helvetica', fillColor=DIM_TEXT))

    # Legend
    d.add(String(bar_area_x+bar_area_w*0.1, 6, '← DECREASE',
                 textAnchor='middle', fontSize=7, fontName='Helvetica-Bold',
                 fillColor=HexColor('#FF5252')))
    d.add(String(bar_area_x+bar_area_w*0.8, 6, 'INCREASE →',
                 textAnchor='middle', fontSize=7, fontName='Helvetica-Bold',
                 fillColor=HexColor('#69F0AE')))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# CHART 2: Body system diagram
# ═══════════════════════════════════════════════════════════════════════════
def make_body_diagram():
    DW, DH = CONTENT_W, 9.5*cm
    d = Drawing(DW, DH)

    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-14, 'BODY SYSTEMS AFFECTED IN PREGNANCY',
                 textAnchor='middle', fontSize=10, fontName='Helvetica-Bold', fillColor=GOLD))

    # Draw simplified body silhouette
    cx = DW/2
    # Head
    d.add(Ellipse(cx, DH-50, 22, 22, fillColor=HexColor('#1C3A5E'), strokeColor=CYAN, strokeWidth=1.2))
    d.add(String(cx, DH-54, 'CNS', textAnchor='middle', fontSize=7, fontName='Helvetica-Bold', fillColor=CYAN))

    # Neck
    d.add(Rect(cx-8, DH-80, 16, 14, fillColor=HexColor('#1C3A5E'), strokeColor=None))

    # Torso
    rounded_rect(d, cx-40, DH-185, 80, 100, 10, HexColor('#0F2840'), CYAN, 1.2)

    # Heart (left chest)
    d.add(Ellipse(cx-15, DH-125, 16, 16,
                  fillColor=HexColor('#7B0000'), strokeColor=RED, strokeWidth=1.5))
    d.add(String(cx-15, DH-129, '❤', textAnchor='middle', fontSize=10, fillColor=RED))

    # Lungs (both sides)
    d.add(Ellipse(cx-28, DH-130, 14, 22,
                  fillColor=HexColor('#01435A'), strokeColor=BLUE, strokeWidth=1.2))
    d.add(Ellipse(cx+10, DH-130, 14, 22,
                  fillColor=HexColor('#01435A'), strokeColor=BLUE, strokeWidth=1.2))

    # Uterus (lower torso)
    d.add(Ellipse(cx, DH-170, 28, 24,
                  fillColor=HexColor('#880E4F'), strokeColor=PINK, strokeWidth=1.5))
    d.add(String(cx, DH-174, 'Uterus', textAnchor='middle', fontSize=7,
                 fontName='Helvetica-Bold', fillColor=PINK))

    # Kidneys
    d.add(Ellipse(cx-38, DH-148, 10, 16,
                  fillColor=HexColor('#1B5E20'), strokeColor=GREEN, strokeWidth=1.2))
    d.add(Ellipse(cx+38, DH-148, 10, 16,
                  fillColor=HexColor('#1B5E20'), strokeColor=GREEN, strokeWidth=1.2))

    # Arms
    rounded_rect(d, cx-72, DH-185, 28, 80, 8, HexColor('#0D2035'), CYAN, 0.8)
    rounded_rect(d, cx+44, DH-185, 28, 80, 8, HexColor('#0D2035'), CYAN, 0.8)

    # Legs
    rounded_rect(d, cx-35, DH-270, 28, 80, 8, HexColor('#0D2035'), CYAN, 0.8)
    rounded_rect(d, cx+7, DH-270, 28, 80, 8, HexColor('#0D2035'), CYAN, 0.8)

    # ── CALLOUT BOXES ──────────────────────────────────────────────────────
    # Left side callouts
    box_w, box_h = 105, 38
    lx = 4

    # CNS box
    rounded_rect(d, lx, DH-70, box_w, box_h, 5, HexColor('#1A0A3E'), PURPLE, 0.8)
    d.add(String(lx+box_w/2, DH-56, '🧠 CNS / NEURO',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=PURPLE))
    d.add(String(lx+box_w/2, DH-68, 'MAC ↓40%  |  Local anesthetic sensitivity ↑',
                 textAnchor='middle', fontSize=6.5, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, lx+box_w, DH-50, cx-22, DH-46, PURPLE)

    # Cardiovascular
    rounded_rect(d, lx, DH-125, box_w, 46, 5, HexColor('#1A0808'), RED, 0.8)
    d.add(String(lx+box_w/2, DH-108, '❤️ CARDIOVASCULAR',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=RED))
    for ii, txt in enumerate(['CO ↑40%  HR ↑20%  SV ↑30%',
                               'Blood vol ↑35%  Plasma ↑55%',
                               'SVR ↓15%  DBP ↓15%']):
        d.add(String(lx+box_w/2, DH-118-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, lx+box_w, DH-102, cx-32, DH-118, RED)

    # Respiratory
    rounded_rect(d, lx, DH-180, box_w, 46, 5, HexColor('#001A2E'), BLUE, 0.8)
    d.add(String(lx+box_w/2, DH-163, '🫁 RESPIRATORY',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=BLUE))
    for ii, txt in enumerate(['MV ↑50%  TV ↑40%  FRC ↓20%',
                               'PaCO₂ ↓15%  PaO₂ ↑10%',
                               'Airway resistance ↓35%']):
        d.add(String(lx+box_w/2, DH-172-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, lx+box_w, DH-158, cx-42, DH-128, BLUE)

    # Right side callouts
    rx = cx + 48

    # Renal
    rounded_rect(d, rx, DH-125, box_w, 38, 5, HexColor('#0A2E0A'), GREEN, 0.8)
    d.add(String(rx+box_w/2, DH-109, '🫘 RENAL',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=GREEN))
    for ii, txt in enumerate(['GFR ↑50%  RPF ↑70%',
                               'Creat ↓  BUN ↓  Uric acid ↓',
                               'Normal Cr = 0.5-0.8 mg/dL']):
        d.add(String(rx+box_w/2, DH-118-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, rx, DH-106, cx+48, DH-135, GREEN)

    # Uterus/Hormonal
    rounded_rect(d, rx, DH-185, box_w, 52, 5, HexColor('#2E0A2E'), PINK, 0.8)
    d.add(String(rx+box_w/2, DH-166, '🤰 UTERUS / HORMONAL',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=PINK))
    for ii, txt in enumerate(['Progesterone ↑20x',
                               'Blood flow 50→700 ml/min',
                               'hCG peaks 8-10 wks',
                               'Relaxin: ligament laxity']):
        d.add(String(rx+box_w/2, DH-175-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, rx, DH-162, cx+28, DH-162, PINK)

    # Hematology (bottom left)
    rounded_rect(d, lx, DH-235, box_w, 46, 5, HexColor('#1A0F00'), ORANGE, 0.8)
    d.add(String(lx+box_w/2, DH-218, '🩸 HEMATOLOGY',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=ORANGE))
    for ii, txt in enumerate(['Hgb ↓20%  Plt ↓10%  WBC ↑',
                               'Fibrinogen doubles',
                               'Clotting factors ↑30-250%']):
        d.add(String(lx+box_w/2, DH-228-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, lx+box_w, DH-212, cx-30, DH-230, ORANGE)

    # GI (bottom right)
    rounded_rect(d, rx, DH-250, box_w, 55, 5, HexColor('#1A0A00'), HexColor('#FF8F00'), 0.8)
    d.add(String(rx+box_w/2, DH-230, '🍽️ GASTROINTESTINAL',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=HexColor('#FF8F00')))
    for ii, txt in enumerate(['Gastric emptying delayed',
                               'LES tone ↓ → GERD ↑',
                               'Aspiration risk ↑↑',
                               'Gallstones 2x more common']):
        d.add(String(rx+box_w/2, DH-240-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, rx, DH-222, cx+20, DH-200, HexColor('#FF8F00'))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# FLOWCHART: Aspiration risk chain
# ═══════════════════════════════════════════════════════════════════════════
def make_aspiration_flowchart():
    DW, DH = CONTENT_W, 4.8*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '⚠️  ASPIRATION RISK FLOWCHART IN PREGNANCY',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=RED))

    boxes = [
        ('Progesterone ↑', HexColor('#4A148C'), 22),
        ('LES tone ↓\nGastric motility ↓', HexColor('#1A237E'), 22),
        ('Delayed emptying\n+ Gravid uterus', HexColor('#1B5E20'), 22),
        ('↑ Intragastric\npressure', HexColor('#BF360C'), 22),
        ('FULL STOMACH\nRISK ↑↑', RED, 22),
        ('RSI + Cricoid\npressure MANDATORY', HexColor('#006064'), 22),
    ]

    bw = 73
    bh = 38
    gap = 10
    total = len(boxes)*bw + (len(boxes)-1)*gap
    start_x = (DW - total) / 2
    y_center = DH/2 - 10

    for i, (label, bg, _) in enumerate(boxes):
        bx = start_x + i*(bw+gap)
        rounded_rect(d, bx, y_center-bh/2, bw, bh, 6, bg, HexColor('#37474F'), 0.8)
        lines = label.split('\n')
        for j, ln in enumerate(lines):
            d.add(String(bx+bw/2, y_center + (len(lines)-1)*5 - j*10,
                         ln, textAnchor='middle', fontSize=7,
                         fontName='Helvetica-Bold', fillColor=WHITE))
        if i < len(boxes)-1:
            arrow_line(d, bx+bw, y_center, bx+bw+gap, y_center, GOLD, 1.5)

    # Bottom note
    d.add(String(DW/2, 6, 'All pregnant patients >12-16 weeks treated as "full stomach" regardless of fasting time',
                 textAnchor='middle', fontSize=7, fontName='Helvetica-Oblique', fillColor=DIM_TEXT))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# FLOWCHART: Cardiovascular cascade
# ═══════════════════════════════════════════════════════════════════════════
def make_cvs_flowchart():
    DW, DH = CONTENT_W, 6.5*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '❤️  CARDIOVASCULAR CHANGES - CAUSE & EFFECT',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=RED))

    # Column 1: Causes
    causes = [
        ('Estrogen\n+ Relaxin', HexColor('#4A0E82'), 50),
        ('Progesterone', HexColor('#1A237E'), 50),
        ('Placental\nA-V shunt', HexColor('#004D40'), 50),
    ]
    # Column 2: Mechanisms
    mechs = [
        ('SVR ↓ 15%', HexColor('#1B5E20'), 50),
        ('Plasma vol\n↑ 55%', HexColor('#0D47A1'), 50),
        ('O₂ demand ↑', HexColor('#E65100'), 50),
    ]
    # Column 3: Effect
    effects = [
        ('HR ↑ 20%', HexColor('#B71C1C'), 50),
        ('SV ↑ 30%', HexColor('#880E4F'), 50),
    ]
    # Column 4: Outcome
    outcomes = [
        ('CARDIAC OUTPUT\n↑ 40%', RED, 80),
    ]

    col_x = [10, 140, 290, 400]
    bw_c = [110, 110, 90, 130]
    bh = 30
    gap_v = 8

    def draw_col(items, col_idx, start_y):
        n = len(items)
        total_h = n*bh + (n-1)*gap_v
        y0 = start_y + (DH-50 - total_h) / 2
        cx_arr = col_x[col_idx] + bw_c[col_idx]/2
        for i, (lbl, bg, _) in enumerate(items):
            by = y0 + i*(bh+gap_v)
            rounded_rect(d, col_x[col_idx], by, bw_c[col_idx], bh, 5, bg, HexColor('#37474F'), 0.6)
            lines = lbl.split('\n')
            for j, ln in enumerate(lines):
                d.add(String(cx_arr, by+bh/2+(len(lines)-1)*4-j*9,
                             ln, textAnchor='middle', fontSize=7.5,
                             fontName='Helvetica-Bold', fillColor=WHITE))
        return y0, bh, n, gap_v

    y0_c, _, n_c, gv_c = draw_col(causes, 0, 12)
    y0_m, _, n_m, gv_m = draw_col(mechs, 1, 12)
    y0_e, _, n_e, gv_e = draw_col(effects, 2, 12)
    y0_o, _, n_o, gv_o = draw_col(outcomes, 3, 12)

    # Arrows: causes -> mechs
    for i in range(3):
        sy = y0_c + i*(bh+gv_c) + bh/2
        ey = y0_m + i*(bh+gv_m) + bh/2
        arrow_line(d, col_x[0]+bw_c[0], sy, col_x[1], ey, CYAN, 1.2)

    # mechs -> effects (fan in)
    effect_ys = [y0_e + i*(bh+gv_e) + bh/2 for i in range(n_e)]
    mech_ys   = [y0_m + i*(bh+gv_m) + bh/2 for i in range(n_m)]
    pairs = [(0,0),(1,1),(2,0),(2,1)]
    for mi, ei in pairs:
        arrow_line(d, col_x[1]+bw_c[1], mech_ys[mi], col_x[2], effect_ys[ei], GREEN, 1)

    # effects -> outcome
    out_y = y0_o + bh/2
    for i in range(n_e):
        sy = y0_e + i*(bh+gv_e) + bh/2
        arrow_line(d, col_x[2]+bw_c[2], sy, col_x[3], out_y, GOLD, 1.5)

    # Labels
    for i, lbl in enumerate(['TRIGGERS', 'MECHANISMS', 'EFFECTS', 'RESULT']):
        d.add(String(col_x[i]+bw_c[i]/2, DH-24, lbl,
                     textAnchor='middle', fontSize=7, fontName='Helvetica-Bold', fillColor=DIM_TEXT))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# FLOWCHART: Respiratory cascade
# ═══════════════════════════════════════════════════════════════════════════
def make_resp_flowchart():
    DW, DH = CONTENT_W, 5.2*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '🫁  RESPIRATORY CHANGES - MECHANISM FLOW',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=BLUE))

    # Row 1: progesterone chain
    r1 = [
        ('Progesterone\n↑ 20x', PURPLE, True),
        ('Stimulates\nmedullary\nresp. center', HexColor('#1A237E'), True),
        ('Tidal Volume\n↑ 40%', BLUE, True),
        ('Minute Vent.\n↑ 50%', BLUE, True),
        ('PaCO₂\n↓ 15%\n(→32 mmHg)', HexColor('#1B5E20'), True),
    ]

    bw, bh = 82, 42
    gap = 9
    total = len(r1)*bw + (len(r1)-1)*gap
    start_x = (DW - total) / 2
    y1 = DH - 70

    for i, (lbl, bg, _) in enumerate(r1):
        bx = start_x + i*(bw+gap)
        rounded_rect(d, bx, y1, bw, bh, 5, bg, HexColor('#37474F'), 0.8)
        lines = lbl.split('\n')
        for j, ln in enumerate(lines):
            d.add(String(bx+bw/2, y1+bh/2+(len(lines)-1)*5-j*9,
                         ln, textAnchor='middle', fontSize=7.5,
                         fontName='Helvetica-Bold', fillColor=WHITE))
        if i < len(r1)-1:
            arrow_line(d, bx+bw, y1+bh/2, bx+bw+gap, y1+bh/2, GOLD, 1.5)

    # Bottom row: FRC danger chain
    r2 = [
        ('Uterus ↑\ndiaphragm', HexColor('#37474F'), False),
        ('FRC\n↓ 20%', RED, False),
        ('+  O₂ demand\n↑ 35%', ORANGE, False),
        ('→ Rapid\ndesaturation\non apnea', RED, False),
        ('Pre-O₂\n3-5 min\nMANDATORY', HexColor('#004D40'), False),
    ]

    y2 = 8
    for i, (lbl, bg, _) in enumerate(r2):
        bx = start_x + i*(bw+gap)
        rounded_rect(d, bx, y2, bw, bh-4, 5, bg, HexColor('#37474F'), 0.8)
        lines = lbl.split('\n')
        for j, ln in enumerate(lines):
            d.add(String(bx+bw/2, y2+(bh-4)/2+(len(lines)-1)*5-j*9,
                         ln, textAnchor='middle', fontSize=7.5,
                         fontName='Helvetica-Bold', fillColor=WHITE))
        if i < len(r2)-1:
            arrow_line(d, bx+bw, y2+(bh-4)/2, bx+bw+gap, y2+(bh-4)/2, HexColor('#FF5252'), 1.5)

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# COAGULATION cascade diagram
# ═══════════════════════════════════════════════════════════════════════════
def make_coag_diagram():
    DW, DH = CONTENT_W, 4.5*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '🩸  VIRCHOW\'S TRIAD IN PREGNANCY (VTE Risk ↑4-5x)',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=ORANGE))

    # Triangle arrangement
    cx = DW/2
    tri_y_top = DH - 52
    tri_y_bot = 14

    # 3 nodes
    nodes = [
        (cx, tri_y_top + 18, 'HYPERCOAGULABILITY', 'Clotting factors ↑30-250%\nFibrinogen doubles\nProtein C/S ↓', HexColor('#7B0000')),
        (cx - 140, tri_y_bot + 18, 'VENOUS STASIS', 'IVC compression\nReduced mobility\nPelvic veins dilated', HexColor('#01579B')),
        (cx + 140, tri_y_bot + 18, 'ENDOTHELIAL INJURY', 'Delivery trauma\nCervical dilation\nSurgical delivery', HexColor('#1B5E20')),
    ]

    node_w, node_h = 155, 42
    node_positions = []
    for (nx, ny, title, sub, bg) in nodes:
        bx = nx - node_w/2
        by = ny - node_h/2
        node_positions.append((nx, ny))
        rounded_rect(d, bx, by, node_w, node_h, 6, bg, HexColor('#37474F'), 1)
        d.add(String(nx, ny+8, title, textAnchor='middle', fontSize=7.5,
                     fontName='Helvetica-Bold', fillColor=WHITE))
        for i, ln in enumerate(sub.split('\n')):
            d.add(String(nx, ny-2-i*9, ln, textAnchor='middle', fontSize=6.5,
                         fontName='Helvetica', fillColor=LIGHT_TEXT))

    # Lines connecting them
    for i in range(3):
        for j in range(i+1, 3):
            x1, y1 = node_positions[i]
            x2, y2 = node_positions[j]
            d.add(Line(x1, y1, x2, y2, strokeColor=GOLD, strokeWidth=1.5, strokeDashArray=[4,3]))

    # Center label
    d.add(String(cx, (tri_y_top+tri_y_bot)/2+10, 'VTE',
                 textAnchor='middle', fontSize=12, fontName='Helvetica-Bold', fillColor=RED))
    d.add(String(cx, (tri_y_top+tri_y_bot)/2-4, 'RISK',
                 textAnchor='middle', fontSize=10, fontName='Helvetica-Bold', fillColor=RED))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# TIMELINE diagram
# ═══════════════════════════════════════════════════════════════════════════
def make_timeline():
    DW, DH = CONTENT_W, 5.8*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '📅  TIMELINE OF KEY PHYSIOLOGICAL CHANGES',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=GOLD))

    # Timeline line
    line_y = DH/2 - 5
    tl_x1, tl_x2 = 35, DW-15
    d.add(Line(tl_x1, line_y, tl_x2, line_y, strokeColor=CYAN, strokeWidth=2))

    # Arrow at end
    d.add(Polygon([tl_x2+10, line_y, tl_x2, line_y+5, tl_x2, line_y-5],
                  fillColor=CYAN, strokeColor=CYAN))

    # Week markers
    weeks = [0, 8, 12, 16, 24, 28, 32, 40]
    w_labels = ['0', '8', '12', '16', '24', '28', '32', '40 wks']
    total_wks = 40
    for wk, lbl in zip(weeks, w_labels):
        px = tl_x1 + (wk/total_wks)*(tl_x2-tl_x1)
        d.add(Line(px, line_y-5, px, line_y+5, strokeColor=CYAN, strokeWidth=1))
        d.add(String(px, line_y-14, lbl, textAnchor='middle', fontSize=6.5,
                     fontName='Helvetica', fillColor=DIM_TEXT))

    # Events - above line
    events_above = [
        (8, 'hCG peaks', PINK, 1),
        (10, 'Nausea peak', HexColor('#FF8F00'), 1),
        (12, 'Plasma vol ↑\nbegins', CYAN, 2),
        (16, 'IVC risk\nstarts', RED, 1),
        (24, 'BP nadir\nDGDM screen', GREEN, 2),
        (32, 'Plasma vol\npeak +55%', BLUE, 1),
        (40, 'MAC ↓40%\nmax term', PURPLE, 2),
    ]
    # Events - below line
    events_below = [
        (6, 'GFR ↑\nbegins', GREEN, 1),
        (8, 'CO ↑ starts', RED, 2),
        (20, 'Fetal\nmovements', HexColor('#FF8F00'), 1),
        (28, 'CO peaks', RED, 2),
        (36, 'Clotting\nfactors max', ORANGE, 2),
        (40, 'Uterus 1kg\n700ml/min', PINK, 1),
    ]

    tick_h = 18
    for (wk, lbl, clr, rows) in events_above:
        px = tl_x1 + (wk/total_wks)*(tl_x2-tl_x1)
        stem_h = tick_h + (rows-1)*10
        d.add(Line(px, line_y+5, px, line_y+stem_h+4, strokeColor=clr, strokeWidth=0.8))
        for i, ln in enumerate(lbl.split('\n')):
            d.add(String(px, line_y+stem_h+4+i*8, ln,
                         textAnchor='middle', fontSize=6, fontName='Helvetica-Bold', fillColor=clr))

    for (wk, lbl, clr, rows) in events_below:
        px = tl_x1 + (wk/total_wks)*(tl_x2-tl_x1)
        stem_h = tick_h + (rows-1)*10
        d.add(Line(px, line_y-5, px, line_y-stem_h-4, strokeColor=clr, strokeWidth=0.8))
        for i, ln in enumerate(lbl.split('\n')):
            d.add(String(px, line_y-stem_h-12-i*8, ln,
                         textAnchor='middle', fontSize=6, fontName='Helvetica-Bold', fillColor=clr))

    # Trimester shading bands
    t1_end = tl_x1 + (12/40)*(tl_x2-tl_x1)
    t2_end = tl_x1 + (28/40)*(tl_x2-tl_x1)
    for (bx, bw2, lbl, clr) in [
        (tl_x1, t1_end-tl_x1, 'T1', HexColor('#3E2700')),
        (t1_end, t2_end-t1_end, 'T2', HexColor('#004D00')),
        (t2_end, tl_x2-t2_end, 'T3', HexColor('#4A0020')),
    ]:
        r = Rect(bx, line_y-3, bw2, 6, fillColor=clr, strokeColor=None)
        d.add(r)

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# SUPINE HYPOTENSION DIAGRAM
# ═══════════════════════════════════════════════════════════════════════════
def make_supine_diagram():
    DW, DH = CONTENT_W, 4.2*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '⚠️  AORTOCAVAL COMPRESSION SYNDROME (Supine Hypotension)',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=RED))

    steps = [
        ('Supine\nposition', HexColor('#37474F')),
        ('Uterus\ncompresses\nIVC + Aorta', RED),
        ('Venous return\n↓ up to 40%', HexColor('#7B0000')),
        ('Cardiac output\n↓ sharply', HexColor('#880E4F')),
        ('Maternal\nhypotension\n+ Fetal distress', RED),
        ('FIX: Left\nuterine tilt 15°', HexColor('#006064')),
    ]

    bw, bh = 75, 44
    gap = 8
    total = len(steps)*bw + (len(steps)-1)*gap
    start_x = (DW - total) / 2
    y = DH/2 - bh/2 - 8

    for i, (lbl, bg) in enumerate(steps):
        bx = start_x + i*(bw+gap)
        rounded_rect(d, bx, y, bw, bh, 5, bg, HexColor('#37474F'), 0.8)
        lines = lbl.split('\n')
        for j, ln in enumerate(lines):
            d.add(String(bx+bw/2, y+bh/2+(len(lines)-1)*4.5-j*9,
                         ln, textAnchor='middle', fontSize=7,
                         fontName='Helvetica-Bold', fillColor=WHITE))
        if i < len(steps)-1:
            col = HexColor('#FF5252') if i < len(steps)-2 else GOLD
            arrow_line(d, bx+bw, y+bh/2, bx+bw+gap, y+bh/2, col, 1.5)

    d.add(String(DW/2, 6, 'Onset after 18-20 weeks gestation  |  Always use left lateral tilt for all procedures',
                 textAnchor='middle', fontSize=7, fontName='Helvetica-Oblique', fillColor=DIM_TEXT))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# BLOOD VOLUME VISUAL (proportional circles)
# ═══════════════════════════════════════════════════════════════════════════
def make_volume_diagram():
    DW, DH = CONTENT_W, 3.8*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '📊  BLOOD VOLUME EXPANSION IN PREGNANCY',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=CYAN))

    items = [
        ('Total Blood\nVolume', 35, CYAN, 55),
        ('Plasma\nVolume', 55, BLUE, 65),
        ('RBC\nMass', 25, RED, 45),
        ('Cardiac\nOutput', 40, PINK, 55),
        ('GFR', 50, GREEN, 60),
    ]

    section_w = DW / len(items)
    cy = DH/2 - 8

    for i, (lbl, pct, clr, base_r) in enumerate(items):
        cx2 = section_w*i + section_w/2
        r_non = 18
        r_preg = r_non * math.sqrt(1 + pct/100)

        # Non-pregnant (dim)
        d.add(Circle(cx2-12, cy, r_non, fillColor=HexColor('#1A3555'),
                     strokeColor=clr, strokeWidth=0.8))
        d.add(String(cx2-12, cy-4, 'Pre', textAnchor='middle',
                     fontSize=6, fontName='Helvetica', fillColor=DIM_TEXT))

        # Pregnant (bright)
        d.add(Circle(cx2+16, cy, r_preg, fillColor=clr.__class__(
            min(255, int(clr.red*255*0.4)), min(255, int(clr.green*255*0.4)),
            min(255, int(clr.blue*255*0.4))),
            strokeColor=clr, strokeWidth=1.5))
        d.add(String(cx2+16, cy-4, 'Preg', textAnchor='middle',
                     fontSize=6, fontName='Helvetica-Bold', fillColor=WHITE))

        # Arrow between
        arrow_line(d, cx2-12+r_non+2, cy, cx2+16-r_preg-2, cy, GOLD, 1)

        # Label and %
        sign = '+' if pct > 0 else ''
        d.add(String(cx2+2, DH-24, lbl.replace('\n', ' '),
                     textAnchor='middle', fontSize=6.5, fontName='Helvetica-Bold', fillColor=LIGHT_TEXT))
        d.add(String(cx2+2, 5, f'{sign}{pct}%',
                     textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=clr))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# SECTION BANNER helper
# ═══════════════════════════════════════════════════════════════════════════
def banner(title, icon, bg):
    data = [[Paragraph(f'{icon}  {title}', sec_s)]]
    t = Table(data, colWidths=[CONTENT_W])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), bg),
        ('TOPPADDING', (0,0), (-1,-1), 8),
        ('BOTTOMPADDING', (0,0), (-1,-1), 8),
        ('LEFTPADDING', (0,0), (-1,-1), 14),
    ]))
    return t


def make_table(rows, accent):
    header = [
        Paragraph('Parameter', S('h', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
        Paragraph('Change', S('h', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
        Paragraph('Clinical Significance', S('h', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
    ]
    data = [header]
    for param, change, note in rows:
        clr = HexColor('#69F0AE') if '+' in str(change) else HexColor('#FF5252') if '-' in str(change) else GOLD
        data.append([
            Paragraph(param, S('p', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT, alignment=TA_LEFT)),
            Paragraph(f'<b>{change}</b>', S('c', fontName='Helvetica-Bold', fontSize=9, textColor=clr, alignment=TA_CENTER)),
            Paragraph(note, S('n', fontName='Helvetica', fontSize=8, textColor=HexColor('#B0BEC5'), alignment=TA_LEFT)),
        ])
    t = Table(data, colWidths=[5.5*cm, 2.5*cm, 9*cm])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), accent),
        ('GRID', (0,0), (-1,-1), 0.3, HexColor('#2C3E50')),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [ROW_ALT, CARD_MID]),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ]))
    return t


# ═══════════════════════════════════════════════════════════════════════════
# CLINICAL PEARLS
# ═══════════════════════════════════════════════════════════════════════════
def make_pearls():
    pearls = [
        ('🔴', 'Rapid desaturation', 'FRC ↓ + O₂ consumption ↑ = very short safe apnea time. Pre-oxygenate 3-5 min.', RED),
        ('🟡', 'Supine hypotension', 'IVC compression after 18-20 wks. Always use LEFT LATERAL TILT 15°.', GOLD),
        ('🟠', 'Full stomach risk', 'RSI mandatory for all GA >12-16 weeks regardless of fasting.', ORANGE),
        ('🩸', 'Dilutional anemia', 'Hgb 10-11 g/dL is NORMAL in pregnancy (plasma ↑ more than RBC).', HexColor('#EF9A9A')),
        ('💨', 'PaCO₂ "normal" = danger', 'Normal PaCO₂ in pregnancy = 32 mmHg. A reading of 40 mmHg = respiratory failure.', BLUE),
        ('🫘', 'Creatinine "normal" = impaired', 'Normal Cr in pregnancy = 0.5-0.8 mg/dL. Cr of 1.0 warrants investigation.', GREEN),
        ('🩺', 'Hypercoagulability', 'VTE risk 4-5x higher. Immobility + surgery = thromboprophylaxis essential.', ORANGE),
        ('💉', 'Reduced MAC', 'Need 40% less volatile anesthetic. Also more sensitive to IV sedatives and opioids.', PURPLE),
    ]

    rows = []
    for i in range(0, len(pearls), 2):
        row = []
        for j in range(2):
            if i+j < len(pearls):
                ico, title, body, clr = pearls[i+j]
                cell_content = Paragraph(
                    f'<b><font color="#{clr.hexval()[1:]}">{ico} {title}</font></b><br/>'
                    f'<font color="#B0BEC5">{body}</font>',
                    S('pc', fontName='Helvetica', fontSize=8, textColor=LIGHT_TEXT,
                      leading=12, alignment=TA_LEFT)
                )
                row.append(cell_content)
            else:
                row.append('')
        rows.append(row)

    t = Table(rows, colWidths=[CONTENT_W/2 - 2*mm, CONTENT_W/2 - 2*mm])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), CARD_MID),
        ('GRID', (0,0), (-1,-1), 0.3, HexColor('#2C3E50')),
        ('TOPPADDING', (0,0), (-1,-1), 8),
        ('BOTTOMPADDING', (0,0), (-1,-1), 8),
        ('LEFTPADDING', (0,0), (-1,-1), 10),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
        ('ROWBACKGROUNDS', (0,0), (-1,-1), [CARD_MID, ROW_ALT]),
    ]))
    return t


# ═══════════════════════════════════════════════════════════════════════════
# HORMONAL EFFECTS diagram
# ═══════════════════════════════════════════════════════════════════════════
def make_hormones_diagram():
    DW, DH = CONTENT_W, 5*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '⚗️  HORMONAL CHANGES & THEIR EFFECTS',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=CYAN))

    hormones = [
        ('PROGESTERONE\n↑ up to 20x', HexColor('#4A148C'), 55, DH-48,
         ['MAC ↓', 'Bronchodilation', 'LES tone ↓', 'GI motility ↓', 'Vasodilation', 'Ventilation ↑']),
        ('ESTROGEN\n↑ markedly', HexColor('#880E4F'), 55, DH-48,
         ['Airway edema', 'Clotting factors ↑', 'TBG ↑', 'Binding proteins ↑', 'Na retention', 'Mucosal hyperemia']),
        ('hPL\n↑ throughout', HexColor('#E65100'), 55, DH-48,
         ['Insulin resistance', 'Lipolysis ↑', 'Glucose ↑', 'GDM risk ↑', 'Fetal nutrition', 'Anti-insulin']),
        ('CORTISOL\n↑ 3x', HexColor('#1B5E20'), 55, DH-48,
         ['Glucose tolerance ↓', 'Striae gravidarum', 'Immune modulation', 'Bone turnover ↑']),
        ('ALDOSTERONE\n↑ 10x', HexColor('#0D47A1'), 55, DH-48,
         ['Na retention', 'Fluid retention', 'Edema', 'K excretion ↑']),
    ]

    n = len(hormones)
    section_w = DW / n
    hormone_y = DH - 55
    h_bw = 85
    h_bh = 30

    for i, (name, bg, _, _, effects) in enumerate(hormones):
        cx2 = section_w*i + section_w/2
        # Hormone box
        bx = cx2 - h_bw/2
        rounded_rect(d, bx, hormone_y, h_bw, h_bh, 5, bg, HexColor('#37474F'), 0.8)
        for j, ln in enumerate(name.split('\n')):
            d.add(String(cx2, hormone_y+h_bh/2+5-j*11, ln,
                         textAnchor='middle', fontSize=7, fontName='Helvetica-Bold', fillColor=WHITE))

        # Effect boxes below
        eff_bh = 11
        eff_gap = 3
        for k, eff in enumerate(effects):
            ey = hormone_y - (k+1)*(eff_bh+eff_gap)
            if ey < 5:
                break
            eff_bg = HexColor(f'#{max(0, int(bg.red*255)-30):02x}'
                              f'{max(0, int(bg.green*255)-30):02x}'
                              f'{max(0, int(bg.blue*255)-30):02x}')
            d.add(Rect(cx2-40, ey, 80, eff_bh, fillColor=eff_bg,
                       strokeColor=bg, strokeWidth=0.5))
            d.add(String(cx2, ey+3.5, eff, textAnchor='middle', fontSize=6,
                         fontName='Helvetica', fillColor=LIGHT_TEXT))
            # connector line
            if k == 0:
                d.add(Line(cx2, hormone_y, cx2, ey+eff_bh,
                           strokeColor=bg, strokeWidth=0.6, strokeDashArray=[2,2]))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# BUILD PDF
# ═══════════════════════════════════════════════════════════════════════════
OUTPUT = '/home/daytona/workspace/pregnancy-physiology/Physiological_Changes_Pregnancy_v2.pdf'

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=1.8*cm, leftMargin=1.8*cm,
    topMargin=1.5*cm, bottomMargin=1.5*cm,
)

story = []

def add_bg(canvas, doc):
    canvas.saveState()
    canvas.setFillColor(DARK_BG)
    canvas.rect(0, 0, A4[0], A4[1], fill=1, stroke=0)
    canvas.restoreState()

# ── PAGE 1: Cover + Bar Chart + Body Diagram ──────────────────────────────
hdr_data = [[Paragraph('PHYSIOLOGICAL CHANGES<br/>DURING PREGNANCY', title_s)]]
hdr_t = Table(hdr_data, colWidths=[CONTENT_W])
hdr_t.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,-1), NAVY),
    ('TOPPADDING', (0,0), (-1,-1), 18),
    ('BOTTOMPADDING', (0,0), (-1,-1), 8),
]))
story.append(hdr_t)
story.append(Paragraph('A Visual Medical Summary — Systems, Flowcharts & Diagrams', sub_s))
story.append(Paragraph('Source: Morgan & Mikhail\'s Clinical Anesthesiology, 7e (pp. 1572–1587)', src_s))
story.append(Spacer(1, 3*mm))

# Bar chart
story.append(banner('MAGNITUDE OF CHANGES — AT A GLANCE', '📊', TABLE_HDR))
story.append(Spacer(1, 2*mm))
story.append(make_bar_chart())
story.append(Spacer(1, 4*mm))

# Body diagram
story.append(banner('BODY SYSTEMS MAP', '🏃', HexColor('#1A237E')))
story.append(Spacer(1, 2*mm))
story.append(make_body_diagram())
story.append(PageBreak())

# ── PAGE 2: CVS Flowchart + Volume diagram + Supine ──────────────────────
story.append(banner('CARDIOVASCULAR CHANGES — FLOWCHART', '❤️', HexColor('#B71C1C')))
story.append(Spacer(1, 2*mm))
story.append(make_cvs_flowchart())
story.append(Spacer(1, 4*mm))

story.append(banner('BLOOD VOLUME EXPANSION', '🔵', HexColor('#0D47A1')))
story.append(Spacer(1, 2*mm))
story.append(make_volume_diagram())
story.append(Spacer(1, 4*mm))

story.append(banner('SUPINE HYPOTENSION / AORTOCAVAL COMPRESSION', '⚠️', HexColor('#7B1515')))
story.append(Spacer(1, 2*mm))
story.append(make_supine_diagram())
story.append(Spacer(1, 4*mm))

# CVS detail table
story.append(make_table([
    ('Blood Volume', '+35%', 'Starts 1st trimester; peaks 28-32 weeks; buffers delivery blood loss'),
    ('Plasma Volume', '+55%', 'Exceeds RBC expansion → physiological dilutional anemia'),
    ('Cardiac Output', '+40%', 'Rises by 8-10 weeks; further ↑ during labor contractions (+10-45%)'),
    ('Stroke Volume', '+30%', 'Increased preload + decreased afterload'),
    ('Heart Rate', '+20%', 'Tachycardia >100 bpm is normal in late pregnancy'),
    ('Systolic BP', '-5%', 'Slight decrease; returns to near baseline at term'),
    ('Diastolic BP', '-15%', 'Nadir at 24-28 weeks; used to diagnose PIH/preeclampsia'),
    ('SVR', '-15%', 'Progesterone + placental AV shunt + prostacyclin'),
    ('Pulmonary resistance', '-30%', 'Reduces RV afterload; important in pulmonary hypertension'),
], HexColor('#C62828')))
story.append(PageBreak())

# ── PAGE 3: Respiratory ────────────────────────────────────────────────────
story.append(banner('RESPIRATORY CHANGES — MECHANISM FLOW', '🫁', HexColor('#01579B')))
story.append(Spacer(1, 2*mm))
story.append(make_resp_flowchart())
story.append(Spacer(1, 4*mm))

story.append(banner('ASPIRATION RISK FLOWCHART', '⚠️', HexColor('#7B1515')))
story.append(Spacer(1, 2*mm))
story.append(make_aspiration_flowchart())
story.append(Spacer(1, 4*mm))

story.append(make_table([
    ('O₂ Consumption', '+20–50%', 'Increased metabolic demands of fetus, uterus, placenta, breasts'),
    ('Minute Ventilation', '+50%', 'Progesterone stimulates medullary respiratory center'),
    ('Tidal Volume', '+40%', 'Primary driver; RR also rises +15%'),
    ('FRC', '-20%', 'Elevated diaphragm; ↓ ERV and RV; predisposes to atelectasis & rapid desaturation'),
    ('Airway Resistance', '-35%', 'Progesterone-mediated bronchodilation'),
    ('PaO₂', '+10%', 'Rises to ~106 mmHg at sea level; hyperventilation effect'),
    ('PaCO₂', '-15%', 'Drops to ~32 mmHg; HCO₃⁻ drops to ~20 mEq/L; pH ~7.44'),
    ('P50', '+27→30 mmHg', 'Right-shifted O₂-Hb curve; facilitates O₂ offloading to fetus'),
], HexColor('#0277BD')))
story.append(PageBreak())

# ── PAGE 4: Hematology + Coagulation ──────────────────────────────────────
story.append(banner('VTE RISK — VIRCHOW\'S TRIAD IN PREGNANCY', '🩸', HexColor('#7B1515')))
story.append(Spacer(1, 2*mm))
story.append(make_coag_diagram())
story.append(Spacer(1, 4*mm))

story.append(banner('HEMATOLOGICAL CHANGES', '🩸', HexColor('#E65100')))
story.append(Spacer(1, 2*mm))
story.append(make_table([
    ('Hemoglobin', '-20%', 'Hgb <11 g/dL (1st tri) or <10.5 g/dL (2nd tri) is pathological'),
    ('Hematocrit', 'Decreases', 'Falls from ~40% to ~34%; nadir at 30-34 weeks'),
    ('Platelets', '-10%', 'Mild thrombocytopenia is normal; <70,000 warrants investigation'),
    ('WBC', 'Increases', 'Up to 12,000/μL; in labor may reach 20,000-30,000/μL'),
    ('Fibrinogen', 'Doubles', 'Rises from 300 → 600 mg/dL; ESR increases markedly'),
    ('Clotting factors II, VII, VIII, X', '+30–250%', 'Pregnancy is strongly hypercoagulable'),
    ('Protein C & S', 'Decreased', 'Further tilts balance toward thrombosis'),
    ('Serum albumin', 'Decreased', '4.0 → 3.0 g/dL; affects protein-bound drug pharmacokinetics'),
], HexColor('#E64A19')))
story.append(PageBreak())

# ── PAGE 5: Hormones + Renal + GI ─────────────────────────────────────────
story.append(banner('HORMONAL CHANGES & THEIR EFFECTS', '⚗️', HexColor('#006064')))
story.append(Spacer(1, 2*mm))
story.append(make_hormones_diagram())
story.append(Spacer(1, 4*mm))

story.append(banner('RENAL CHANGES', '🫘', HexColor('#1B5E20')))
story.append(Spacer(1, 2*mm))
story.append(make_table([
    ('GFR', '+50%', 'Starts 1st trimester; renal plasma flow ↑70%; kidneys enlarge ~1 cm'),
    ('Serum Creatinine', 'Decreased', 'Normal = 0.5–0.8 mg/dL; "normal" 1.0 mg/dL suggests impairment'),
    ('Serum BUN', 'Decreased', 'Normal ~8-9 mg/dL; lower due to ↑GFR'),
    ('Glycosuria', 'May occur', 'Tubular reabsorption does not scale with GFR; not pathological alone'),
    ('Urine protein', 'Up to 300 mg/day', '>300 mg/24h = pathological; marker for preeclampsia'),
], HexColor('#2E7D32')))
story.append(Spacer(1, 4*mm))

story.append(banner('GASTROINTESTINAL CHANGES', '🤰', HexColor('#4E342E')))
story.append(Spacer(1, 2*mm))
story.append(make_table([
    ('Gastric emptying', 'Delayed', 'Progesterone ↓ GI motility; aspiration risk (Mendelson syndrome)'),
    ('LES tone', 'Decreased', 'Combined with ↑ intragastric pressure → GERD in >80%'),
    ('Nausea & vomiting', 'Common', 'Affects 70-80%; hyperemesis gravidarum in <2%; peak 8-10 wks'),
    ('Alkaline phosphatase', 'Increased', 'Placenta produces ALP; ALT/AST should remain normal'),
    ('Gallbladder', 'Delayed emptying', 'Cholesterol gallstones 2x more common in pregnancy'),
], HexColor('#5D4037')))
story.append(PageBreak())

# ── PAGE 6: Timeline + Clinical Pearls ────────────────────────────────────
story.append(banner('TIMELINE OF KEY PHYSIOLOGICAL CHANGES', '📅', HexColor('#1A237E')))
story.append(Spacer(1, 2*mm))
story.append(make_timeline())
story.append(Spacer(1, 5*mm))

story.append(banner('⭐ HIGH-YIELD CLINICAL PEARLS', '🏆', HexColor('#1A3020')))
story.append(Spacer(1, 2*mm))
story.append(make_pearls())
story.append(Spacer(1, 5*mm))

# Footer
story.append(HRFlowable(width='100%', thickness=0.5, color=HexColor('#37474F')))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
    'Source: Morgan & Mikhail\'s Clinical Anesthesiology, 7e, Chapter 40 (pp. 1572–1587) | '
    'Compiled for educational purposes | Orris Medical Summary  —  6-page visual reference',
    note_s
))

doc.build(story, onFirstPage=add_bg, onLaterPages=add_bg)
print(f'✅ PDF created: {OUTPUT}')
Running Command

cd /home/daytona/workspace/pregnancy-physiology && python make_pdf_v2.py 2>&1

Editing File

~/pregnancy-physiology/make_pdf_v2.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/pregnancy-physiology/make_pdf_v2.py'
Running Command

cd /home/daytona/workspace/pregnancy-physiology && python make_pdf_v2.py 2>&1

The .hexval() returns something like 0xEF5350 - need to strip the 0x prefix. Let me fix that and also fix the volume diagram color construction.
Editing File

~/pregnancy-physiology/make_pdf_v2.py

Error: String not found in file: '    for i, (ico, title, body, clr) in enumerate(pearls[i+j:i+j+1]):
                cell_content = Paragraph(
                    f'<b><font color="#{clr.hexval()[1:]}">{ico} {title}</font></b><br/>'
                    f'<font color="#B0BEC5">{body}</font>',
                    S('pc', fontName='Helvetica', fontSize=8, textColor=LIGHT_TEXT,
                      leading=12, alignment=TA_LEFT)
                )
                row.append(cell_content)'
Searching Content

"hexval" in ~/pregnancy-physiology

Reading File
Reading File
Running Command

python3 -c "from reportlab.lib.colors import HexColor; c=HexColor('#EF5350'); print(repr(c.hexval())); print('%02X%02X%02X' % (int(c.red*255), int(c.green*255), int(c.blue*255)))"

Now I'll fix all instances that use .hexval() and also fix the volume diagram color issue:
Editing File

~/pregnancy-physiology/make_pdf_v2.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/pregnancy-physiology/make_pdf_v2.py'
Editing File

~/pregnancy-physiology/make_pdf_v2.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/pregnancy-physiology/make_pdf_v2.py'
Now fix the volume diagram color construction (using clr.__class__(...) with float values that may overflow):
Editing File

~/pregnancy-physiology/make_pdf_v2.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/pregnancy-physiology/make_pdf_v2.py'
Running Command

cd /home/daytona/workspace/pregnancy-physiology && python make_pdf_v2.py 2>&1

Running Command

ls -lh /home/daytona/workspace/pregnancy-physiology/Physiological_Changes_Pregnancy_v2.pdf

Your enhanced 6-page visual PDF is ready:

Physiological Changes Pregnancy v2

PDF Document · PDF


Here's what's inside all 6 pages:
Page 1 - Overview
  • Horizontal bar chart showing all key % changes (green = increase, red = decrease) for every parameter at a glance
  • Full body system map with annotated callout boxes pointing to CNS, heart, lungs, kidneys, uterus, GI - with arrows connecting each organ to its changes
Page 2 - Cardiovascular
  • Cause-and-effect flowchart: Triggers → Mechanisms → Effects → Cardiac Output
  • Proportional circle diagram showing blood volume/plasma/RBC/CO/GFR expansion (bigger circle = bigger change)
  • Supine hypotension step-by-step flowchart (6 boxes with arrows): supine → IVC compression → ↓venous return → ↓CO → hypotension → FIX: left tilt
Page 3 - Respiratory
  • Mechanism flow (progesterone → medullary stimulation → TV ↑ → MV ↑ → PaCO₂ ↓)
  • Danger chain (uterus pushes diaphragm → FRC ↓ + O₂ demand ↑ → rapid desaturation → pre-O₂ mandatory)
  • Aspiration risk flowchart: Progesterone → LES tone ↓ → delayed emptying → ↑intragastric pressure → full stomach → RSI mandatory
Page 4 - Hematology
  • Virchow's triad triangle diagram with VTE at center (hypercoagulability + venous stasis + endothelial injury nodes)
  • Hematological changes table with color-coded values
Page 5 - Endocrine, Renal, GI
  • Hormonal effect tree: 5 hormones (progesterone, estrogen, hPL, cortisol, aldosterone) each branching into their downstream effects
  • Renal and GI tables
Page 6 - Timeline + Pearls
  • Full pregnancy timeline (0-40 weeks) with labeled events above and below the line, trimester color bands
  • 8 high-yield clinical pearls in a 2-column color-coded grid
This is a shared conversation. Sign in to Orris to start your own chat.