Why mannitol is contraindicated in acute pulmonary edema

Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
I now have comprehensive, textbook-confirmed information. Here is the full answer:

Why Mannitol is Contraindicated in Acute Pulmonary Edema

The contraindication arises from mannitol's mechanism of action, specifically its biphasic fluid-shifting effect before diuresis occurs.

1. The Core Problem: Transient Intravascular Volume Expansion

Mannitol is a hypertonic, osmotically active agent. When administered IV, it cannot enter cells and stays in the extracellular space. Before any diuresis occurs, it creates a powerful osmotic gradient that pulls water out of cells and into the intravascular compartment.
"Mannitol is rapidly distributed in the extracellular compartment and extracts water from cells. Prior to the diuresis, this leads to expansion of the extracellular volume... This effect can complicate heart failure and may produce florid pulmonary edema."
  • Katzung's Basic and Clinical Pharmacology, 16th Ed.
"Because mannitol expands the ECFV [extracellular fluid volume] en route to its diuretic site of action, it may precipitate pulmonary edema in HF patients and must be used cautiously in this circumstance, if at all."
  • NKF Primer on Kidney Diseases, 8th Ed.

2. Mechanism Step-by-Step

StepWhat HappensEffect
1. Mannitol given IVStays in extracellular compartment (not reabsorbed)Raises plasma osmolality
2. Osmotic gradient createdWater shifts from intracellular to extracellular spaceAcutely expands intravascular volume
3. Increased hydrostatic pressureFluid is pushed into pulmonary capillariesWorsens pulmonary edema
4. Diuresis (delayed)Eventually excreted via kidneys, with waterComes too late if cardiac/renal reserve is limited
The problem is the timing gap - the volume expansion happens immediately, but the diuretic effect is delayed (onset 30-60 minutes). In a patient already drowning in fluid, this initial surge of intravascular volume is dangerous.

3. Additional Compounding Factors

  • Hemodilution / Hyponatremia: The rapid influx of water into plasma dilutes sodium, causing transient hyponatremia. This can further impair cardiac function.
  • Limited cardiac reserve: In acute pulmonary edema, the heart is already failing to handle its preload. Any additional increase in venous return will directly worsen pulmonary congestion.
  • Renal compromise: In anuric/severely oliguric patients (common in cardiogenic edema), mannitol cannot be excreted and accumulates, perpetuating the osmotic volume load indefinitely.
"A rapid intracellular-to-extracellular shift of water can transiently increase intravascular volume and precipitate cardiac decompensation and pulmonary edema in patients with limited cardiac reserve."
  • Morgan & Mikhail's Clinical Anesthesiology, 7th Ed.

4. What to Use Instead

In acute pulmonary edema, the correct diuretic class is loop diuretics (e.g., furosemide/lasix), which:
  • Reduce preload rapidly via venodilation (within minutes, before diuresis)
  • Promote net fluid removal from the intravascular space
  • Do not expand volume before working

Summary

Mannitol is contraindicated in acute pulmonary edema because its osmotic mechanism causes an acute, transient expansion of intravascular volume by drawing water out of cells before any diuresis can occur. In a patient with pulmonary edema - where the lungs are already flooded due to elevated capillary hydrostatic pressure - this added fluid load dramatically worsens the condition and can be life-threatening.

Can you simplify asthma from fishman and gina 2026

Reading File
Finding Sources
Finding Sources
Searching the Web

GINA 2026 asthma guidelines key updates summary

Finding Sources
Reading Web Page

https://www.pulmonologyadvisor.com/features/asthma-gina-2026…

Reading File
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Finding Sources
Reading File
Reading File
Reading File
Loading Image
Here is a simplified but complete breakdown of asthma from Fishman's Pulmonary Diseases and Disorders combined with GINA 2026:

Asthma - Simplified

Sources: Fishman's Pulmonary Diseases and Disorders + GINA 2026 Strategy Report

1. What Is Asthma?

