Abg analysis from basic to clinic application

Reading File
ABG (arterial blood gas) analysis involves measuring pH, PaCO2, PaO2, HCO3-, and base excess to assess acid-base status and oxygenation. The systematic approach: check pH (normal 7.35-7.45), identify primary disorder, assess compensation, then look for mixed disorders. Clinical applications range from respiratory failure management to metabolic emergencies.
Searching sources...
Finding Sources
Finding Sources
Searching PubMed

"arterial blood gas" AND "acid-base" interpretation

Excellent sources found. Now let me read the key textbook sections in parallel.
Reading File
Reading File
Reading File
Good content. Let me now pull the core ABG physiology and compensation sections, plus clinical application content.
Reading File
Reading File
Excellent material. Let me get the compensation tables and clinical application sections.
Reading File
Reading File
I now have comprehensive material. Let me also get the compensation formulas and the oxygenation parameters section.
Reading File
I now have all the core content needed. Let me compile the comprehensive ABG guide.

Arterial Blood Gas (ABG) Analysis: Basic to Clinical Application


1. What Is an ABG and Why Does It Matter?

An arterial blood gas measures pH, PaCO2, PaO2, HCO3-, and often base excess (BE) from an arterial sample. It is the best single tool for assessing oxygenation, ventilation, and acid-base status simultaneously. ABG analysis is relevant in virtually every critically ill patient - acid-base disorders occur in 51-56% of hospitalized patients.

2. Normal ABG Values

ParameterNormal RangeMeaning
pH7.35 - 7.45Acidity/alkalinity of blood
PaCO235 - 45 mmHgVentilatory (respiratory) component
PaO280 - 100 mmHgOxygenation
HCO3-22 - 26 mEq/LMetabolic/renal component
Base Excess (BE)-2 to +2 mEq/LNet metabolic acid-base deviation
SaO295 - 100%Hemoglobin oxygen saturation
pH < 7.35 = acidemia | pH > 7.45 = alkalemia

3. The Henderson-Hasselbalch Equation (The Core Physiology)

$$\text{pH} = 6.1 + \log_{10}\left(\frac{[\text{HCO}_3^-]}{0.03 \times \text{PaCO}_2}\right)$$
  • The numerator (HCO3-) is controlled by the kidneys (slow, days)
  • The denominator (PaCO2) is controlled by the lungs (fast, minutes)
  • Together they maintain pH at 7.40
Every day, the body produces ~10,000-15,000 mmol of volatile acid (CO2) and 50-100 mEq of nonvolatile acid. These are buffered in cells and ECF, then excreted via lungs and kidneys respectively.

4. The Four Primary Acid-Base Disorders

DisorderpHPrimary ChangeCompensation
Metabolic AcidosisLow↓ HCO3-↓ PaCO2 (hyperventilation)
Metabolic AlkalosisHigh↑ HCO3-↑ PaCO2 (hypoventilation)
Respiratory AcidosisLow↑ PaCO2↑ HCO3- (renal retention)
Respiratory AlkalosisHigh↓ PaCO2↓ HCO3- (renal excretion)

5. Compensation Formulas (Memorize These)

These formulas tell you what compensation is expected for a simple disorder. If measured values differ from predicted, a mixed disorder is present.

Metabolic Acidosis

Winter's Formula: PaCO2 = 1.5 × [HCO3-] + 8 ± 2 mmHg
  • Compensation begins within 12-24 hours
  • Alternatively: ↓PaCO2 = 1.1 × ↓[HCO3-]

Metabolic Alkalosis

PaCO2 = 0.7 × [HCO3-] + 20 ± 5 mmHg
  • Compensation within 24-48 hours
  • Alternatively: ↑PaCO2 = 0.75 × ↑[HCO3-]

Respiratory Acidosis

  • Acute: Δ[HCO3-] = +1 mEq/L per 10 mmHg rise in PaCO2
  • Chronic: Δ[HCO3-] = +4 mEq/L per 10 mmHg rise in PaCO2
  • Compensation develops over 48-96 hours

Respiratory Alkalosis

  • Acute: Δ[HCO3-] = -2 mEq/L per 10 mmHg fall in PaCO2
  • Chronic: Δ[HCO3-] = -4 to -5 mEq/L per 10 mmHg fall in PaCO2
  • Compensation develops over 48-96 hours

6. Systematic Step-by-Step ABG Interpretation

Step 1: Is the Patient Acidemic or Alkalemic?

  • pH < 7.35 → acidemia
  • pH > 7.45 → alkalemia
  • pH 7.35-7.45 → normal (but a mixed disorder may still exist!)

Step 2: Identify the Primary Disorder

  • PaCO2 high + low pH → Respiratory Acidosis
  • PaCO2 low + high pH → Respiratory Alkalosis
  • HCO3- low + low pH → Metabolic Acidosis
  • HCO3- high + high pH → Metabolic Alkalosis
The primary disorder is the one that matches the direction of the pH change.

Step 3: Is Compensation Appropriate?

Apply the relevant compensation formula above. If the measured value falls outside the expected range:
  • More acidotic than expected → additional metabolic acidosis
  • More alkalotic than expected → additional metabolic alkalosis

Step 4: Calculate the Anion Gap (if metabolic acidosis present)

AG = [Na+] - ([Cl-] + [HCO3-])
  • Normal: 8-12 mEq/L (or up to 13 with albumin correction)
  • Correct for albumin: For every 1 g/dL albumin below 4 g/dL, add 2.5 mEq/L to AG
