Management of hypokalemia and hyperkalemia (pharmacology)
| Severity | Serum K⁺ |
|---|---|
| Mild | 3.0 - 3.5 mEq/L |
| Moderate | 2.5 - 3.0 mEq/L |
| Severe | < 2.5 mEq/L |
Key rule: Each 0.3 mEq/L drop in serum K⁺ below normal corresponds to roughly 100 mEq of total body potassium deficit.

| Drug Class | Agents | Mechanism |
|---|---|---|
| Mineralocorticoid receptor antagonists | Spironolactone, eplerenone | Block aldosterone-driven K⁺ secretion |
| ENaC blockers | Amiloride, triamterene | Block sodium reabsorption in collecting duct, reduce K⁺ secretion |
| ACE inhibitors / ARBs | Enalapril, losartan | Suppress RAAS, reduce aldosterone |
| Direct renin inhibitors | Aliskiren | Suppress RAAS upstream |
| Severity | Serum K⁺ |
|---|---|
| Mild | 5.5 - 6.0 mEq/L |
| Moderate | 6.1 - 6.9 mEq/L |
| Severe | ≥ 7.0 mEq/L |

Step 1: Stabilize the cardiac membrane Step 2: Shift K⁺ into cells (temporizing) Step 3: Remove K⁺ from the body (definitive)
| Drug | Dose | Onset | Duration | Notes |
|---|---|---|---|---|
| Calcium gluconate 10% | 10 mL (1 g) IV over 2-3 min; repeat after 5 min if needed | 1-3 min | 30-60 min | First-line for ECG changes |
| Calcium chloride 10% | 5-10 mL (0.5-1 g) IV | 1-3 min | 30-60 min | More elemental Ca²⁺ per mL (3x), can cause tissue necrosis if extravasated - prefer central line |
| Drug | Dose | Onset | Peak Effect | K⁺ Reduction |
|---|---|---|---|---|
| Regular insulin + Dextrose | Insulin 10 units IV push + Dextrose 50% 50 mL (25 g) IV push | < 15 min | 30-60 min | ~0.6 mEq/L |
| Nebulized albuterol | 10-15 mg by continuous inhalation (high dose) | < 15 min | 30-60 min | 0.5-1.0 mEq/L |
| Sodium bicarbonate | 50-100 mEq IV infusion | ~15 min | Variable | Modest |
| Beta-2 agonists (IV/SC) | Low-dose epinephrine infusion | Minutes | Rapid | Useful in massive transfusion |
| Method | Onset | Notes |
|---|---|---|
| Hemodialysis | Immediate/reliable | Reduces K⁺ by ~1 mEq/L in first hour, another 1 mEq/L over next 2 hours. Definitive treatment. Required in renal failure. |
| Furosemide (loop diuretic) + IV fluids | Minutes to hours | Effective with intact renal function (e.g., rhabdomyolysis, tumor lysis). Administer by slow infusion (not bolus) to reduce ototoxicity risk. Not reliable in acute management. |
| Sodium polystyrene sulfonate (SPS, Kayexalate) | 4-6+ hours | NOT effective for acute/urgent management. Onset too slow. FDA black box warning: risk of intestinal necrosis, especially with abnormal bowel function. |
| Patiromer (Veltassa) | Hours (chronic use) | Non-absorbed cation exchange polymer - binds K⁺ in exchange for Ca²⁺ in GI tract. FDA-approved for chronic hyperkalemia. Not for acute/urgent use. |
| Sodium zirconium cyclosilicate (Lokelma) | Hours | Highly selective cation exchanger - traps K⁺ in intestines in exchange for Na⁺ and H⁺. Useful for chronic hyperkalemia in CKD and heart failure. |
| Feature | Hypokalemia | Hyperkalemia |
|---|---|---|
| ECG | T-wave flat, U wave, ↑QT | Peaked T, wide QRS, P loss, sine wave |
| Cardiac danger | Arrhythmias, digoxin toxicity | VF/asystole, cardiac arrest |
| Acute drug Rx | KCl IV 10-20 mEq/hr | Calcium gluconate → Insulin/glucose → Albuterol |
| Oral Rx | KCl 40-60 mEq q2-4h | Patiromer, SPS (chronic only) |
| Associated deficiency to correct | Magnesium | N/A |
| Definitive removal | N/A | Hemodialysis (renal failure), furosemide (intact kidneys) |
| Avoid | Dextrose-only IVF, insulin without glucose | Succinylcholine, K⁺-containing IVF, ACEi/ARBs |
from kd tripathi
Management of hypokalemia and hyperkalemia kd tripathi
Note: KD Tripathi's textbook is not available in this library. This response is presented in KD Tripathi's characteristic writing style - concise, tabular, drug-classification-based, with mechanism, dose, and notes - drawing from Katzung's Basic & Clinical Pharmacology (16e), Rosen's Emergency Medicine (9e), Barash's Clinical Anesthesia (9e), and Morgan & Mikhail's Clinical Anesthesiology (7e).
| Severity | K⁺ level |
|---|---|
| Mild | 3.0 - 3.5 mEq/L |
| Moderate | 2.5 - 3.0 mEq/L |
| Severe | < 2.5 mEq/L |

| Route | Max Rate | Condition |
|---|---|---|
| Peripheral IV | 10 mEq/hr (max 20 mEq/hr) | Standard |
| Peripheral IV | Do NOT exceed 8 mEq/hr | Avoids vein irritation |
| Central venous | 10-20 mEq/hr | Rapid replacement with ECG monitoring |
| Any route | > 20 mEq/hr | Only for K⁺ < 2.0 mEq/L or QT > 500 ms; mandatory cardiac monitoring |
| Drug | Class | Mechanism | Dose |
|---|---|---|---|
| Spironolactone | Aldosterone antagonist | Blocks mineralocorticoid receptor → reduces K⁺ secretion in collecting duct | 25-100 mg/day |
| Eplerenone | Selective aldosterone antagonist | Same as spironolactone; fewer hormonal SE | 25-50 mg/day |
| Amiloride | ENaC blocker | Blocks Na⁺ channel in collecting duct → reduces electrochemical gradient for K⁺ secretion | 5-10 mg/day |
| Triamterene | ENaC blocker | Same as amiloride | 50-150 mg/day |
Note from Katzung: Loop diuretics increase K⁺ secretion by 4 mechanisms - ↑tubular flow, ↑AVP, ↑aldosterone, metabolic alkalosis. K⁺-sparing agents counteract these. At least one study showed K⁺ supplementation at initiation of loop diuretics (regardless of serum K⁺) improves survival.
| Severity | K⁺ level |
|---|---|
| Mild | 5.5 - 6.0 mEq/L |
| Moderate | 6.1 - 6.9 mEq/L |
| Severe | ≥ 7.0 mEq/L |

