Glucocorticoids dosing and tapering

Reading File
Now let me search the medical library for glucocorticoid dosing and tapering content in parallel.
Finding Sources
Finding Sources
Searching PubMed

glucocorticoid tapering dosing

Good results. Now let me read the key sections from Dermatology (dedicated tapering section) and Rheumatology in parallel.
Reading File
Finding Sources
Finding Sources
Excellent - I got the dermatology block with a lot of content. Let me read the tapering section more carefully, and also get the corticosteroid equivalency table.
Reading File
Reading File
Now let me get the specific tapering section from Dermatology and any dosing section from the rheumatology book.
Reading File
Finding Sources
I now have excellent, detailed textbook content on glucocorticoid dosing and tapering. Let me compile the comprehensive answer.

Glucocorticoids: Dosing and Tapering

1. Relative Potency and Equivalent Doses

Before dosing, understanding equivalencies is essential:
CorticosteroidRelative Anti-inflammatory PotencyEquivalent Dose
Cortisone0.825 mg
Hydrocortisone1.0 (reference)20 mg
Prednisone3.55 mg
Prednisolone4.05 mg
Triamcinolone5.04 mg
Methylprednisolone5.04 mg
Dexamethasone250.6 mg
Betamethasone250.6 mg
Source: Pfenninger and Fowler's Procedures for Primary Care
Key rule: greater water solubility = faster onset, shorter duration. Short-acting agents (hydrocortisone, cortisone) suit acute conditions; intermediate-acting agents (prednisone, triamcinolone) suit chronic conditions.

2. Dose Classification (Prednisone Equivalents)

CategoryDose
Low dose< 7.5 mg/day
Moderate dose7.5 - 30 mg/day
High dose30 - 100 mg/day
Very high / pulse> 100 mg/day (IV methylprednisolone 250-1000 mg/day for 1-3 days)
  • Low dose (e.g. 5-20 mg prednisone/day): connective tissue diseases, RA maintenance, PMR
  • Moderate-high dose (20-60 mg/day): autoimmune conditions (lupus, vasculitis, myositis, pemphigus), severe asthma
  • Pulse dose (IV methylprednisolone 500-1000 mg/day x 3 days): lupus nephritis, severe ANCA vasculitis, acute transplant rejection

3. Dosing Principles

  • Single morning dose is preferred for prolonged therapy - minimizes HPA axis suppression by aligning with the natural cortisol peak.
  • Alternate-day therapy reduces adrenal suppression further; appropriate for chronic low-to-moderate dose regimens using intermediate-acting agents (e.g. prednisone, NOT dexamethasone).
  • Evenings dosing increases the risk of HPA suppression and should be avoided when possible.
  • Adrenal suppression typically occurs after 4 weeks of therapy at doses just above physiologic levels (approx. >7.5 mg/day prednisone), or earlier with higher doses.

4. When to Taper

Tapering is advised after:
  1. 40 mg/day prednisone (or equivalent) for more than 1 week
  2. Any dose of glucocorticoid for more than 3 weeks
  3. Repeated doses given in the evening
  4. A glucocorticoid course within 1 year of stopping long-term therapy, or with other risk factors for adrenal insufficiency
Source: Dermatology 2-Volume Set 5e, Ch. 125

5. Tapering Regimen (General Schema)

For courses longer than 3-4 weeks, taper prednisone (or equivalent) as follows:
Current DoseReduction StepFrequency
> 40 mg/dayDecrease by 5-10 mgEvery 1 week
20-40 mg/dayDecrease by 5 mgEvery 1 week
10-20 mg/dayDecrease by 2.5 mgEvery 1 week
5-10 mg/dayDecrease by 1 mgEvery 2-3 weeks
Rule of thumb: As the dose decreases, the taper rate should slow. The lower the dose, the smaller the reduction intervals.
Source: Dermatology 2-Volume Set 5e, Ch. 125

6. Converting to Alternate-Day Therapy

Once prednisone is at ~20-30 mg/day, consider switching to alternate-day dosing:
  • Simple method: Multiply the previous daily dose by 2-2.5x for the on-day dose, then rapidly taper the off-day dose to zero.
  • Step-down method: Increase on-day dose by 5 mg and decrease off-day dose by 5 mg increments until the full dose is consolidated to every other day.