GINA 2026 definition:
Asthma is a heterogeneous disease, usually characterized by chronic airway inflammation. It is defined by a history of respiratory symptoms - wheeze, shortness of breath, chest tightness, and cough - that vary over time and in intensity, together with variable expiratory airflow limitation.
Three core features (Fishman's):
  1. Bronchoconstriction - airway smooth muscle contracts
  2. Airway hyperresponsiveness (AHR) - airways over-react to triggers
  3. Chronic airway inflammation - the underlying driver of everything else

2. Pathophysiology (The "Why")

Two Main Inflammatory Pathways

Inflammatory pathways in asthma - Fishman's Pulmonary Diseases and Disorders
PathwayDriverKey CellsResult
T2 (Type 2) - 65-80% of patientsAllergens, alarminsTh2, ILC2, eosinophils, mast cellsEosinophilic inflammation, IgE production
Non-T2Smoke, pollutants, infectionsTh1, Th17 cellsNeutrophilic inflammation

The Allergic (T2) Cascade - Step by Step

  1. Allergen enters airway - trapped in mucus, endocytosed by dendritic cells
  2. Dendritic cells activate naive T cells - polarize toward Th2
  3. Th2 cells release cytokines: IL-4, IL-5, IL-13
    • IL-4 and IL-13 - drive IgE production by B cells
    • IL-5 - recruits and activates eosinophils
  4. IgE binds to mast cells - on re-exposure to allergen, mast cells degranulate
  5. Mast cells release histamine, prostaglandins, leukotrienes - causing bronchoconstriction, mucus, vascular leak
  6. Eosinophils cause further airway damage and inflammation

Alarmins (Innate Pathway - Important in GINA 2026)

The bronchial epithelium releases alarm signals in response to injury:
  • TSLP (target of tezepelumab)
  • IL-33 (target of itepekimab)
  • IL-25
These activate ILC2 cells, linking innate and adaptive responses.

Airway Remodeling (Chronic Disease)

With repeated injury, structural changes occur:
  • Basement membrane thickening
  • Goblet cell metaplasia (excess mucus)
  • Smooth muscle hypertrophy/hyperplasia
  • Submucosal fibrosis
  • Irreversible airflow obstruction in severe chronic cases

3. Phenotypes (GINA 2026)

PhenotypeFeaturesTreatment Implication
Allergic asthmaChildhood onset, family/personal atopy, responds to ICSMost common
Non-allergic asthmaNo atopy, neutrophilic/paucigranulocyticLess ICS-responsive
Late-onset eosinophilicAdult women, high blood eosinophilsBiologic-responsive
Exercise-inducedTriggered by exertionPre-treatment with SABA
Aspirin/NSAID-sensitiveNasal polyps, chronic sinusitisAvoid NSAIDs
Obesity-associatedNon-eosinophilic, mechanically drivenWeight loss helps

4. Diagnosis

Symptoms to look for:

  • Wheeze (high-pitched expiratory)
  • Episodic breathlessness
  • Chest tightness
  • Cough (especially at night / early morning)
  • Symptoms vary - worse at night, with exercise, allergen exposure, infections

Spirometry (Key test):

  • Obstructive pattern: FEV1/FVC < 0.7 (or below lower limit of normal)
  • Reversibility: FEV1 increases ≥12% and ≥200 mL after bronchodilator = confirms asthma
  • Variability: Peak flow variation >10% on multiple days also supports diagnosis

Supportive Tests (when spirometry is normal):

  • FeNO (fractional exhaled nitric oxide) - elevated in T2 eosinophilic asthma
  • Blood eosinophils - elevated supports T2 asthma
  • Methacholine challenge (PC20) - confirms airway hyperresponsiveness

Asthma Control Assessment (GINA 2026):

LevelDaytime symptomsNight wakingReliever useActivity limitation
Controlled≤2x/weekNone≤2x/weekNone
Partly controlled>2x/weekAny>2x/weekAny
Uncontrolled3+ features of partly controlled
New GINA 2026 tools: CAAT (Chronic Airways Assessment Test), Peds-AIRQ (pediatric), PRAM (acute pediatric exacerbations)

5. Treatment - The Stepwise Approach

GINA/Fishman's principle: treat to achieve control, then step down. The goal is minimal or no symptoms with the lowest effective treatment.

Adults and Adolescents

StepPreferred ControllerPreferred RelieverNotes
Step 1 (mild intermittent)Low-dose ICS-formoterol as neededICS-formoterol (not just SABA alone)GINA 2026 pushes anti-inflammatory even at Step 1
Step 2 (mild persistent)Low-dose ICS dailyICS-formoterol or SABALTRA as alternative
Step 3 (moderate)Low-dose ICS-LABAICS-formoterolSMART strategy begins here
Step 4 (uncontrolled on Step 3)Medium-dose ICS-LABAICS-formoterolAdd LAMA (tiotropium)
Step 5 (severe)High-dose ICS-LABA + specialist reviewICS-formoterolAdd biologics; minimize OCS

Key GINA 2026 Changes:

  • SABA monotherapy is out at Step 1 - replace with ICS-formoterol as reliever
  • ICS-formoterol (SMART) is the preferred strategy at Steps 3-5 (one inhaler for both controller and reliever)
  • OCS minimization - optimize ICS, treat modifiable risk factors before using oral steroids
  • Oxygen target in acute asthma: SpO2 92-95% (not 100%) - updated threshold

6. Drug Classes - Quick Summary

Bronchodilators

  • SABA (salbutamol/albuterol, terbutaline) - rapid relief, short-acting. Overuse = poor control indicator
  • LABA (formoterol, salmeterol) - long-acting, must always be combined with ICS, never monotherapy
  • LAMA (tiotropium) - add-on at Step 4; reduces exacerbations

Controllers

  • ICS (budesonide, beclomethasone, fluticasone) - cornerstone of treatment, reduces airway inflammation
  • LTRA (montelukast) - alternative/add-on, less effective than ICS
  • Theophylline - rarely used, narrow therapeutic index

Biologics (Step 5 - Severe Asthma)

DrugTargetFor
OmalizumabIgEAllergic asthma
Mepolizumab, ReslizumabIL-5Eosinophilic asthma
BenralizumabIL-5 receptorEosinophilic asthma
DupilumabIL-4Rα (blocks IL-4 and IL-13)Eosinophilic / type 2
TezepelumabTSLPBroad (all phenotypes)
Depemokimab (new 2026)IL-5 (ultra-long acting)Eosinophilic asthma

7. Acute Exacerbations (GINA 2026 Updated Flowcharts)

Severity Classification:

SeveritySpO2RRSpeechWheeze
Mild≥94%Normal/mild increaseFull sentencesMild
Moderate90-93%IncreasedPhrasesModerate
Severe/Life-threatening<92%>30/minWords or unableSilent chest

Treatment:

  • Mild: Salbutamol 4 puffs (pMDI + spacer) OR budesonide-formoterol 2 puffs
  • Moderate-Severe: Salbutamol 6-10 puffs repeated every 20-30 min + ipratropium 4 puffs (up to 3 doses) + systemic corticosteroids + controlled O2 (target 92-95%)
  • Anaphylaxis + asthma: Give epinephrine first, then salbutamol
  • Life-threatening: Transfer to acute care, IV magnesium sulfate, consider intubation

8. Red Flags for Fatal Asthma (GINA 2026)

  • Previous near-fatal attack (intubated, ICU admission)
  • Hospitalization or ER visit in past year
  • Currently not on ICS, or poor adherence
  • Overuse of SABA (>1 canister/month)
  • Psychosocial problems or low socioeconomic status
  • Food allergy with asthma
  • Smoking

One-Line Summary

Asthma = chronic variable airway inflammation + bronchoconstriction + hyperresponsiveness, driven mainly by T2 cytokines (IL-4, IL-5, IL-13). GINA 2026 moves toward anti-inflammatory reliever therapy (ICS-formoterol) at all steps, discourages SABA-only use, and expands biologic options for severe disease with a new SpO2 target of 92-95% in acute attacks.

Create a PDF cheat sheet of GINA 2026 asthma stepwise treatment

Reading File
Running Command

ls /home/daytona/workspace/ 2>/dev/null && echo "---" && python3 -c "import repo…

Running Command

mkdir -p /home/daytona/workspace/gina2026-cheatsheet

Writing File

~/gina2026-cheatsheet/generate_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
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate

OUTPUT = "/home/daytona/workspace/gina2026-cheatsheet/GINA_2026_Asthma_Stepwise_Cheatsheet.pdf"

# ── Colour palette ──────────────────────────────────────────────────────────
BLUE_DARK   = colors.HexColor("#1a3a5c")
BLUE_MID    = colors.HexColor("#2563a8")
BLUE_LIGHT  = colors.HexColor("#dbeafe")
TEAL        = colors.HexColor("#0d9488")
TEAL_LIGHT  = colors.HexColor("#ccfbf1")
ORANGE      = colors.HexColor("#d97706")
ORANGE_LIGHT= colors.HexColor("#fef3c7")
RED         = colors.HexColor("#dc2626")
RED_LIGHT   = colors.HexColor("#fee2e2")
GREEN       = colors.HexColor("#16a34a")
GREEN_LIGHT = colors.HexColor("#dcfce7")
PURPLE      = colors.HexColor("#7c3aed")
PURPLE_LIGHT= colors.HexColor("#ede9fe")
GREY_LIGHT  = colors.HexColor("#f1f5f9")
GREY_MED    = colors.HexColor("#94a3b8")
WHITE       = colors.white
BLACK       = colors.HexColor("#0f172a")

W, H = A4   # 595.27 x 841.89 pt

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

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

title_style = S("Title2",
    fontName="Helvetica-Bold", fontSize=18, textColor=WHITE,
    alignment=TA_CENTER, leading=22)
subtitle_style = S("Sub2",
    fontName="Helvetica", fontSize=9, textColor=colors.HexColor("#bfdbfe"),
    alignment=TA_CENTER, leading=12)
section_header = S("SecHdr",
    fontName="Helvetica-Bold", fontSize=10, textColor=WHITE,
    alignment=TA_CENTER, leading=13, spaceAfter=2)
body = S("Body2",
    fontName="Helvetica", fontSize=8, textColor=BLACK,
    leading=11, spaceAfter=1)
body_bold = S("BodyB",
    fontName="Helvetica-Bold", fontSize=8, textColor=BLACK,
    leading=11, spaceAfter=1)
small = S("Small",
    fontName="Helvetica", fontSize=7, textColor=colors.HexColor("#475569"),
    leading=10, spaceAfter=1)
small_bold = S("SmallB",
    fontName="Helvetica-Bold", fontSize=7.5, textColor=BLACK,
    leading=10)
step_label = S("StepLbl",
    fontName="Helvetica-Bold", fontSize=9, textColor=WHITE,
    alignment=TA_CENTER, leading=12)
cell_body = S("CellB",
    fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=10)
cell_bold = S("CellBold",
    fontName="Helvetica-Bold", fontSize=7.5, textColor=BLACK, leading=10)
cell_small = S("CellSm",
    fontName="Helvetica", fontSize=7, textColor=colors.HexColor("#334155"), leading=9)
note_style = S("Note",
    fontName="Helvetica-Oblique", fontSize=7.5, textColor=colors.HexColor("#475569"),
    leading=10)
warn_style = S("Warn",
    fontName="Helvetica-Bold", fontSize=7.5, textColor=RED,
    leading=10)
green_style = S("Grn",
    fontName="Helvetica-Bold", fontSize=7.5, textColor=GREEN,
    leading=10)

# ── Helpers ─────────────────────────────────────────────────────────────────
def colored_header(text, bg, fg=WHITE, height=16):
    """Single-cell table used as a coloured section header bar."""
    t = Table([[Paragraph(text, S("h_"+text[:6],
                fontName="Helvetica-Bold", fontSize=9.5, textColor=fg,
                alignment=TA_CENTER, leading=12))]],
              colWidths=[W - 28*mm])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 4),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
        ("RIGHTPADDING",  (0,0), (-1,-1), 8),
        ("ROUNDEDCORNERS", [4]),
    ]))
    return t