High AG Metabolic Acidosis - MUDPILES mnemonic:
  • Methanol
  • Uremia
  • DKA (and other ketoacidosis)
  • Propylene glycol / Paraldehyde
  • Isoniazid / Iron
  • Lactic acidosis
  • Ethylene glycol
  • Salicylates
Normal AG (Hyperchloremic) Metabolic Acidosis:
  • Diarrhea (GI bicarbonate loss)
  • Renal tubular acidosis (RTA)
  • Carbonic anhydrase inhibitors (acetazolamide)
  • Saline resuscitation (dilutional)
  • Ureteral diversion

Step 5: Delta-Delta Ratio (for High AG Acidosis)

ΔAG / ΔHCO3- = (measured AG - 12) / (24 - measured HCO3-)
RatioInterpretation
< 1Mixed: high AG + normal AG acidosis
1 - 2Pure high AG metabolic acidosis
> 2Mixed: high AG acidosis + metabolic alkalosis

7. Physiologic Consequences of Extreme Derangements

Severe Acidemia (pH < 7.2)

SystemEffect
CardiovascularImpaired myocardial contractility, ↓ cardiac output, ↑ pulmonary vascular resistance, arrhythmias, reduced catecholamine responsiveness
RespiratoryHyperventilation, dyspnea, respiratory muscle fatigue
MetabolicInsulin resistance, ↓ ATP synthesis, hyperkalemia, protein catabolism
CerebralAltered mental status, coma, inhibited cellular metabolism

Severe Alkalemia (pH > 7.6)

SystemEffect
CardiovascularArteriolar constriction, ↓ coronary flow, arrhythmias, left shift of O2 dissociation curve
RespiratoryHypoventilation
MetabolicHypokalemia, ↓ ionized Ca2+, Mg2+, and phosphate
Cerebral↓ Cerebral blood flow, tetany, seizures, delirium, coma

8. Oxygenation Assessment

A-a Gradient (Alveolar-Arterial Oxygen Difference)

PAO2 = (FiO2 × [Patm - PH2O]) - (PaCO2 / R)
  • On room air at sea level: PAO2 = 150 - (PaCO2/0.8)
  • A-a gradient = PAO2 - PaO2
  • Normal: < 10-15 mmHg (increases with age: ~age/4 + 4)