Hypocalcemia, hyponatremia, and acidosis accentuate the cardiac toxicity of hyperkalemia.
STEP 1 → Stabilize cardiac membrane (fastest, buys time)
STEP 2 → Shift K⁺ into cells (temporizing, ~60 min)
STEP 3 → Remove K⁺ from body (definitive)
| Drug | Dose | Onset | Duration |
|---|---|---|---|
| Calcium gluconate 10% | 10 mL (1 g) IV over 2-3 min; repeat after 5 min if no response | 1-3 min | 30-60 min |
| Calcium chloride 10% | 5-10 mL IV | 1-3 min | 30-60 min |
| Parameter | Detail |
|---|---|
| Drug | Regular insulin + 50% Dextrose |
| Dose | Insulin 10 units IV bolus + Dextrose 50 mL (25 g) IV |
| In renal failure | Insulin 5 units (to reduce hypoglycemia risk) |
| In hyperglycemia | Insulin without dextrose if glucose > ~250 mg/dL |
| Onset | < 15 minutes |
| Duration | 30-60 minutes |
| K⁺ reduction | ~0.6 mEq/L |
| Mechanism | Activates Na⁺/K⁺-ATPase → drives K⁺ intracellularly |
| Monitor | Blood glucose (hypoglycemia risk) |
| Parameter | Detail |
|---|---|
| Drug | Salbutamol (Albuterol) nebulized |
| Dose | 10-15 mg by continuous nebulization (high dose) |
| Onset | < 15 minutes |
| K⁺ reduction | 0.5-1.0 mEq/L |
| Mechanism | Stimulates β₂ receptors → activates Na⁺/K⁺-ATPase → intracellular K⁺ shift |
| Note | Additive with insulin - combined effect > either alone |
| Caution | Do NOT use as monotherapy in severe hyperkalemia. Tachycardia as SE. |
| Parameter | Detail |
|---|---|
| Dose | 50-100 mEq IV over 5-10 min |
| Onset | ~15 minutes |
| Mechanism | Corrects acidosis → H⁺ exits cells in exchange for K⁺ (K⁺ shifts intracellularly) |
| Best used | Only when metabolic acidosis is concurrently present |
| Least effective | Hyperkalemia without acidosis |
| Drug | Mechanism | Onset | Use |
|---|---|---|---|
| Sodium polystyrene sulfonate (SPS, Kayexalate) | Exchanges Na⁺ for K⁺ in gut | 4-6 hours | NOT for acute/emergency management. Risk of intestinal necrosis (FDA black box warning). Oral or rectal. |
| Patiromer (Veltassa) | Non-absorbed polymer; binds K⁺ in exchange for Ca²⁺ in GI tract | Hours | Chronic hyperkalemia (CKD, heart failure). FDA-approved. NOT for acute use. |
| Sodium Zirconium Cyclosilicate (SZC, Lokelma) | Highly selective cation exchanger; traps K⁺ in intestine in exchange for Na⁺/H⁺ | ~4 hours (K⁺ < 5.5 mEq/L in median 4 hrs in trials) | Chronic hyperkalemia. Approved in US and EU. NOT for acute/emergency use. |
SPS is no longer recommended for emergent management due to lack of efficacy within 4 hours and serious GI complications. Patiromer and SZC are preferred for outpatient chronic hyperkalemia management.
| Drug/Class | Mechanism |
|---|---|
| ACE inhibitors, ARBs | ↓ angiotensin II → ↓ aldosterone → ↓ K⁺ excretion |
| Spironolactone, amiloride, triamterene | Direct K⁺-sparing action |
| NSAIDs | ↓ renin → ↓ aldosterone (type IV RTA pattern) |
| Beta-blockers | Impair K⁺ uptake into cells |
| Succinylcholine | Depolarization → K⁺ efflux from muscle; absolutely contraindicated in hyperkalemia |
| Heparin | ↓ adrenal aldosterone synthesis |
| Digoxin overdose | Inhibits Na⁺/K⁺-ATPase → K⁺ leaks out of cells |
| Feature | Hypokalemia | Hyperkalemia |
|---|---|---|
| K⁺ level | < 3.5 mEq/L | > 5.0 mEq/L |
| ECG hallmark | Flat T, prominent U wave, ↑QT | Peaked T waves → sine wave |
| First-line acute drug | KCl oral/IV | Calcium gluconate IV |
| Temporizing (shift K⁺) | N/A | Insulin + glucose, Albuterol |
| Definitive removal | N/A | Dialysis (renal failure), Furosemide (intact kidneys) |
| Chronic oral drug | KCl + K⁺-sparing diuretic | Patiromer / SZC |
| Avoid | Dextrose IVF alone, delay in Mg²⁺ correction | Succinylcholine, K⁺-containing IVF, SPS in acute setting |
| Key associated deficiency | Hypomagnesemia | N/A |
| Digoxin interaction | Potentiates toxicity (replace K⁺ aggressively) | Calcium potentiates digoxin toxicity (give cautiously) |
Create a concise PDF reference card for hypokalemia and hyperkalemia management
ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace not found"
mkdir -p /home/daytona/workspace/potassium-refcard && python3 -c "import reportl…
~/potassium-refcard/build_refcard.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
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
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate
# ── Colour palette ─────────────────────────────────────────────────────────────
BLUE_DARK = colors.HexColor("#1a3a5c") # header bar
BLUE_MID = colors.HexColor("#1e6091") # section title
BLUE_LIGHT = colors.HexColor("#d6eaf8") # hypo col header bg
RED_DARK = colors.HexColor("#7b1a1a") # hyperK accents
RED_LIGHT = colors.HexColor("#fde8e8") # hyperK col header bg
AMBER = colors.HexColor("#fff3cd") # warning rows
GREEN_LIGHT = colors.HexColor("#d5f5e3") # step header bg
GRAY_LIGHT = colors.HexColor("#f4f6f8") # alternating rows
WHITE = colors.white
BLACK = colors.HexColor("#1a1a1a")
# ── Output path ────────────────────────────────────────────────────────────────
OUTPUT = "/home/daytona/workspace/potassium-refcard/Potassium_Management_Refcard.pdf"
W, H = A4 # 595 x 842 pt
# ── Document ───────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=12*mm, rightMargin=12*mm,
topMargin=10*mm, bottomMargin=10*mm,
)
# ── Base styles ────────────────────────────────────────────────────────────────
SS = getSampleStyleSheet()
def sty(name, **kw):
return ParagraphStyle(name, **kw)
TITLE = sty("Title", fontSize=15, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, spaceAfter=0, leading=18)
SUBTITLE = sty("Sub", fontSize=8, textColor=colors.HexColor("#cce3f5"),
fontName="Helvetica", alignment=TA_CENTER, spaceAfter=0)
SEC = sty("Sec", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, spaceAfter=0, leading=11)
BODY = sty("Body", fontSize=7.5, textColor=BLACK, fontName="Helvetica",
leading=10, spaceAfter=0)
BODY_B = sty("BodyB", fontSize=7.5, textColor=BLACK, fontName="Helvetica-Bold",
leading=10, spaceAfter=0)
SMALL = sty("Small", fontSize=6.5, textColor=colors.HexColor("#444444"),
fontName="Helvetica", leading=9)
WARN = sty("Warn", fontSize=7, textColor=colors.HexColor("#7b4f00"),
fontName="Helvetica-Bold", leading=9)
FOOT = sty("Foot", fontSize=5.5, textColor=colors.HexColor("#888888"),
fontName="Helvetica", alignment=TA_CENTER)
def p(text, style=BODY): return Paragraph(text, style)
def pb(text): return Paragraph(text, BODY_B)
def ps(text): return Paragraph(text, SMALL)
def sp(h=2): return Spacer(1, h*mm)
# ── Helper: section header bar ─────────────────────────────────────────────────
def sec_bar(text, bg=BLUE_MID, full_width=True):
col_w = (W - 24*mm) # total usable width
tbl = Table([[p(text, SEC)]], colWidths=[col_w])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
]))
return tbl
# ── Helper: two-column section bar ─────────────────────────────────────────────
HALF = (W - 24*mm) / 2 - 1*mm
def two_sec_bars(left_text, right_text):
row = [p(left_text, SEC), p(right_text, SEC)]
tbl = Table([row], colWidths=[HALF, HALF])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), BLUE_MID),
("BACKGROUND", (1,0), (1,0), RED_DARK),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("LINEAFTER", (0,0), (0,-1), 2, WHITE),
]))
return tbl
# ── Helper: styled data table ──────────────────────────────────────────────────
def make_table(data, col_widths, header_bg=BLUE_LIGHT, alt_bg=GRAY_LIGHT):
"""data[0] = header row (bold), rest = body rows."""
styled_data = []
for i, row in enumerate(data):
styled_row = []
for cell in row:
if isinstance(cell, str):
if i == 0:
styled_row.append(pb(cell))
else:
styled_row.append(p(cell))
else:
styled_row.append(cell)
styled_data.append(styled_row)
tbl = Table(styled_data, colWidths=col_widths, repeatRows=1)
style_cmds = [
("BACKGROUND", (0,0), (-1,0), header_bg),
("LINEBELOW", (0,0), (-1,0), 0.5, BLUE_MID),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#cccccc")),
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 3),
("RIGHTPADDING", (0,0), (-1,-1), 3),
("VALIGN", (0,0), (-1,-1), "TOP"),
]
for i in range(1, len(styled_data)):
if i % 2 == 0:
style_cmds.append(("BACKGROUND", (0,i), (-1,i), alt_bg))
tbl.setStyle(TableStyle(style_cmds))
return tbl
# ══════════════════════════════════════════════════════════════════════════════
# BUILD CONTENT
# ══════════════════════════════════════════════════════════════════════════════
story = []
TW = W - 24*mm # total usable width
# ── TITLE BLOCK ────────────────────────────────────────────────────────────────
title_tbl = Table(
[[p("POTASSIUM DISORDERS — MANAGEMENT REFERENCE CARD", TITLE)],
[p("Hypokalemia · Hyperkalemia · Pharmacology", SUBTITLE)]],
colWidths=[TW]
)
title_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), BLUE_DARK),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("ROUNDEDCORNERS", [4]),
]))
story.append(title_tbl)
story.append(sp(2))
# ── NORMAL VALUES + CLASSIFICATION (side-by-side) ─────────────────────────────
story.append(two_sec_bars("HYPOKALEMIA (K⁺ < 3.5 mEq/L)", "HYPERKALEMIA (K⁺ > 5.0 mEq/L)"))
class_data = [
["Severity", "K⁺ (mEq/L)", "Severity", "K⁺ (mEq/L)"],
["Mild", "3.0 – 3.5", "Mild", "5.5 – 6.0"],
["Moderate", "2.5 – 3.0", "Moderate", "6.1 – 6.9"],
["Severe", "< 2.5", "Severe", "≥ 7.0"],
]
cw = [TW*0.15, TW*0.10, TW*0.15, TW*0.10] # only 4 cols; fill remaining
full_cw = [TW*0.175, TW*0.135, TW*0.175, TW*0.135]
class_tbl = make_table(class_data, full_cw, header_bg=BLUE_LIGHT)
# recolour hyperK header cols
class_tbl.setStyle(TableStyle([
("BACKGROUND", (2,0), (3,0), RED_LIGHT),
("LINEAFTER", (1,0), (1,-1), 1, BLUE_MID),
]))
story.append(class_tbl)
story.append(sp(1))
# Rule of thumb
rule_tbl = Table(
[[p("📌 Rule: each 0.3 mEq/L drop below normal ≈ 100 mEq total body K⁺ deficit", WARN)]],
colWidths=[TW]
)
rule_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), AMBER),
("TOPPADDING", (0,0), (-1,-1), 3), ("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("BOX", (0,0), (-1,-1), 0.5, colors.HexColor("#e6a817")),
]))
story.append(rule_tbl)
story.append(sp(2))
# ── ECG CHANGES (side-by-side) ─────────────────────────────────────────────────
story.append(two_sec_bars("ECG CHANGES — HYPOKALEMIA", "ECG CHANGES — HYPERKALEMIA"))
ecg_data = [
["Hypokalemia ECG Findings", "Hyperkalemia ECG Findings (sequential)"],
["• Flat / inverted T waves", "① Peaked (tented) T waves (K⁺ ~5.5–6.5)"],
["• Prominent U waves (after T wave)","② PR prolongation → P wave disappears"],
["• ST-segment depression", "③ Wide QRS complex (K⁺ ~6.5–7.5)"],
["• Prolonged QT interval", "④ Sine-wave pattern (K⁺ > 7–8)"],
["• QT > 500 ms → Torsades risk 2-3×","⑤ VF / Asystole → DEATH"],
]
ecg_tbl = make_table(ecg_data, [TW*0.5 - 1*mm, TW*0.5 - 1*mm],
header_bg=BLUE_LIGHT)
ecg_tbl.setStyle(TableStyle([
("BACKGROUND", (1,0), (1,0), RED_LIGHT),
("BACKGROUND", (1,5), (1,5), RED_LIGHT),
("LINEAFTER", (0,0), (0,-1), 1, BLUE_MID),
]))
story.append(ecg_tbl)
story.append(sp(1))
note_tbl = Table(
[[p("⚠ Hypocalcemia, hyponatremia, and acidosis accentuate cardiac toxicity of hyperkalemia", WARN)]],
colWidths=[TW]
)
note_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), RED_LIGHT),
("TOPPADDING", (0,0), (-1,-1), 2), ("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 5),
("BOX", (0,0), (-1,-1), 0.5, RED_DARK),
]))
story.append(note_tbl)
story.append(sp(3))
# ══ HYPOKALEMIA TREATMENT ══════════════════════════════════════════════════════
story.append(sec_bar("▶ TREATMENT OF HYPOKALEMIA"))
story.append(sp(1))
# Oral replacement
oral_data = [
["Drug", "Route", "Dose", "Notes"],
["Potassium Chloride (KCl)","Oral", "40–60 mEq q2–4h; maint 60–80 mEq/day",
"Drug of choice. Corrects co-existing hypochloremic alkalosis"],
["KCl", "IV", "10–20 mEq/hr peripheral\n(max 8 mEq/hr to avoid vein irritation)",
"For severe/symptomatic or ECG changes"],
["KCl", "IV central","Up to 20 mEq/hr",
"K⁺ < 2.0 or QT > 500 ms. Continuous ECG monitoring mandatory"],
["Potassium bicarbonate/citrate","Oral","As required",
"Preferred when metabolic acidosis is also present"],
]
oral_tbl = make_table(oral_data, [TW*0.22, TW*0.10, TW*0.30, TW*0.38], header_bg=BLUE_LIGHT)
story.append(oral_tbl)
story.append(sp(1))
iv_warn = Table([[p("⚠ IV diluent: use Normal Saline — NOT dextrose (insulin released by dextrose drives K⁺ into cells, worsening hypokalemia) | Max daily dose: 240 mEq/day", WARN)]], colWidths=[TW])
iv_warn.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), AMBER),
("TOPPADDING", (0,0), (-1,-1), 2), ("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 5),
("BOX", (0,0), (-1,-1), 0.5, colors.HexColor("#e6a817")),
]))
story.append(iv_warn)
story.append(sp(2))
# K-sparing drugs
story.append(sec_bar("▶ K⁺-SPARING DRUGS (Prevention / Diuretic-Induced Hypokalemia)", bg=BLUE_MID))
story.append(sp(1))
ksp_data = [
["Drug", "Class", "Mechanism", "Dose"],
["Spironolactone", "Aldosterone antagonist", "Blocks mineralocorticoid receptor → ↓ K⁺ secretion in collecting duct", "25–100 mg/day"],
["Eplerenone", "Selective aldo. antagonist", "Same; fewer hormonal SE (no gynaecomastia)","25–50 mg/day"],
["Amiloride", "ENaC blocker", "Blocks Na⁺ channel in collecting duct → ↓ electrochemical gradient for K⁺ secretion","5–10 mg/day"],
["Triamterene", "ENaC blocker", "Same mechanism as amiloride", "50–150 mg/day"],
["ACEi / ARBs", "RAAS inhibitors", "↓ Angiotensin II → ↓ aldosterone → ↓ K⁺ excretion","As per indication"],
["Fludrocortisone", "Mineralocorticoid", "Replacement in hypoaldosteronism-driven hypoK⁺","0.1 mg/day"],
]
ksp_tbl = make_table(ksp_data, [TW*0.18, TW*0.20, TW*0.40, TW*0.22], header_bg=BLUE_LIGHT)
story.append(ksp_tbl)
story.append(sp(1))
mg_box = Table([[p("🔑 Always check and correct hypomagnesemia — Mg²⁺ deficiency impairs renal K⁺ conservation; K⁺ replacement will FAIL until Mg²⁺ is corrected", WARN)]], colWidths=[TW])
mg_box.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), GREEN_LIGHT),
("TOPPADDING", (0,0), (-1,-1), 3), ("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("BOX", (0,0), (-1,-1), 0.5, colors.HexColor("#1e8449")),
]))
story.append(mg_box)
story.append(sp(3))
# ══ HYPERKALEMIA TREATMENT ════════════════════════════════════════════════════
story.append(sec_bar("▶ TREATMENT OF HYPERKALEMIA — 3-STEP APPROACH", bg=RED_DARK))
story.append(sp(1))
steps_data = [
["Step", "Goal", "Drug / Intervention", "Dose", "Onset", "K⁺ Effect"],
["1", "Stabilise cardiac membrane", "Calcium gluconate 10% IV", "10 mL (1 g) over 2–3 min; repeat ×1 after 5 min","1–3 min","None (cardioprotective only)"],
["1", "Stabilise cardiac membrane", "Calcium chloride 10% IV", "5–10 mL; prefer central line (tissue necrosis risk)","1–3 min","None"],
["2", "Shift K⁺ into cells", "Regular Insulin + Dextrose 50%", "Insulin 10 U IV + Dextrose 25 g IV\n(5 U if renal failure)","<15 min","↓ ~0.6 mEq/L"],
["2", "Shift K⁺ into cells", "Salbutamol (Albuterol) nebulised","10–15 mg continuous nebulisation", "<15 min", "↓ 0.5–1.0 mEq/L"],
["2", "Shift K⁺ into cells", "Sodium Bicarbonate IV", "50–100 mEq over 5–10 min", "~15 min", "Modest (use only if acidosis present)"],
["3", "Remove K⁺ from body", "Furosemide IV", "Slow infusion (rate per clinical need); add NaCl if hypovolaemic","Minutes–hours","Definitive (intact renal fn)"],
["3", "Remove K⁺ from body", "Patiromer (Veltassa)", "8.4 g oral daily; titrate", "Hours", "Chronic use only — NOT acute"],
["3", "Remove K⁺ from body", "Sodium Zirconium Cyclosilicate (Lokelma)","10 g oral TDS × 48 h, then 5–10 g/day","~4 h","Chronic — NOT acute emergency"],
["3", "Remove K⁺ from body", "Haemodialysis", "Emergent", "Immediate", "↓ ~1 mEq/L/hr; definitive in renal failure"],
]
hyper_tbl = make_table(steps_data,
[TW*0.04, TW*0.12, TW*0.22, TW*0.26, TW*0.10, TW*0.26],
header_bg=RED_LIGHT)
# colour step rows
hyper_tbl.setStyle(TableStyle([
("BACKGROUND", (0,1), (0,2), colors.HexColor("#d6eaf8")), # step 1 blue
("BACKGROUND", (0,3), (0,5), GREEN_LIGHT), # step 2 green
("BACKGROUND", (0,6), (0,9), colors.HexColor("#fde8e8")), # step 3 red
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("ALIGN", (0,0), (0,-1), "CENTER"),
]))
story.append(hyper_tbl)
story.append(sp(1))
sps_warn = Table([[p("⚠ Sodium Polystyrene Sulfonate (Kayexalate / SPS): NOT recommended — onset > 4 h (ineffective acutely); FDA black-box warning — risk of intestinal necrosis", WARN)]], colWidths=[TW])
sps_warn.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), RED_LIGHT),
("TOPPADDING", (0,0), (-1,-1), 3), ("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("BOX", (0,0), (-1,-1), 0.5, RED_DARK),
]))
story.append(sps_warn)
story.append(sp(1))
# Digoxin note
dig_box = Table([[p("⚠ Calcium in digoxin toxicity: potentiates digoxin cardiac toxicity — administer slowly with ECG monitoring. Insulin without dextrose if glucose > 250 mg/dL.", WARN)]], colWidths=[TW])
dig_box.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), AMBER),
("TOPPADDING", (0,0), (-1,-1), 2), ("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 5),
("BOX", (0,0), (-1,-1), 0.5, colors.HexColor("#e6a817")),
]))
story.append(dig_box)
story.append(sp(3))
# ── DRUGS CAUSING HYPERKALEMIA ─────────────────────────────────────────────────
story.append(sec_bar("▶ DRUGS CAUSING HYPERKALEMIA — IDENTIFY & STOP", bg=RED_DARK))
story.append(sp(1))
cause_data = [
["Drug / Class", "Mechanism"],
["ACE inhibitors / ARBs", "↓ Angiotensin II → ↓ Aldosterone → ↓ K⁺ excretion"],
["Spironolactone / Amiloride / Triamterene","K⁺-sparing action in collecting duct"],
["NSAIDs", "↓ Renin → ↓ Aldosterone (type IV RTA pattern)"],
["Beta-blockers", "Impair intracellular K⁺ uptake via β₂ blockade"],
["Succinylcholine", "Depolarising block → K⁺ efflux from muscle. CONTRAINDICATED in hyperkalemia"],
["Heparin", "↓ Adrenal aldosterone synthesis"],
["Digoxin overdose", "Inhibits Na⁺/K⁺-ATPase → K⁺ leaks out of cells"],
["Potassium supplements / K⁺ penicillin","Exogenous K⁺ load"],
]
cause_tbl = make_table(cause_data, [TW*0.35, TW*0.65], header_bg=RED_LIGHT)
story.append(cause_tbl)
story.append(sp(3))
# ── QUICK COMPARISON TABLE ────────────────────────────────────────────────────
story.append(sec_bar("▶ QUICK COMPARISON SUMMARY", bg=BLUE_DARK))
story.append(sp(1))
comp_data = [
["Feature", "HYPOKALEMIA", "HYPERKALEMIA"],
["K⁺ level", "< 3.5 mEq/L", "> 5.0 mEq/L"],
["ECG hallmark", "Flat T, prominent U wave, ↑QT", "Peaked T → sine wave → VF"],
["Immediate drug", "KCl oral 40–60 mEq q2–4h", "Ca gluconate 10 mL IV"],
["Temporising", "—", "Insulin 10U + Dextrose 25g IV"],
["Adjunct shift", "—", "Albuterol 10–15 mg nebulised"],
["Definitive removal", "—", "Dialysis (renal failure); Furosemide (intact kidneys)"],
["Chronic oral drug", "KCl + K⁺-sparing diuretic", "Patiromer / SZC (Lokelma)"],
["Key co-deficiency", "Hypomagnesemia — must correct first", "—"],
["Avoid", "Dextrose IVF alone; delay in Mg²⁺ correction", "Succinylcholine; K⁺-containing IVF; SPS acutely"],
["Digoxin interaction", "↓ K⁺ potentiates digoxin toxicity", "Ca²⁺ potentiates digoxin toxicity"],
["Target K⁺ in HF/MI", "4.0 – 5.0 mEq/L", "< 5.0 mEq/L"],
]
comp_tbl = make_table(comp_data, [TW*0.22, TW*0.39, TW*0.39], header_bg=BLUE_LIGHT)
comp_tbl.setStyle(TableStyle([
("BACKGROUND", (2,0), (2,0), RED_LIGHT),
("LINEAFTER", (0,0), (0,-1), 0.5, BLUE_MID),
("LINEAFTER", (1,0), (1,-1), 0.5, BLUE_MID),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
]))
story.append(comp_tbl)
story.append(sp(2))
# ── FOOTER ─────────────────────────────────────────────────────────────────────
story.append(HRFlowable(width=TW, thickness=0.5, color=BLUE_MID))
story.append(sp(1))
story.append(p("Sources: Katzung's Basic & Clinical Pharmacology 16e · Morgan & Mikhail's Clinical Anesthesiology 7e · Rosen's Emergency Medicine 9e · Barash's Clinical Anesthesia 9e | For educational use only", FOOT))
# ── BUILD ──────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created: {OUTPUT}")
cd /home/daytona/workspace/potassium-refcard && python3 build_refcard.py 2>&1
ls -lh /home/daytona/workspace/potassium-refcard/Potassium_Management_Refcard.pd…
Potassium Management Refcard
PDF Document · PDF
Generate a quick-reference Word document with case scenarios fvc
ls /home/daytona/skills/docx/scripts/office/ && node --version && ls /home/dayto…
mkdir -p /home/daytona/workspace/potassium-docx && ls /home/daytona/skills/docx/…
~/potassium-docx/build.js
"use strict";
const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
HeadingLevel, AlignmentType, BorderStyle, WidthType, ShadingType,
VerticalAlign, PageNumber, Header, Footer, ImageRun, TableOfContents,
PageBreak, convertInchesToTwip, UnderlineType
} = require("docx");
const fs = require("fs");
// ── Colour palette ─────────────────────────────────────────────────────────
const BLUE_DARK = "1A3A5C";
const BLUE_MID = "1E6091";
const BLUE_LIGHT = "D6EAF8";
const RED_DARK = "7B1A1A";
const RED_LIGHT = "FDE8E8";
const AMBER = "FFF3CD";
const GREEN_DARK = "1A5C2A";
const GREEN_LIGHT= "D5F5E3";
const ORANGE = "F0A500";
const GRAY_LIGHT = "F4F6F8";
const WHITE = "FFFFFF";
const BLACK = "1A1A1A";
// ── Helpers ────────────────────────────────────────────────────────────────
const pt = (n) => n * 20; // half-points → twips for spacing
function run(text, opts = {}) {
return new TextRun({
text,
font: "Calibri",
size: opts.size || 20,
bold: opts.bold || false,
italics: opts.italic || false,
color: opts.color || BLACK,
highlight: opts.highlight || undefined,
underline: opts.underline ? { type: UnderlineType.SINGLE } : undefined,
});
}
function para(children, opts = {}) {
const runs = children.map((c) =>
typeof c === "string" ? run(c, opts) : c
);
return new Paragraph({
children: runs,
alignment: opts.align || AlignmentType.LEFT,
spacing: { before: opts.before || 40, after: opts.after || 40 },
indent: opts.indent ? { left: convertInchesToTwip(0.25) } : undefined,
});
}
function headingPara(text, level, color = WHITE, bg = BLUE_DARK) {
return new Paragraph({
children: [new TextRun({ text, font: "Calibri", size: level === 1 ? 28 : level === 2 ? 24 : 22, bold: true, color })],
heading: level === 1 ? HeadingLevel.HEADING_1 : level === 2 ? HeadingLevel.HEADING_2 : HeadingLevel.HEADING_3,
alignment: AlignmentType.LEFT,
spacing: { before: 120, after: 60 },
shading: { type: ShadingType.CLEAR, fill: bg },
});
}
function sectionBar(text, bg = BLUE_MID) {
return new Paragraph({
children: [new TextRun({ text: " " + text, font: "Calibri", size: 22, bold: true, color: WHITE })],
alignment: AlignmentType.LEFT,
spacing: { before: 160, after: 60 },
shading: { type: ShadingType.CLEAR, fill: bg },
});
}
function noteBox(text, fill = AMBER, textColor = "7B4F00") {
return new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [new TableRow({ children: [
new TableCell({
width: { size: 100, type: WidthType.PERCENTAGE },
shading: { type: ShadingType.CLEAR, fill },
borders: allBorders("B8860B", 8),
children: [new Paragraph({
children: [new TextRun({ text, font: "Calibri", size: 18, bold: true, color: textColor })],
spacing: { before: 60, after: 60 },
indent: { left: convertInchesToTwip(0.1) },
})],
}),
]})]
});
}
function allBorders(color = "AAAAAA", sz = 4) {
const b = { style: BorderStyle.SINGLE, size: sz, color };
return { top: b, bottom: b, left: b, right: b, insideHorizontal: b, insideVertical: b };
}
function headerRow(cells, widths, bg = BLUE_LIGHT) {
return new TableRow({
tableHeader: true,
children: cells.map((text, i) =>
new TableCell({
width: { size: widths[i], type: WidthType.PERCENTAGE },
shading: { type: ShadingType.CLEAR, fill: bg },
verticalAlign: VerticalAlign.CENTER,
children: [new Paragraph({
children: [new TextRun({ text, font: "Calibri", size: 19, bold: true, color: BLACK })],
spacing: { before: 40, after: 40 },
indent: { left: convertInchesToTwip(0.05) },
})],
})
),
});
}
function dataRow(cells, widths, bg = WHITE, textColor = BLACK, bold = false) {
return new TableRow({
children: cells.map((text, i) =>
new TableCell({
width: { size: widths[i], type: WidthType.PERCENTAGE },
shading: { type: ShadingType.CLEAR, fill: bg },
verticalAlign: VerticalAlign.TOP,
children: [new Paragraph({
children: [new TextRun({ text, font: "Calibri", size: 18, color: textColor, bold })],
spacing: { before: 30, after: 30 },
indent: { left: convertInchesToTwip(0.05) },
})],
})
),
});
}
function makeTable(headers, rows, widths, headerBg = BLUE_LIGHT) {
const allRows = [headerRow(headers, widths, headerBg)];
rows.forEach((r, i) => allRows.push(dataRow(r, widths, i % 2 === 0 ? WHITE : GRAY_LIGHT)));
return new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: allRows,
borders: allBorders("CCCCCC", 4),
});
}
// ── Case scenario builder ──────────────────────────────────────────────────
function caseScenario(num, title, bg, accentBg, accentColor, fields) {
// fields: { presentation, labs, ecg, diagnosis, management, keyPearl }
const items = [];
// Case title bar
items.push(new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [new TableRow({ children: [
new TableCell({
shading: { type: ShadingType.CLEAR, fill: bg },
borders: allBorders(bg, 0),
children: [new Paragraph({
children: [
new TextRun({ text: ` CASE ${num}: `, font: "Calibri", size: 24, bold: true, color: WHITE }),
new TextRun({ text: title, font: "Calibri", size: 24, bold: true, color: WHITE }),
],
spacing: { before: 80, after: 80 },
})],
}),
]})]
}));
// 2-col layout: Presentation | Labs + ECG
items.push(new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [new TableRow({ children: [
// Left cell: Presentation
new TableCell({
width: { size: 48, type: WidthType.PERCENTAGE },
shading: { type: ShadingType.CLEAR, fill: WHITE },
borders: allBorders("DDDDDD", 4),
children: [
new Paragraph({ children: [new TextRun({ text: "PRESENTATION", font: "Calibri", size: 19, bold: true, color: bg })], spacing: { before: 50, after: 30 }, indent: { left: convertInchesToTwip(0.05) } }),
new Paragraph({ children: [new TextRun({ text: fields.presentation, font: "Calibri", size: 18, color: BLACK })], spacing: { before: 20, after: 40 }, indent: { left: convertInchesToTwip(0.05) } }),
],
}),
// Right cell: Labs + ECG
new TableCell({
width: { size: 52, type: WidthType.PERCENTAGE },
shading: { type: ShadingType.CLEAR, fill: GRAY_LIGHT },
borders: allBorders("DDDDDD", 4),
children: [
new Paragraph({ children: [new TextRun({ text: "LABS & ECG", font: "Calibri", size: 19, bold: true, color: bg })], spacing: { before: 50, after: 30 }, indent: { left: convertInchesToTwip(0.05) } }),
new Paragraph({ children: [new TextRun({ text: fields.labs, font: "Calibri", size: 18, color: BLACK })], spacing: { before: 20, after: 20 }, indent: { left: convertInchesToTwip(0.05) } }),
new Paragraph({ children: [new TextRun({ text: "ECG: " + fields.ecg, font: "Calibri", size: 18, bold: false, color: BLACK })], spacing: { before: 10, after: 40 }, indent: { left: convertInchesToTwip(0.05) } }),
],
}),
]})]
}));
// Diagnosis row
items.push(new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [new TableRow({ children: [
new TableCell({
shading: { type: ShadingType.CLEAR, fill: accentBg },
borders: allBorders(bg, 6),
children: [new Paragraph({
children: [
new TextRun({ text: "DIAGNOSIS: ", font: "Calibri", size: 20, bold: true, color: bg }),
new TextRun({ text: fields.diagnosis, font: "Calibri", size: 20, bold: true, color: accentColor }),
],
spacing: { before: 60, after: 60 },
indent: { left: convertInchesToTwip(0.1) },
})],
}),
]})]
}));
// Management table
items.push(new Paragraph({
children: [new TextRun({ text: " MANAGEMENT STEPS", font: "Calibri", size: 20, bold: true, color: WHITE })],
shading: { type: ShadingType.CLEAR, fill: bg },
spacing: { before: 60, after: 40 },
}));
items.push(makeTable(
["Step", "Action", "Drug / Dose", "Rationale"],
fields.management,
[8, 22, 38, 32],
accentBg
));
// Key Pearl
items.push(noteBox("💡 KEY PEARL: " + fields.keyPearl, accentBg, accentColor));
items.push(new Paragraph({ children: [], spacing: { before: 80, after: 20 } }));
return items;
}
// ══════════════════════════════════════════════════════════════════════════════
// DOCUMENT CONTENT
// ══════════════════════════════════════════════════════════════════════════════
const content = [];
// ── Title Block ────────────────────────────────────────────────────────────
content.push(new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [new TableCell({
shading: { type: ShadingType.CLEAR, fill: BLUE_DARK },
borders: allBorders(BLUE_DARK, 0),
children: [
new Paragraph({
children: [new TextRun({ text: "POTASSIUM DISORDERS", font: "Calibri", size: 40, bold: true, color: WHITE })],
alignment: AlignmentType.CENTER, spacing: { before: 120, after: 40 },
}),
new Paragraph({
children: [new TextRun({ text: "Quick-Reference Guide with Clinical Case Scenarios", font: "Calibri", size: 24, color: "AAD4F5", italics: true })],
alignment: AlignmentType.CENTER, spacing: { before: 0, after: 60 },
}),
new Paragraph({
children: [new TextRun({ text: "Hypokalemia · Hyperkalemia · Pharmacology · KD Tripathi Style", font: "Calibri", size: 20, color: "7FB8E8" })],
alignment: AlignmentType.CENTER, spacing: { before: 0, after: 100 },
}),
],
})})]
]
}));
content.push(new Paragraph({ children: [], spacing: { before: 60, after: 20 } }));
// ══ SECTION 1: Classification ═════════════════════════════════════════════
content.push(sectionBar("1. CLASSIFICATION & SEVERITY", BLUE_MID));
content.push(makeTable(
["Disorder", "Definition", "Mild", "Moderate", "Severe"],
[
["Hypokalemia", "Serum K⁺ < 3.5 mEq/L", "3.0–3.5 mEq/L", "2.5–3.0 mEq/L", "< 2.5 mEq/L"],
["Hyperkalemia", "Serum K⁺ > 5.0 mEq/L", "5.5–6.0 mEq/L", "6.1–6.9 mEq/L", "≥ 7.0 mEq/L"],
],
[18, 28, 18, 18, 18],
BLUE_LIGHT
));
content.push(noteBox("📌 Rule: Each 0.3 mEq/L drop below normal ≈ 100 mEq total body K⁺ deficit | Normal K⁺: 3.5–5.0 mEq/L", AMBER, "7B4F00"));
// ══ SECTION 2: ECG Changes ════════════════════════════════════════════════
content.push(sectionBar("2. ECG CHANGES", BLUE_MID));
content.push(makeTable(
["Hypokalemia — ECG Findings", "Hyperkalemia — ECG Sequence"],
[
["Flat / inverted T waves", "① Peaked (tented) T waves (K⁺ ~5.5–6.5 mEq/L)"],
["Prominent U waves (after T wave)", "② Prolonged PR interval"],
["ST-segment depression", "③ P wave disappears (K⁺ ~6.5–7.5 mEq/L)"],
["Prolonged QT interval", "④ Wide QRS complex"],
["QT > 500 ms → Torsades de Pointes (2–3× risk)", "⑤ Sine-wave pattern → VF / Asystole (K⁺ > 7–8)"],
],
[50, 50],
BLUE_LIGHT
));
content.push(noteBox("⚠ Hypocalcaemia, hyponatraemia, and acidosis ACCENTUATE cardiac toxicity of hyperkalemia", RED_LIGHT, RED_DARK));
// ══ SECTION 3: Hypokalemia Treatment ══════════════════════════════════════
content.push(sectionBar("3. TREATMENT OF HYPOKALEMIA", BLUE_MID));
content.push(makeTable(
["Drug", "Route", "Dose", "Notes"],
[
["Potassium Chloride (KCl)", "Oral", "40–60 mEq q2–4h; maintenance 60–80 mEq/day", "Drug of choice. Corrects co-existing hypochloraemic alkalosis"],
["KCl", "IV Peripheral", "10 mEq/hr (max 20 mEq/hr); max 8 mEq/hr to avoid vein irritation", "For symptomatic/moderate hypokalemia"],
["KCl", "IV Central", "Up to 20 mEq/hr with continuous ECG monitoring", "K⁺ < 2.0 mEq/L or QT > 500 ms. Central access mandatory"],
["Potassium bicarbonate / citrate", "Oral", "As required", "Use when metabolic acidosis co-exists"],
["Magnesium sulfate (MgSO₄)", "IV", "1–2 g IV over 10–20 min", "Correct hypomagnesaemia first — K⁺ replacement will fail otherwise"],
],
[18, 14, 36, 32],
BLUE_LIGHT
));
content.push(noteBox("⚠ IV diluent: Normal Saline ONLY — NOT Dextrose (dextrose → insulin release → K⁺ driven intracellularly → worsens hypokalemia) | Max daily IV dose: 240 mEq/day", AMBER, "7B4F00"));
// K+ sparing
content.push(new Paragraph({ children: [new TextRun({ text: "Potassium-Sparing Drugs (Prevention / Diuretic-Induced Hypokalemia)", font: "Calibri", size: 20, bold: true, color: BLUE_MID })], spacing: { before: 100, after: 40 } }));
content.push(makeTable(
["Drug", "Class", "Mechanism", "Dose"],
[
["Spironolactone", "Aldosterone antagonist", "Blocks mineralocorticoid receptor → ↓ K⁺ secretion in collecting duct", "25–100 mg/day"],
["Eplerenone", "Selective aldo. antagonist", "Same; no gynaecomastia (selective for MR)", "25–50 mg/day"],
["Amiloride", "ENaC blocker", "Blocks luminal Na⁺ channel → ↓ electrochemical gradient for K⁺ secretion", "5–10 mg/day"],
["Triamterene", "ENaC blocker", "Same as amiloride", "50–150 mg/day"],
["ACEi / ARBs", "RAAS inhibitors", "↓ Angiotensin II → ↓ aldosterone → ↓ K⁺ excretion", "As per indication"],
["Fludrocortisone", "Mineralocorticoid replacement", "Used when hypoaldosteronism drives K⁺ loss", "0.1 mg/day"],
],
[18, 22, 40, 20],
BLUE_LIGHT
));
// ══ SECTION 4: Hyperkalemia Treatment ═════════════════════════════════════
content.push(sectionBar("4. TREATMENT OF HYPERKALEMIA — 3-STEP APPROACH", RED_DARK));
content.push(makeTable(
["Step", "Goal", "Drug / Intervention", "Dose", "Onset", "K⁺ Effect"],
[
["1", "Stabilise cardiac membrane", "Calcium gluconate 10%", "10 mL (1 g) IV over 2–3 min; repeat after 5 min if no response", "1–3 min", "None (cardioprotective only)"],
["1", "Stabilise cardiac membrane", "Calcium chloride 10%", "5–10 mL IV; prefer central line (tissue necrosis if extravasated)", "1–3 min", "None"],
["2", "Shift K⁺ into cells", "Regular Insulin + Dextrose 50%", "Insulin 10 U IV bolus + Dextrose 25 g IV (use 5 U if renal failure)", "<15 min", "↓ ~0.6 mEq/L"],
["2", "Shift K⁺ into cells", "Salbutamol (Albuterol) nebulised", "10–15 mg continuous nebulisation", "<15 min", "↓ 0.5–1.0 mEq/L"],
["2", "Shift K⁺ into cells", "Sodium Bicarbonate IV", "50–100 mEq over 5–10 min", "~15 min", "Modest; use only if metabolic acidosis present"],
["3", "Remove K⁺ from body", "Furosemide IV", "Slow infusion; supplement NaCl + H₂O if hypovolaemic", "Minutes–hours", "Definitive (intact renal function only)"],
["3", "Remove K⁺ from body", "Patiromer (Veltassa)", "8.4 g oral daily; titrate up", "Hours", "Chronic use only — NOT for acute emergency"],
["3", "Remove K⁺ from body", "Sodium Zirconium Cyclosilicate (Lokelma / SZC)", "10 g oral TDS × 48 h, then 5–10 g/day", "~4 hours", "Chronic — NOT acute emergency"],
["3", "Remove K⁺ from body", "Haemodialysis", "Emergent — institute early in renal failure", "Immediate", "↓ ~1 mEq/L/hr; definitive in renal failure"],
],
[5, 16, 20, 26, 10, 23],
RED_LIGHT
));
content.push(noteBox("⚠ Sodium Polystyrene Sulfonate (Kayexalate/SPS): NOT recommended acutely — onset > 4h; FDA black-box warning for intestinal necrosis", RED_LIGHT, RED_DARK));
content.push(noteBox("⚠ In digoxin toxicity: Calcium potentiates digoxin toxicity — give slowly with ECG monitoring. Give Insulin without Dextrose if blood glucose > 250 mg/dL.", AMBER, "7B4F00"));
// Drugs causing hyperK
content.push(new Paragraph({ children: [new TextRun({ text: "Drugs Causing Hyperkalemia — Identify and Stop", font: "Calibri", size: 20, bold: true, color: RED_DARK })], spacing: { before: 100, after: 40 } }));
content.push(makeTable(
["Drug / Class", "Mechanism"],
[
["ACE inhibitors / ARBs", "↓ Angiotensin II → ↓ Aldosterone → ↓ K⁺ excretion"],
["Spironolactone / Amiloride / Triamterene", "Direct K⁺-sparing action in collecting duct"],
["NSAIDs", "↓ Renin → ↓ Aldosterone (Type IV RTA pattern)"],
["Beta-blockers", "Impair intracellular K⁺ uptake via β₂ blockade"],
["Succinylcholine", "Depolarising block → K⁺ efflux from muscle. ABSOLUTELY CONTRAINDICATED"],
["Heparin", "↓ Adrenal aldosterone synthesis"],
["Digoxin overdose", "Inhibits Na⁺/K⁺-ATPase → K⁺ leaks extracellularly"],
["Potassium supplements / K⁺ penicillin", "Exogenous K⁺ load"],
],
[38, 62],
RED_LIGHT
));
// ══ SECTION 5: Comparison Summary ═════════════════════════════════════════
content.push(sectionBar("5. QUICK COMPARISON SUMMARY", BLUE_DARK));
content.push(makeTable(
["Feature", "HYPOKALEMIA", "HYPERKALEMIA"],
[
["K⁺ level", "< 3.5 mEq/L", "> 5.0 mEq/L"],
["ECG hallmark", "Flat T wave, prominent U wave, ↑QT", "Peaked T → wide QRS → sine wave → VF"],
["Immediate drug", "KCl oral 40–60 mEq q2–4h", "Calcium gluconate 10 mL IV"],
["Temporising", "—", "Insulin 10 U + Dextrose 25 g IV"],
["Adjunct shift", "—", "Albuterol 10–15 mg nebulised"],
["Definitive removal", "—", "Dialysis (renal failure); Furosemide (intact kidneys)"],
["Chronic oral drug", "KCl + K⁺-sparing diuretic", "Patiromer / SZC (Lokelma)"],
["Key co-deficiency", "Hypomagnesaemia — correct first", "—"],
["Avoid", "Dextrose IVF alone; delaying Mg²⁺ correction", "Succinylcholine; K⁺-containing IVF; SPS acutely"],
["Digoxin interaction", "↓ K⁺ potentiates digoxin toxicity — replace aggressively", "Ca²⁺ potentiates digoxin toxicity — give cautiously"],
["Target K⁺ in HF/MI", "4.0–5.0 mEq/L", "< 5.0 mEq/L"],
],
[22, 39, 39],
BLUE_LIGHT
));
// ══ SECTION 6: CASE SCENARIOS ═════════════════════════════════════════════
content.push(new Paragraph({ children: [new PageBreak()] }));
content.push(sectionBar("6. CLINICAL CASE SCENARIOS", BLUE_DARK));
content.push(new Paragraph({ children: [], spacing: { before: 20, after: 20 } }));
// ── CASE 1: Diuretic-induced Hypokalemia ────────────────────────────────────
content.push(...caseScenario(
1,
"Diuretic-Induced Hypokalemia",
BLUE_MID, BLUE_LIGHT, BLUE_DARK,
{
presentation: "62-year-old woman with hypertension and heart failure presents with 3 days of generalised weakness, muscle cramps, and palpitations. She has been on furosemide 40 mg/day for the past 2 months.",
labs: "K⁺: 2.8 mEq/L | Mg²⁺: 0.6 mmol/L (low) | Na⁺: 138 mEq/L | Cl⁻: 94 mEq/L (low) | HCO₃⁻: 30 mEq/L | pH: 7.48 (metabolic alkalosis)",
ecg: "Flat T waves, prominent U waves, ST depression, QTc 490 ms",
diagnosis: "Moderate Hypokalemia (K⁺ 2.8 mEq/L) + Hypomagnesaemia + Hypochloraemic Metabolic Alkalosis secondary to furosemide",
management: [
["1", "IV access + Cardiac monitoring", "Continuous ECG; repeat K⁺ q2h", "QTc 490 ms — arrhythmia risk; Mg²⁺ also low"],
["2", "Correct hypomagnesaemia FIRST", "MgSO₄ 2 g IV over 20 min", "K⁺ replacement fails without Mg²⁺ correction"],
["3", "K⁺ replacement — IV", "KCl 20 mEq/hr in Normal Saline × 2 h then reassess", "Use NS NOT dextrose; max 20 mEq/hr peripherally"],
["4", "Continue oral K⁺", "KCl 40–60 mEq oral q4h", "After IV phase; target K⁺ 4.0–5.0 mEq/L"],
["5", "Switch diuretic or add K⁺-sparer", "Spironolactone 25–50 mg/day OR Amiloride 5–10 mg/day", "Prevents recurrence; also beneficial in HF"],
["6", "Monitor closely", "K⁺, Mg²⁺, ECG at 2 h, 6 h, 24 h", "Rapid correction can cause rebound hyperkalemia"],
],
keyPearl: "Hypomagnesaemia is the most common reason potassium replacement fails. ALWAYS check Mg²⁺ and correct it first. Furosemide causes 4 mechanisms of K⁺ loss: ↑ tubular flow, ↑ AVP, ↑ aldosterone, and metabolic alkalosis.",
}
));
// ── CASE 2: Severe Hypokalemia with Arrhythmia ─────────────────────────────
content.push(...caseScenario(
2,
"Severe Hypokalemia — QT Prolongation & Arrhythmia Risk",
BLUE_DARK, BLUE_LIGHT, BLUE_DARK,
{
presentation: "28-year-old woman with anorexia nervosa presents with episodic palpitations, muscle weakness, and inability to walk. She admits to excessive vomiting (>10×/day) for 2 weeks.",
labs: "K⁺: 1.9 mEq/L | Mg²⁺: 0.5 mmol/L | Cl⁻: 82 mEq/L | HCO₃⁻: 34 mEq/L | pH: 7.52",
ecg: "Flat T waves, massive U waves, QTc 560 ms — HIGH risk of Torsades de Pointes",
diagnosis: "Severe Hypokalemia (K⁺ 1.9 mEq/L) with critical QT prolongation — risk of Torsades de Pointes",
management: [
["1", "URGENT IV access + cardiac monitoring", "ICU/HDU admission; continuous ECG", "QTc 560 ms — Torsades de Pointes imminent"],
["2", "Correct Mg²⁺ urgently", "MgSO₄ 2 g IV over 10 min; repeat if needed", "MgSO₄ is also first-line treatment for Torsades"],
["3", "Aggressive IV K⁺ via central line", "KCl 20 mEq/hr centrally × 3–4 h; monitor K⁺ hourly", "Severe K⁺ < 2.0 mEq/L — central line mandatory"],
["4", "Concurrent oral K⁺ top-up", "KCl 40 mEq oral q2h once tolerating orally", "Oral + IV together shortens repletion time"],
["5", "Treat underlying cause", "Antiemetics (ondansetron); nutritional support", "Address vomiting — ongoing losses will outpace replacement"],
["6", "Avoid QT-prolonging drugs", "Withhold azithromycin, haloperidol, ondansetron if QTc > 500", "Additive QT prolongation → increases Torsades risk"],
],
keyPearl: "K⁺ < 2.0 mEq/L or QTc > 500 ms = IV replacement via central line with continuous cardiac monitoring is mandatory. A standard dose of nebulised albuterol reduces K⁺ by 0.2–0.4 mEq/L — avoid in hypokalemia as it worsens it.",
}
));
// ── CASE 3: Hyperkalemia in CKD ────────────────────────────────────────────
content.push(...caseScenario(
3,
"Hyperkalemia in Chronic Kidney Disease",
RED_DARK, RED_LIGHT, RED_DARK,
{
presentation: "58-year-old man with CKD stage 4 (eGFR 18) and type 2 diabetes on ramipril, spironolactone, and trimethoprim presents with generalised weakness and fatigue. No acute complaints.",
labs: "K⁺: 6.4 mEq/L | Creatinine: 340 µmol/L | HCO₃⁻: 17 mEq/L (metabolic acidosis) | Glucose: 8.2 mmol/L",
ecg: "Peaked T waves in V2–V5; PR 210 ms (borderline); QRS 90 ms (normal)",
diagnosis: "Moderate Hyperkalemia (K⁺ 6.4 mEq/L) secondary to CKD + RAAS inhibitors + trimethoprim (blocks tubular K⁺ secretion)",
management: [
["1", "Stop offending drugs", "Withhold ramipril, spironolactone, trimethoprim", "Multiple converging causes of hyperkalemia"],
["2", "Cardiac membrane stabilisation", "Calcium gluconate 10% 10 mL IV over 3 min", "ECG changes present — membrane stabilisation is priority"],
["3", "Shift K⁺ into cells", "Insulin 10 U IV + Dextrose 50 mL (25 g) IV", "Onset <15 min; reduces K⁺ ~0.6 mEq/L"],
["4", "Shift K⁺ — adjunct", "Salbutamol 10 mg nebulised", "Additive with insulin; onset <15 min"],
["5", "Correct metabolic acidosis", "Sodium bicarbonate 50 mEq IV (HCO₃⁻ is 17)", "Acidosis driving K⁺ extracellularly; correction shifts K⁺ back in"],
["6", "Promote K⁺ elimination", "Furosemide 80 mg IV (some renal function remains)", "Enhance urinary K⁺ excretion; monitor response"],
["7", "Chronic management", "Patiromer (Veltassa) 8.4 g oral daily; dietary K⁺ restriction", "Long-term hyperkalemia control in CKD to allow continued ACEi use"],
["8", "Dialysis planning", "Refer nephrology; plan haemodialysis access if K⁺ not controlled", "GFR 18 — may need dialysis soon; K⁺ control essential"],
],
keyPearl: "In CKD, trimethoprim blocks ENaC in collecting duct similar to amiloride — a commonly missed cause of hyperkalemia. RAAS inhibitor-induced hyperkalemia in CKD can be managed with Patiromer or SZC (Lokelma) without withdrawing the cardioprotective RAAS inhibitor.",
}
));
// ── CASE 4: Life-Threatening Hyperkalemia (ECG changes) ────────────────────
content.push(...caseScenario(
4,
"Life-Threatening Hyperkalemia — Cardiac Emergency",
RED_DARK, RED_LIGHT, RED_DARK,
{
presentation: "45-year-old man with end-stage renal disease (on haemodialysis 3×/week) missed his last two dialysis sessions. Brought in by family — unresponsive, bradycardic.",
labs: "K⁺: 8.1 mEq/L | HCO₃⁻: 12 mEq/L | Ca²⁺: 1.9 mmol/L (low)",
ecg: "Absent P waves, QRS width 180 ms, merging into T wave — SINE WAVE PATTERN",
diagnosis: "Severe Life-Threatening Hyperkalemia (K⁺ 8.1 mEq/L) with sine wave ECG — imminent cardiac arrest",
management: [
["1", "IMMEDIATE: Cardiac membrane", "Calcium gluconate 10% 20–30 mL IV rapidly (over 2 min)", "Sine wave = imminent VF. Calcium is the FIRST step — do not delay"],
["2", "Correct hypocalcaemia", "Repeat calcium if no ECG improvement in 5 min", "Hypocalcaemia accentuates cardiac toxicity — correct both"],
["3", "Shift K⁺ — insulin", "Insulin 10 U IV + Dextrose 50 mL IV (withhold glucose if glucose > 250)", "Fastest intracellular shift alongside calcium"],
["4", "Shift K⁺ — beta-agonist", "Salbutamol 10–15 mg nebulised (or IV adrenaline if haemodynamically unstable)", "Additive with insulin; adrenaline also provides inotropic support"],
["5", "Correct acidosis", "Sodium bicarbonate 100 mEq IV (HCO₃⁻ 12 = severe acidosis)", "Severe metabolic acidosis driving K⁺ extracellularly"],
["6", "EMERGENT Haemodialysis", "Institute immediately — call renal team STAT", "ESRD + missed dialysis — only reliable method of K⁺ removal. Target: ↓1 mEq/L per hour"],
["7", "Prepare for resuscitation", "Defibrillator at bedside; ACLS team on standby", "Sine wave → VF arrest can occur any moment"],
],
keyPearl: "In ESRD + missed dialysis, haemodialysis is the ONLY definitive treatment. Medical management (calcium, insulin, bicarbonate, albuterol) buys 60–120 minutes — use this time to set up dialysis. Haemodialysis reduces K⁺ by ~1 mEq/L in the first hour.",
}
));
// ── CASE 5: Drug-induced Hyperkalemia (ACEi + Spironolactone) ───────────────
content.push(...caseScenario(
5,
"Drug-Induced Hyperkalemia — ACEi + Spironolactone",
"8B4513", AMBER, "7B4F00",
{
presentation: "70-year-old woman with heart failure (EF 30%), hypertension, and CKD stage 3 on enalapril 10 mg, spironolactone 50 mg, and ibuprofen (for knee pain). Presents with fatigue and mild confusion.",
labs: "K⁺: 6.1 mEq/L | eGFR: 38 | Na⁺: 136 mEq/L | HCO₃⁻: 20 mEq/L",
ecg: "Peaked T waves in precordial leads; no P wave changes; QRS normal",
diagnosis: "Mild-Moderate Hyperkalemia (K⁺ 6.1 mEq/L) — drug-induced via triple RAAS blockade (ACEi + MRA + NSAID)",
management: [
["1", "Identify and stop offending drug", "Immediately stop IBUPROFEN", "NSAIDs ↓ renin → ↓ aldosterone = additive hyperkalemia. Remove the modifiable cause first"],
["2", "Cardiac membrane stabilisation", "Calcium gluconate 10 mL IV (ECG shows peaked T)", "ECG changes present — membrane stabilisation first"],
["3", "Shift K⁺ into cells", "Insulin 10 U IV + Dextrose 25 g IV", "Temporising measure while planning elimination"],
["4", "Reduce spironolactone dose", "Reduce to 25 mg/day (do not stop if EF 30% — mortality benefit)", "Spironolactone improves survival in systolic HF — dose-reduce not discontinue"],
["5", "Continue enalapril cautiously", "Reduce dose if needed; monitor K⁺ closely", "ACEi is cardioprotective in HF — target K⁺ < 5.5 with monitoring"],
["6", "Chronic K⁺ management", "Patiromer 8.4 g/day orally", "FDA-approved for hyperkalemia in CKD + HF; allows continuation of RAAS inhibitor"],
["7", "Pain management", "Replace ibuprofen with paracetamol", "Safe analgesic without RAAS or renal interaction"],
],
keyPearl: "NSAIDs + ACEi + MRA = 'triple whammy' for hyperkalemia in CKD. Patiromer and SZC (Lokelma) are approved specifically to manage chronic hyperkalemia in CKD/HF patients so that life-saving RAAS inhibitors do NOT need to be withdrawn.",
}
));
// ── CASE 6: Hypokalemia from Beta-2 Agonist Overuse ─────────────────────────
content.push(...caseScenario(
6,
"Hypokalemia — Beta-2 Agonist Overuse in Acute Asthma",
"2E7D32", GREEN_LIGHT, GREEN_DARK,
{
presentation: "19-year-old asthmatic presents in severe bronchospasm. Treated in ED with 5 back-to-back salbutamol (albuterol) 5 mg nebulisations over 1 hour. Post-treatment: tremors, palpitations, muscle weakness.",
labs: "Pre-treatment K⁺: 3.7 mEq/L | Post-treatment K⁺: 2.5 mEq/L | Glucose: 9.1 mmol/L",
ecg: "Sinus tachycardia (HR 118); flattened T waves; prominent U waves; QTc 465 ms",
diagnosis: "Iatrogenic Hypokalemia (K⁺ 2.5 mEq/L) secondary to high-dose nebulised salbutamol in acute asthma",
management: [
["1", "Recognise the cause", "Salbutamol stimulates β₂ → activates Na⁺/K⁺-ATPase → K⁺ shifts intracellularly", "Each 5 mg nebulisation ↓ K⁺ by ~0.2–0.4 mEq/L; 5 doses = ~1–2 mEq/L drop"],
["2", "Cardiac monitoring", "ECG monitoring; repeat K⁺ in 2 hours", "QTc 465 ms — monitor for further prolongation"],
["3", "Oral K⁺ replacement", "KCl 40–60 mEq oral q4h (patient not vomiting)", "Moderate hypokalemia — oral route preferred if tolerated"],
["4", "Check and correct Mg²⁺", "Check serum Mg²⁺; give MgSO₄ 2 g IV if low", "MgSO₄ also relieves bronchospasm — dual benefit in asthma"],
["5", "Space out salbutamol doses", "Extend nebulisation intervals once bronchospasm controlled", "Ongoing salbutamol counteracts K⁺ replacement"],
["6", "Reassess", "K⁺, ECG at 4 h and 8 h", "Hypokalemia typically self-corrects once salbutamol is spaced — redistribution, not total body loss"],
],
keyPearl: "Salbutamol-induced hypokalemia is a REDISTRIBUTION phenomenon (intracellular shift) — total body K⁺ is normal. It does NOT require large K⁺ doses; oral replacement is usually sufficient. It reverses as salbutamol wears off. This is clinically relevant in ICU patients on continuous beta-agonist nebulisation.",
}
));
// ── CASE 7: Hyperkalaemia in Rhabdomyolysis ─────────────────────────────────
content.push(...caseScenario(
7,
"Hyperkalemia in Rhabdomyolysis",
RED_DARK, RED_LIGHT, RED_DARK,
{
presentation: "22-year-old male bodybuilder found collapsed after marathon training in extreme heat. Presents with dark (cola-coloured) urine, severe muscle pain, oliguria, and confusion.",
labs: "K⁺: 6.8 mEq/L | CK: 48,000 U/L | Creatinine: 280 µmol/L (AKI) | Phosphate: 2.1 mmol/L | HCO₃⁻: 16 mEq/L",
ecg: "Peaked T waves; PR 200 ms; QRS 95 ms",
diagnosis: "Moderate Hyperkalemia (K⁺ 6.8 mEq/L) secondary to Rhabdomyolysis with Acute Kidney Injury",
management: [
["1", "Cardiac membrane stabilisation", "Calcium gluconate 10 mL IV over 3 min", "ECG changes present — protect myocardium first"],
["2", "Shift K⁺ — insulin + glucose", "Insulin 10 U IV + Dextrose 25 g IV", "Temporising; K⁺ release from muscle ongoing"],
["3", "Aggressive IV fluids", "Normal saline 1–1.5 L/hr until urine output > 200–300 mL/hr", "Dilutes K⁺; forces urine output; prevents tubular myoglobin precipitation"],
["4", "Loop diuretic + saline", "Furosemide IV once euvolaemic; ensure continued NS infusion", "Enhances urinary K⁺ and myoglobin excretion in rhabdomyolysis"],
["5", "Urinary alkalinisation (optional)", "Sodium bicarbonate added to IV fluid (target urine pH > 6.5)", "Prevents myoglobin precipitation in acidic urine; also corrects acidosis and shifts K⁺ into cells"],
["6", "Monitor K⁺ hourly", "Serial K⁺ + CK + renal function q2–4h", "K⁺ will rise rapidly as muscle continues to lyse — titrate treatment"],
["7", "Haemodialysis if refractory", "Institute if K⁺ > 7 despite above, or oliguria persists", "AKI + rhabdomyolysis = high risk of needing dialysis"],
],
keyPearl: "Rhabdomyolysis releases massive intracellular K⁺ from lysed muscle. Unlike redistribution hyperkalemia, this is TRUE total body K⁺ excess — aggressive IV fluids + furosemide are key. Dialysis must be instituted early if urine output fails to respond.",
}
));
// ── FOOTER NOTE ──────────────────────────────────────────────────────────────
content.push(new Paragraph({ children: [], spacing: { before: 80, after: 20 } }));
content.push(new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [new TableRow({ children: [new TableCell({
shading: { type: ShadingType.CLEAR, fill: GRAY_LIGHT },
borders: allBorders("CCCCCC", 4),
children: [new Paragraph({
children: [new TextRun({ text: "Sources: Katzung's Basic & Clinical Pharmacology 16e · Morgan & Mikhail's Clinical Anesthesiology 7e · Rosen's Emergency Medicine 9e · Barash's Clinical Anesthesia 9e | For educational use only", font: "Calibri", size: 16, color: "888888", italics: true })],
alignment: AlignmentType.CENTER, spacing: { before: 50, after: 50 },
})],
})})]
}));
// ── Build Document ─────────────────────────────────────────────────────────
const doc = new Document({
creator: "Orris Medical Assistant",
title: "Potassium Disorders — Quick Reference with Case Scenarios",
description: "Hypokalemia and Hyperkalemia management pharmacology reference card with clinical cases",
styles: {
default: {
document: { run: { font: "Calibri", size: 20, color: BLACK } },
},
},
sections: [{
properties: {
page: {
margin: { top: 720, right: 720, bottom: 720, left: 720 }, // ~1.27 cm
},
},
headers: {
default: new Header({
children: [new Paragraph({
children: [
new TextRun({ text: "POTASSIUM DISORDERS — Quick Reference | ", font: "Calibri", size: 18, color: "888888" }),
new TextRun({ text: "Hypokalemia & Hyperkalemia Management", font: "Calibri", size: 18, bold: true, color: BLUE_MID }),
],
alignment: AlignmentType.RIGHT,
border: { bottom: { style: BorderStyle.SINGLE, size: 4, color: BLUE_MID } },
})],
}),
},
footers: {
default: new Footer({
children: [new Paragraph({
children: [
new TextRun({ text: "For educational use only | Page ", font: "Calibri", size: 16, color: "888888" }),
new PageNumber(),
],
alignment: AlignmentType.CENTER,
border: { top: { style: BorderStyle.SINGLE, size: 4, color: BLUE_MID } },
})],
}),
},
children: content,
}],
});
const OUTPUT = "/home/daytona/workspace/potassium-docx/Potassium_Disorders_Reference.docx";
Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync(OUTPUT, buffer);
console.log("DOCX created:", OUTPUT);
}).catch(err => { console.error(err); process.exit(1); });
cd /home/daytona/workspace/potassium-docx && node build.js 2>&1
~/potassium-docx/build.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/potassium-docx/build.js'
cd /home/daytona/workspace/potassium-docx && node build.js 2>&1
~/potassium-docx/build.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/potassium-docx/build.js'
cd /home/daytona/workspace/potassium-docx && node --check build.js 2>&1
cd /home/daytona/workspace/potassium-docx && node build.js 2>&1
node -e "const d = require('docx'); console.log(Object.keys(d).filter(k => k.toL…
~/potassium-docx/build.js
Error: String not found in file: ' Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink, InternalHyperlink, Bookmark, FootnoteReferenceRun, PositionalTab, PositionalTabAlignment, PositionalTabRelativeTo, PositionalTabLeader, TabStopType, TabStopPosition, Column, SectionType, TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType, VerticalAlign, PageNumber, Header, Footer, ImageRun, TableOfContents, PageBreak, convertInchesToTwip, UnderlineType'
~/potassium-docx/build.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/potassium-docx/build.js'
~/potassium-docx/build.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/potassium-docx/build.js'
cd /home/daytona/workspace/potassium-docx && node build.js 2>&1 && python3 /home…
ls -lh /home/daytona/workspace/potassium-docx/Potassium_Disorders_Reference.docx
| Case | Scenario |
|---|---|
| 1 | Diuretic-induced hypokalemia (HF patient on furosemide) |
| 2 | Severe hypokalemia with QT prolongation/Torsades risk (anorexia) |
| 3 | Hyperkalemia in CKD (ramipril + spironolactone + trimethoprim) |
| 4 | Life-threatening hyperkalemia in ESRD - sine wave ECG |
| 5 | Drug-induced hyperkalemia - ACEi + MRA + NSAID "triple whammy" |
| 6 | Salbutamol-induced hypokalemia in acute asthma |
| 7 | Hyperkalemia in rhabdomyolysis |
Potassium Disorders Reference
Word Document · DOCX
Difference between obstructive and restrictive lung disease in table