7. Disease Flares During Tapering

  • If the disease flares during the taper, return to the last dose at which the condition was controlled, then taper more slowly.
  • Factors influencing the regimen: severity and chronicity of the underlying condition, time for steroid-sparing agents to become effective, patient age, and comorbidities (diabetes, hypertension, osteoporosis, psychiatric history).
Duration by condition type:
  • Acute conditions (e.g. allergic contact dermatitis, moderate severity): 2-3 week course, no slow taper needed
  • Serious chronic conditions (SLE, dermatomyositis, pyoderma gangrenosum, vasculitis): longer courses with slow taper over 6-8+ weeks

8. HPA Axis Monitoring

  • Primary screening test: morning serum cortisol (6-8 AM)
    • Impaired basal HPA axis: cortisol < 10 mcg/dL
  • Confirmatory test: ACTH (cosyntropin) stimulation test - standard dose 250 mcg IV/IM; measure cortisol at baseline and 30/60 minutes
    • Low-dose test (1 mcg) may be more sensitive
  • If stress responsiveness in question, consider endocrinology referral for corticotropin-releasing factor test or insulin hypoglycemia test

9. Special Situations

  • Perioperative ("stress dosing"): For major surgical stress (e.g. liver resection), target 100-150 mg hydrocortisone equivalent on the day of surgery, then taper rapidly over the following days. Typically: preoperative dose + 50 mg hydrocortisone IV intraoperatively.
  • PMR: No standardized tapering regimen; symptoms often wax and wane over years. A meta-analysis suggests that when prednisone reaches 10 mg/day in PMR, the dose should be reduced very slowly (e.g. 1 mg/month). A 2026 systematic review (PMID: 41678240) confirms tapering strategies remain inconsistent and highlights the need for individualized approaches.
  • Lupus nephritis: Standardized tapering regimens now incorporate newer agents (e.g. voclosporin + mycophenolate) that allow more rapid glucocorticoid tapering.
  • ANCA vasculitis (PEXIVAS trial): Compared standard vs. reduced-dose tapering regimens - the reduced regimen was non-inferior for efficacy with fewer serious infections.

10. Key Monitoring During Therapy

SystemSide Effect to Monitor
MetabolicHyperglycemia, dyslipidemia, weight gain
BoneOsteoporosis (start bisphosphonate + calcium/vitamin D if > 3 months use)
HPA axisAdrenal insufficiency symptoms, morning cortisol
CardiovascularHypertension, fluid retention
GIPeptic ulceration (especially with concurrent NSAIDs)
PsychiatricMood changes, anxiety, insomnia, psychosis
OphthalmologicCataracts, glaucoma (long-term use)

Create a quick-reference tapering calculator PDF for common doses

Reading File
Running Command

mkdir -p /tmp/workspace/glucocorticoid-pdf && ls /tmp/workspace/glucocorticoid-pdf/

Writing File

~/glucocorticoid-pdf/make_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
    SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer,
    HRFlowable, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import PageBreak

# ── Colors ────────────────────────────────────────────────────────────
DARK_BLUE   = colors.HexColor("#1A3A5C")
MED_BLUE    = colors.HexColor("#2E6DA4")
LIGHT_BLUE  = colors.HexColor("#D6E8F7")
TEAL        = colors.HexColor("#0E7B82")
LIGHT_TEAL  = colors.HexColor("#D0F0F2")
AMBER       = colors.HexColor("#E87722")
AMBER_LIGHT = colors.HexColor("#FDF0E0")
RED         = colors.HexColor("#C0392B")
RED_LIGHT   = colors.HexColor("#FADBD8")
GREEN       = colors.HexColor("#1E8449")
GREEN_LIGHT = colors.HexColor("#D5F5E3")
GRAY_DARK   = colors.HexColor("#333333")
GRAY_MID    = colors.HexColor("#666666")
GRAY_LIGHT  = colors.HexColor("#F2F4F6")
WHITE       = colors.white