ConditionPaO2PaCO2A-a Gradient
HypoventilationLowHighNormal
V/Q mismatchLowLow/NormalElevated
Diffusion defectLowNormal/LowElevated
Right-to-left shuntLowLowElevated (doesn't correct with O2)

P/F Ratio (Oxygenation Index)

P/F = PaO2 / FiO2
  • Normal: > 400 mmHg
  • Mild ARDS: 200-300
  • Moderate ARDS: 100-200
  • Severe ARDS: < 100

9. Mixed Acid-Base Disorders

A mixed disorder occurs when two or more primary disturbances coexist. Key clues:
  1. pH is normal but PaCO2 and HCO3- are both abnormal
  2. Compensation exceeds or falls short of expected range
  3. Delta-delta ratio is outside 1-2
Classic clinical example - Salicylate toxicity (from Rosen's Emergency Medicine):
  • ABG: pH 7.47 / PaCO2 25 / PaO2 180
  • Step 1: pH 7.47 → alkalemia
  • Step 2: PaCO2 25 → respiratory alkalosis
  • Step 3: Predicted pH for this PaCO2 = 7.40 + [(40-25)/10 × 0.08] = 7.52
  • Measured pH (7.47) is lower than predicted (7.52) → concurrent metabolic acidosis
  • Final diagnosis: Mixed respiratory alkalosis + metabolic acidosis
Another example: An alcoholic patient with vomiting develops metabolic alkalosis (pH 7.55, HCO3- 40), then develops superimposed alcoholic ketoacidosis. The pH normalizes to 7.40, HCO3- 25, PaCO2 40 - all "normal" values - but the AG is 25. This demonstrates a mixed metabolic alkalosis + metabolic acidosis that is invisible without AG calculation.

10. Potassium and Acid-Base

Plasma K+ and pH are closely linked:
  • Metabolic acidosis → K+ shifts out of cells → hyperkalemia
  • For each ↓0.10 in pH, K+ rises ~0.6 mEq/L
  • Metabolic alkalosis → K+ shifts into cells → hypokalemia
  • Hypokalemia itself maintains metabolic alkalosis by enhancing H+-K+-ATPase in the collecting duct and increasing NH4+ excretion
DKA and lactic acidosis are exceptions - they often present with low total body K+ despite acidemia due to osmotic diuresis and poor intake.

11. Clinical Applications by Setting

ICU / Critical Care

  • Serial ABGs guide mechanical ventilation settings (target PaCO2, pH)
  • ABG is superior to pulse oximetry alone - SpO2 cannot detect hypercapnia or acid-base disorders
  • In septic shock, lactic acidosis drives high-AG metabolic acidosis; pH < 7.2 carries increased mortality
  • BICAR-ICU trial: NaHCO3 showed no overall mortality benefit in severe metabolic acidemia but did reduce need for renal replacement therapy in patients with AKI

Respiratory Failure

  • ABG distinguishes Type 1 (hypoxemic, PaO2 < 60, normal PaCO2) from Type 2 (hypercapnic, PaCO2 > 45) respiratory failure
  • COPD exacerbation: chronic compensated respiratory acidosis with elevated HCO3-; acute decompensation shows pH fall without proportional HCO3- rise
  • Use BE + PaCO2 trend to guide NIV/intubation decisions

Metabolic Emergencies

  • DKA: High-AG metabolic acidosis, pH can be 6.9-7.2, hyperkalemia, acetone on breath
  • HHS: Minimal acidosis (if any), extreme hyperglycemia, severe dehydration
  • Lactic acidosis: Sepsis, mesenteric ischemia, metformin overdose, type B causes
  • Hyperchloremic acidosis: Aggressive saline resuscitation, diarrhea, RTA

Poisoning/Toxicology

  • Salicylates: Mixed respiratory alkalosis + metabolic acidosis (classic)
  • Methanol/ethylene glycol: High AG acidosis + elevated osmol gap
  • Opioids: Respiratory acidosis with hypoxia
  • TCA overdose: Mixed respiratory and metabolic acidosis

Perioperative/Anesthesia

  • Goal-directed fluid therapy: Excessive 0.9% saline causes hyperchloremic metabolic acidosis; balanced crystalloids (LR, PlasmaLyte) reduce this risk
  • Post-cardiac surgery: Metabolic alkalosis from citrate in blood products, diuretics
  • Permissive hypercapnia in laparoscopic surgery (CO2 pneumoperitoneum) → respiratory acidosis

12. Clinical Clues Without ABG

Even serum electrolytes alone can hint at acid-base disorders:
  • Elevated AG on chemistry panel → high-AG metabolic acidosis even without blood gas
  • Low Cl- + high HCO3- → metabolic alkalosis (vomiting, diuretics)
  • Physical exam: tetany (alkalemia), Kussmaul breathing (metabolic acidosis), cyanosis (respiratory failure)
  • Drug history: acetazolamide → metabolic acidosis; loop/thiazide diuretics → metabolic alkalosis

13. Three-Step Clinical Algorithm (Quick Reference)

1. Is the patient acidemic or alkalemic?
   ├── pH < 7.35 → Acidemia
   └── pH > 7.45 → Alkalemia

2. Is the primary disorder metabolic or respiratory?
   ├── pH↓ + PaCO2↑ → Respiratory Acidosis
   ├── pH↑ + PaCO2↓ → Respiratory Alkalosis
   ├── pH↓ + HCO3-↓ → Metabolic Acidosis
   └── pH↑ + HCO3-↑ → Metabolic Alkalosis

3. Is compensation appropriate?
   └── If not → Mixed disorder present
       ├── If high-AG acidosis: Calculate delta-delta ratio
       └── Interpret oxygenation: P/F ratio, A-a gradient

Sources

  • Barash, Cullen & Stoelting's Clinical Anesthesia, 9e - Chapters 16 (Acid-Base, Fluids, Electrolytes), pp. 1146-1155
  • Brenner and Rector's The Kidney - Chapter 16, Stepwise Approach to Acid-Base Disorders, pp. 700-705
  • Rosen's Emergency Medicine - Box 113.2, Three-Step ABG Algorithm, p. 2505
  • Recent review: Sanagustín MN & Osredkar J, "Blood gas analysis: Clinical applications, interpretation and future directions," Medicine International, 2026 [PMID: 41473681]
  • Practice guideline: Habib T et al., "Mastering blood gas interpretation: A practical guide for primary care providers," S Afr Fam Pract, 2025 [PMID: 40336441]

Create a quick reference PDF with compensation formulas and MUDPILES mnemonics

Reading File
Running Command

ls -la /home/daytona/workspace/

Running Command

mkdir -p /home/daytona/workspace/abg-reference

Writing File

~/abg-reference/generate_abg_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import 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 PageBreak

OUTPUT = "/home/daytona/workspace/abg-reference/ABG_Quick_Reference.pdf"

# ── Colour palette ─────────────────────────────────────────────────────────────
NAVY    = colors.HexColor("#1a2e4a")
TEAL    = colors.HexColor("#0d7377")
GOLD    = colors.HexColor("#f0a500")
LIGHT   = colors.HexColor("#eaf4f4")
RED_BOX = colors.HexColor("#c0392b")
GREEN   = colors.HexColor("#1a7a4a")
ACIDRED = colors.HexColor("#d32f2f")
ALKBLUE = colors.HexColor("#1565c0")
WHITE   = colors.white
GREY    = colors.HexColor("#f5f5f5")
MID_GREY= colors.HexColor("#cccccc")

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=14*mm, leftMargin=14*mm,
    topMargin=14*mm, bottomMargin=14*mm,
    title="ABG Quick Reference",
    author="Orris Medical"
)

W = A4[0] - 28*mm   # usable width

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

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

TITLE_STYLE = S("title_s",
    fontSize=22, textColor=WHITE, fontName="Helvetica-Bold",
    alignment=TA_CENTER, spaceAfter=2)

SUB_STYLE = S("sub_s",
    fontSize=10, textColor=LIGHT, fontName="Helvetica",
    alignment=TA_CENTER, spaceAfter=0)

SEC_STYLE = S("sec_s",
    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold",
    alignment=TA_LEFT, leftIndent=4, spaceAfter=0, spaceBefore=0)

BODY = S("body_s",
    fontSize=8.5, textColor=NAVY, fontName="Helvetica",
    leading=13, spaceAfter=2)

BOLD_BODY = S("bold_body",
    fontSize=8.5, textColor=NAVY, fontName="Helvetica-Bold",
    leading=13, spaceAfter=2)

FORMULA = S("formula",
    fontSize=9, textColor=TEAL, fontName="Helvetica-Bold",
    leading=14, leftIndent=8, spaceAfter=1)

MNEMONIC = S("mnemonic",
    fontSize=11, textColor=NAVY, fontName="Helvetica-Bold",
    leading=16, spaceAfter=1, alignment=TA_CENTER)

SMALL = S("small_s",
    fontSize=7.5, textColor=colors.HexColor("#555555"),
    fontName="Helvetica", leading=11)

FOOTER_STYLE = S("footer_s",
    fontSize=7, textColor=colors.HexColor("#888888"),
    fontName="Helvetica", alignment=TA_CENTER)

# ── Helper: Section header ─────────────────────────────────────────────────────
def section_header(text, bg=NAVY):
    data = [[Paragraph(text, SEC_STYLE)]]
    t = Table(data, colWidths=[W])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
        ("RIGHTPADDING",  (0,0), (-1,-1), 8),
        ("ROWBACKGROUNDS", (0,0), (-1,-1), [bg]),
    ]))
    return t