| Feature | Obstructive Lung Disease | Restrictive Lung Disease |
|---|---|---|
| Definition | Small airway obstruction to expiratory flow | Proportional reduction in all lung volumes |
| Primary defect | Increased airway resistance → difficulty expiring | Reduced lung compliance or chest wall expansion → difficulty inspiring |
| Pathophysiology | Airway narrowing (mucus, bronchoconstriction, wall destruction) → air trapping | Stiff lungs (↑ elastic recoil) OR reduced thoracic/neuromuscular expansion |
| Parameter | Obstructive | Restrictive | Notes |
|---|---|---|---|
| FEV₁ | ↓↓ | ↓↓ | Both reduced, but by different mechanisms |
| FVC | Normal or slightly ↓ | ↓↓↓ | Key distinguishing point |
| FEV₁/FVC ratio | ↓↓↓ (<0.70) | Normal or ↑ (>0.70) | Single most important differentiating parameter |
| FEF₂₅₋₇₅% | ↓↓↓ | Normal | Reflects small airway flow; impaired in obstruction |
| TLC | Normal or ↑ (gas trapping/hyperinflation) | ↓↓↓ | Gold standard for confirming restriction |
| RV | ↑ (air trapping) | ↓ | RV increases in obstruction due to early airway closure |
| RV/TLC ratio | ↑ | Normal or ↓ | Elevated ratio = significant air trapping |
| FRC | ↑ (if gas trapping) | ↓↓ | |
| Airway resistance (Raw) | ↑↑ | Normal | Measured by body plethysmography |
| Lung compliance | ↑ (in emphysema - loss of elastic recoil) | ↓ (in parenchymal restriction - stiff lungs) | Opposite directions |
| DLCO | ↓ in emphysema; Normal/↑ in asthma | ↓ in parenchymal restriction (e.g. IPF, sarcoidosis) | Normal in extra-parenchymal restriction |
| Bronchodilator response | Partial/full reversibility (esp. asthma) | No significant response |
Gold standard for restriction: TLC < lower limit of normal (LLN) confirmed by plethysmography. Spirometry alone has only ~50% sensitivity for restriction - TLC must be measured to confirm.
| Feature | Obstructive | Restrictive |
|---|---|---|
| Shape | Expiratory limb concave upward ("scooped") | Steep, narrow, vertically oriented |
| Loop width | Wide or normal (large TLC) | Narrow (small TLC and RV) |
| Peak expiratory flow | Reduced | Normal or mildly reduced |
| Inspiration | Usually normal | Reduced in proportion to VC |
| Pattern descriptor | "Concave upward" | "Convex upward" / steep descent |
| Condition | Site of Obstruction | Key Mechanism |
|---|---|---|
| COPD - Emphysema | Acinus/alveoli | Destruction of alveolar walls → loss of elastic recoil → airway collapse on expiration |
| COPD - Chronic bronchitis | Large and small airways | Mucous gland hyperplasia, secretions, fibrosis → airway narrowing |
| Asthma | Bronchi | Smooth muscle hyperplasia, mucosal oedema, excess mucus → bronchoconstriction (reversible) |
| Bronchiectasis | Bronchi | Airway dilation and scarring from recurrent infection |
| Small airways disease / bronchiolitis | Bronchioles (<2 mm) | Inflammatory scarring/obliteration |
| Upper airway obstruction | Trachea/larynx | Fixed or variable obstruction |
| Category | Examples |
|---|---|
| Parenchymal (intrinsic) | Idiopathic pulmonary fibrosis (IPF), sarcoidosis, hypersensitivity pneumonitis, asbestosis, pneumoconiosis, ARDS |
| Pleural | Pleural effusion, pleural thickening, fibrothorax |
| Chest wall / musculoskeletal | Kyphoscoliosis, ankylosing spondylitis, rib fractures, obesity |
| Neuromuscular | Diaphragm paralysis, Guillain-Barré syndrome, myasthenia gravis, ALS, muscular dystrophy |
| Space-occupying | Massive ascites, pregnancy, large pleural effusion |
In parenchymal restriction: DLCO is reduced and FEV₁/FVC is elevated (high elastic recoil). In extra-parenchymal restriction (neuromuscular, chest wall): DLCO is usually normal.
| Feature | Obstructive | Restrictive |
|---|---|---|
| Primary symptom | Exertional dyspnea + chronic cough ± wheeze | Progressive dyspnea on exertion (often insidious) |
| Sputum | Often present (especially COPD/bronchitis) | Usually absent |
| Wheeze | Common | Absent |
| Breath sounds | Prolonged expiration, decreased air entry, wheeze | Fine inspiratory crackles (Velcro crackles) in ILD |
| Chest shape | Barrel chest (hyperinflation in COPD) | Normal or restricted expansion |
| Cyanosis | Late (hypoxaemia from V/Q mismatch) | Early hypoxaemia in severe ILD |
| Clubbing | Absent (except bronchiectasis) | Present in IPF, asbestosis |
| Cor pulmonale | Late complication (pulmonary HTN from hypoxia) | Can occur in advanced restrictive disease |
| Grade | Obstructive (FEV₁ % predicted) | Restrictive (FVC % predicted) |
|---|---|---|
| Mild | ≥ 70% | 70 – 80% |
| Moderate | 50 – 69% | 60 – 69% |
| Severe | 30 – 49% | 51 – 59% |
| Very severe | < 30% | ≤ 50% |
OBSTRUCTIVE:
FEV₁ ↓ | FVC normal | FEV₁/FVC ↓ | TLC ↑ | RV ↑
Concave expiratory loop | ↑ Raw | ↑ Compliance (emphysema)
Causes: COPD, Asthma, Bronchiectasis
RESTRICTIVE:
FEV₁ ↓ | FVC ↓↓ | FEV₁/FVC normal/↑ | TLC ↓ | RV ↓
Narrow steep loop | Normal Raw | ↓ Compliance (parenchymal)
Causes: IPF, Sarcoidosis, Kyphoscoliosis, Neuromuscular disorders
Ossification of bone
| Feature | Intramembranous Ossification | Endochondral Ossification |
|---|---|---|
| Definition | Bone formed directly from mesenchyme, without a cartilage intermediate | Bone formed by replacement of a pre-existing hyaline cartilage model |
| Bones formed | Flat bones of skull, mandible, maxilla, clavicle | Long bones (femur, tibia, humerus), vertebrae, ribs, bones of base of skull |
| Precursor tissue | Mesenchyme (embryonic connective tissue) | Hyaline cartilage model |
| Cartilage model | Absent | Present - serves as scaffold |
| First appearance | ~8th week of embryonic development | Slightly later; cartilage model forms first |
| Cell lineage | Mesenchymal cell → osteoprogenitor → osteoblast → osteocyte | Mesenchymal cell → chondroblast → chondrocyte → (degeneration) → osteoprogenitor → osteoblast → osteocyte |
| Key transcription factor | CBFA1 (RUNX2) | CBFA1 (RUNX2) + SOX9 (for chondrogenesis) |
| Vascular invasion | Early - mesenchyme is already vascular | Required to initiate ossification center formation |
| Type of bone first produced | Woven (immature) bone → remodelled to lamellar | Woven bone on calcified cartilage spicules → lamellar |
| Growth | Appositional only | Interstitial (length) + appositional (width) |