OUTPUT = "/tmp/workspace/glucocorticoid-pdf/Glucocorticoid_Tapering_Reference.pdf"

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

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

styles = getSampleStyleSheet()

def style(name, **kw):
    s = ParagraphStyle(name, parent=styles["Normal"], **kw)
    return s

H1 = style("H1", fontSize=18, textColor=WHITE, fontName="Helvetica-Bold",
           alignment=TA_CENTER, spaceAfter=2)
H2 = style("H2", fontSize=11, textColor=WHITE, fontName="Helvetica-Bold",
           alignment=TA_LEFT, spaceAfter=2, spaceBefore=2)
H3 = style("H3", fontSize=9.5, textColor=DARK_BLUE, fontName="Helvetica-Bold",
           alignment=TA_LEFT, spaceAfter=1, spaceBefore=4)
BODY = style("BODY", fontSize=8.5, textColor=GRAY_DARK, fontName="Helvetica",
             leading=12, spaceAfter=2)
SMALL = style("SMALL", fontSize=7.5, textColor=GRAY_MID, fontName="Helvetica",
              leading=10, spaceAfter=1)
FOOTER = style("FOOTER", fontSize=7, textColor=GRAY_MID, fontName="Helvetica-Oblique",
               alignment=TA_CENTER)
CELL = style("CELL", fontSize=8, textColor=GRAY_DARK, fontName="Helvetica", leading=11)
CELL_B = style("CELL_B", fontSize=8, textColor=GRAY_DARK, fontName="Helvetica-Bold", leading=11)
CELL_H = style("CELL_H", fontSize=8, textColor=WHITE, fontName="Helvetica-Bold",
               alignment=TA_CENTER, leading=11)
WARN = style("WARN", fontSize=8, textColor=RED, fontName="Helvetica-Bold", leading=11)
NOTE = style("NOTE", fontSize=7.5, textColor=GRAY_MID, fontName="Helvetica-Oblique", leading=10)

def section_header(text, color=MED_BLUE):
    t = Table([[Paragraph(text, H2)]], colWidths=[W])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), color),
        ("TOPPADDING",   (0,0), (-1,-1), 5),
        ("BOTTOMPADDING",(0,0), (-1,-1), 5),
        ("LEFTPADDING",  (0,0), (-1,-1), 8),
        ("RIGHTPADDING", (0,0), (-1,-1), 8),
        ("ROUNDEDCORNERS", [3]),
    ]))
    return t

def col_header_row(cells, bg=DARK_BLUE):
    return [Paragraph(c, CELL_H) for c in cells]

def body_cell(text, bold=False):
    return Paragraph(text, CELL_B if bold else CELL)

def tbl_style(row_data, col_widths, header_color=DARK_BLUE, alt_color=GRAY_LIGHT,
              alt_color2=WHITE, zebra=True, font_size=8):
    n = len(row_data)
    cmds = [
        ("BACKGROUND",   (0,0), (-1,0), header_color),
        ("TEXTCOLOR",    (0,0), (-1,0), WHITE),
        ("FONTNAME",     (0,0), (-1,0), "Helvetica-Bold"),
        ("FONTSIZE",     (0,0), (-1,-1), font_size),
        ("ALIGN",        (0,0), (-1,-1), "CENTER"),
        ("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),
        ("GRID",         (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
        ("LINEBELOW",    (0,0), (-1,0), 1.2, header_color),
    ]
    if zebra:
        for i in range(1, n):
            bg = alt_color if i % 2 == 1 else alt_color2
            cmds.append(("BACKGROUND", (0,i), (-1,i), bg))
    return cmds

# ═══════════════════════════════════════════════════════════════════════
# BUILD CONTENT
# ═══════════════════════════════════════════════════════════════════════
story = []

# ── TITLE BANNER ──────────────────────────────────────────────────────
title_data = [[
    Paragraph("GLUCOCORTICOID", H1),
    Paragraph("Dosing &amp; Tapering Quick Reference", H1),
]]
title_tbl = Table(title_data, colWidths=[W*0.38, W*0.62])
title_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,-1), DARK_BLUE),
    ("TOPPADDING",    (0,0), (-1,-1), 10),
    ("BOTTOMPADDING", (0,0), (-1,-1), 10),
    ("LEFTPADDING",   (0,0), (-1,-1), 10),
    ("RIGHTPADDING",  (0,0), (-1,-1), 10),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
]))
story.append(title_tbl)
story.append(Spacer(1, 5*mm))