def hr():
    return HRFlowable(width="100%", thickness=0.5, color=MID_GREY, spaceAfter=4, spaceBefore=4)

# ══════════════════════════════════════════════════════════════════════════════
# BUILD STORY
# ══════════════════════════════════════════════════════════════════════════════
story = []

# ── TITLE BANNER ──────────────────────────────────────────────────────────────
banner_data = [[
    Paragraph("ABG Quick Reference Card", TITLE_STYLE),
    Paragraph("Arterial Blood Gas · Acid-Base · Oxygenation", SUB_STYLE),
]]
banner = Table([[Paragraph("ABG Quick Reference Card", TITLE_STYLE)],
                [Paragraph("Arterial Blood Gas  ·  Compensation Formulas  ·  MUDPILES", SUB_STYLE)]],
               colWidths=[W])
banner.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(banner)
story.append(Spacer(1, 5))

# ── ROW 1: Normal Values + Henderson-Hasselbalch ─────────────────────────────
# Left: Normal Values table
nv_header = [
    [Paragraph("NORMAL ABG VALUES", S("nh", fontSize=9, fontName="Helvetica-Bold",
               textColor=WHITE, alignment=TA_CENTER))]
]
nv_rows = [
    ["pH",       "7.35 – 7.45"],
    ["PaCO₂",    "35 – 45 mmHg"],
    ["PaO₂",     "80 – 100 mmHg"],
    ["HCO₃⁻",   "22 – 26 mEq/L"],
    ["Base Excess", "−2 to +2 mEq/L"],
    ["SaO₂",     "95 – 100%"],
]
nv_style = 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), [GREY, WHITE]),
    ("TEXTCOLOR",     (0,1), (-1,-1), NAVY),
    ("FONTNAME",      (0,1), (0,-1), "Helvetica-Bold"),
    ("GRID",          (0,0), (-1,-1), 0.4, MID_GREY),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("ALIGN",         (1,0), (1,-1), "CENTER"),
])
nv_table_data = [["Parameter", "Normal Range"]] + nv_rows
nv_table = Table(nv_table_data, colWidths=[45*mm, 38*mm])
nv_table.setStyle(nv_style)

# Right: Henderson-Hasselbalch + pH rules
hh_content = [
    Paragraph("Henderson–Hasselbalch", S("hh_h", fontSize=9, fontName="Helvetica-Bold",
              textColor=TEAL)),
    Spacer(1,3),
    Paragraph("pH = 6.1 + log₁₀( [HCO₃⁻] / 0.03 × PaCO₂ )", FORMULA),
    Spacer(1,6),
    Paragraph("Buffers", S("buf_h", fontSize=9, fontName="Helvetica-Bold", textColor=TEAL)),
    Spacer(1,3),
    Paragraph("• Lungs control PaCO₂ (fast: minutes)", BODY),
    Paragraph("• Kidneys control HCO₃⁻ (slow: hours–days)", BODY),
    Paragraph("• Bicarbonate buffer: H⁺ + HCO₃⁻ ⇌ H₂CO₃ ⇌ H₂O + CO₂", BODY),
    Spacer(1,6),
    Paragraph("pH Rules", S("buf_h", fontSize=9, fontName="Helvetica-Bold", textColor=TEAL)),
    Spacer(1,3),
    Paragraph("pH < 7.35 → Acidemia", S("ar", fontSize=9, fontName="Helvetica-Bold", textColor=ACIDRED)),
    Paragraph("pH > 7.45 → Alkalemia", S("al", fontSize=9, fontName="Helvetica-Bold", textColor=ALKBLUE)),
    Paragraph("pH 7.35–7.45 → Normal (mixed disorder may still exist!)", BODY),
]

row1 = Table([[nv_table, hh_content]],
             colWidths=[87*mm, W - 87*mm - 4*mm],
             spaceBefore=0)