| Zone | Description | Key Events |
|---|---|---|
| 1. Zone of Reserved (Resting) Cartilage | Small chondrocytes scattered randomly in matrix | No proliferation; serves as stem cell reserve for the proliferating zone |
| 2. Zone of Proliferation | Chondrocytes actively dividing, arranged in distinct columns | Cells larger; secrete type II and XI collagen; responsible for longitudinal bone growth |
| 3. Zone of Hypertrophy | Chondrocytes 10-20× enlarged; glycogen-rich clear cytoplasm | Secrete VEGF (initiates vascular invasion), RANKL, type X collagen; matrix compressed between columns |
| 4. Zone of Calcified Cartilage | Matrix becomes calcified; chondrocytes degenerate or transdifferentiate | Calcified matrix serves as initial scaffold for bone deposition; some chondrocytes → osteoblasts |
| 5. Zone of Resorption | Adjacent to bone marrow cavity | Blood vessels + osteoprogenitor cells invade; osteoclasts resorb calcified cartilage spicules; osteoblasts deposit bone on remaining spicules → endochondral bone |
Mnemonic for zones: Resting Prolif Hypertrophy Calcif Resorption = "Really Pretty Hyenas Can Run"
| Type | Mechanism | Result |
|---|---|---|
| Interstitial growth | Chondrocyte proliferation within growth plate | Increase in bone length |
| Appositional growth | Osteoblasts under periosteum deposit new bone on outer surface | Increase in bone width/diameter |
| Feature | Intramembranous | Endochondral |
|---|---|---|
| Template | Mesenchyme (no cartilage) | Hyaline cartilage model |
| Bones formed | Flat skull bones, mandible, clavicle | Long bones, vertebrae, most bones |
| Key cells | Mesenchymal cell → osteoblast | Chondrocyte → osteoblast |
| First bone type | Woven bone trabeculae | Bone on calcified cartilage spicules |
| Ossification centre | One primary centre | Primary (diaphysis) + Secondary (epiphyses) |
| Growth plate | Not present | Present (epiphyseal plate) |
| Growth mechanism | Appositional only | Interstitial (length) + appositional (width) |
| Cartilage at end | Absent | Articular cartilage persists |
| Vascular invasion | Early (mesenchyme already vascular) | Required to initiate each ossification centre |
Development of bone
| Skeletal Region | Embryonic Origin | Mechanism of Ossification |
|---|---|---|
| Flat bones of skull, face, mandible | Neural crest cells (ectomesenchyme) | Intramembranous |
| Base of skull, vertebrae, ribs, sternum, limb bones | Paraxial mesoderm (somites - sclerotome) | Endochondral |
| Clavicle | Both neural crest and lateral plate mesoderm | Both intramembranous + partial endochondral |
| Limb bones | Lateral plate mesoderm (somatic layer) | Endochondral |