# ── ROW 1: two columns layout ─────────────────────────────────────────
# LEFT: Potency & Equivalence  |  RIGHT: Dose Classification

# --- POTENCY TABLE ---
pot_data = [
    [Paragraph("Agent", CELL_H), Paragraph("Relative\nPotency", CELL_H),
     Paragraph("Equiv.\nDose (mg)", CELL_H), Paragraph("Duration", CELL_H)],
    # Short-acting
    [body_cell("Cortisone", bold=True), body_cell("0.8"), body_cell("25"), body_cell("Short")],
    [body_cell("Hydrocortisone"), body_cell("1.0 ★"), body_cell("20"), body_cell("Short")],
    # Intermediate
    [body_cell("Prednisone", bold=True), body_cell("3.5"), body_cell("5"), body_cell("Interm.")],
    [body_cell("Prednisolone"), body_cell("4.0"), body_cell("5"), body_cell("Interm.")],
    [body_cell("Triamcinolone"), body_cell("5.0"), body_cell("4"), body_cell("Interm.")],
    [body_cell("Methylprednisolone"), body_cell("5.0"), body_cell("4"), body_cell("Interm.")],
    # Long-acting
    [body_cell("Dexamethasone", bold=True), body_cell("25"), body_cell("0.6"), body_cell("Long")],
    [body_cell("Betamethasone"), body_cell("25"), body_cell("0.6"), body_cell("Long")],
]

CW_pot = [W*0.21, W*0.11, W*0.12, W*0.11]  # total ~0.55*W

pot_cmds = tbl_style(pot_data, CW_pot, header_color=DARK_BLUE, alt_color=LIGHT_BLUE, alt_color2=WHITE)
# Shade short-acting rows
pot_cmds += [
    ("BACKGROUND", (0,1), (-1,2), colors.HexColor("#EAF4FB")),
    ("BACKGROUND", (0,3), (-1,6), LIGHT_BLUE),
    ("BACKGROUND", (0,7), (-1,8), colors.HexColor("#E8F4D0")),
    ("FONTNAME",   (0,1), (-1,2), "Helvetica"),
    ("TEXTCOLOR",  (1,2), (1,2), AMBER),
    ("FONTNAME",   (1,2), (1,2), "Helvetica-Bold"),
]

pot_tbl = Table(pot_data, colWidths=CW_pot)
pot_tbl.setStyle(TableStyle(pot_cmds))

# Separator label rows for short/intermediate/long
def section_row(label, ncols, bg_color):
    row = [[Paragraph(label, style("SL", fontSize=7, textColor=WHITE,
                                   fontName="Helvetica-BoldOblique",
                                   alignment=TA_CENTER))
            ] + [""] * (ncols - 1)]
    return row

# --- DOSE CLASSIFICATION TABLE ---
cls_data = [
    [Paragraph("Category", CELL_H), Paragraph("Prednisone\nEquivalent", CELL_H),
     Paragraph("Typical Use", CELL_H)],
    [body_cell("Low dose"),        body_cell("< 7.5 mg/day"),   body_cell("RA maintenance, PMR")],
    [body_cell("Moderate dose"),   body_cell("7.5–30 mg/day"),  body_cell("SLE, vasculitis")],
    [body_cell("High dose"),       body_cell("30–100 mg/day"),  body_cell("Severe autoimmune")],
    [body_cell("Very high / pulse"), body_cell("> 100 mg/day\n(or IV MP 500–1000 mg\n× 1–3 d)"),
     body_cell("Lupus nephritis,\nAAV, transplant\nrejection")],
]
CW_cls = [W*0.13, W*0.16, W*0.15]

