Ppt on Approach To Chest Pain

Asking for Preferences
Reading File
Reading File
Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Finding Sources
Reading File
Reading File
Reading File
Finding Sources
Reading File
Reading File
Running Command

mkdir -p /home/daytona/workspace/chest-pain-ppt && ls /home/daytona/workspace/ch…

Writing File

~/chest-pain-ppt/build.js

const pptxgen = require("pptxgenjs");
const pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.title = "Approach To Chest Pain";
pres.author = "Emergency Medicine";

// ─── PALETTE ────────────────────────────────────────────────────────────────
const DARK    = "0D1B2A";   // deep navy  (dominant background for title/section slides)
const MID     = "1B3A5C";   // medium navy
const ACCENT  = "E63946";   // sharp red  (emergency / danger)
const LIGHT   = "F1FAEE";   // near-white
const YELLOW  = "FFB703";   // gold accent (warnings / tables)
const GRAY    = "457B9D";   // cool slate  (supporting text / boxes)
const WHITE   = "FFFFFF";
const LGRAY   = "A8DADC";   // light teal accent

// ─── HELPERS ────────────────────────────────────────────────────────────────
function addSectionDivider(title) {
  const s = pres.addSlide();
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: DARK } });
  s.addShape(pres.ShapeType.rect, { x: 0, y: 2.4, w: 0.18, h: 0.9, fill: { color: ACCENT } });
  s.addText(title, {
    x: 0.35, y: 2.25, w: 9.3, h: 1.2,
    fontSize: 38, bold: true, color: WHITE, fontFace: "Calibri", align: "left", valign: "middle"
  });
}

function addSlideHeader(slide, title) {
  // dark navy header bar
  slide.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 0.72, fill: { color: DARK } });
  slide.addShape(pres.ShapeType.rect, { x: 0, y: 0.72, w: 10, h: 0.06, fill: { color: ACCENT } });
  slide.addText(title, {
    x: 0.35, y: 0, w: 9.3, h: 0.72, margin: 0,
    fontSize: 22, bold: true, color: WHITE, fontFace: "Calibri", align: "left", valign: "middle"
  });
}