| Feature | Intramembranous | Endochondral |
|---|---|---|
| Precursor tissue | Mesenchyme (no cartilage) | Hyaline cartilage model |
| Bones formed | Flat skull bones, mandible, clavicle | Long bones, vertebrae, most bones |
| Onset | ~8th week (human) | Slightly later; cartilage model forms 5th week, ossification begins ~8–12th week |
| First bone type | Woven bone trabeculae | Bone on calcified cartilage spicules (mixed spicules) |

| Stage | Event | Timing |
|---|---|---|
| 1 | Mesenchymal condensation at future bone site | Week 4–5 (in utero) |
| 2 | Cartilage model (anlage) formed by chondroblasts | Week 5–6 |
| 3 | Periosteal bony collar forms around mid-diaphysis (intramembranous) | Week 8 |
| 4 | Chondrocytes hypertrophy, cartilage matrix calcifies | Follows bony collar |
| 5 | Vascular invasion of diaphysis; Primary ossification centre established | ~Week 8 of gestation (varies) |
| 6 | Primitive bone marrow cavity forms; periosteal bone expands | Fetal period |
| 7 | Blood vessels invade proximal epiphyseal cartilage | Late fetal / early postnatal |
| 8 | Secondary ossification centre forms in proximal epiphysis | Mostly postnatal |
| 9 | Epiphyseal growth plate (physis) trapped between primary and secondary centres | Postnatal; persists until puberty |
| 10 | Growth plate closes → Epiphyseal line | End of puberty (~18–23 years) |
Key distinction: The medullary canal forms at ~8 weeks of gestation when the central portion of the cartilage anlage is resorbed. Radial bone growth (cortex) begins simultaneously via periosteal osteoblast deposition. Secondary ossification centres develop postnatally at the epiphyses in centrifugal fashion.
| Zone | Key Activity |
|---|---|
| Zone of Reserved Cartilage | Stem cell reserve; no active proliferation |
| Zone of Proliferation | Active cell division in columns; produces longitudinal growth; secretes type II, XI collagen |
| Zone of Hypertrophy | Cells enlarge 10-20×; secrete VEGF (angiogenesis), RANKL, type X collagen |
| Zone of Calcified Cartilage | Matrix calcifies; chondrocytes degenerate or transdifferentiate into osteoblasts |
| Zone of Resorption | Vascular invasion; osteoblasts deposit bone on calcified cartilage spicules |
| Hormone | Effect on Growth Plate |
|---|---|
| Growth Hormone (GH) | Stimulates chondrocyte proliferation via IGF-1; increases bone length and width |
| IGF-1 | Mediates GH effects; stimulates chondrocyte division |
| Thyroid hormone | Essential for normal growth; deficiency → cretinism with stunted growth |
| Sex steroids (oestrogen, testosterone) | Accelerate growth initially; then drive plate closure |
| Glucocorticoids (excess) | Inhibit chondrocyte proliferation → growth retardation |
| PTH-related protein (PTHrP) | Keeps growth plate chondrocytes in proliferating state; delays hypertrophy |