cls_cmds = tbl_style(cls_data, CW_cls, header_color=TEAL, alt_color=LIGHT_TEAL, alt_color2=WHITE)
cls_cmds += [
    ("BACKGROUND", (0,4), (-1,4), RED_LIGHT),
    ("TEXTCOLOR",  (0,4), (0,4), RED),
    ("FONTNAME",   (0,4), (0,4), "Helvetica-Bold"),
]
cls_tbl = Table(cls_data, colWidths=CW_cls)
cls_tbl.setStyle(TableStyle(cls_cmds))

# Place side by side
left_col = [
    section_header("POTENCY & EQUIVALENCE", MED_BLUE),
    Spacer(1, 2*mm),
    pot_tbl,
    Spacer(1, 1*mm),
    Paragraph("★ Reference standard. MP = methylprednisolone. Short < 12 h, Interm. 12–36 h, Long > 48 h.", NOTE),
]
right_col = [
    section_header("DOSE CLASSIFICATION", TEAL),
    Spacer(1, 2*mm),
    cls_tbl,
    Spacer(1, 2*mm),
    section_header("ADMINISTRATION TIPS", TEAL),
    Spacer(1, 2*mm),
    Paragraph("• <b>Single morning dose</b> preferred — aligns with natural cortisol peak, reduces HPA suppression.", BODY),
    Paragraph("• <b>Alternate-day therapy:</b> use intermediate-acting agents (prednisone / prednisolone). NOT dexamethasone.", BODY),
    Paragraph("• Avoid <b>evening dosing</b> — significantly increases adrenal suppression risk.", BODY),
    Paragraph("• Adrenal suppression typically occurs after <b>4 weeks</b> at doses &gt; 7.5 mg/day prednisone equiv.", BODY),
]

CW_left  = W * 0.55 - 3*mm
CW_right = W * 0.45 - 3*mm

def mini_story_to_flowable(items, w):
    tbl = Table([[items]], colWidths=[w])
    tbl.setStyle(TableStyle([
        ("VALIGN", (0,0), (-1,-1), "TOP"),
        ("LEFTPADDING",  (0,0), (-1,-1), 0),
        ("RIGHTPADDING", (0,0), (-1,-1), 0),
        ("TOPPADDING",   (0,0), (-1,-1), 0),
        ("BOTTOMPADDING",(0,0), (-1,-1), 0),
    ]))
    return tbl

from reportlab.platypus import BalancedColumns

two_col = Table(
    [[left_col, right_col]],
    colWidths=[CW_left + 3*mm, CW_right + 3*mm]
)
two_col.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(two_col)
story.append(Spacer(1, 4*mm))

# ── TAPERING REGIMEN ──────────────────────────────────────────────────
story.append(section_header("TAPERING REGIMEN  (for courses > 3–4 weeks)", AMBER))
story.append(Spacer(1, 2*mm))

tap_data = [
    [Paragraph("Current Prednisone Dose", CELL_H),
     Paragraph("Reduction per Step", CELL_H),
     Paragraph("Frequency", CELL_H),
     Paragraph("Clinical Note", CELL_H)],
    [body_cell("> 40 mg/day", bold=True),
     body_cell("↓ 5–10 mg"),
     body_cell("Every 1 week"),
     body_cell("Disease usually controlled; rapid initial reduction acceptable")],
    [body_cell("20–40 mg/day", bold=True),
     body_cell("↓ 5 mg"),
     body_cell("Every 1 week"),
     body_cell("Monitor for flare; add steroid-sparing agent if not started")],
    [body_cell("10–20 mg/day", bold=True),
     body_cell("↓ 2.5 mg"),
     body_cell("Every 1 week"),
     body_cell("HPA axis begins to recover; slow taper critical here")],
    [body_cell("5–10 mg/day", bold=True),
     body_cell("↓ 1 mg"),
     body_cell("Every 2–3 weeks"),
     body_cell("Near-physiologic range; very slow reduction to prevent adrenal crisis")],
]