def page_bg(canvas, doc):
    """Draw header banner and footer on every page."""
    canvas.saveState()
    # header band
    canvas.setFillColor(BLUE_DARK)
    canvas.rect(0, H - 38*mm, W, 38*mm, fill=1, stroke=0)
    # thin accent line under header
    canvas.setFillColor(TEAL)
    canvas.rect(0, H - 38.8*mm, W, 1.5, fill=1, stroke=0)
    # title
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica-Bold", 20)
    canvas.drawCentredString(W/2, H - 16*mm, "GINA 2026 — Asthma Stepwise Treatment")
    canvas.setFont("Helvetica", 9)
    canvas.setFillColor(colors.HexColor("#93c5fd"))
    canvas.drawCentredString(W/2, H - 24*mm,
        "Global Initiative for Asthma  ·  2026 Strategy Report  ·  Quick Reference")
    canvas.setFont("Helvetica", 8)
    canvas.setFillColor(colors.HexColor("#bfdbfe"))
    canvas.drawCentredString(W/2, H - 30*mm,
        "Adults & Adolescents (≥12 yrs)   |   Anti-inflammatory first approach")
    # footer
    canvas.setFillColor(BLUE_DARK)
    canvas.rect(0, 0, W, 12*mm, fill=1, stroke=0)
    canvas.setFillColor(GREY_MED)
    canvas.setFont("Helvetica", 7)
    canvas.drawCentredString(W/2, 4*mm,
        "Reference: GINA 2026 Strategy Report  ·  ginasthma.org  ·  For educational use only")
    canvas.restoreState()