function bulletItems(items, color, bold) {
  return items.map((t, i) => ({
    text: t,
    options: {
      bullet: true,
      color: color || DARK,
      bold: bold || false,
      breakLine: i < items.length - 1
    }
  }));
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 1 — TITLE
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  // full-bleed dark background
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: DARK } });
  // left accent bar
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 0.22, h: 5.625, fill: { color: ACCENT } });
  // diagonal decorative shape
  s.addShape(pres.ShapeType.rtTriangle, { x: 6.5, y: 2.2, w: 3.5, h: 3.4, fill: { color: MID }, line: { color: MID } });
  // ECG-style decoration strip
  s.addShape(pres.ShapeType.rect, { x: 0.22, y: 4.5, w: 9.78, h: 0.08, fill: { color: ACCENT } });

  s.addText("APPROACH TO", {
    x: 0.5, y: 0.9, w: 8.5, h: 0.75,
    fontSize: 28, bold: false, color: LGRAY, fontFace: "Calibri", charSpacing: 6
  });
  s.addText("CHEST PAIN", {
    x: 0.5, y: 1.55, w: 8.5, h: 1.3,
    fontSize: 64, bold: true, color: WHITE, fontFace: "Calibri"
  });
  s.addText("A Systematic Emergency Medicine Framework", {
    x: 0.5, y: 2.85, w: 7, h: 0.55,
    fontSize: 18, color: LGRAY, fontFace: "Calibri", italic: true
  });
  s.addText("Based on Rosen's Emergency Medicine", {
    x: 0.5, y: 4.7, w: 8, h: 0.4,
    fontSize: 12, color: GRAY, fontFace: "Calibri"
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 2 — EPIDEMIOLOGY & SCOPE
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "Epidemiology & Scope");

  // large stat boxes
  const stats = [
    { val: "~5–8%", label: "of all ED visits", col: ACCENT },
    { val: "#3", label: "Most common ED complaint", col: MID },
    { val: "35%", label: "Seek care for chest pain", col: GRAY },
  ];
  stats.forEach((st, i) => {
    const x = 0.4 + i * 3.1;
    s.addShape(pres.ShapeType.roundRect, { x, y: 0.9, w: 2.8, h: 1.55, fill: { color: st.col }, rectRadius: 0.12 });
    s.addText(st.val, { x, y: 0.95, w: 2.8, h: 0.85, fontSize: 36, bold: true, color: WHITE, fontFace: "Calibri", align: "center" });
    s.addText(st.label, { x, y: 1.78, w: 2.8, h: 0.6, fontSize: 13, color: WHITE, fontFace: "Calibri", align: "center", wrap: true });
  });

  s.addText("Key Clinical Context", {
    x: 0.4, y: 2.65, w: 9, h: 0.38,
    fontSize: 14, bold: true, color: MID, fontFace: "Calibri"
  });
  s.addText([
    ...bulletItems([
      "Chest pain is the 5th most common type of temporary pain in population surveys",
      "12% of ED pain cases, yet the #1 cause prompting patients to seek emergency care",
      "Wide spectrum: from benign musculoskeletal to immediately life-threatening ACS, dissection, PE",
      "Diagnosis complicated by vague presentations and indistinct anatomic localization",
      "Considerable clinical judgment required — empirical therapy may need to begin during evaluation"
    ], DARK)
  ], {
    x: 0.4, y: 3.05, w: 9.2, h: 2.3,
    fontSize: 13.5, fontFace: "Calibri", lineSpacingMultiple: 1.3
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 3 — THE BIG 6 LIFE-THREATENING CAUSES
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: "0A1628" };

  s.addShape(pres.ShapeType.rect, { x: 0, y: 0.72, w: 10, h: 0.06, fill: { color: ACCENT } });
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 0.72, fill: { color: ACCENT } });
  s.addText("⚠  THE BIG 6 — Must-Not-Miss Diagnoses", {
    x: 0.3, y: 0, w: 9.4, h: 0.72, margin: 0,
    fontSize: 20, bold: true, color: WHITE, fontFace: "Calibri", align: "left", valign: "middle"
  });

  const diagnoses = [
    { name: "ACS / AMI", detail: "Most common lethal cause\nSTEMI, NSTEMI, Unstable Angina", icon: "❤" },
    { name: "Aortic Dissection", detail: "Tearing pain to back\nBlood pressure differential", icon: "🔴" },
    { name: "Pulmonary Embolism", detail: "Pleuritic pain, dyspnea\nRisk factors: DVT, immobility", icon: "🫁" },
    { name: "Tension Pneumothorax", detail: "Absent breath sounds\nTracheal deviation, hypotension", icon: "💨" },
    { name: "Cardiac Tamponade", detail: "Beck's triad: hypotension,\nJVD, muffled heart sounds", icon: "🫀" },
    { name: "Oesophageal Rupture", detail: "Boerhaave syndrome\nPost-vomiting, mediastinitis", icon: "⚡" },
  ];

  diagnoses.forEach((d, i) => {
    const col = i % 2 === 0 ? MID : "142847";
    const row = Math.floor(i / 3);
    const col_idx = i % 3;
    const x = 0.25 + col_idx * 3.2;
    const y = 0.98 + row * 2.15;
    s.addShape(pres.ShapeType.roundRect, { x, y, w: 3.05, h: 2.0, fill: { color: col }, rectRadius: 0.12 });
    s.addShape(pres.ShapeType.rect, { x, y, w: 0.18, h: 2.0, fill: { color: ACCENT } });
    s.addText(d.name, { x: x + 0.25, y: y + 0.12, w: 2.7, h: 0.48, fontSize: 15, bold: true, color: YELLOW, fontFace: "Calibri" });
    s.addText(d.detail, { x: x + 0.25, y: y + 0.58, w: 2.7, h: 1.25, fontSize: 12.5, color: LGRAY, fontFace: "Calibri", wrap: true, lineSpacingMultiple: 1.3 });
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 4 — DIFFERENTIAL DIAGNOSIS (Broad)
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "Differential Diagnosis — By System");

  const cats = [
    { cat: "Cardiac", items: ["ACS / STEMI / NSTEMI", "Unstable angina", "Myocarditis / Pericarditis", "Aortic stenosis", "Cardiomyopathy"], col: ACCENT },
    { cat: "Vascular", items: ["Aortic dissection", "Pulmonary embolism", "Pulmonary hypertension", "Thoracic outlet syndrome"], col: MID },
    { cat: "Pulmonary", items: ["Pneumothorax", "Pneumonia / Pleuritis", "Pleural effusion", "Tracheobronchitis", "Lung malignancy"], col: GRAY },
    { cat: "GI / Other", items: ["GERD / Oesophageal spasm", "Oesophageal rupture", "Pancreatitis", "Biliary colic", "Peptic ulcer disease"], col: "2A7D6B" },
    { cat: "MSK / Neuro", items: ["Costochondritis", "Rib fracture", "Intercostal neuralgia", "Herpes zoster (pre-rash)", "Cervical radiculopathy"], col: "5C4033" },
    { cat: "Psychogenic", items: ["Panic disorder", "Anxiety / Hyperventilation", "Somatisation disorder", "Depression-related", "Functional chest pain"], col: "7B5EA7" },
  ];

  cats.forEach((c, i) => {
    const row = Math.floor(i / 3);
    const col = i % 3;
    const x = 0.2 + col * 3.25;
    const y = 0.88 + row * 2.32;
    s.addShape(pres.ShapeType.rect, { x, y, w: 3.05, h: 0.38, fill: { color: c.col } });
    s.addText(c.cat, { x, y, w: 3.05, h: 0.38, fontSize: 13, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
    s.addShape(pres.ShapeType.rect, { x, y: y + 0.38, w: 3.05, h: 1.75, fill: { color: "EEF4F8" } });
    s.addText(bulletItems(c.items, DARK), {
      x: x + 0.05, y: y + 0.4, w: 2.95, h: 1.65,
      fontSize: 11.5, fontFace: "Calibri", lineSpacingMultiple: 1.25
    });
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 5 — HISTORY TAKING
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "History Taking — The OPQRST Framework");

  const items = [
    { letter: "O", word: "ONSET", desc: "Sudden (dissection, PE, PTX) vs gradual (pericarditis, GERD)\nTiming: exertional vs rest, nocturnal" },
    { letter: "P", word: "PROVOCATION", desc: "Worse on inspiration (pleuritis, PE, PTX)\nReproducible by palpation (MSK) — low but not zero ACS risk\nRelieved by nitrates (angina) vs antacids (GERD)" },
    { letter: "Q", word: "QUALITY", desc: "Pressure / squeezing / heaviness → ischemic\nTearing / ripping → dissection\nSharp / stabbing → pleuritic, MSK\nBurning → GERD, oesophageal" },
    { letter: "R", word: "RADIATION", desc: "Left arm / jaw → ACS\nBack / between shoulder blades → aortic dissection\nShoulder tip → diaphragmatic irritation" },
    { letter: "S", word: "SEVERITY", desc: "Severity (1–10) and impact on activity\nAssociated symptoms: dyspnea, diaphoresis, nausea, syncope, palpitations" },
    { letter: "T", word: "TIME", desc: "Duration and progression\nPrevious similar episodes\nTime since onset for thrombolysis / PCI window" },
  ];

  items.forEach((item, i) => {
    const row = Math.floor(i / 2);
    const col = i % 2;
    const x = 0.25 + col * 4.85;
    const y = 0.88 + row * 1.52;
    s.addShape(pres.ShapeType.roundRect, { x, y, w: 4.6, h: 1.4, fill: { color: "EAF2FB" }, rectRadius: 0.09 });
    s.addShape(pres.ShapeType.roundRect, { x, y, w: 0.55, h: 1.4, fill: { color: MID }, rectRadius: 0.09 });
    s.addText(item.letter, { x, y, w: 0.55, h: 1.4, fontSize: 22, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
    s.addText(item.word, { x: x + 0.62, y: y + 0.06, w: 3.85, h: 0.34, fontSize: 12, bold: true, color: MID, fontFace: "Calibri", margin: 0 });
    s.addText(item.desc, { x: x + 0.62, y: y + 0.4, w: 3.85, h: 0.9, fontSize: 10.5, color: DARK, fontFace: "Calibri", wrap: true, lineSpacingMultiple: 1.2, margin: 0 });
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 6 — RISK FACTORS
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "Risk Factor Assessment");

  // Left column — Cardiac Risk Factors
  s.addShape(pres.ShapeType.rect, { x: 0.2, y: 0.85, w: 4.5, h: 0.42, fill: { color: ACCENT } });
  s.addText("Cardiac Risk Factors", { x: 0.2, y: 0.85, w: 4.5, h: 0.42, fontSize: 14, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
  s.addShape(pres.ShapeType.rect, { x: 0.2, y: 1.27, w: 4.5, h: 3.55, fill: { color: "FEF0EF" } });
  s.addText(bulletItems([
    "Age > 45 (men), > 55 (women)",
    "Hypertension",
    "Diabetes mellitus",
    "Hypercholesterolaemia",
    "Smoking",
    "Family history of premature CAD",
    "Prior MI or PCI / CABG history",
    "Cocaine / stimulant use",
    "Obesity, sedentary lifestyle",
    "Chronic kidney disease"
  ], DARK), {
    x: 0.3, y: 1.3, w: 4.3, h: 3.3,
    fontSize: 12.5, fontFace: "Calibri", lineSpacingMultiple: 1.3
  });

  // Right column — PE / Dissection risk
  s.addShape(pres.ShapeType.rect, { x: 5.1, y: 0.85, w: 4.5, h: 0.42, fill: { color: GRAY } });
  s.addText("PE & Dissection Risk Factors", { x: 5.1, y: 0.85, w: 4.5, h: 0.42, fontSize: 14, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
  s.addShape(pres.ShapeType.rect, { x: 5.1, y: 1.27, w: 4.5, h: 1.88, fill: { color: "EFF4F8" } });
  s.addText("PE:", { x: 5.2, y: 1.3, w: 4.3, h: 0.3, fontSize: 12, bold: true, color: GRAY, fontFace: "Calibri" });
  s.addText(bulletItems([
    "Prolonged immobility, recent surgery / hospitalisation",
    "Active malignancy, DVT history",
    "Pregnancy / OCP, thrombophilia"
  ], DARK), {
    x: 5.2, y: 1.6, w: 4.3, h: 1.3,
    fontSize: 12, fontFace: "Calibri", lineSpacingMultiple: 1.3
  });

  s.addShape(pres.ShapeType.rect, { x: 5.1, y: 3.17, w: 4.5, h: 1.65, fill: { color: "EFF4F8" } });
  s.addText("Aortic Dissection:", { x: 5.2, y: 3.2, w: 4.3, h: 0.3, fontSize: 12, bold: true, color: MID, fontFace: "Calibri" });
  s.addText(bulletItems([
    "Hypertension (most common modifiable factor)",
    "Marfan / connective tissue disorders",
    "Bicuspid aortic valve, coarctation",
    "Cocaine use, pregnancy"
  ], DARK), {
    x: 5.2, y: 3.5, w: 4.3, h: 1.2,
    fontSize: 12, fontFace: "Calibri", lineSpacingMultiple: 1.3
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 7 — PHYSICAL EXAMINATION
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "Physical Examination — Targeted Approach");

  // Vital signs box
  s.addShape(pres.ShapeType.rect, { x: 0.2, y: 0.88, w: 9.6, h: 0.4, fill: { color: ACCENT } });
  s.addText("VITALS FIRST: BP (both arms), HR, RR, SpO₂, Temperature — Abnormalities may point to specific diagnoses", {
    x: 0.2, y: 0.88, w: 9.6, h: 0.4, fontSize: 12.5, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0
  });

  const exams = [
    {
      system: "General / Appearance",
      findings: ["Diaphoresis, pallor, distress → ACS", "Anxiety, hyperventilation → panic / PE", "Marfanoid habitus → dissection risk"]
    },
    {
      system: "Cardiovascular",
      findings: ["JVD → right heart strain (PE, tamponade)", "Muffled heart sounds → tamponade", "BP differential (>20 mmHg) → dissection", "New murmur → papillary muscle rupture"]
    },
    {
      system: "Respiratory",
      findings: ["Absent breath sounds unilaterally → PTX", "Dullness to percussion → effusion / haemothorax", "Wheeze, crackles → pulmonary oedema / asthma"]
    },
    {
      system: "Musculoskeletal",
      findings: ["Chest wall tenderness → MSK (low but not zero ACS risk)", "Reproducibility identical to pain → suggests MSK", "Rash in dermatomal pattern → zoster"]
    },
    {
      system: "Abdomen",
      findings: ["Epigastric tenderness → GERD, peptic ulcer, pancreatitis", "RUQ tenderness → biliary colic / hepatitis", "Pulsatile mass → AAA"]
    },
    {
      system: "Vascular / Peripheral",
      findings: ["Leg swelling / tenderness → DVT → PE", "Pulse deficit in extremities → dissection", "Peripheral stigmata of IE"]
    },
  ];

  exams.forEach((e, i) => {
    const row = Math.floor(i / 3);
    const col = i % 3;
    const x = 0.2 + col * 3.25;
    const y = 1.42 + row * 2.0;
    s.addShape(pres.ShapeType.rect, { x, y, w: 3.05, h: 0.38, fill: { color: MID } });
    s.addText(e.system, { x, y, w: 3.05, h: 0.38, fontSize: 12, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
    s.addShape(pres.ShapeType.rect, { x, y: y + 0.38, w: 3.05, h: 1.55, fill: { color: "EAF2FB" } });
    s.addText(bulletItems(e.findings, DARK), {
      x: x + 0.08, y: y + 0.42, w: 2.9, h: 1.42,
      fontSize: 11, fontFace: "Calibri", lineSpacingMultiple: 1.25
    });
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 8 — 12-LEAD ECG INTERPRETATION
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: "0A1628" };
  addSlideHeader(s, "12-Lead ECG — Systematic Interpretation in Chest Pain");

  s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 0.72, fill: { color: DARK } });
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0.72, w: 10, h: 0.06, fill: { color: ACCENT } });
  s.addText("12-Lead ECG — Systematic Interpretation in Chest Pain", {
    x: 0.35, y: 0, w: 9.3, h: 0.72, margin: 0,
    fontSize: 20, bold: true, color: WHITE, fontFace: "Calibri", align: "left", valign: "middle"
  });

  const ecgItems = [
    { title: "STEMI Criteria", items: ["≥2 mm ST elevation in ≥2 contiguous precordial leads", "≥1 mm ST elevation in ≥2 contiguous limb leads", "New LBBB with ischaemic symptoms = STEMI equivalent", "De Winter T-waves — LAD occlusion pattern"], col: ACCENT },
    { title: "NSTEMI / UA Patterns", items: ["ST depression ≥0.5 mm — subendocardial ischaemia", "T-wave inversions: Wellens pattern (LAD warning)", "Dynamic ECG changes correlating with symptoms", "Troponin elevation with no ST elevation"], col: GRAY },
    { title: "Hyperacute T Waves", items: ["Earliest STEMI sign — broad, peaked T waves", "Appears within minutes of occlusion", "Progresses to ST elevation rapidly", "Differential: hyperkalaemia, BER, LVH"], col: MID },
    { title: "Non-Ischaemic Patterns", items: ["Saddle-shaped STE in all leads → pericarditis", "Sinus tachycardia + S1Q3T3 → PE (non-specific)", "Electrical alternans → tamponade", "Low voltage → effusion / hypothyroidism"], col: "2A7D6B" },
  ];

  ecgItems.forEach((item, i) => {
    const x = 0.2 + i * 2.4;
    s.addShape(pres.ShapeType.rect, { x, y: 0.88, w: 2.22, h: 0.42, fill: { color: item.col } });
    s.addText(item.title, { x, y: 0.88, w: 2.22, h: 0.42, fontSize: 11.5, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
    s.addShape(pres.ShapeType.rect, { x, y: 1.3, w: 2.22, h: 4.0, fill: { color: MID } });
    s.addText(bulletItems(item.items, LGRAY), {
      x: x + 0.08, y: 1.35, w: 2.05, h: 3.85,
      fontSize: 11, fontFace: "Calibri", lineSpacingMultiple: 1.35
    });
  });

  s.addText("⚡ Get ECG within 10 minutes of arrival — STEMI identification is the 1st-phase goal", {
    x: 0.2, y: 5.2, w: 9.6, h: 0.32,
    fontSize: 12, bold: true, color: YELLOW, fontFace: "Calibri", align: "center"
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 9 — CARDIAC BIOMARKERS
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "Cardiac Biomarkers — Troponin-Centred Approach");

  // Troponin timeline box
  s.addShape(pres.ShapeType.rect, { x: 0.2, y: 0.88, w: 9.6, h: 1.45, fill: { color: "EAF2FB" } });
  s.addText("Troponin Rise & Fall Timeline", {
    x: 0.35, y: 0.9, w: 4, h: 0.35,
    fontSize: 13, bold: true, color: MID, fontFace: "Calibri"
  });

  const timelineData = [
    { label: "0–3 hrs", desc: "Troponin may be normal\nSerial testing essential" },
    { label: "3–6 hrs", desc: "Rises above detection\nHigh-sensitivity assays detect earlier" },
    { label: "6–12 hrs", desc: "Peak sensitivity achieved\nPositive = AMI likely" },
    { label: "Days 1–14", desc: "Gradual decline\nPeak at 12–24 h (TnI)" },
  ];
  timelineData.forEach((t, i) => {
    const x = 0.3 + i * 2.38;
    s.addShape(pres.ShapeType.roundRect, { x, y: 1.28, w: 2.1, h: 0.9, fill: { color: i < 2 ? ACCENT : MID }, rectRadius: 0.08 });
    s.addText(t.label, { x, y: 1.3, w: 2.1, h: 0.32, fontSize: 12, bold: true, color: WHITE, fontFace: "Calibri", align: "center" });
    s.addText(t.desc, { x, y: 1.62, w: 2.1, h: 0.52, fontSize: 10, color: WHITE, fontFace: "Calibri", align: "center", wrap: true });
  });

  // High-sensitivity troponin
  s.addShape(pres.ShapeType.rect, { x: 0.2, y: 2.48, w: 4.65, h: 0.38, fill: { color: MID } });
  s.addText("High-Sensitivity Troponin (hsTn)", {
    x: 0.2, y: 2.48, w: 4.65, h: 0.38,
    fontSize: 13, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0
  });
  s.addShape(pres.ShapeType.rect, { x: 0.2, y: 2.86, w: 4.65, h: 2.45, fill: { color: "EAF2FB" } });
  s.addText(bulletItems([
    "Detects troponin at much lower concentrations",
    "0/1-hour or 0/2-hour rapid rule-out protocols",
    "High NPV (>99%) for AMI when combined with clinical assessment",
    "Can be elevated in non-ACS causes: PE, myocarditis, sepsis, renal failure",
    "Delta troponin (rise ≥20% at 1–2 hrs) supports dynamic ischaemia"
  ], DARK), {
    x: 0.3, y: 2.9, w: 4.4, h: 2.3,
    fontSize: 12, fontFace: "Calibri", lineSpacingMultiple: 1.3
  });

  // D-dimer box
  s.addShape(pres.ShapeType.rect, { x: 5.15, y: 2.48, w: 4.65, h: 0.38, fill: { color: GRAY } });
  s.addText("Other Key Biomarkers", {
    x: 5.15, y: 2.48, w: 4.65, h: 0.38,
    fontSize: 13, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0
  });
  s.addShape(pres.ShapeType.rect, { x: 5.15, y: 2.86, w: 4.65, h: 2.45, fill: { color: "EFF4F8" } });
  s.addText(bulletItems([
    "D-dimer: High NPV for PE when pre-test probability is low (PERC / Wells score)",
    "BNP / NT-proBNP: Heart failure, RV strain in PE",
    "ABG: Hypoxia / hypocapnia in PE, respiratory causes",
    "CXR + CT-PA / CT Aortogram: imaging to confirm/exclude",
    "Multimarker approach NOT superior to isolated troponin for ACS"
  ], DARK), {
    x: 5.25, y: 2.9, w: 4.4, h: 2.3,
    fontSize: 12, fontFace: "Calibri", lineSpacingMultiple: 1.3
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 10 — CHEST X-RAY
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "Chest X-Ray — Key Findings in Chest Pain");

  const findings = [
    { dx: "ACS / Heart Failure", cxr: ["Cardiomegaly", "Pulmonary vascular congestion", "Interstitial / alveolar oedema", "Pleural effusions (bilateral)"], col: ACCENT },
    { dx: "Aortic Dissection", cxr: ["Widened mediastinum (>8 cm)", "Blurring of aortic knuckle", "Left pleural effusion", "Tracheal shift to right"], col: MID },
    { dx: "Pneumothorax", cxr: ["Absent lung markings", "Visible lung edge / pleural line", "Tracheal deviation (tension)", "Deep sulcus sign (supine film)"], col: GRAY },
    { dx: "PE", cxr: ["Often normal (most common)", "Hampton's hump (wedge opacity)", "Westermark sign (oligaemia)", "Pleural-based atelectasis"], col: "5C4033" },
    { dx: "Pneumonia", cxr: ["Lobar / segmental consolidation", "Air bronchograms", "Parapneumonic effusion", "Bilateral infiltrates (ARDS)"], col: "2A7D6B" },
    { dx: "Oesophageal Rupture", cxr: ["Mediastinal air / widening", "Left pleural effusion", "Pneumomediastinum", "Subcutaneous emphysema"], col: "7B5EA7" },
  ];

  findings.forEach((f, i) => {
    const row = Math.floor(i / 3);
    const col = i % 3;
    const x = 0.2 + col * 3.25;
    const y = 0.88 + row * 2.32;
    s.addShape(pres.ShapeType.rect, { x, y, w: 3.05, h: 0.4, fill: { color: f.col } });
    s.addText(f.dx, { x, y, w: 3.05, h: 0.4, fontSize: 12.5, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
    s.addShape(pres.ShapeType.rect, { x, y: y + 0.4, w: 3.05, h: 1.78, fill: { color: "EEF4F8" } });
    s.addText(bulletItems(f.cxr, DARK), {
      x: x + 0.08, y: y + 0.44, w: 2.9, h: 1.65,
      fontSize: 11.5, fontFace: "Calibri", lineSpacingMultiple: 1.3
    });
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 11 — HEART SCORE
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: "0A1628" };

  s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 0.72, fill: { color: DARK } });
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0.72, w: 10, h: 0.06, fill: { color: ACCENT } });
  s.addText("HEART Score — Risk Stratification for ACS", {
    x: 0.35, y: 0, w: 9.3, h: 0.72, margin: 0,
    fontSize: 22, bold: true, color: WHITE, fontFace: "Calibri", align: "left", valign: "middle"
  });

  // Table
  const rows = [
    ["Component", "0 Points", "1 Point", "2 Points"],
    ["H — History", "Slightly suspicious", "Moderately suspicious", "Highly suspicious"],
    ["E — ECG", "Normal", "Non-specific repolarisation disturbance", "Significant ST deviation"],
    ["A — Age", "< 45 years", "45–64 years", "≥ 65 years"],
    ["R — Risk Factors", "No risk factors", "1–2 risk factors OR history of DM", "≥ 3 risk factors OR prior atherosclerotic disease"],
    ["T — Troponin", "≤ Normal limit", "1–3× normal limit", "> 3× normal limit"],
  ];

  const colWidths = [2.0, 2.1, 2.8, 3.1];
  const colX = [0.2, 2.2, 4.3, 7.1];
  const rowH = 0.72;
  const startY = 0.88;

  rows.forEach((row, ri) => {
    row.forEach((cell, ci) => {
      const isHeader = ri === 0;
      const bg = isHeader ? ACCENT : (ri % 2 === 0 ? "142847" : "1B3A5C");
      s.addShape(pres.ShapeType.rect, {
        x: colX[ci], y: startY + ri * rowH, w: colWidths[ci], h: rowH,
        fill: { color: bg }, line: { color: "0A1628", pt: 0.5 }
      });
      s.addText(cell, {
        x: colX[ci] + 0.05, y: startY + ri * rowH, w: colWidths[ci] - 0.1, h: rowH,
        fontSize: isHeader ? 12.5 : 11.5, bold: isHeader, color: isHeader ? WHITE : LGRAY,
        fontFace: "Calibri", align: "center", valign: "middle", wrap: true
      });
    });
  });

  // Risk group summary
  s.addText([
    { text: "Score 0–3: ", options: { bold: true, color: "6FCF97" } },
    { text: "Low risk — discharge with follow-up    ", options: { color: LGRAY } },
    { text: "Score 4–6: ", options: { bold: true, color: YELLOW } },
    { text: "Moderate risk — observation / further testing    ", options: { color: LGRAY } },
    { text: "Score 7–10: ", options: { bold: true, color: ACCENT } },
    { text: "High risk — admit, cardiology consult", options: { color: LGRAY } },
  ], {
    x: 0.2, y: 5.12, w: 9.6, h: 0.42, fontSize: 12, fontFace: "Calibri", align: "center"
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 12 — HEART PATHWAY & ACCELERATED PROTOCOLS
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "Accelerated Diagnostic Protocols (ADP)");

  s.addText("The 3-Phase ED Evaluation Model (Rosen's EM)", {
    x: 0.25, y: 0.88, w: 9.5, h: 0.38,
    fontSize: 14, bold: true, color: MID, fontFace: "Calibri"
  });

  // Phase boxes
  const phases = [
    { phase: "Phase 1\n0–10 min", title: "STEMI Recognition", actions: ["12-lead ECG within 10 min", "Focused history & exam", "Identify for immediate cath lab activation", "Goals: identify STEMI or equiv."], col: ACCENT },
    { phase: "Phase 2\n0.5–6 hrs", title: "Rule-Out ACS", actions: ["Serial ECGs", "Serial troponin (0h & 3h)", "Clinical reassessment", "NSTEMI identified here"], col: GRAY },
    { phase: "Phase 3\n6–12+ hrs", title: "CAD Evaluation", actions: ["Stress testing (ETT)", "CCTA in selected patients", "Myocardial perfusion imaging", "Echocardiography"], col: MID },
  ];

  phases.forEach((p, i) => {
    const x = 0.2 + i * 3.25;
    s.addShape(pres.ShapeType.roundRect, { x, y: 1.35, w: 3.05, h: 0.75, fill: { color: p.col }, rectRadius: 0.12 });
    s.addText(p.phase, { x, y: 1.35, w: 3.05, h: 0.75, fontSize: 12.5, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle" });
    s.addText(p.title, { x, y: 2.15, w: 3.05, h: 0.35, fontSize: 12, bold: true, color: p.col, fontFace: "Calibri", align: "center" });
    s.addShape(pres.ShapeType.rect, { x, y: 2.52, w: 3.05, h: 1.75, fill: { color: "EAF2FB" } });
    s.addText(bulletItems(p.actions, DARK), {
      x: x + 0.08, y: 2.56, w: 2.9, h: 1.65,
      fontSize: 12, fontFace: "Calibri", lineSpacingMultiple: 1.3
    });
  });

  // HEART Pathway box
  s.addShape(pres.ShapeType.roundRect, { x: 0.2, y: 4.42, w: 9.6, h: 1.05, fill: { color: "FFF3CD" }, rectRadius: 0.1 });
  s.addShape(pres.ShapeType.rect, { x: 0.2, y: 4.42, w: 0.18, h: 1.05, fill: { color: YELLOW } });
  s.addText("HEART Pathway:", { x: 0.5, y: 4.48, w: 2.0, h: 0.35, fontSize: 12.5, bold: true, color: "7A5800", fontFace: "Calibri" });
  s.addText("HEART Score + serial troponin at 0h & 3h. Score 0–3 AND both troponins negative = low risk → early discharge with follow-up. Score 0–3 with positive troponin OR score 4–10 negative → observation. Score 4–10 positive → admit.", {
    x: 0.5, y: 4.82, w: 9.1, h: 0.55,
    fontSize: 11.5, color: DARK, fontFace: "Calibri", wrap: true
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 13 — AORTIC DISSECTION APPROACH
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: "0A1628" };

  s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 0.72, fill: { color: MID } });
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0.72, w: 10, h: 0.06, fill: { color: ACCENT } });
  s.addText("Aortic Dissection — Approach & Red Flags", {
    x: 0.35, y: 0, w: 9.3, h: 0.72, margin: 0,
    fontSize: 22, bold: true, color: WHITE, fontFace: "Calibri", align: "left", valign: "middle"
  });

  s.addShape(pres.ShapeType.rect, { x: 0.2, y: 0.88, w: 4.6, h: 0.4, fill: { color: ACCENT } });
  s.addText("High-Risk Clinical Features", { x: 0.2, y: 0.88, w: 4.6, h: 0.4, fontSize: 13, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
  s.addShape(pres.ShapeType.rect, { x: 0.2, y: 1.28, w: 4.6, h: 2.8, fill: { color: "142847" } });
  s.addText(bulletItems([
    "Sudden onset severe 'tearing' or 'ripping' pain",
    "Maximal at onset — worse than previous pain",
    "Radiation to back, between shoulder blades",
    "BP differential > 20 mmHg between arms",
    "Pulse deficit or neurological deficit",
    "Widened mediastinum on CXR",
    "Risk factors: HTN, Marfan, cocaine, prior cardiac surgery"
  ], LGRAY), {
    x: 0.35, y: 1.33, w: 4.3, h: 2.65,
    fontSize: 12, fontFace: "Calibri", lineSpacingMultiple: 1.35
  });

  s.addShape(pres.ShapeType.rect, { x: 5.15, y: 0.88, w: 4.6, h: 0.4, fill: { color: GRAY } });
  s.addText("Investigation & Classification", { x: 5.15, y: 0.88, w: 4.6, h: 0.4, fontSize: 13, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
  s.addShape(pres.ShapeType.rect, { x: 5.15, y: 1.28, w: 4.6, h: 2.8, fill: { color: "142847" } });
  s.addText(bulletItems([
    "CT Aortogram — gold standard imaging",
    "TOE (transoesophageal echo) — if haemodynamically unstable",
    "CXR: widened mediastinum — initial screen (not definitive)",
    "Type A: Ascending aorta — Emergency surgical repair",
    "Type B: Descending aorta — Medical management (IV labetalol)",
    "D-dimer > 500 ng/mL has high sensitivity as initial screen",
    "Do NOT anticoagulate if dissection suspected before imaging"
  ], LGRAY), {
    x: 5.3, y: 1.33, w: 4.3, h: 2.65,
    fontSize: 12, fontFace: "Calibri", lineSpacingMultiple: 1.35
  });

  s.addShape(pres.ShapeType.roundRect, { x: 0.2, y: 4.25, w: 9.6, h: 1.15, fill: { color: "1B3050" }, rectRadius: 0.1 });
  s.addShape(pres.ShapeType.rect, { x: 0.2, y: 4.25, w: 0.18, h: 1.15, fill: { color: YELLOW } });
  s.addText("ADD Score (Aortic Dissection Detection):", { x: 0.5, y: 4.3, w: 4.5, h: 0.38, fontSize: 12.5, bold: true, color: YELLOW, fontFace: "Calibri" });
  s.addText("High-risk conditions (Marfan etc.) + high-risk pain features (abrupt onset, tearing) + high-risk exam (pulse deficit, BP differential, focal neuro) → score 0 = low risk; ≥1 requires CT aortogram", {
    x: 0.5, y: 4.65, w: 9.1, h: 0.65,
    fontSize: 11.5, color: LGRAY, fontFace: "Calibri", wrap: true
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 14 — PE APPROACH
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "Pulmonary Embolism — Clinical Approach");

  // Wells score table
  s.addText("Wells Score for PE", { x: 0.2, y: 0.88, w: 4.5, h: 0.38, fontSize: 14, bold: true, color: MID, fontFace: "Calibri" });

  const wellsRows = [
    ["Clinical Variable", "Points"],
    ["Clinical signs/symptoms of DVT", "3"],
    ["Alternative diagnosis less likely than PE", "3"],
    ["HR > 100 bpm", "1.5"],
    ["Immobilisation ≥ 3 days / surgery in last 4 wks", "1.5"],
    ["Prior DVT or PE", "1.5"],
    ["Haemoptysis", "1"],
    ["Malignancy (treated within 6 months)", "1"],
  ];
  const wColW = [3.3, 1.0];
  const wColX = [0.2, 3.5];
  wellsRows.forEach((row, ri) => {
    row.forEach((cell, ci) => {
      const isH = ri === 0;
      s.addShape(pres.ShapeType.rect, {
        x: wColX[ci], y: 1.3 + ri * 0.46, w: wColW[ci], h: 0.46,
        fill: { color: isH ? MID : (ri % 2 === 0 ? "EFF8FF" : "D9EFFF") }, line: { color: "C0D0E0", pt: 0.5 }
      });
      s.addText(cell, {
        x: wColX[ci] + 0.06, y: 1.3 + ri * 0.46, w: wColW[ci] - 0.12, h: 0.46,
        fontSize: 11.5, bold: isH, color: isH ? WHITE : DARK, fontFace: "Calibri", align: ci === 1 ? "center" : "left", valign: "middle"
      });
    });
  });

  s.addText([
    { text: "Score > 4: ", options: { bold: true, color: ACCENT } },
    { text: "PE likely → CT-PA\n", options: { color: DARK } },
    { text: "Score ≤ 4: ", options: { bold: true, color: "2A7D6B" } },
    { text: "PE unlikely → D-dimer (if age-adjusted negative → exclude)", options: { color: DARK } },
  ], {
    x: 0.2, y: 4.66, w: 4.5, h: 0.8,
    fontSize: 12, fontFace: "Calibri", lineSpacingMultiple: 1.4
  });

  // Right side — management
  s.addShape(pres.ShapeType.rect, { x: 5.0, y: 0.88, w: 4.75, h: 0.38, fill: { color: GRAY } });
  s.addText("Management Approach", { x: 5.0, y: 0.88, w: 4.75, h: 0.38, fontSize: 13, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });

  const mgmt = [
    { heading: "Haemodynamically Unstable:", points: ["Massive PE: IV thrombolysis (alteplase) or surgical embolectomy", "Anticoagulate with IV UFH immediately"] },
    { heading: "Haemodynamically Stable:", points: ["Sub-massive: Consider thrombolysis if RV strain", "Anticoagulate: LMWH, fondaparinux, or DOAC", "DOACs (rivaroxaban / apixaban) preferred in most"] },
    { heading: "PERC Rule:", points: ["If all 8 criteria negative in low pretest probability → PE excluded without D-dimer"] },
  ];

  let yPos = 1.35;
  mgmt.forEach(m => {
    s.addText(m.heading, { x: 5.1, y: yPos, w: 4.5, h: 0.3, fontSize: 12, bold: true, color: MID, fontFace: "Calibri" });
    yPos += 0.32;
    s.addText(bulletItems(m.points, DARK), {
      x: 5.1, y: yPos, w: 4.5, h: 0.3 * m.points.length + 0.15,
      fontSize: 11.5, fontFace: "Calibri", lineSpacingMultiple: 1.3
    });
    yPos += 0.3 * m.points.length + 0.3;
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 15 — NON-CARDIAC CAUSES
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "Non-Cardiac Chest Pain — Systematic Approach");

  const causes = [
    {
      title: "Pericarditis",
      clues: "Sharp pain, worse supine, better leaning forward\nFriction rub on auscultation",
      tests: "ECG: saddle-shaped ST elevation\nEcho, CRP, troponin (mild elevation)",
      tx: "NSAIDs + colchicine\nRestrict activity 3 months",
      col: ACCENT
    },
    {
      title: "Oesophageal / GI",
      clues: "GERD: burning, worse post-meals\nSpasm: can mimic angina, relieved by nitrates\nBoerhaave: post-vomiting, mediastinitis",
      tests: "CXR (Boerhaave), Endoscopy\nBarium swallow, pH monitoring",
      tx: "PPIs for GERD\nEmergency surgery for Boerhaave",
      col: "2A7D6B"
    },
    {
      title: "Musculoskeletal",
      clues: "Reproducible by palpation\nCostochondritis: sternal junction tenderness\nTietze syndrome: swelling present",
      tests: "Primarily clinical diagnosis\nX-ray if rib fracture suspected",
      tx: "NSAIDs, reassurance\nPhysiotherapy, heat",
      col: GRAY
    },
    {
      title: "Herpes Zoster",
      clues: "Dermatomal pattern\nPre-rash: burning, allodynia\nPost-rash: vesicular eruption",
      tests: "Clinical; viral PCR if uncertain\nDermatomal distribution is key",
      tx: "Antivirals within 72 hrs\nAnalgesia, nerve block",
      col: "7B5EA7"
    },
  ];

  causes.forEach((c, i) => {
    const x = 0.2 + i * 2.4;
    s.addShape(pres.ShapeType.rect, { x, y: 0.88, w: 2.22, h: 0.44, fill: { color: c.col } });
    s.addText(c.title, { x, y: 0.88, w: 2.22, h: 0.44, fontSize: 13, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });

    const sections = [
      { label: "Clues", text: c.clues },
      { label: "Investigations", text: c.tests },
      { label: "Management", text: c.tx },
    ];
    let yy = 1.35;
    sections.forEach(sec => {
      s.addText(sec.label + ":", { x: x + 0.05, y: yy, w: 2.12, h: 0.28, fontSize: 11, bold: true, color: c.col, fontFace: "Calibri" });
      yy += 0.28;
      const lines = sec.text.split("\n");
      s.addText(bulletItems(lines, DARK), {
        x: x + 0.05, y: yy, w: 2.12, h: lines.length * 0.38 + 0.1,
        fontSize: 11, fontFace: "Calibri", lineSpacingMultiple: 1.2
      });
      yy += lines.length * 0.38 + 0.25;
    });
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 16 — MANAGEMENT ALGORITHM
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: "0A1628" };
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 0.72, fill: { color: DARK } });
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0.72, w: 10, h: 0.06, fill: { color: ACCENT } });
  s.addText("Management Algorithm — Chest Pain in the ED", {
    x: 0.35, y: 0, w: 9.3, h: 0.72, margin: 0,
    fontSize: 22, bold: true, color: WHITE, fontFace: "Calibri", align: "left", valign: "middle"
  });

  // Flowchart as nested boxes with arrows
  // Box 1: Initial Assessment
  s.addShape(pres.ShapeType.roundRect, { x: 3.3, y: 0.88, w: 3.4, h: 0.65, fill: { color: ACCENT }, rectRadius: 0.12 });
  s.addText("Chest Pain Patient Arrives", { x: 3.3, y: 0.88, w: 3.4, h: 0.65, fontSize: 13, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle" });

  s.addShape(pres.ShapeType.rect, { x: 4.92, y: 1.53, w: 0.16, h: 0.3, fill: { color: LGRAY } });

  // Box 2
  s.addShape(pres.ShapeType.roundRect, { x: 2.8, y: 1.83, w: 4.4, h: 0.55, fill: { color: MID }, rectRadius: 0.1 });
  s.addText("ABC + Vitals + IV access + O₂ + Monitor + ECG (< 10 min)", { x: 2.8, y: 1.83, w: 4.4, h: 0.55, fontSize: 11.5, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle" });

  s.addShape(pres.ShapeType.rect, { x: 4.92, y: 2.38, w: 0.16, h: 0.3, fill: { color: LGRAY } });

  // Branch
  const branches = [
    { label: "STEMI / Equiv.", action: "Activate Cath Lab\nAspirin + P2Y12\nHeparin + Primary PCI", col: ACCENT, x: 0.3 },
    { label: "NSTEMI / ACS", action: "Aspirin + P2Y12\nHeparin\nGlycoprotein IIb/IIIa if needed\nCardiology consult", col: GRAY, x: 3.55 },
    { label: "Rule-Out ACS", action: "Serial ECG + Troponin\nHEART Score / Pathway\nImaging if indicated\nDischarge vs Obs vs Admit", col: MID, x: 6.8 },
  ];

  // branch bar
  s.addShape(pres.ShapeType.roundRect, { x: 0.25, y: 2.68, w: 9.5, h: 0.5, fill: { color: "1B3A5C" }, rectRadius: 0.08 });
  s.addText("12-Lead ECG Interpretation", { x: 0.25, y: 2.68, w: 9.5, h: 0.5, fontSize: 13, bold: true, color: LGRAY, fontFace: "Calibri", align: "center", valign: "middle" });

  branches.forEach((b) => {
    s.addShape(pres.ShapeType.roundRect, { x: b.x, y: 3.28, w: 2.95, h: 0.42, fill: { color: b.col }, rectRadius: 0.08 });
    s.addText(b.label, { x: b.x, y: 3.28, w: 2.95, h: 0.42, fontSize: 12, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle" });
    s.addShape(pres.ShapeType.roundRect, { x: b.x, y: 3.76, w: 2.95, h: 1.65, fill: { color: "142847" }, rectRadius: 0.08 });
    s.addText(b.action, { x: b.x + 0.1, y: 3.82, w: 2.75, h: 1.55, fontSize: 11, color: LGRAY, fontFace: "Calibri", wrap: true, lineSpacingMultiple: 1.35 });
  });

  s.addText("Non-ACS diagnosis confirmed → treat specific cause (dissection, PE, PTX, pericarditis, MSK, GI)", {
    x: 0.2, y: 5.2, w: 9.6, h: 0.32, fontSize: 11.5, color: YELLOW, fontFace: "Calibri", align: "center", italic: true
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 17 — DISPOSITION & SPECIAL POPULATIONS
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "Disposition & Special Populations");

  // Disposition boxes
  s.addText("Disposition Strategy", { x: 0.2, y: 0.88, w: 9.5, h: 0.35, fontSize: 14, bold: true, color: MID, fontFace: "Calibri" });
  const dispos = [
    { title: "Discharge Home", criteria: ["Low HEART score (0–3) + negative serial troponins", "Alternative non-cardiac diagnosis established", "Adequate follow-up within 72 hrs arranged", "Patient educated on return precautions"], col: "2A7D6B" },
    { title: "Observation / Short Stay", criteria: ["Intermediate HEART score (4–6)", "Positive delta troponin awaiting 2nd sample", "Needs stress testing / CCTA before discharge", "Symptoms resolved, ECG normalised"], col: YELLOW },
    { title: "Inpatient Admission", criteria: ["STEMI — direct to cath lab", "NSTEMI / High-risk UA — cardiology", "HEART score 7–10 or troponin positive", "Non-ACS emergency: dissection, massive PE, PTX"], col: ACCENT },
  ];
  dispos.forEach((d, i) => {
    const x = 0.2 + i * 3.25;
    s.addShape(pres.ShapeType.rect, { x, y: 1.28, w: 3.05, h: 0.4, fill: { color: d.col } });
    s.addText(d.title, { x, y: 1.28, w: 3.05, h: 0.4, fontSize: 12.5, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
    s.addShape(pres.ShapeType.rect, { x, y: 1.68, w: 3.05, h: 2.08, fill: { color: "EAF2FB" } });
    s.addText(bulletItems(d.criteria, DARK), {
      x: x + 0.08, y: 1.72, w: 2.9, h: 1.95,
      fontSize: 11.5, fontFace: "Calibri", lineSpacingMultiple: 1.3
    });
  });

  // Special Populations
  s.addText("Special Considerations", { x: 0.2, y: 3.88, w: 9.5, h: 0.35, fontSize: 13, bold: true, color: MID, fontFace: "Calibri" });
  const special = [
    { grp: "Women", note: "More atypical presentations; jaw pain, fatigue, nausea without chest pain; higher rate of false-positive stress tests" },
    { grp: "Elderly", note: "Dyspnea may be anginal equivalent; higher baseline troponin; cognitive impairment may mask symptoms" },
    { grp: "Diabetics", note: "Silent MI common due to autonomic neuropathy; present with dyspnea, fatigue rather than pain" },
    { grp: "Cocaine users", note: "Vasospasm + atherosclerosis; benzos as first-line; avoid beta-blockers unless calcium-channel blocker also given" },
  ];
  special.forEach((sp, i) => {
    const x = 0.2 + (i % 2) * 4.85;
    const y = 4.28 + Math.floor(i / 2) * 0.6;
    s.addShape(pres.ShapeType.roundRect, { x, y, w: 4.6, h: 0.52, fill: { color: "EFF8FF" }, rectRadius: 0.08 });
    s.addText([
      { text: sp.grp + ": ", options: { bold: true, color: MID } },
      { text: sp.note, options: { color: DARK } }
    ], { x: x + 0.08, y, w: 4.45, h: 0.52, fontSize: 11, fontFace: "Calibri", valign: "middle", wrap: true });
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 18 — KEY TAKE-HOME POINTS
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: DARK } });
  s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 0.22, h: 5.625, fill: { color: ACCENT } });
  s.addShape(pres.ShapeType.rect, { x: 0.22, y: 0, w: 9.78, h: 0.08, fill: { color: ACCENT } });
  s.addShape(pres.ShapeType.rect, { x: 0.22, y: 5.545, w: 9.78, h: 0.08, fill: { color: ACCENT } });

  s.addText("KEY TAKE-HOME POINTS", {
    x: 0.5, y: 0.12, w: 9, h: 0.58,
    fontSize: 26, bold: true, color: WHITE, fontFace: "Calibri", charSpacing: 4
  });

  const points = [
    "Get ECG within 10 minutes — STEMI recognition is time-critical (PCI within 90 min)",
    "Never anchor on the first diagnosis — chest pain has a broad differential; rule out the Big 6 first",
    "Atypical presentations are common in women, elderly, and diabetics — maintain a low threshold",
    "Serial troponins + clinical assessment > single troponin alone; dynamic change confirms ACS",
    "HEART Score 0–3 + negative serial troponins → safe early discharge with appropriate follow-up",
    "Reproducible chest wall tenderness reduces but does NOT exclude ACS risk",
    "Aortic dissection: do NOT anticoagulate before imaging; BP differential and tearing pain are key clues",
    "PE: use PERC rule to exclude in low-probability patients; Wells score guides CT-PA decision",
    "75–80% of chest pain patients can be safely evaluated and discharged from the ED",
  ];

  points.forEach((pt, i) => {
    const y = 0.82 + i * 0.52;
    s.addShape(pres.ShapeType.roundRect, { x: 0.5, y, w: 0.36, h: 0.36, fill: { color: ACCENT }, rectRadius: 0.06 });
    s.addText(String(i + 1), { x: 0.5, y, w: 0.36, h: 0.36, fontSize: 12, bold: true, color: WHITE, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
    s.addText(pt, {
      x: 0.95, y: y + 0.01, w: 8.75, h: 0.42,
      fontSize: 12.5, color: LGRAY, fontFace: "Calibri", valign: "middle"
    });
  });
}

// ═══════════════════════════════════════════════════════════════════════════
// SLIDE 19 — REFERENCES
// ═══════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: LIGHT };
  addSlideHeader(s, "References");

  const refs = [
    "Rosen's Emergency Medicine: Concepts and Clinical Practice, 10th Edition (Elsevier, 2023) — Chapters 64 & 65",
    "Murray & Nadel's Textbook of Respiratory Medicine, 7th Edition — Chapter: Evaluation of Chest Pain",
    "Goldman-Cecil Medicine, 26th Edition — Differential Diagnosis of Chest Pain",
    "Amsterdam EA, et al. 2014 AHA/ACC Guideline for the Management of Patients with NSTE-ACS. JACC. 2014",
    "O'Gara PT, et al. 2013 ACCF/AHA Guideline for the Management of STEMI. JACC. 2013",
    "Konstantinides SV, et al. 2019 ESC Guidelines on Pulmonary Embolism. Eur Heart J. 2020",
    "Erbel R, et al. 2014 ESC Guidelines on Aortic Diseases. Eur Heart J. 2014",
    "Brady WJ, et al. The HEART Pathway for Evaluation of Acute Chest Pain. Ann Emerg Med. 2019",
    "Backus BE, et al. A prospective validation of the HEART score. Eur J Emerg Med. 2010",
  ];

  refs.forEach((r, i) => {
    const y = 0.9 + i * 0.51;
    s.addShape(pres.ShapeType.rect, { x: 0.25, y: y + 0.12, w: 0.08, h: 0.2, fill: { color: ACCENT } });
    s.addText(r, {
      x: 0.42, y, w: 9.3, h: 0.46,
      fontSize: 12, color: DARK, fontFace: "Calibri", valign: "middle"
    });
  });
}

// ─── WRITE FILE ─────────────────────────────────────────────────────────────
pres.writeFile({ fileName: "/home/daytona/workspace/chest-pain-ppt/Approach_To_Chest_Pain.pptx" })
  .then(() => console.log("Done!"))
  .catch(e => console.error(e));
Running Command

cd /home/daytona/workspace/chest-pain-ppt && node build.js 2>&1

Running Command

ls -lh /home/daytona/workspace/chest-pain-ppt/

Your presentation is ready. Download it here:

Approach To Chest Pain

Presentation · PPTX


What's inside (19 slides, designed for emergency physicians):
#SlideHighlights
1Title SlideBold dark-navy + red design
2Epidemiology & ScopeStat boxes - ~5-8% ED visits, #3 chief complaint
3The Big 6 Must-Not-MissACS, Dissection, PE, PTX, Tamponade, Boerhaave — card layout
4Differential by System6-system grid: Cardiac / Vascular / Pulmonary / GI / MSK / Psychogenic
5History — OPQRSTEach letter as a visual tile with key discriminators
6Risk Factor AssessmentCardiac risk factors vs PE/Dissection risk in parallel columns
7Physical Examination6-system targeted exam with specific ED-relevant clues
812-Lead ECG InterpretationSTEMI, NSTEMI, Hyperacute T, Non-ischaemic patterns — column layout
9Cardiac BiomarkersTroponin timeline, hsTn rapid protocols, D-dimer, BNP
10Chest X-RayPer-diagnosis CXR findings (6 diagnoses in grid)
11HEART ScoreFull scoring table with risk group colour coding
12Accelerated Diagnostic Protocols3-Phase model + HEART Pathway explained
13Aortic DissectionADD score, CT aortogram indications, Type A vs B management
14Pulmonary EmbolismWells score table, PERC rule, management by haemodynamic status
15Non-Cardiac Chest PainPericarditis, GERD/Boerhaave, MSK, Zoster - clues + investigations + Tx
16Management AlgorithmVisual flowchart: arrival → ECG → 3-branch disposition
17Disposition & Special PopulationsWomen, elderly, diabetics, cocaine users
18Key Take-Home Points9 numbered pearls on dark background
19ReferencesRosen's EM, AHA/ACC, ESC guidelines, HEART Pathway papers
Design: Deep navy + crimson red palette (emergency medicine feel), with teal accents, yellow warnings, and dark section dividers throughout.

Search for recent clinical images of acute MI, PE, and aortic dissection to add to the presentation

Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Loading Image
Loading Image
Loading Image
Loading Image
Loading Image
Writing File

~/chest-pain-ppt/add_images.js

/**
 * add_images.js
 * Appends 3 clinical image slides (AMI, PE, Aortic Dissection)
 * to the existing Approach_To_Chest_Pain.pptx by rebuilding from scratch,
 * keeping all original slides and adding the new ones just before the final
 * References slide.
 *
 * Strategy: use PptxGenJS to append slides to the existing file is not
 * supported; instead we download and embed images via the fetch_images helper,
 * then call the original build script with extra slides injected.
 * Because modifying the original is complex, we build a SEPARATE
 * "image supplement" deck and then use LibreOffice to merge them.
 */

const pptxgen = require("pptxgenjs");
const { execSync } = require("child_process");
const fs = require("fs");

// ─── PALETTE (mirrors main deck) ────────────────────────────────────────────
const DARK   = "0D1B2A";
const MID    = "1B3A5C";
const ACCENT = "E63946";
const LIGHT  = "F1FAEE";
const YELLOW = "FFB703";
const GRAY   = "457B9D";
const WHITE  = "FFFFFF";
const LGRAY  = "A8DADC";

// ─── IMAGE URLS ──────────────────────────────────────────────────────────────
const IMAGES = {
  // Acute MI
  hyperacute_t:   "https://cdn.orris.care/cdss_images/dd7add6a659e1f043b800ebded783ee8a1956dde25d18cac87d2b5f99a8dd9a8.png",
  anterior_stemi: "https://cdn.orris.care/cdss_images/779f6d419b0a92f4ddbbf7533f11e2047e00de9f40fc28c7c6bccc9af32e5a5b.png",
  // Pulmonary Embolism
  ctpa_saddle:    "https://cdn.orris.care/cdss_images/523344f233d140ab08d479e64322858940fa3107e5071a7ca9677346180f880b.png",
  ctpa_lobar:     "https://cdn.orris.care/cdss_images/88cee07971792db37e862bfcf0c5e0dfd3ba07388c7972b303717aedf9b80d9a.png",
  // Aortic Dissection
  dissection_ct:  "https://cdn.orris.care/cdss_images/9c4b34c63b5c5f39c656e1d1660c28b0ea000e4b172d8c46b314c25e55ae914c.png",
};

console.log("Downloading images via fetch_images helper...");
const urls = Object.values(IMAGES);
const raw = execSync(
  `node /home/daytona/skills/shared/scripts/fetch_images.js ${urls.map(u => `"${u}"`).join(" ")}`,
  { maxBuffer: 50 * 1024 * 1024 }
).toString();

const fetched = JSON.parse(raw);
const byUrl = {};
fetched.forEach(f => { byUrl[f.url] = f; });

function img(key) {
  const f = byUrl[IMAGES[key]];
  if (!f || f.error) { console.error("Failed:", key, f?.error); process.exit(1); }
  return f.base64;
}

console.log("All images downloaded. Building image supplement deck...");

// ─── BUILD SUPPLEMENT DECK ───────────────────────────────────────────────────
const pres = new pptxgen();
pres.layout = "LAYOUT_16x9";

function addHeader(slide, title, subtitle, accentColor) {
  accentColor = accentColor || ACCENT;
  slide.addShape(pres.ShapeType.rect, { x:0, y:0, w:10, h:0.72, fill:{ color: DARK } });
  slide.addShape(pres.ShapeType.rect, { x:0, y:0.72, w:10, h:0.06, fill:{ color: accentColor } });
  slide.addText(title, {
    x:0.35, y:0, w:9.3, h:0.72, margin:0,
    fontSize:22, bold:true, color:WHITE, fontFace:"Calibri", align:"left", valign:"middle"
  });
  if (subtitle) {
    slide.addText(subtitle, {
      x:0.35, y:0.78, w:9.3, h:0.3, margin:0,
      fontSize:12, color:LGRAY, fontFace:"Calibri", italic:true
    });
  }
}

// ══════════════════════════════════════════════════════════════════════════════
// SLIDE A — ACUTE MI: ECG IMAGES
// ══════════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: "0A1628" };
  addHeader(s, "Acute MI — ECG Findings", "Source: Rosen's Emergency Medicine, 10th Ed.", ACCENT);

  // Red accent bar label left image
  s.addShape(pres.ShapeType.rect, { x:0.2, y:1.15, w:4.45, h:0.38, fill:{ color: ACCENT } });
  s.addText("Fig A — Hyperacute T Waves (Early STEMI)", {
    x:0.2, y:1.15, w:4.45, h:0.38, margin:0,
    fontSize:11.5, bold:true, color:WHITE, fontFace:"Calibri", align:"center", valign:"middle"
  });
  s.addImage({ data: img("hyperacute_t"), x:0.2, y:1.53, w:4.45, h:2.85 });
  s.addText([
    { text: "Panel A: ", options:{ bold:true, color: YELLOW } },
    { text: "Broad, peaked T waves in V3–V4. ST just beginning to rise. Classic hyperacute T wave — earliest STEMI sign.", options:{ color: LGRAY } }
  ], { x:0.2, y:4.42, w:4.45, h:0.75, fontSize:11, fontFace:"Calibri", wrap:true, lineSpacingMultiple:1.3 });

  // Right image
  s.addShape(pres.ShapeType.rect, { x:5.15, y:1.15, w:4.65, h:0.38, fill:{ color: MID } });
  s.addText("Fig B — Anterior Wall STEMI (V1–V4)", {
    x:5.15, y:1.15, w:4.65, h:0.38, margin:0,
    fontSize:11.5, bold:true, color:WHITE, fontFace:"Calibri", align:"center", valign:"middle"
  });
  s.addImage({ data: img("anterior_stemi"), x:5.15, y:1.53, w:4.65, h:2.85 });
  s.addText([
    { text: "Panel B: ", options:{ bold:true, color: YELLOW } },
    { text: "ST elevation V1–V4 with oblique-straight morphology. LAD 90% stenosis confirmed on cath; stented successfully.", options:{ color: LGRAY } }
  ], { x:5.15, y:4.42, w:4.65, h:0.75, fontSize:11, fontFace:"Calibri", wrap:true, lineSpacingMultiple:1.3 });

  // Bottom key points bar
  s.addShape(pres.ShapeType.roundRect, {
    x:0.2, y:5.2, w:9.6, h:0.32, fill:{ color:"1B3050" }, rectRadius:0.06
  });
  s.addText("⚡ ECG within 10 min of arrival. Hyperacute T → STEMI evolving. STE in V1–V4 = anterior LAD territory. Activate cath lab immediately.", {
    x:0.25, y:5.2, w:9.5, h:0.32, fontSize:11, bold:true, color:YELLOW, fontFace:"Calibri", align:"center", valign:"middle"
  });
}

// ══════════════════════════════════════════════════════════════════════════════
// SLIDE B — PULMONARY EMBOLISM: CT-PA IMAGES
// ══════════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: "0A1628" };
  addHeader(s, "Pulmonary Embolism — CT Pulmonary Angiogram", "Source: Murray & Nadel's Respiratory Medicine, 7th Ed. | Tintinalli's Emergency Medicine", GRAY);

  // Left image — saddle PE (4 panels)
  s.addShape(pres.ShapeType.rect, { x:0.2, y:1.15, w:4.65, h:0.38, fill:{ color: GRAY } });
  s.addText("Fig A — Bilateral Saddle Embolism (CTPA)", {
    x:0.2, y:1.15, w:4.65, h:0.38, margin:0,
    fontSize:11.5, bold:true, color:WHITE, fontFace:"Calibri", align:"center", valign:"middle"
  });
  s.addImage({ data: img("ctpa_saddle"), x:0.2, y:1.53, w:4.65, h:2.85 });
  s.addText([
    { text: "Bilateral emboli: ", options:{ bold:true, color: YELLOW } },
    { text: '"Saddle" embolism (arrowheads B–C), right upper lobe emboli (white arrowheads A–C), interlobar emboli (arrows B–D). High clot burden — consider systemic thrombolysis if haemodynamically unstable.', options:{ color: LGRAY } }
  ], { x:0.2, y:4.42, w:4.65, h:0.85, fontSize:10.5, fontFace:"Calibri", wrap:true, lineSpacingMultiple:1.2 });

  // Right image — lobar PE with filling defect
  s.addShape(pres.ShapeType.rect, { x:5.15, y:1.15, w:4.65, h:0.38, fill:{ color: MID } });
  s.addText("Fig B — Lobar PE: Filling Defect (CTPA)", {
    x:5.15, y:1.15, w:4.65, h:0.38, margin:0,
    fontSize:11.5, bold:true, color:WHITE, fontFace:"Calibri", align:"center", valign:"middle"
  });
  s.addImage({ data: img("ctpa_lobar"), x:5.15, y:1.53, w:4.65, h:2.85 });
  s.addText([
    { text: "Filling defect: ", options:{ bold:true, color: YELLOW } },
    { text: "White arrowheads outline circular filling defect in right middle lobar pulmonary artery (arrowhead). Long arrow = segmental defect posterior medial segment. Diagnostic of acute PE.", options:{ color: LGRAY } }
  ], { x:5.15, y:4.42, w:4.65, h:0.85, fontSize:10.5, fontFace:"Calibri", wrap:true, lineSpacingMultiple:1.2 });

  s.addShape(pres.ShapeType.roundRect, {
    x:0.2, y:5.32, w:9.6, h:0.22, fill:{ color:"1B3050" }, rectRadius:0.05
  });
  s.addText("CT-PA sensitivity >95% for main & lobar arteries. Filling defect = absent contrast in vessel lumen. Saddle PE: embolus straddles pulmonary trunk bifurcation.", {
    x:0.25, y:5.32, w:9.5, h:0.22, fontSize:10.5, color:LGRAY, fontFace:"Calibri", align:"center", valign:"middle"
  });
}

// ══════════════════════════════════════════════════════════════════════════════
// SLIDE C — AORTIC DISSECTION: CT IMAGES
// ══════════════════════════════════════════════════════════════════════════════
{
  const s = pres.addSlide();
  s.background = { color: "0A1628" };
  addHeader(s, "Aortic Dissection — CT Aortogram", "Source: Tintinalli's Emergency Medicine, 9th Ed.", MID);

  // Full-width image
  s.addShape(pres.ShapeType.rect, { x:0.2, y:1.15, w:9.6, h:0.38, fill:{ color: MID } });
  s.addText("Type A Aortic Dissection — Non-Contrast (left) vs Contrast (right) CT", {
    x:0.2, y:1.15, w:9.6, h:0.38, margin:0,
    fontSize:12.5, bold:true, color:WHITE, fontFace:"Calibri", align:"center", valign:"middle"
  });
  s.addImage({ data: img("dissection_ct"), x:0.2, y:1.53, w:9.6, h:3.35 });

  // Annotation boxes
  const annots = [
    { label:"AT", desc:"Ascending True Lumen", col: GRAY, x:0.3 },
    { label:"AF", desc:"Ascending False Lumen", col: ACCENT, x:2.7 },
    { label:"DT", desc:"Descending True Lumen", col: MID, x:5.1 },
    { label:"↑ Arrow", desc:"Descending False Lumen", col: YELLOW, x:7.5 },
  ];
  annots.forEach(a => {
    s.addShape(pres.ShapeType.roundRect, { x:a.x, y:4.98, w:2.1, h:0.5, fill:{ color: a.col }, rectRadius:0.08 });
    s.addText([
      { text: a.label + " = ", options:{ bold:true, color: WHITE } },
      { text: a.desc, options:{ color: WHITE } }
    ], { x:a.x+0.06, y:4.98, w:2.0, h:0.5, fontSize:11, fontFace:"Calibri", valign:"middle", wrap:true });
  });

  s.addText([
    { text: "Type A: ", options:{ bold:true, color: ACCENT } },
    { text: "Involves ascending aorta → Emergency surgical repair    ", options:{ color: LGRAY } },
    { text: "Type B: ", options:{ bold:true, color: YELLOW } },
    { text: "Descending only → Medical management (IV labetalol, target SBP <120 mmHg)", options:{ color: LGRAY } }
  ], {
    x:0.2, y:5.52, w:9.6, h:0.32, fontSize:12, fontFace:"Calibri", align:"center"
  });
}

// ─── WRITE SUPPLEMENT FILE ────────────────────────────────────────────────────
const SUPPLEMENT = "/home/daytona/workspace/chest-pain-ppt/Image_Supplement.pptx";
pres.writeFile({ fileName: SUPPLEMENT })
  .then(() => {
    console.log("Supplement deck written:", SUPPLEMENT);

    // Merge with LibreOffice using python-pptx approach instead
    // Use python-pptx to merge the two presentations
    const mergeScript = `
import sys
from pptx import Presentation
from pptx.util import Inches
import copy
import lxml.etree as etree

main_path = "/home/daytona/workspace/chest-pain-ppt/Approach_To_Chest_Pain.pptx"
supp_path = "/home/daytona/workspace/chest-pain-ppt/Image_Supplement.pptx"
out_path  = "/home/daytona/workspace/chest-pain-ppt/Approach_To_Chest_Pain_WithImages.pptx"

main_prs = Presentation(main_path)
supp_prs = Presentation(supp_path)

# Insert supplement slides before the last slide (References)
# We'll append at position len-1 (before final References slide)
def add_slide(dest_prs, src_slide):
    """Clone a slide from src_prs into dest_prs."""
    # Add blank slide with same layout index
    layout = dest_prs.slide_layouts[6]  # blank
    new_slide = dest_prs.slides.add_slide(layout)
    
    # Copy the XML tree
    new_slide.shapes._spTree.clear()
    for el in src_slide.shapes._spTree:
        new_slide.shapes._spTree.append(copy.deepcopy(el))
    
    # Copy slide background
    if src_slide.background.fill.type is not None:
        pass  # background handled via XML below
    
    # Deep copy the entire slide XML to preserve background
    slide_xml = src_slide._element
    new_slide_xml = new_slide._element
    
    # Replace the cSld element (contains background + shapes)
    src_cSld = slide_xml.find('.//{http://schemas.openxmlformats.org/presentationml/2006/main}cSld')
    dst_cSld = new_slide_xml.find('.//{http://schemas.openxmlformats.org/presentationml/2006/main}cSld')
    if src_cSld is not None and dst_cSld is not None:
        dst_cSld.getparent().replace(dst_cSld, copy.deepcopy(src_cSld))
    
    # Copy relationships (images, etc.)
    for rel in src_slide.part.rels.values():
        if "image" in rel.reltype:
            try:
                img_part = rel.target_part
                new_rel = new_slide.part.relate_to(img_part, rel.reltype)
                # Update rId references in the new slide XML
                old_rId = rel.rId
                new_cSld = new_slide._element.find('.//{http://schemas.openxmlformats.org/presentationml/2006/main}cSld')
                if new_cSld is not None:
                    xml_str = etree.tostring(new_cSld, encoding='unicode')
                    xml_str = xml_str.replace(f'r:embed="{old_rId}"', f'r:embed="{new_rel}"')
                    new_elem = etree.fromstring(xml_str)
                    new_cSld.getparent().replace(new_cSld, new_elem)
            except Exception as e:
                print(f"Rel copy warning: {e}")
    
    return new_slide

# Get all slides from main
all_main = list(main_prs.slides)
# Insert supplement slides before the last slide (index = len-1)
insert_pos = len(all_main) - 1  # before References slide

# We need to rebuild: copy main slides, then at insert_pos add supp slides, then finish main
# Simplest: just append supp slides at the end before last main slide
# Actually use python-pptx slide order manipulation

# Append supplement slides to main
for src_slide in supp_prs.slides:
    add_slide(main_prs, src_slide)

# Now reorder: move last 3 slides (our new image slides) to position insert_pos
n = len(main_prs.slides)
# The slides XML list
slides_xml_list = main_prs.slides._sldIdLst
all_slide_ids = list(slides_xml_list)

# Move the last 3 elements to position insert_pos (before the last original slide)
# Original last slide is now at index n-4 (since we added 3)
# New image slides are at indices n-3, n-2, n-1
# References slide is at index n-4

image_slides = all_slide_ids[n-3:]  # last 3
for el in image_slides:
    slides_xml_list.remove(el)

# Now insert before what is now the last element (References)
ref_pos = len(list(slides_xml_list)) - 1
for i, el in enumerate(image_slides):
    slides_xml_list.insert(ref_pos + i, el)

main_prs.save(out_path)
print("Merged presentation saved to:", out_path)
`;

    fs.writeFileSync("/home/daytona/workspace/chest-pain-ppt/merge.py", mergeScript);
    try {
      const result = execSync("python3 /home/daytona/workspace/chest-pain-ppt/merge.py 2>&1").toString();
      console.log(result);
    } catch(e) {
      console.error("Merge error:", e.stdout?.toString(), e.stderr?.toString());
      process.exit(1);
    }
  })
  .catch(e => { console.error(e); process.exit(1); });
Running Command

cd /home/daytona/workspace/chest-pain-ppt && node add_images.js 2>&1

Running Command

pip install --user python-pptx 2>&1 | tail -5

Running Command

cd /home/daytona/workspace/chest-pain-ppt && python3 merge.py 2>&1

Reading File
Editing File

~/chest-pain-ppt/build.js

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/chest-pain-ppt/build.js'
Running Command

cd /home/daytona/workspace/chest-pain-ppt && node build.js 2>&1

Running Command

ls -lh /home/daytona/workspace/chest-pain-ppt/Approach_To_Chest_Pain.pptx

The updated presentation (now 22 slides, 5.7 MB with embedded images) is ready:

Approach To Chest Pain

Presentation · PPTX


3 new clinical image slides added (slides 19-21, before References):
Slide 19 — Acute MI: ECG Findings
  • Fig A: Hyperacute T wave ECG (Rosen's Fig 64.1) - broad peaked T waves in V3-V4, ST just rising, minutes after occlusion
  • Fig B: Anterior STEMI ECG (Rosen's Fig 64.6) - ST elevation V1-V4, confirmed 90% LAD stenosis on cath
Slide 20 — Pulmonary Embolism: CT Pulmonary Angiogram
  • Fig A: Bilateral saddle embolism CTPA (Murray & Nadel Fig 81.6) - saddle PE straddling pulmonary trunk bifurcation, right upper lobe + interlobar emboli
  • Fig B: Lobar PE with filling defect (Tintinalli Fig 56-3) - circular filling defect in right middle lobar pulmonary artery
Slide 21 — Aortic Dissection: CT Aortogram
  • Type A dissection, non-contrast vs contrast CT side-by-side (Tintinalli Fig 59-2)
  • Annotated: Ascending True Lumen (AT), Ascending False Lumen (AF), Descending True Lumen (DT), Descending False Lumen with intimal flap arrow
  • Type A vs Type B management summary at the bottom
All images are sourced from Rosen's Emergency Medicine, Murray & Nadel, and Tintinalli's Emergency Medicine - fully authoritative clinical textbook sources.
This is a shared conversation. Sign in to Orris to start your own chat.