CW_tap = [W*0.22, W*0.14, W*0.14, W*0.50]
tap_cmds = tbl_style(tap_data, CW_tap, header_color=AMBER, alt_color=AMBER_LIGHT, alt_color2=WHITE)
tap_cmds += [
    ("TEXTCOLOR",  (0,4), (1,4), RED),
    ("FONTNAME",   (0,4), (0,4), "Helvetica-Bold"),
]
tap_tbl = Table(tap_data, colWidths=CW_tap)
tap_tbl.setStyle(TableStyle(tap_cmds))
story.append(tap_tbl)
story.append(Spacer(1, 1*mm))
story.append(Paragraph(
    "⚠ If disease <b>flares</b> during taper: resume the last dose that controlled disease, then taper MORE slowly. "
    "As dose decreases, always slow the rate of reduction.",
    style("FLARE", fontSize=8, textColor=RED, fontName="Helvetica-Bold",
          backColor=RED_LIGHT, borderPadding=(4,6,4,6), leading=11)
))
story.append(Spacer(1, 4*mm))

# ── ROW 3: Alternate-day + Taper schedule cards ───────────────────────
# Left: Alternate-day conversion | Right: Common starting doses by disease

altday_content = [
    section_header("ALTERNATE-DAY CONVERSION", MED_BLUE),
    Spacer(1, 2*mm),
    Paragraph("Switch when prednisone reaches <b>~20–30 mg/day</b>:", BODY),
    Spacer(1, 1*mm),
]

ad_data = [
    [Paragraph("Method", CELL_H), Paragraph("How to Do It", CELL_H)],
    [body_cell("Simple\n(Quick)"),
     body_cell("Multiply daily dose × 2–2.5 for the ON day. Taper OFF day rapidly to zero.")],
    [body_cell("Step-down\n(Gradual)"),
     body_cell("Increase ON day by +5 mg and decrease OFF day by –5 mg each week, until OFF day = 0.")],
]
CW_ad = [W*0.17, W*0.38]
ad_tbl = Table(ad_data, colWidths=CW_ad)
ad_tbl.setStyle(TableStyle(tbl_style(ad_data, CW_ad, header_color=MED_BLUE,
                                      alt_color=LIGHT_BLUE, alt_color2=WHITE)))
altday_content.append(ad_tbl)
altday_content += [
    Spacer(1, 2*mm),
    Paragraph("• Only intermediate-acting agents (prednisone, prednisolone) are suitable.", BODY),
    Paragraph("• NOT suitable for dexamethasone or betamethasone (too long-acting).", BODY),
]

# Disease-specific doses
dis_content = [
    section_header("COMMON STARTING DOSES BY CONDITION", TEAL),
    Spacer(1, 2*mm),
]

dis_data = [
    [Paragraph("Condition", CELL_H), Paragraph("Starting Dose\n(Prednisone equiv.)", CELL_H),
     Paragraph("Typical Duration", CELL_H)],
    [body_cell("Allergic contact derm."),   body_cell("40–60 mg/day"),      body_cell("2–3 weeks")],
    [body_cell("Asthma exacerbation"),      body_cell("40–60 mg/day"),      body_cell("5–10 days")],
    [body_cell("PMR"),                      body_cell("12.5–25 mg/day"),    body_cell("12–18+ months")],
    [body_cell("RA flare"),                 body_cell("5–20 mg/day"),       body_cell("Weeks–months")],
    [body_cell("SLE / vasculitis"),         body_cell("0.5–1 mg/kg/day"),   body_cell("Months; slow taper")],
    [body_cell("Dermatomyositis / PG"),     body_cell("1 mg/kg/day"),       body_cell("6–8+ weeks taper")],
    [body_cell("Lupus nephritis"),          body_cell("0.5–1 mg/kg/day"),   body_cell("+ steroid-sparing")],
    [body_cell("Pulse (severe disease)"),   body_cell("IV MP 500–1000 mg/day × 3"), body_cell("Then oral taper")],
    [body_cell("Perioperative (major Sx)"), body_cell("HC 100–150 mg equiv on day"), body_cell("Taper rapidly post-op")],
]

CW_dis = [W*0.27, W*0.22, W*0.17]
dis_tbl = Table(dis_data, colWidths=CW_dis)
dis_cmds = tbl_style(dis_data, CW_dis, header_color=TEAL, alt_color=LIGHT_TEAL, alt_color2=WHITE)
dis_cmds += [("BACKGROUND", (0,8), (-1,8), colors.HexColor("#F9E9D0")),
             ("BACKGROUND", (0,9), (-1,9), colors.HexColor("#EAF0E8"))]