# ── Document setup ───────────────────────────────────────────────────────────
doc = BaseDocTemplate(OUTPUT, pagesize=A4,
    leftMargin=14*mm, rightMargin=14*mm,
    topMargin=42*mm, bottomMargin=15*mm)
frame = Frame(doc.leftMargin, doc.bottomMargin,
              doc.width, doc.height, id="main")
doc.addPageTemplates([PageTemplate(id="main", frames=[frame], onPage=page_bg)])

story = []
COL = doc.width   # usable width

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# SECTION 1: KEY GINA 2026 PRINCIPLES (info boxes)
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
story.append(colored_header("▸  KEY GINA 2026 PRINCIPLES", BLUE_MID))
story.append(Spacer(1, 3))

principles = [
    ("🚫", "No SABA monotherapy", "ICS-formoterol is now the preferred reliever at ALL steps. SABA alone is no longer recommended as first-line reliever."),
    ("✅", "Anti-inflammatory first", "Every patient with asthma should receive ICS-containing therapy. Inflammation, not just bronchospasm, must be treated."),
    ("🔄", "SMART strategy", "Single Maintenance And Reliever Therapy (ICS-formoterol) at Steps 3-5: one inhaler for both daily control AND rescue."),
    ("🎯", "Treat to control", "Assess control every 1-3 months. Step UP if uncontrolled; Step DOWN if well-controlled for ≥3 months."),
    ("💊", "Minimize OCS", "Optimize ICS, treat triggers, use add-ons and biologics to avoid oral corticosteroids."),
    ("🩺", "SpO₂ target 92-95%", "New 2026 update: target O₂ saturation 92-95% in acute exacerbations (not 100%)."),
]

pcols = COL / 3
p_data = []
row = []
for i, (icon, title, detail) in enumerate(principles):
    cell_content = [
        Paragraph(f"<b>{icon} {title}</b>", S("pi_t", fontName="Helvetica-Bold",
                  fontSize=8, textColor=BLUE_DARK, leading=11)),
        Paragraph(detail, S("pi_d", fontName="Helvetica", fontSize=7,
                  textColor=BLACK, leading=10))
    ]
    row.append(cell_content)
    if len(row) == 3:
        p_data.append(row)
        row = []
if row:
    while len(row) < 3:
        row.append([""])
    p_data.append(row)

ptable = Table(p_data, colWidths=[pcols]*3, rowHeights=None)
ptable.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,-1), BLUE_LIGHT),
    ("BACKGROUND",    (0,1), (-1,1), colors.HexColor("#e0f2fe")),
    ("TOPPADDING",    (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("RIGHTPADDING",  (0,0), (-1,-1), 6),
    ("GRID",          (0,0), (-1,-1), 0.5, WHITE),
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ("ROUNDEDCORNERS", [3]),
]))
story.append(ptable)
story.append(Spacer(1, 6))

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# SECTION 2: STEPWISE TREATMENT TABLE
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
story.append(colored_header("▸  STEPWISE TREATMENT  —  Adults & Adolescents (≥12 years)", TEAL))
story.append(Spacer(1, 3))

# Step colours
step_colors = [
    colors.HexColor("#16a34a"),   # step 1 - green
    colors.HexColor("#2563a8"),   # step 2 - blue
    colors.HexColor("#d97706"),   # step 3 - amber
    colors.HexColor("#dc6f07"),   # step 4 - deep orange
    colors.HexColor("#dc2626"),   # step 5 - red
]

step_data = [
    # (step#, label, severity, controller, reliever, add-ons, notes)
    (
        "STEP 1",
        "Intermittent",
        "Low-dose ICS-formoterol\nas needed (preferred)\nOR low-dose ICS taken\nwhenever SABA taken",
        "Low-dose ICS-formoterol\n(as needed)\n[e.g. budesonide/formoterol\n100/6 mcg]",
        "—",
        "• No daily controller needed if truly intermittent\n• If using SABA ≥2×/week → Step up\n• Consider daily low-dose ICS if frequent symptoms",
    ),
    (
        "STEP 2",
        "Mild\nPersistent",
        "Low-dose ICS daily\n(preferred)\nOR LTRA daily",
        "ICS-formoterol\n(as needed)\nOR SABA",
        "LTRA (alternative\nto ICS if ICS refused\nor not tolerated)",
        "• Low-dose ICS is the cornerstone\n• ICS+SABA combo inhaler is an alternative\n• Review adherence and inhaler technique",
    ),
    (
        "STEP 3",
        "Moderate\n(uncontrolled\non Step 2)",
        "Low-dose ICS-LABA\ndaily (preferred)\n[SMART therapy preferred]",
        "ICS-formoterol\n(SMART reliever)\n[same inhaler as controller]",
        "LAMA (tiotropium)\nas add-on\nLTRA as add-on",
        "• SMART = one inhaler for maintenance + relief\n• Preferred: budesonide/formoterol or BDP/formoterol\n• Assess FeNO / eosinophils to guide therapy",
    ),
    (
        "STEP 4",
        "Moderate-Severe\n(uncontrolled\non Step 3)",
        "Medium-dose ICS-LABA\ndaily\n[+ consider LAMA]",
        "ICS-formoterol\n(SMART reliever)",
        "LAMA (tiotropium)\nLTRA\nHigh-dose ICS",
        "• Refer to specialist for assessment\n• Check for type 2 biomarkers (eosinophils, FeNO)\n• Rule out: poor adherence, wrong diagnosis, triggers",
    ),
    (
        "STEP 5",
        "Severe\n(uncontrolled\non Step 4)",
        "High-dose ICS-LABA\n+ specialist-directed\nbiologic therapy",
        "ICS-formoterol\n(SMART reliever)\nOR SABA",
        "Biologics (see below)\nLAMA\nLTRA\nMinimize OCS",
        "• Mandatory specialist referral\n• Phenotype-guided biologic selection\n• Add-on tiotropium if not already used\n• OCS only as last resort / short course",
    ),
]