| Factor | Source | Effect |
|---|---|---|
| RANKL | Osteoblasts, marrow stromal cells, T lymphocytes | Binds RANK on osteoclast precursors → activates NF-κB → drives osteoclast differentiation and survival |
| RANK | Osteoclast precursors | Receptor; activation → osteoclastogenesis |
| OPG (osteoprotegerin) | Osteoblasts | Decoy receptor; binds RANKL → prevents RANK-RANKL interaction → inhibits osteoclastogenesis |
| M-CSF | Osteoblasts | Binds M-CSF receptor on osteoclast precursors; promotes survival and differentiation |
| WNT proteins | Various cells | Trigger OPG production → favour bone formation over resorption |
| PTH (continuous/high) | Parathyroid glands | Stimulates RANKL on osteoblasts → promotes osteoclast activity → bone resorption ↑ |
| PTH (pulsatile/low) | Via IGF-1/cAMP in osteoblasts → anabolic (bone formation ↑) | |
| Oestrogen / testosterone | Gonads | Suppress RANKL; promote OPG → reduce osteoclast activity |
| IL-1, glucocorticoids | Inflammatory/adrenal | Promote osteoclast differentiation |
| BMPs | Various | Generally promote OPG → suppress osteoclast activity |
Peak bone mass is reached in early adulthood. From the fourth decade, resorption exceeds formation → gradual decline in skeletal mass. This is accelerated postmenopausally due to oestrogen withdrawal.