dis_tbl.setStyle(TableStyle(dis_cmds))
dis_content.append(dis_tbl)
dis_content += [
    Spacer(1, 1*mm),
    Paragraph("PG = pyoderma gangrenosum. MP = methylprednisolone. HC = hydrocortisone.", NOTE),
]

three_col = Table(
    [[altday_content, dis_content]],
    colWidths=[W*0.57 + 3*mm, W*0.43 + 3*mm]
)
three_col.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(three_col)
story.append(Spacer(1, 4*mm))

# ── WHEN TO TAPER + HPA MONITORING ───────────────────────────────────
when_hpa_left = [
    section_header("WHEN TO TAPER (Endocrinology Guidance)", DARK_BLUE),
    Spacer(1, 2*mm),
    Paragraph("Tapering advised after ANY of the following:", BODY),
]

wt_data = [
    [Paragraph("#", CELL_H), Paragraph("Trigger", CELL_H)],
    [body_cell("1"), body_cell("≥ 40 mg/day prednisone (equiv.) for <b>more than 1 week</b>")],
    [body_cell("2"), body_cell("<b>Any dose</b> of glucocorticoid for <b>more than 3 weeks</b>")],
    [body_cell("3"), body_cell("Repeated glucocorticoid doses given in the <b>evening</b>")],
    [body_cell("4"), body_cell("Glucocorticoid course within <b>1 year</b> of stopping long-term therapy")],
    [body_cell("5"), body_cell("Other <b>risk factors</b> for adrenal insufficiency present")],
]
CW_wt = [W*0.05, W*0.40]
wt_tbl = Table(wt_data, colWidths=CW_wt)
wt_tbl.setStyle(TableStyle(tbl_style(wt_data, CW_wt, header_color=DARK_BLUE,
                                      alt_color=GRAY_LIGHT, alt_color2=WHITE)))
when_hpa_left += [wt_tbl]

hpa_right = [
    section_header("HPA AXIS MONITORING", DARK_BLUE),
    Spacer(1, 2*mm),
]

hpa_data = [
    [Paragraph("Test", CELL_H), Paragraph("Detail", CELL_H)],
    [body_cell("Morning cortisol\n(6–8 AM)", bold=True),
     body_cell("Impaired basal HPA: cortisol <b>&lt; 10 mcg/dL</b>. Omit morning GC dose on test day.")],
    [body_cell("Standard ACTH\nstimulation", bold=True),
     body_cell("Cosyntropin <b>250 mcg</b> IV/IM; cortisol at 0, 30, 60 min. Normal = peak > 18 mcg/dL.")],
    [body_cell("Low-dose ACTH\nstimulation", bold=True),
     body_cell("Cosyntropin <b>1 mcg</b> IV. More sensitive for partial adrenal insufficiency.")],
    [body_cell("Adrenal crisis\nrisk factors", bold=True),
     body_cell("Physiologic stress (infection, surgery, trauma). Give stress doses: HC 50–100 mg IV q8h.")],
]
CW_hpa = [W*0.13, W*0.35]
hpa_tbl = Table(hpa_data, colWidths=CW_hpa)
hpa_tbl.setStyle(TableStyle(tbl_style(hpa_data, CW_hpa, header_color=DARK_BLUE,
                                       alt_color=GRAY_LIGHT, alt_color2=WHITE)))
hpa_right += [hpa_tbl]

bot_row = Table(
    [[when_hpa_left, hpa_right]],
    colWidths=[W*0.47 + 3*mm, W*0.53 + 3*mm]
)
bot_row.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(bot_row)
story.append(Spacer(1, 3*mm))

# ── MONITORING TABLE ──────────────────────────────────────────────────
story.append(section_header("SIDE EFFECT MONITORING  (Long-term Use)", GRAY_MID))
story.append(Spacer(1, 2*mm))