# Header row
col_widths = [COL*0.085, COL*0.10, COL*0.22, COL*0.20, COL*0.13, COL*0.265]

def mp(txt, sty):
    lines = txt.strip().split("\n")
    return [Paragraph(l, sty) for l in lines if l.strip()]

hdr_row = [
    Paragraph("STEP", S("sh", fontName="Helvetica-Bold", fontSize=8, textColor=WHITE,
              alignment=TA_CENTER, leading=11)),
    Paragraph("SEVERITY", S("sh2", fontName="Helvetica-Bold", fontSize=8, textColor=WHITE,
              alignment=TA_CENTER, leading=11)),
    Paragraph("PREFERRED CONTROLLER", S("sh3", fontName="Helvetica-Bold", fontSize=8,
              textColor=WHITE, alignment=TA_CENTER, leading=11)),
    Paragraph("PREFERRED RELIEVER", S("sh4", fontName="Helvetica-Bold", fontSize=8,
              textColor=WHITE, alignment=TA_CENTER, leading=11)),
    Paragraph("ADD-ON OPTIONS", S("sh5", fontName="Helvetica-Bold", fontSize=8,
              textColor=WHITE, alignment=TA_CENTER, leading=11)),
    Paragraph("CLINICAL NOTES", S("sh6", fontName="Helvetica-Bold", fontSize=8,
              textColor=WHITE, alignment=TA_CENTER, leading=11)),
]

rows = [hdr_row]
for idx, (step, sev, ctrl, rel, addon, notes) in enumerate(step_data):
    col = step_colors[idx]
    s_cell = Paragraph(step, S("sc"+str(idx), fontName="Helvetica-Bold", fontSize=9,
                       textColor=WHITE, alignment=TA_CENTER, leading=12))
    sev_cell  = mp(sev,   S("sv", fontName="Helvetica-Bold", fontSize=7.5, textColor=col, leading=10))
    ctrl_cell = mp(ctrl,  S("ct", fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=10))
    rel_cell  = mp(rel,   S("rl", fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=10))
    add_cell  = mp(addon, S("ad", fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=10))
    note_cell = mp(notes, S("nt", fontName="Helvetica", fontSize=7.5, textColor=colors.HexColor("#1e293b"), leading=10))
    rows.append([s_cell, sev_cell, ctrl_cell, rel_cell, add_cell, note_cell])

step_table = Table(rows, colWidths=col_widths, repeatRows=1)

ts = TableStyle([
    # Header
    ("BACKGROUND",    (0,0), (-1,0), BLUE_DARK),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("TOPPADDING",    (0,0), (-1,0), 5),
    ("BOTTOMPADDING", (0,0), (-1,0), 5),
    # Step number cells
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
    ("ALIGN",         (0,0), (0,-1),  "CENTER"),
    ("TOPPADDING",    (0,1), (-1,-1), 5),
    ("BOTTOMPADDING", (0,1), (-1,-1), 5),
    ("LEFTPADDING",   (0,0), (-1,-1), 4),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#cbd5e1")),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [GREY_LIGHT, WHITE]),
    ("VALIGN",        (0,1), (-1,-1), "TOP"),
])
# Color the step number column per step
for i, col in enumerate(step_colors):
    ts.add("BACKGROUND", (0, i+1), (0, i+1), col)

step_table.setStyle(ts)
story.append(step_table)
story.append(Spacer(1, 6))

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# SECTION 3: BIOLOGICS + CONTROL ASSESSMENT  (two columns)
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
half = COL / 2 - 2*mm

# -- Biologics table --
bio_hdr_style = S("bhs", fontName="Helvetica-Bold", fontSize=8, textColor=WHITE,
                  alignment=TA_CENTER, leading=11)
bio_cell_style = S("bcs", fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=10)
bio_bold_style = S("bbs", fontName="Helvetica-Bold", fontSize=7.5, textColor=PURPLE, leading=10)

bio_rows = [
    [Paragraph("BIOLOGIC", bio_hdr_style),
     Paragraph("TARGET", bio_hdr_style),
     Paragraph("PHENOTYPE", bio_hdr_style)],
    [Paragraph("Omalizumab", bio_bold_style),     Paragraph("IgE", bio_cell_style),          Paragraph("Allergic (T2)", bio_cell_style)],
    [Paragraph("Mepolizumab", bio_bold_style),    Paragraph("IL-5", bio_cell_style),         Paragraph("Eosinophilic", bio_cell_style)],
    [Paragraph("Reslizumab", bio_bold_style),     Paragraph("IL-5", bio_cell_style),         Paragraph("Eosinophilic", bio_cell_style)],
    [Paragraph("Benralizumab", bio_bold_style),   Paragraph("IL-5R", bio_cell_style),        Paragraph("Eosinophilic", bio_cell_style)],
    [Paragraph("Dupilumab", bio_bold_style),      Paragraph("IL-4Rα", bio_cell_style),       Paragraph("T2 (IL-4/IL-13)", bio_cell_style)],
    [Paragraph("Tezepelumab", bio_bold_style),    Paragraph("TSLP", bio_cell_style),         Paragraph("Broad / all phenotypes", bio_cell_style)],
    [Paragraph("Depemokimab ★NEW", bio_bold_style), Paragraph("IL-5", bio_cell_style),      Paragraph("Eosinophilic (ultra-LA)", bio_cell_style)],
]
bio_table = Table(bio_rows, colWidths=[half*0.38, half*0.25, half*0.37])
bio_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), PURPLE),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [PURPLE_LIGHT, WHITE]),
    ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#c4b5fd")),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 4),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
]))