row1.setStyle(TableStyle([
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("TOPPADDING",    (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(row1)
story.append(Spacer(1, 7))

# ── SECTION: Compensation Formulas ───────────────────────────────────────────
story.append(section_header("  COMPENSATION FORMULAS", NAVY))
story.append(Spacer(1, 4))

comp_rows = [
    # header
    [
        Paragraph("Disorder", S("ch", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)),
        Paragraph("Primary Change", S("ch", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)),
        Paragraph("Compensation", S("ch", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)),
        Paragraph("Formula", S("ch", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)),
        Paragraph("Onset", S("ch", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, alignment=TA_CENTER)),
    ],
    # Metabolic Acidosis
    [
        Paragraph("Metabolic\nAcidosis", S("d", fontSize=8.5, fontName="Helvetica-Bold", textColor=ACIDRED, leading=12)),
        Paragraph("↓ HCO₃⁻\n↓ pH", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("↓ PaCO₂\n(hyperventilation)", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("Winter's: PaCO₂ = 1.5×[HCO₃⁻] + 8 ± 2\nor ΔPaCO₂ = 1.1 × ΔHCO₃⁻",
                  S("f", fontSize=8.5, fontName="Helvetica-Bold", textColor=TEAL, leading=13)),
        Paragraph("12–24 h", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
    ],
    # Metabolic Alkalosis
    [
        Paragraph("Metabolic\nAlkalosis", S("d", fontSize=8.5, fontName="Helvetica-Bold", textColor=ALKBLUE, leading=12)),
        Paragraph("↑ HCO₃⁻\n↑ pH", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("↑ PaCO₂\n(hypoventilation)", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("PaCO₂ = 0.7×[HCO₃⁻] + 20 ± 5\nor ΔPaCO₂ = 0.75 × ΔHCO₃⁻",
                  S("f", fontSize=8.5, fontName="Helvetica-Bold", textColor=TEAL, leading=13)),
        Paragraph("24–48 h", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
    ],
    # Respiratory Acidosis Acute
    [
        Paragraph("Respiratory\nAcidosis\n(ACUTE)", S("d", fontSize=8.5, fontName="Helvetica-Bold", textColor=ACIDRED, leading=12)),
        Paragraph("↑ PaCO₂\n↓ pH", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("↑ HCO₃⁻\n(renal retention)", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("ΔHCO₃⁻ = +1 mEq/L per ↑10 mmHg PaCO₂\nΔpH = −0.08 per ↑10 mmHg PaCO₂",
                  S("f", fontSize=8.5, fontName="Helvetica-Bold", textColor=TEAL, leading=13)),
        Paragraph("Minutes\n(immediate)", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
    ],
    # Respiratory Acidosis Chronic
    [
        Paragraph("Respiratory\nAcidosis\n(CHRONIC)", S("d", fontSize=8.5, fontName="Helvetica-Bold", textColor=colors.HexColor("#b71c1c"), leading=12)),
        Paragraph("↑ PaCO₂\n↓ pH", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("↑ HCO₃⁻\n(full renal)", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("ΔHCO₃⁻ = +4 mEq/L per ↑10 mmHg PaCO₂\nΔpH = −0.03 per ↑10 mmHg PaCO₂",
                  S("f", fontSize=8.5, fontName="Helvetica-Bold", textColor=TEAL, leading=13)),
        Paragraph("48–96 h", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
    ],
    # Respiratory Alkalosis Acute
    [
        Paragraph("Respiratory\nAlkalosis\n(ACUTE)", S("d", fontSize=8.5, fontName="Helvetica-Bold", textColor=ALKBLUE, leading=12)),
        Paragraph("↓ PaCO₂\n↑ pH", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("↓ HCO₃⁻\n(renal loss)", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("ΔHCO₃⁻ = −2 mEq/L per ↓10 mmHg PaCO₂",
                  S("f", fontSize=8.5, fontName="Helvetica-Bold", textColor=TEAL, leading=13)),
        Paragraph("Minutes\n(immediate)", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
    ],
    # Respiratory Alkalosis Chronic
    [
        Paragraph("Respiratory\nAlkalosis\n(CHRONIC)", S("d", fontSize=8.5, fontName="Helvetica-Bold", textColor=colors.HexColor("#0d47a1"), leading=12)),
        Paragraph("↓ PaCO₂\n↑ pH", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("↓ HCO₃⁻\n(full renal)", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
        Paragraph("ΔHCO₃⁻ = −4 to −5 mEq/L per ↓10 mmHg PaCO₂",
                  S("f", fontSize=8.5, fontName="Helvetica-Bold", textColor=TEAL, leading=13)),
        Paragraph("48–96 h", S("d", fontSize=8.5, fontName="Helvetica", textColor=NAVY, leading=12)),
    ],
]

comp_table = Table(comp_rows,
                   colWidths=[30*mm, 25*mm, 32*mm, 68*mm, 22*mm])
comp_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), NAVY),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [GREY, WHITE, colors.HexColor("#fff0f0"),
                                       colors.HexColor("#ffe8e8"),
                                       colors.HexColor("#e8f0ff"), colors.HexColor("#ddeeff")]),
    ("GRID",          (0,0), (-1,-1), 0.4, MID_GREY),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
    ("TOPPADDING",    (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("ALIGN",         (0,0), (-1,0), "CENTER"),
]))
story.append(comp_table)
story.append(Spacer(1, 7))

# ── ROW 3: MUDPILES + Delta-Delta in two columns ──────────────────────────────
story.append(section_header("  METABOLIC ACIDOSIS CLASSIFICATION & TOOLS", NAVY))
story.append(Spacer(1, 4))

# Left: MUDPILES
mudpiles_letter_style = S("ml", fontSize=16, fontName="Helvetica-Bold",
                          textColor=GOLD, leading=20)
mudpiles_text_style   = S("mt", fontSize=8.5, fontName="Helvetica",
                          textColor=NAVY, leading=13)
mudpiles_bold_style   = S("mb", fontSize=8.5, fontName="Helvetica-Bold",
                          textColor=NAVY, leading=13)

mudpiles_items = [
    ("M", "Methanol"),
    ("U", "Uremia (renal failure)"),
    ("D", "DKA / Diabetic Ketoacidosis\n   (also: alcoholic, starvation)"),
    ("P", "Propylene glycol / Paraldehyde"),
    ("I", "Isoniazid / Iron"),
    ("L", "Lactic Acidosis (sepsis, ischemia,\n   metformin, mitochondrial)"),
    ("E", "Ethylene Glycol"),
    ("S", "Salicylates"),
]

mudpiles_rows = [[Paragraph(l, mudpiles_letter_style), Paragraph(t, mudpiles_text_style)]
                 for l, t in mudpiles_items]
mudpiles_header = [[
    Paragraph("MUDPILES — High Anion Gap Metabolic Acidosis",
              S("mh", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE)),
    ""
]]
mudpiles_data = mudpiles_header + mudpiles_rows
mudpiles_table = Table(mudpiles_data, colWidths=[12*mm, 75*mm])
mudpiles_table.setStyle(TableStyle([
    ("SPAN",          (0,0), (1,0)),
    ("BACKGROUND",    (0,0), (-1,0), RED_BOX),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.HexColor("#fff8e1"), colors.HexColor("#fff3cd")] * 5),
    ("GRID",          (0,0), (-1,-1), 0.4, MID_GREY),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 5),
    ("ALIGN",         (0,1), (0,-1), "CENTER"),
]))

# Right column: Anion Gap + Non-AG + Delta-Delta
right_content_items = []

# Anion Gap formula box
ag_box_data = [[
    Paragraph("Anion Gap Formula", S("agb_h", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE)),
]],[
    Paragraph("AG = [Na⁺] − ([Cl⁻] + [HCO₃⁻])", FORMULA),
    Paragraph("Normal: 8–12 mEq/L  (up to 13 mEq/L)", BODY),
    Paragraph("⚠ Albumin Correction: Add 2.5 mEq/L per\n   1 g/dL albumin below 4 g/dL", BODY),
]]
ag_box = Table([
    [Paragraph("Anion Gap Formula", S("agb_h", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE))],
    [Paragraph("AG = [Na⁺] − ([Cl⁻] + [HCO₃⁻])", FORMULA)],
    [Paragraph("Normal: 8–12 mEq/L  (up to 13 mEq/L)", BODY)],
    [Paragraph("⚠ Albumin correction: +2.5 per 1 g/dL below 4", BODY)],
], colWidths=[W - 87*mm - 6*mm])
ag_box.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), GREEN),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("BACKGROUND",    (0,1), (-1,-1), colors.HexColor("#e8f5e9")),
    ("GRID",          (0,0), (-1,-1), 0.4, MID_GREY),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("RIGHTPADDING",  (0,0), (-1,-1), 6),
]))

# Non-AG causes
nonag_rows = [
    [Paragraph("NON-AG (Hyperchloremic) Acidosis",
               S("nah", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE))],
    [Paragraph("D  Diarrhea (GI HCO₃⁻ loss)", BODY)],
    [Paragraph("R  Renal Tubular Acidosis (RTA I, II, IV)", BODY)],
    [Paragraph("U  Ureteral diversion", BODY)],
    [Paragraph("G  Go easy on saline (0.9% NaCl resuscitation)", BODY)],
    [Paragraph("S  acetazolamide (Carbonic anhydrase inhibitors)", BODY)],
]
nonag_table = Table(nonag_rows, colWidths=[W - 87*mm - 6*mm])
nonag_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), colors.HexColor("#455a64")),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.HexColor("#eceff1"), WHITE] * 5),
    ("GRID",          (0,0), (-1,-1), 0.4, MID_GREY),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("RIGHTPADDING",  (0,0), (-1,-1), 6),
]))

# Delta-Delta
dd_rows = [
    [Paragraph("Delta–Delta Ratio  (High-AG only)",
               S("ddh", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE)), ""],
    [Paragraph("ΔAG / ΔHCO₃⁻  =  (AG−12) / (24−HCO₃⁻)",
               S("ddf", fontSize=9, fontName="Helvetica-Bold", textColor=TEAL)), ""],
    [Paragraph("< 1", S("d1", fontSize=9, fontName="Helvetica-Bold", textColor=ACIDRED)),
     Paragraph("Mixed: High-AG + Normal-AG acidosis", BODY)],
    [Paragraph("1 – 2", S("d2", fontSize=9, fontName="Helvetica-Bold", textColor=GREEN)),
     Paragraph("Pure High-AG metabolic acidosis", BODY)],
    [Paragraph("> 2", S("d3", fontSize=9, fontName="Helvetica-Bold", textColor=ALKBLUE)),
     Paragraph("Mixed: High-AG acidosis + Metabolic alkalosis", BODY)],
]
dd_table = Table(dd_rows, colWidths=[18*mm, W - 87*mm - 6*mm - 18*mm])
dd_table.setStyle(TableStyle([
    ("SPAN",          (0,0), (1,0)),
    ("SPAN",          (0,1), (1,1)),
    ("BACKGROUND",    (0,0), (-1,0), TEAL),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("BACKGROUND",    (0,1), (-1,1), colors.HexColor("#e0f7f7")),
    ("ROWBACKGROUNDS",(0,2), (-1,-1), [colors.HexColor("#fce4ec"),
                                       colors.HexColor("#e8f5e9"),
                                       colors.HexColor("#e3f2fd")]),
    ("GRID",          (0,0), (-1,-1), 0.4, MID_GREY),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
    ("ALIGN",         (0,2), (0,-1), "CENTER"),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("RIGHTPADDING",  (0,0), (-1,-1), 6),
]))

right_stack = Table([
    [ag_box],
    [Spacer(1, 4)],
    [nonag_table],
    [Spacer(1, 4)],
    [dd_table],
], colWidths=[W - 87*mm - 4*mm])
right_stack.setStyle(TableStyle([
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 0),
    ("TOPPADDING",    (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))

mud_row = Table([[mudpiles_table, right_stack]],
                colWidths=[90*mm, W - 90*mm - 2*mm])
mud_row.setStyle(TableStyle([
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 3),
    ("TOPPADDING",    (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(mud_row)
story.append(Spacer(1, 7))

# ── SECTION: Step-by-step approach ────────────────────────────────────────────
story.append(section_header("  STEP-BY-STEP ABG INTERPRETATION", TEAL))
story.append(Spacer(1, 4))

steps = [
    ("1", "Is the patient acidemic or alkalemic?",
     "pH < 7.35 → Acidemia    |    pH > 7.45 → Alkalemia    |    Normal pH does NOT rule out a mixed disorder"),
    ("2", "Identify the PRIMARY disorder",
     "pH↓ + PaCO₂↑ → Resp. Acidosis   |   pH↑ + PaCO₂↓ → Resp. Alkalosis\n"
     "pH↓ + HCO₃⁻↓ → Met. Acidosis   |   pH↑ + HCO₃⁻↑ → Met. Alkalosis"),
    ("3", "Is compensation APPROPRIATE?",
     "Apply formulas above. If values fall outside expected range → Mixed disorder present"),
    ("4", "Calculate Anion Gap (if met. acidosis)",
     "AG = Na⁺ − (Cl⁻ + HCO₃⁻).  Correct for albumin.  If AG elevated → apply Delta–Delta ratio"),
    ("5", "Assess OXYGENATION",
     "P/F ratio = PaO₂/FiO₂  (Normal >400 | Mild ARDS 200–300 | Mod 100–200 | Severe <100)\n"
     "A-a gradient = PAO₂ − PaO₂ (PAO₂ = 150 − PaCO₂/0.8 on room air)  Normal <15 mmHg"),
]

step_rows = []
for num, title, detail in steps:
    step_rows.append([
        Paragraph(num, S("sn", fontSize=14, fontName="Helvetica-Bold",
                         textColor=WHITE, alignment=TA_CENTER)),
        Paragraph(title, S("st", fontSize=9, fontName="Helvetica-Bold", textColor=NAVY)),
        Paragraph(detail, S("sd", fontSize=8, fontName="Helvetica", textColor=NAVY, leading=12)),
    ])

steps_table = Table(step_rows, colWidths=[10*mm, 52*mm, W - 62*mm - 2*mm])
steps_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (0,-1), TEAL),
    ("ROWBACKGROUNDS",(1,0), (-1,-1), [GREY, WHITE] * 5),
    ("GRID",          (0,0), (-1,-1), 0.4, MID_GREY),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
    ("ALIGN",         (0,0), (0,-1), "CENTER"),
    ("TOPPADDING",    (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("RIGHTPADDING",  (0,0), (-1,-1), 6),
    ("LINEBELOW",     (0,0), (-1,-2), 0.5, MID_GREY),
]))
story.append(steps_table)
story.append(Spacer(1, 7))

# ── SECTION: Clinical consequences + worked example in 2 columns ─────────────
story.append(section_header("  PHYSIOLOGIC CONSEQUENCES  &  WORKED EXAMPLE", NAVY))
story.append(Spacer(1, 4))

# Left: consequences tables
acid_rows = [
    [Paragraph("SEVERE ACIDEMIA (pH < 7.2)", S("ah", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE)),
     Paragraph("SEVERE ALKALEMIA (pH > 7.6)", S("alh", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE))],
    [Paragraph("CV: ↓ contractility, ↑ PVR, arrhythmias\n   reduced catecholamine response",
               S("d", fontSize=8, fontName="Helvetica", textColor=NAVY, leading=12)),
     Paragraph("CV: arteriolar constriction, ↓ coronary flow\n   arrhythmias, left-shift O₂ curve",
               S("d", fontSize=8, fontName="Helvetica", textColor=NAVY, leading=12))],
    [Paragraph("Resp: hyperventilation, dyspnea\n   respiratory muscle fatigue",
               S("d", fontSize=8, fontName="Helvetica", textColor=NAVY, leading=12)),
     Paragraph("Resp: hypoventilation",
               S("d", fontSize=8, fontName="Helvetica", textColor=NAVY, leading=12))],
    [Paragraph("Metabolic: insulin resistance, ↓ ATP\n   HYPERKALEMIA, protein catabolism",
               S("d", fontSize=8, fontName="Helvetica-Bold", textColor=ACIDRED, leading=12)),
     Paragraph("Metabolic: HYPOKALEMIA\n   ↓ ionized Ca²⁺, Mg²⁺, phosphate",
               S("d", fontSize=8, fontName="Helvetica-Bold", textColor=ALKBLUE, leading=12))],
    [Paragraph("Cerebral: AMS, coma,\n   inhibited cellular metabolism",
               S("d", fontSize=8, fontName="Helvetica", textColor=NAVY, leading=12)),
     Paragraph("Cerebral: ↓ CBF, tetany, seizures\n   delirium, coma",
               S("d", fontSize=8, fontName="Helvetica", textColor=NAVY, leading=12))],
]
conseq_table = Table(acid_rows, colWidths=[(W*0.52)/2]*2)
conseq_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (0,0), ACIDRED),
    ("BACKGROUND",    (1,0), (1,0), ALKBLUE),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.HexColor("#fce4ec"), colors.HexColor("#fff"),
                                       colors.HexColor("#ffebee"), colors.HexColor("#fff")]),
    ("GRID",          (0,0), (-1,-1), 0.4, MID_GREY),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 5),
]))