mon_data = [
    [Paragraph("System", CELL_H), Paragraph("Adverse Effect", CELL_H),
     Paragraph("Action", CELL_H),
     Paragraph("System", CELL_H), Paragraph("Adverse Effect", CELL_H),
     Paragraph("Action", CELL_H)],
    [body_cell("Bone",    bold=True), body_cell("Osteoporosis"),
     body_cell("Bisphosphonate + Ca²⁺/vit D if > 3 months"),
     body_cell("Metabolic", bold=True), body_cell("Hyperglycemia"),
     body_cell("Monitor BG; adjust anti-diabetic therapy")],
    [body_cell("CV",      bold=True), body_cell("Hypertension, fluid retention"),
     body_cell("BP monitoring; sodium restriction"),
     body_cell("GI",        bold=True), body_cell("PUD / GI bleed"),
     body_cell("PPI if concurrent NSAID use")],
    [body_cell("Ophthalmic", bold=True), body_cell("Cataracts, glaucoma"),
     body_cell("Annual eye exam if > 1 year use"),
     body_cell("Infectious", bold=True), body_cell("Opportunistic infections"),
     body_cell("PJP prophylaxis if > 20 mg/day > 4 weeks")],
    [body_cell("Psych",   bold=True), body_cell("Mood, insomnia, psychosis"),
     body_cell("Counsel patient; lowest effective dose"),
     body_cell("Skin",      bold=True), body_cell("Atrophy, striae, purpura"),
     body_cell("Minimize dose; monitor skin integrity")],
]

CW_mon = [W*0.10, W*0.15, W*0.22, W*0.10, W*0.15, W*0.28]
mon_tbl = Table(mon_data, colWidths=CW_mon)
mon_cmds = tbl_style(mon_data, CW_mon, header_color=colors.HexColor("#555555"),
                     alt_color=GRAY_LIGHT, alt_color2=WHITE)
mon_cmds += [("ALIGN", (0,0), (-1,-1), "LEFT")]
mon_tbl.setStyle(TableStyle(mon_cmds))
story.append(mon_tbl)
story.append(Spacer(1, 3*mm))

# ── FOOTER ────────────────────────────────────────────────────────────
story.append(HRFlowable(width=W, color=GRAY_MID, thickness=0.5))
story.append(Spacer(1, 1*mm))
story.append(Paragraph(
    "Sources: Dermatology 2-Volume Set 5e (Ch. 125) | Firestein &amp; Kelley's Textbook of Rheumatology | "
    "Pfenninger &amp; Fowler's Procedures for Primary Care | Kooijman et al., Rheumatology (Oxford) 2026 (PMID: 41678240). "
    "For educational/clinical decision support only. Always individualise therapy.",
    FOOTER
))

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

cd /tmp/workspace/glucocorticoid-pdf && python make_pdf.py 2>&1

Running Command

ls -lh /tmp/workspace/glucocorticoid-pdf/Glucocorticoid_Tapering_Reference.pdf

Your PDF is ready. Here's what's packed onto the single A4 quick-reference page:

Glucocorticoid Tapering Reference

PDF Document · PDF


What's included:
SectionContent
Potency & EquivalenceAll 9 major agents with relative potency, equivalent dose, and duration class
Dose ClassificationLow / moderate / high / pulse with typical mg/day ranges and use cases
Administration TipsMorning dosing, alternate-day guidance, evening dosing warning
Tapering RegimenStep-down table: >40 / 20-40 / 10-20 / 5-10 mg/day with reduction steps and clinical notes
Flare WarningHighlighted box with action if disease flares during taper
Alternate-Day ConversionSimple and step-down methods, when to switch (~20-30 mg/day)
Common Starting Doses9 conditions (asthma, SLE, PMR, vasculitis, perioperative, pulse, etc.)
When to Taper5 endocrinology triggers
HPA Axis MonitoringMorning cortisol, standard & low-dose ACTH stimulation, adrenal crisis action
Side Effect Monitoring8 systems with specific actions (bisphosphonate, PPI, PJP prophylaxis, etc.)
Sources cited at the footer: Dermatology 5e, Firestein & Kelley's Rheumatology, Pfenninger & Fowler, and the 2026 PMR tapering systematic review (PMID: 41678240).
This is a shared conversation. Sign in to Orris to start your own chat.