# -- Control assessment table --
ctrl_hdr_s = S("chs", fontName="Helvetica-Bold", fontSize=8, textColor=WHITE,
               alignment=TA_CENTER, leading=11)
ctrl_cell_s = S("ccs", fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=10)

def ctrl_label(text, c):
    return Paragraph(f"<b>{text}</b>", S("cl_"+text[:3], fontName="Helvetica-Bold",
                     fontSize=7.5, textColor=c, alignment=TA_CENTER, leading=10))

ctrl_rows = [
    [Paragraph("CRITERION\n(last 4 weeks)", ctrl_hdr_s),
     ctrl_label("CONTROLLED", GREEN),
     ctrl_label("PARTLY\nCONTROLLED", ORANGE),
     ctrl_label("UNCONTROLLED", RED)],
    [Paragraph("Daytime symptoms", ctrl_cell_s),
     Paragraph("≤2×/week", ctrl_cell_s),
     Paragraph(">2×/week", ctrl_cell_s),
     Paragraph("3-4 features\nof 'partly\ncontrolled'", S("uc", fontName="Helvetica", fontSize=7.5,
               textColor=BLACK, leading=10))],
    [Paragraph("Night waking", ctrl_cell_s),
     Paragraph("None", ctrl_cell_s),
     Paragraph("Any", ctrl_cell_s),
     Paragraph("", ctrl_cell_s)],
    [Paragraph("Reliever use", ctrl_cell_s),
     Paragraph("≤2×/week", ctrl_cell_s),
     Paragraph(">2×/week", ctrl_cell_s),
     Paragraph("", ctrl_cell_s)],
    [Paragraph("Activity limitation", ctrl_cell_s),
     Paragraph("None", ctrl_cell_s),
     Paragraph("Any", ctrl_cell_s),
     Paragraph("", ctrl_cell_s)],
    [Paragraph("ACTION", S("act", fontName="Helvetica-Bold", fontSize=7.5, textColor=BLACK, leading=10)),
     Paragraph("Maintain /\nStep down", S("act_g", fontName="Helvetica-Bold", fontSize=7.5,
               textColor=GREEN, leading=10)),
     Paragraph("Consider\nStep up", S("act_o", fontName="Helvetica-Bold", fontSize=7.5,
               textColor=ORANGE, leading=10)),
     Paragraph("Step UP", S("act_r", fontName="Helvetica-Bold", fontSize=7.5,
               textColor=RED, leading=10))],
]

ctrl_table = Table(ctrl_rows, colWidths=[half*0.36, half*0.21, half*0.21, half*0.22])
ctrl_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), TEAL),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("BACKGROUND",    (0,5), (-1,5), GREY_LIGHT),
    ("ROWBACKGROUNDS",(0,1), (-1,4), [TEAL_LIGHT, WHITE]),
    ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#99f6e4")),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 4),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
    ("SPAN",          (3,1), (3,4)),
    ("ALIGN",         (1,0), (-1,-1), "CENTER"),
]))

def section_label(text, bg):
    t = Table([[Paragraph(f"<b>{text}</b>", S("slb_"+text[:4],
               fontName="Helvetica-Bold", fontSize=8.5, textColor=WHITE,
               alignment=TA_CENTER, leading=12))]],
             colWidths=[half])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ]))
    return t

bio_section = [
    [section_label("▸  STEP 5 BIOLOGICS  (Severe Asthma)", PURPLE),
     section_label("▸  ASTHMA CONTROL ASSESSMENT  (GINA 2026)", TEAL)],
    [bio_table, ctrl_table],
]
two_col = Table(bio_section, colWidths=[half + 2*mm, half + 2*mm])
two_col.setStyle(TableStyle([
    ("VALIGN",  (0,0), (-1,-1), "TOP"),
    ("TOPPADDING",    (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
]))
story.append(two_col)
story.append(Spacer(1, 6))

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# SECTION 4: ACUTE EXACERBATION MANAGEMENT + RED FLAGS  (two columns)
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

# -- Acute Exacerbation --
ae_hdr = S("ae_h", fontName="Helvetica-Bold", fontSize=8, textColor=WHITE,
           alignment=TA_CENTER, leading=11)
ae_cell = S("ae_c", fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=10)
ae_bold = S("ae_b", fontName="Helvetica-Bold", fontSize=7.5, textColor=BLACK, leading=10)

ae_rows = [
    [Paragraph("SEVERITY", ae_hdr),
     Paragraph("KEY FEATURES", ae_hdr),
     Paragraph("TREATMENT", ae_hdr)],
    [Paragraph("MILD", S("mild_l", fontName="Helvetica-Bold", fontSize=8, textColor=GREEN,
               alignment=TA_CENTER, leading=11)),
     Paragraph("SpO₂ ≥94%  |  Normal-mild ↑RR\nFull sentences  |  Mild wheeze", ae_cell),
     Paragraph("Salbutamol 4 puffs (pMDI + spacer)\nOR ICS-formoterol 2 puffs\nReassess 20 min", ae_cell)],
    [Paragraph("MODERATE", S("mod_l", fontName="Helvetica-Bold", fontSize=8, textColor=ORANGE,
               alignment=TA_CENTER, leading=11)),
     Paragraph("SpO₂ 90-93%  |  ↑RR  |  ↑HR\nPhrases only  |  Mod. wheeze\nAccessory muscles", ae_cell),
     Paragraph("Salbutamol 4-6 puffs q20min × 3\n+ Ipratropium 4 puffs (up to 3×)\n+ Oral prednisolone\n+ Controlled O₂ (target 92-95%)", ae_cell)],
    [Paragraph("SEVERE /\nLIFE-\nTHREATENING", S("sev_l", fontName="Helvetica-Bold", fontSize=8,
               textColor=RED, alignment=TA_CENTER, leading=11)),
     Paragraph("SpO₂ <92%  |  RR >30/min\nWords/unable to speak\nSilent chest  |  Cyanosis\nDrowsy / confused", ae_cell),
     Paragraph("TRANSFER TO ACUTE CARE\nSalbutamol 6-10 puffs q20-30min\n+ Ipratropium + IV/IM corticosteroids\n+ Controlled O₂ (92-95%)\n+ IV Magnesium sulfate\n★ Anaphylaxis → Epinephrine FIRST", ae_bold)],
]

ae_table = Table(ae_rows, colWidths=[half*0.22, half*0.38, half*0.40])
ae_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), RED),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [GREEN_LIGHT, ORANGE_LIGHT, RED_LIGHT]),
    ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#fca5a5")),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 4),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
    ("ALIGN",         (0,0), (0,-1), "CENTER"),
]))