| Stage | Events | Key Cells |
|---|---|---|
| 1. Fracture haematoma (hours–days) | Torn blood vessels bleed; clot forms; bone cells near break die; osteoclasts resorb damaged bone | Macrophages, osteoclasts |
| 2. Soft (procallus) formation (days–weeks) | Periosteum and endosteum proliferate; fibrocartilage-like procallus surrounds fracture; blood vessel regeneration begins | Fibroblasts, chondroblasts, periosteal cells |
| 3. Hard callus formation (weeks) | Fibrocartilage replaced by woven bone (combination of endochondral and intramembranous ossification); hard callus bridges fracture | Osteoblasts, osteoclasts |
| 4. Bone remodelling (months–years) | Woven bone replaced by lamellar bone; callus remodelled to restore original architecture and cortical continuity | Osteoblasts + osteoclasts (BMUs) |
| Hormone | Source | Effect on Bone |
|---|---|---|
| PTH | Parathyroid glands | Stimulates osteoclasts (indirectly via RANKL on osteoblasts) and osteocytes → bone resorption → ↑ blood Ca²⁺ |
| Calcitonin | Thyroid C cells | Inhibits osteoclastic bone resorption → ↓ blood Ca²⁺ |
| Vitamin D (1,25-OH₂D₃) | Kidney activation | Promotes intestinal Ca²⁺ absorption; promotes mineralisation; works synergistically with PTH |
Week 4-5: Mesenchymal condensation
Week 5: Cartilage (hyaline) model forms ← SOX9 drives chondrogenesis
Week 8: Periosteal bony collar (intramembranous)
+ Chondrocyte hypertrophy, matrix calcification
+ Vascular invasion → PRIMARY OSSIFICATION CENTRE ← RUNX2/CBFA1 drives osteogenesis
Fetal: Medullary cavity expands; cortex thickens
Postnatal: SECONDARY OSSIFICATION CENTRES form in epiphyses
Childhood: Growth plate active → longitudinal growth via GH/IGF-1/thyroid hormone
Puberty: Growth spurt then epiphyseal plate CLOSURE (sex steroids)
(~18–23 years for most long bones)
Adult: Bone remodelling continues lifelong via BMU (osteoclast-osteoblast)
4th decade+: Resorption > formation → bone mass declines