# Right: Worked example - Salicylate toxicity
example_content = [
    Paragraph("Worked Example: Salicylate Toxicity",
              S("ex_h", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE)),
]
eg_box_data = [
    [Paragraph("Worked Example: Salicylate Toxicity",
               S("ex_h", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE))],
    [Paragraph("ABG:  pH 7.47  /  PaCO₂ 25 mmHg  /  PaO₂ 180 mmHg",
               S("eg", fontSize=8.5, fontName="Helvetica-Bold", textColor=NAVY))],
    [Paragraph("Step 1: pH 7.47 → Alkalemia", BODY)],
    [Paragraph("Step 2: PaCO₂ low (25) + pH high → Respiratory alkalosis", BODY)],
    [Paragraph("Step 3: Expected pH = 7.40 + [(40−25)/10 × 0.08] = 7.52\n"
               "Measured 7.47 < predicted 7.52 → concurrent Metabolic acidosis",
               S("eg3", fontSize=8.5, fontName="Helvetica-Bold", textColor=RED_BOX, leading=13))],
    [Paragraph("✓ Diagnosis: Mixed Respiratory Alkalosis + Metabolic Acidosis",
               S("eg4", fontSize=9, fontName="Helvetica-Bold", textColor=GREEN))],
    [Spacer(1, 3)],
    [Paragraph("K⁺ – pH Relationship",
               S("kph_h", fontSize=9, fontName="Helvetica-Bold", textColor=TEAL))],
    [Paragraph("Each ↓0.10 pH unit → K⁺ rises ~0.6 mEq/L\n"
               "Metabolic acidosis → Hyperkalemia (exception: DKA, lactic acidosis)\n"
               "Metabolic alkalosis → Hypokalemia", BODY)],
]
eg_box = Table(eg_box_data, colWidths=[W - (W*0.52) - 4*mm])
eg_box.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), GOLD),
    ("TEXTCOLOR",     (0,0), (-1,0), NAVY),
    ("BACKGROUND",    (0,1), (-1,-1), colors.HexColor("#fffde7")),
    ("GRID",          (0,0), (-1,-1), 0.4, MID_GREY),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("RIGHTPADDING",  (0,0), (-1,-1), 6),
]))