# -- Red Flags --
rf_items = [
    "Previous near-fatal attack (ICU / intubation)",
    "ER visit or hospitalization in past 12 months",
    "Not on ICS, or poor adherence / technique",
    "Using >1 SABA canister per month",
    "Psychological / socioeconomic problems",
    "Food allergy coexisting with asthma",
    "Heavy smoking (current or past)",
    "Elevated blood eosinophils or FeNO",
]

rf_body = S("rfs", fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=11)
rf_data = [[Paragraph(f"⚠  {item}", rf_body)] for item in rf_items]
rf_table = Table(rf_data, colWidths=[half])
rf_table.setStyle(TableStyle([
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [RED_LIGHT, WHITE]),
    ("TOPPADDING",    (0,0), (-1,-1), 3),
    ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 5),
    ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#fca5a5")),
]))

ae_section = [
    [section_label("▸  ACUTE EXACERBATION MANAGEMENT  (GINA 2026)", RED),
     section_label("▸  RED FLAGS FOR FATAL / NEAR-FATAL ASTHMA", RED)],
    [ae_table, rf_table],
]
ae_two_col = Table(ae_section, colWidths=[half + 2*mm, half + 2*mm])
ae_two_col.setStyle(TableStyle([
    ("VALIGN",  (0,0), (-1,-1), "TOP"),
    ("TOPPADDING",    (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
]))
story.append(ae_two_col)
story.append(Spacer(1, 5))

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# SECTION 5: ICS DOSE TABLE + KEY DRUG CLASSES  (bottom strip)
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
story.append(colored_header("▸  ICS DOSE REFERENCE  &  KEY DRUG CLASSES", BLUE_DARK))
story.append(Spacer(1, 3))

third = COL / 3 - 2*mm

# ICS dose table
ics_hdr = S("ics_h", fontName="Helvetica-Bold", fontSize=7.5, textColor=WHITE,
            alignment=TA_CENTER, leading=10)
ics_cell = S("ics_c", fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=10)
ics_rows = [
    [Paragraph("ICS DRUG", ics_hdr),
     Paragraph("LOW DOSE\n(mcg/day)", ics_hdr),
     Paragraph("MEDIUM DOSE\n(mcg/day)", ics_hdr),
     Paragraph("HIGH DOSE\n(mcg/day)", ics_hdr)],
    [Paragraph("Beclomethasone\n(HFA pMDI)", ics_cell),
     Paragraph("100-200", ics_cell), Paragraph("200-400", ics_cell), Paragraph(">400", ics_cell)],
    [Paragraph("Budesonide\n(DPI)", ics_cell),
     Paragraph("200-400", ics_cell), Paragraph("400-800", ics_cell), Paragraph(">800", ics_cell)],
    [Paragraph("Fluticasone\npropionate (DPI)", ics_cell),
     Paragraph("100-250", ics_cell), Paragraph("250-500", ics_cell), Paragraph(">500", ics_cell)],
    [Paragraph("Fluticasone\nfuroate (DPI)", ics_cell),
     Paragraph("100", ics_cell), Paragraph("—", ics_cell), Paragraph("200", ics_cell)],
    [Paragraph("Ciclesonide\n(HFA pMDI)", ics_cell),
     Paragraph("80-160", ics_cell), Paragraph("160-320", ics_cell), Paragraph(">320", ics_cell)],
]
ics_t = Table(ics_rows, colWidths=[third*0.37, third*0.21, third*0.21, third*0.21])
ics_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), BLUE_MID),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [BLUE_LIGHT, WHITE]),
    ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#bfdbfe")),
    ("TOPPADDING",    (0,0), (-1,-1), 3),
    ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ("LEFTPADDING",   (0,0), (-1,-1), 4),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("ALIGN",         (1,0), (-1,-1), "CENTER"),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
]))

# Drug classes quick ref
drug_s = S("drg_s", fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=10)
drug_b = S("drg_b", fontName="Helvetica-Bold", fontSize=7.5, textColor=BLUE_DARK, leading=10)