conseq_row = Table([[conseq_table, eg_box]],
                   colWidths=[W*0.52, W - W*0.52 - 2*mm])
conseq_row.setStyle(TableStyle([
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 3),
    ("TOPPADDING",    (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(conseq_row)
story.append(Spacer(1, 7))

# ── FOOTER ────────────────────────────────────────────────────────────────────
story.append(hr())
story.append(Paragraph(
    "Sources: Barash Clinical Anesthesia 9e · Brenner & Rector's The Kidney · Rosen's Emergency Medicine · "
    "Sanagustín & Osredkar, Med Int 2026 [PMID 41473681] · Habib et al., S Afr Fam Pract 2025 [PMID 40336441]",
    SMALL))
story.append(Spacer(1, 2))
story.append(Paragraph("Generated by Orris Medical AI · For educational use only · Always verify against current clinical guidelines",
                        FOOTER_STYLE))

# ── BUILD ──────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF written to {OUTPUT}")
Running Command

cd /home/daytona/workspace/abg-reference && python generate_abg_pdf.py 2>&1

Reading File
I see the issue - there's a leftover unused variable assignment with a syntax error. Let me fix it.
Editing File

~/abg-reference/generate_abg_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/abg-reference/generate_abg_pdf.py'
Running Command

cd /home/daytona/workspace/abg-reference && python generate_abg_pdf.py 2>&1

PDF generated successfully. Here it is:

ABG Quick Reference

PDF Document · PDF


The single-page A4 PDF includes:
Normal Values - all 6 parameters with reference ranges
Henderson-Hasselbalch - the core equation + pH rules (acidemia/alkalemia thresholds)
Compensation Formulas table - all 6 disorders (metabolic acidosis/alkalosis, respiratory acidosis acute/chronic, respiratory alkalosis acute/chronic) with formulas, direction of compensation, and time to onset
MUDPILES mnemonic - colour-coded letter-by-letter with full cause names
Non-AG Acidosis causes - diarrhea, RTA, ureteral diversion, saline, acetazolamide
Anion Gap formula + albumin correction rule
Delta-Delta ratio - with the 3 interpretation ranges colour-coded (red/green/blue)
5-Step ABG interpretation algorithm
Physiologic consequences of severe acidemia vs alkalemia side-by-side
Worked example - the classic salicylate toxicity mixed disorder walk-through
K+ - pH relationship quick reference
This is a shared conversation. Sign in to Orris to start your own chat.