drug_rows = [
    [Paragraph("CLASS", S("dh", fontName="Helvetica-Bold", fontSize=7.5, textColor=WHITE,
               alignment=TA_CENTER, leading=10)),
     Paragraph("EXAMPLES", S("dh2", fontName="Helvetica-Bold", fontSize=7.5, textColor=WHITE,
               alignment=TA_CENTER, leading=10)),
     Paragraph("ROLE", S("dh3", fontName="Helvetica-Bold", fontSize=7.5, textColor=WHITE,
               alignment=TA_CENTER, leading=10))],
    [Paragraph("SABA", drug_b), Paragraph("Salbutamol, Terbutaline", drug_s),
     Paragraph("Acute relief (use only with ICS)", drug_s)],
    [Paragraph("LABA", drug_b), Paragraph("Formoterol, Salmeterol", drug_s),
     Paragraph("Add-on to ICS — NEVER alone", drug_s)],
    [Paragraph("ICS", drug_b), Paragraph("Budesonide, BDP,\nFluticasone", drug_s),
     Paragraph("Cornerstone — all steps", drug_s)],
    [Paragraph("ICS-LABA", drug_b), Paragraph("Budesonide/formoterol\nBDP/formoterol\nFluticasone/salmeterol", drug_s),
     Paragraph("Preferred Steps 3-5\n(SMART at Steps 3-5)", drug_s)],
    [Paragraph("LAMA", drug_b), Paragraph("Tiotropium", drug_s),
     Paragraph("Add-on Steps 4-5", drug_s)],
    [Paragraph("LTRA", drug_b), Paragraph("Montelukast", drug_s),
     Paragraph("Alternative/add-on\n(less effective than ICS)", drug_s)],
]
drug_t = Table(drug_rows, colWidths=[third*0.25, third*0.38, third*0.37])
drug_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), TEAL),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [TEAL_LIGHT, WHITE]),
    ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#99f6e4")),
    ("TOPPADDING",    (0,0), (-1,-1), 3),
    ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ("LEFTPADDING",   (0,0), (-1,-1), 4),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
]))

# New 2026 highlights
new_items = [
    ("★", "ICS-formoterol reliever", "Preferred at ALL steps — even Step 1"),
    ("★", "No SABA monotherapy", "Avoid SABA alone as sole treatment"),
    ("★", "SpO₂ target 92-95%", "New threshold in acute exacerbation (not 100%)"),
    ("★", "Depemokimab (biologic)", "Ultra-long-acting anti-IL-5 (q6 months SC)"),
    ("★", "OCS minimization", "Biologics preferred over chronic OCS"),
    ("★", "Pediatric PRAM score", "Validated severity score for children <18 yrs"),
    ("★", "CAAT & Peds-AIRQ", "New control/assessment tools added in 2026"),
    ("★", "RSV/flu/COVID vaccines", "Updated vaccine evidence included"),
]
new_s = S("nw_s", fontName="Helvetica", fontSize=7.5, textColor=BLACK, leading=10)
new_b = S("nw_b", fontName="Helvetica-Bold", fontSize=7.5, textColor=ORANGE, leading=10)
new_rows = [[Paragraph("★ NEW IN 2026", S("nh", fontName="Helvetica-Bold", fontSize=8,
             textColor=WHITE, alignment=TA_CENTER, leading=11)),
             Paragraph("DETAIL", S("nh2", fontName="Helvetica-Bold", fontSize=8,
             textColor=WHITE, alignment=TA_CENTER, leading=11))]]
for icon, title, detail in new_items:
    new_rows.append([Paragraph(f"<b>{title}</b>", new_b),
                     Paragraph(detail, new_s)])
new_t = Table(new_rows, colWidths=[third*0.44, third*0.56])
new_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), ORANGE),
    ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [ORANGE_LIGHT, WHITE]),
    ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#fde68a")),
    ("TOPPADDING",    (0,0), (-1,-1), 3),
    ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ("LEFTPADDING",   (0,0), (-1,-1), 4),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
]))

# labels
def mini_label(txt, bg):
    t = Table([[Paragraph(f"<b>{txt}</b>", S("ml_"+txt[:3], fontName="Helvetica-Bold",
               fontSize=7.5, textColor=WHITE, alignment=TA_CENTER, leading=10))]],
             colWidths=[third])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 3),
        ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ]))
    return t

bottom_section = [
    [mini_label("ICS DOSE REFERENCE", BLUE_MID),
     mini_label("KEY DRUG CLASSES", TEAL),
     mini_label("★ WHAT'S NEW IN GINA 2026", ORANGE)],
    [ics_t, drug_t, new_t],
]
bottom_col = Table(bottom_section, colWidths=[third + 3*mm, third + 3*mm, third + 3*mm])
bottom_col.setStyle(TableStyle([
    ("VALIGN",  (0,0), (-1,-1), "TOP"),
    ("TOPPADDING",    (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
]))
story.append(bottom_col)

# ── Build ────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created: {OUTPUT}")
Running Command

cd /home/daytona/workspace/gina2026-cheatsheet && python3 generate_pdf.py 2>&1

Generated successfully. Here's your cheat sheet:

GINA 2026 Asthma Stepwise Cheatsheet

PDF Document · PDF


The single-page A4 PDF includes:
  • Key GINA 2026 Principles - 6 principle boxes (no SABA monotherapy, SMART strategy, OCS minimization, new SpO2 target, etc.)
  • Stepwise Treatment Table (Steps 1-5) - severity, preferred controller, preferred reliever, add-on options, and clinical notes for each step - colour-coded green through red
  • Step 5 Biologics - all 7 agents with target and phenotype, including new Depemokimab
  • Asthma Control Assessment - controlled / partly controlled / uncontrolled with action guide
  • Acute Exacerbation Management - mild / moderate / severe with specific drug doses
  • Red Flags for Fatal Asthma - all 8 risk factors
  • ICS Dose Reference - low/medium/high doses for 5 ICS drugs
  • Key Drug Classes quick reference
  • What's New in GINA 2026 - 8 highlighted updates
This is a shared conversation. Sign in to Orris to start your own chat.