/**
 * Helix Engage — Weekly Update (Apr 6–11, 2026)
 * "Clinical Precision" design — dark/light alternating, geometric, executive healthcare
 */
const PptxGenJS = require("pptxgenjs");

// ── Design System ───────────────────────────────────────────────
const P = {
  // Dark palette (hero slides)
  navyDeep:   "0F172A",  // slate-900
  navyMid:    "1E293B",  // slate-800
  navyLight:  "334155",  // slate-700

  // Light palette (content slides)
  white:      "FFFFFF",
  snow:       "F8FAFC",  // slate-50
  mist:       "F1F5F9",  // slate-100
  silver:     "E2E8F0",  // slate-200

  // Text
  inkDark:    "0F172A",
  inkMid:     "475569",  // slate-600
  inkLight:   "94A3B8",  // slate-400
  inkOnDark:  "F1F5F9",
  inkMuted:   "64748B",  // slate-500

  // Accents — healthcare-inspired
  teal:       "0D9488",  // primary brand
  tealLight:  "14B8A6",
  tealPale:   "CCFBF1",  // teal-100
  blue:       "0284C7",  // sky-600
  blueLight:  "38BDF8",
  indigo:     "4F46E5",
  amber:      "D97706",
  rose:       "E11D48",
  emerald:    "059669",
  violet:     "7C3AED",
};

const F = "Calibri";  // Clean, universally available
const FB = "Calibri Light";

// ── Helpers ─────────────────────────────────────────────────────
function sn(s, n) {
  s.addText(`${n}`, {
    x: 9.3, y: 5.15, w: 0.5, h: 0.3,
    fontSize: 8, color: P.inkLight, fontFace: FB, align: "right",
  });
}

function darkSlide(pptx) {
  const s = pptx.addSlide();
  s.background = { color: P.navyDeep };
  return s;
}

function lightSlide(pptx) {
  const s = pptx.addSlide();
  s.background = { color: P.white };
  return s;
}

// Thin teal accent line at top
function topLine(s, color) {
  s.addShape("rect", { x: 0, y: 0, w: 10, h: 0.04, fill: { color: color || P.teal } });
}

// Section label pill
function pill(s, text, color, x, y) {
  const w = text.length * 0.075 + 0.5;
  s.addShape("roundRect", {
    x, y, w, h: 0.26,
    fill: { color, transparency: 85 },
    rectRadius: 0.13,
  });
  s.addText(text.toUpperCase(), {
    x, y, w, h: 0.26,
    fontSize: 7, fontFace: F, bold: true, color,
    align: "center", valign: "middle",
  });
}

// Metric block (for dark slides)
function metric(s, { x, y, value, label, color, w = 2.0 }) {
  // Subtle card
  s.addShape("roundRect", {
    x, y, w, h: 1.4,
    fill: { color: P.navyMid },
    line: { color: P.navyLight, width: 0.5 },
    rectRadius: 0.08,
  });
  // Accent top bar
  s.addShape("rect", { x: x + 0.15, y: y + 0.06, w: w - 0.3, h: 0.025, fill: { color } });
  // Value
  s.addText(value, {
    x, y: y + 0.15, w, h: 0.75,
    fontSize: 38, fontFace: F, bold: true, color,
    align: "center", valign: "middle",
  });
  // Label
  s.addText(label, {
    x, y: y + 0.9, w, h: 0.35,
    fontSize: 9, fontFace: FB, color: P.inkLight,
    align: "center", valign: "top",
  });
}

// Content card (for light slides)
function card(s, { x, y, w, h, title, accent, items }) {
  // Card with left accent border
  s.addShape("roundRect", {
    x, y, w, h,
    fill: { color: P.snow },
    line: { color: P.silver, width: 0.5 },
    rectRadius: 0.06,
  });
  // Left accent bar
  s.addShape("rect", { x, y: y + 0.1, w: 0.035, h: h - 0.2, fill: { color: accent } });
  // Title
  s.addText(title, {
    x: x + 0.25, y: y + 0.08, w: w - 0.4, h: 0.32,
    fontSize: 10.5, fontFace: F, bold: true, color: accent,
  });
  // Items
  if (items?.length) {
    s.addText(
      items.map(t => ({
        text: t,
        options: {
          fontSize: 8.5, fontFace: FB, color: P.inkMid,
          bullet: { code: "2022" }, // bullet dot
          paraSpaceAfter: 3, breakLine: true,
        },
      })),
      { x: x + 0.25, y: y + 0.4, w: w - 0.5, h: h - 0.5, valign: "top", lineSpacingMultiple: 1.15 }
    );
  }
}

// Section heading for light slides
function sectionHead(s, title, subtitle) {
  s.addText(title, {
    x: 0.6, y: 0.35, w: 8, h: 0.45,
    fontSize: 22, fontFace: F, bold: true, color: P.inkDark,
  });
  if (subtitle) {
    s.addText(subtitle, {
      x: 0.6, y: 0.78, w: 8, h: 0.3,
      fontSize: 10, fontFace: FB, color: P.inkMuted,
    });
  }
}

// ═════════════════════════════════════════════════════════════════
async function build() {
  const pptx = new PptxGenJS();
  pptx.layout = "LAYOUT_16x9";
  pptx.author = "Satya Suman Sari";
  pptx.company = "FortyTwo Platform";
  pptx.title = "Helix Engage — Weekly Update (Apr 6–11, 2026)";

  // ─── SLIDE 1: Title (Dark) ────────────────────────────────────
  {
    const s = darkSlide(pptx);
    topLine(s, P.teal);

    // Geometric accent — vertical teal line
    s.addShape("rect", { x: 0.6, y: 1.2, w: 0.035, h: 2.8, fill: { color: P.teal } });

    pill(s, "Weekly Status", P.tealLight, 0.85, 1.3);

    s.addText("Helix Engage", {
      x: 0.85, y: 1.7, w: 7, h: 0.9,
      fontSize: 42, fontFace: F, bold: true, color: P.white,
    });

    s.addText("Engineering Progress Report", {
      x: 0.85, y: 2.5, w: 7, h: 0.4,
      fontSize: 16, fontFace: FB, color: P.inkLight,
    });

    // Date block
    s.addShape("rect", { x: 0.85, y: 3.2, w: 2.2, h: 0.04, fill: { color: P.teal, transparency: 50 } });
    s.addText("April 6 – 11, 2026", {
      x: 0.85, y: 3.35, w: 3, h: 0.3,
      fontSize: 11, fontFace: F, bold: true, color: P.tealLight,
    });

    s.addText("Satya Suman Sari  |  FortyTwo Platform", {
      x: 0.85, y: 4.8, w: 5, h: 0.25,
      fontSize: 8, fontFace: FB, color: P.inkLight,
    });
    sn(s, 1);
  }

  // ─── SLIDE 2: At a Glance (Dark) ─────────────────────────────
  {
    const s = darkSlide(pptx);
    topLine(s, P.teal);

    pill(s, "Overview", P.tealLight, 0.5, 0.3);
    s.addText("Week at a Glance", {
      x: 0.5, y: 0.6, w: 5, h: 0.45,
      fontSize: 22, fontFace: F, bold: true, color: P.white,
    });

    metric(s, { x: 0.5,  y: 1.25, value: "57",  label: "Commits Shipped", color: P.blueLight, w: 2.05 });
    metric(s, { x: 2.7,  y: 1.25, value: "9",   label: "Defects Resolved", color: P.rose, w: 2.05 });
    metric(s, { x: 4.9,  y: 1.25, value: "40",  label: "E2E Tests Passing", color: P.emerald, w: 2.05 });
    metric(s, { x: 7.1,  y: 1.25, value: "17",  label: "Docker Containers", color: P.violet, w: 2.05 });

    // Key highlights
    const highlights = [
      "Multi-tenant EC2 architecture deployed — Ramaiah + Global on single instance",
      "Woodpecker CI/CD pipeline operational with Teams notifications",
      "Cross-tenant security vulnerability identified and patched",
      "Complete documentation: architecture, runbook, CI/CD guide",
    ];
    s.addText(
      highlights.map(h => ({
        text: h,
        options: {
          fontSize: 10, fontFace: FB, color: P.inkOnDark,
          bullet: { code: "25B8" }, paraSpaceAfter: 6, breakLine: true,
        },
      })),
      { x: 0.6, y: 2.9, w: 8.5, h: 2.0, valign: "top", lineSpacingMultiple: 1.2 }
    );

    sn(s, 2);
  }

  // ─── SLIDE 3: Defect Fixes (Light) ────────────────────────────
  {
    const s = lightSlide(pptx);
    topLine(s, P.rose);
    sectionHead(s, "Defect Resolution", "9 of 17 triaged bugs fixed and deployed this week");

    const bugs = [
      ["#527", "Appointment creation overwrites patient details"],
      ["#529", "Break/Training status doesn't block outbound calls"],
      ["#531", "Agent can log out during an active call"],
      ["#533", "Redundant Call History page header"],
      ["#534", "Redundant Patients page header"],
      ["#536", "My Performance displays wrong agent data"],
      ["#538", "Supervisor dashboard metrics incorrect"],
      ["#540", "Ghost calls visible for logged-out agents"],
      ["#547", "SLA priority rules not reflected in worklist"],
    ];

    const rows = [
      [
        { text: "ID", options: { bold: true, color: P.white, fill: { color: P.navyMid }, fontSize: 8.5, fontFace: F } },
        { text: "Description", options: { bold: true, color: P.white, fill: { color: P.navyMid }, fontSize: 8.5, fontFace: F } },
        { text: "Status", options: { bold: true, color: P.white, fill: { color: P.navyMid }, fontSize: 8.5, fontFace: F } },
      ],
      ...bugs.map(([id, desc], i) => [
        { text: id, options: { fontSize: 8.5, fontFace: F, color: P.inkMid, fill: { color: i % 2 === 0 ? P.snow : P.white } } },
        { text: desc, options: { fontSize: 8.5, fontFace: FB, color: P.inkMid, fill: { color: i % 2 === 0 ? P.snow : P.white } } },
        { text: "Resolved", options: { fontSize: 8.5, fontFace: F, bold: true, color: P.emerald, fill: { color: i % 2 === 0 ? P.snow : P.white } } },
      ]),
    ];

    s.addTable(rows, {
      x: 0.5, y: 1.2, w: 9.0,
      border: { type: "solid", pt: 0.3, color: P.silver },
      colW: [0.7, 6.6, 1.7], rowH: 0.36,
    });

    s.addText("Deferred by product:  #516 recordings  |  #517 AI transcription  |  #519 supervisor calling  |  #539 real-time missed calls  |  #541 whisper/barge", {
      x: 0.5, y: 4.9, w: 9, h: 0.3,
      fontSize: 7.5, fontFace: FB, color: P.inkLight, italic: true,
    });
    sn(s, 3);
  }

  // ─── SLIDE 4: Security Fix (Dark) ────────────────────────────
  {
    const s = darkSlide(pptx);
    topLine(s, P.rose);

    pill(s, "Security", P.rose, 0.5, 0.3);
    s.addText("Cross-Tenant Isolation Vulnerability", {
      x: 0.5, y: 0.6, w: 9, h: 0.45,
      fontSize: 22, fontFace: F, bold: true, color: P.white,
    });
    s.addText("Discovered and patched within the same sprint", {
      x: 0.5, y: 1.0, w: 9, h: 0.3,
      fontSize: 10, fontFace: FB, color: P.inkLight,
    });

    // Problem
    s.addShape("roundRect", {
      x: 0.4, y: 1.5, w: 4.4, h: 2.6,
      fill: { color: P.navyMid }, line: { color: P.navyLight, width: 0.5 }, rectRadius: 0.06,
    });
    s.addShape("rect", { x: 0.4, y: 1.5, w: 0.035, h: 2.6, fill: { color: P.rose } });
    s.addText("Impact", {
      x: 0.65, y: 1.55, w: 3, h: 0.3,
      fontSize: 11, fontFace: F, bold: true, color: P.rose,
    });
    s.addText(
      [
        "Shared OZONETEL_AGENT_ID env var across sidecars",
        "6 endpoints used silent fallback to wrong agent",
        "Ramaiah operations could modify Global's session",
        "Agent state, disposition, dial, metrics all affected",
        "No error or warning — completely silent",
      ].map(t => ({
        text: t, options: { fontSize: 8.5, fontFace: FB, color: P.inkOnDark, bullet: { code: "25B8" }, paraSpaceAfter: 4, breakLine: true },
      })),
      { x: 0.65, y: 1.9, w: 3.9, h: 2.0, valign: "top" }
    );

    // Resolution
    s.addShape("roundRect", {
      x: 5.1, y: 1.5, w: 4.5, h: 2.6,
      fill: { color: P.navyMid }, line: { color: P.navyLight, width: 0.5 }, rectRadius: 0.06,
    });
    s.addShape("rect", { x: 5.1, y: 1.5, w: 0.035, h: 2.6, fill: { color: P.emerald } });
    s.addText("Resolution", {
      x: 5.35, y: 1.55, w: 3, h: 0.3,
      fontSize: 11, fontFace: F, bold: true, color: P.emerald,
    });
    s.addText(
      [
        "Removed all defaultAgentId fallbacks",
        "All 6 endpoints now require agentId (400 if absent)",
        "Frontend sends agentId from localStorage",
        "OZONETEL_AGENT_ID removed from config entirely",
        "Verified with 40 E2E tests — zero regressions",
      ].map(t => ({
        text: t, options: { fontSize: 8.5, fontFace: FB, color: P.inkOnDark, bullet: { code: "25B8" }, paraSpaceAfter: 4, breakLine: true },
      })),
      { x: 5.35, y: 1.9, w: 4.0, h: 2.0, valign: "top" }
    );

    // Clean layers footer
    s.addText("Unaffected layers:  Login (DB lookup)  |  Telephony dispatcher (event payload)  |  Sidecar registration (GraphQL)  |  Supervisor (webhook events)", {
      x: 0.5, y: 4.4, w: 9, h: 0.3,
      fontSize: 7.5, fontFace: FB, color: P.inkLight,
    });
    sn(s, 4);
  }

  // ─── SLIDE 5: EC2 Architecture (Light) ────────────────────────
  {
    const s = lightSlide(pptx);
    topLine(s, P.blue);
    sectionHead(s, "AWS EC2 Multi-Tenant Architecture", "Single instance, strict tenant isolation, host-routed Caddy");

    card(s, {
      x: 0.4, y: 1.2, w: 4.4, h: 2.0,
      title: "Shared Platform Layer", accent: P.blue,
      items: [
        "NestJS server — multi-tenant by Origin header",
        "PostgreSQL 16 with workspace-per-schema",
        "BullMQ worker, ClickHouse analytics, Redpanda events",
        "MinIO S3-compatible object storage",
      ],
    });

    card(s, {
      x: 5.1, y: 1.2, w: 4.5, h: 2.0,
      title: "Isolated Sidecar Layer", accent: P.amber,
      items: [
        "Per-hospital: sidecar + Redis + data volume",
        "Caddy host-routes — no catchall, no cross-tenant",
        "ramaiah.engage.healix360.net \u2192 sidecar-ramaiah",
        "global.engage.healix360.net \u2192 sidecar-global",
      ],
    });

    card(s, {
      x: 0.4, y: 3.4, w: 4.4, h: 1.7,
      title: "Telephony Dispatcher", accent: P.teal,
      items: [
        "Routes Ozonetel events by agentId via Redis lookup",
        "Sidecars self-register on boot with heartbeat",
        "Zero config when onboarding new hospitals",
      ],
    });

    card(s, {
      x: 5.1, y: 3.4, w: 4.5, h: 1.7,
      title: "Live Endpoints", accent: P.indigo,
      items: [
        "ramaiah.engage / global.engage — Hospital UIs",
        "telephony.engage — Event dispatcher",
        "operations — CI/CD dashboard",
        "git — Gitea forge (mirrors Azure DevOps)",
      ],
    });
    sn(s, 5);
  }

  // ─── SLIDE 6: E2E Tests (Dark) ────────────────────────────────
  {
    const s = darkSlide(pptx);
    topLine(s, P.emerald);

    pill(s, "Quality Assurance", P.emerald, 0.5, 0.3);
    s.addText("40 Automated E2E Tests", {
      x: 0.5, y: 0.6, w: 9, h: 0.45,
      fontSize: 22, fontFace: F, bold: true, color: P.white,
    });
    s.addText("Playwright smoke tests covering every page across both hospitals", {
      x: 0.5, y: 1.0, w: 9, h: 0.3,
      fontSize: 10, fontFace: FB, color: P.inkLight,
    });

    // Ramaiah
    s.addShape("roundRect", {
      x: 0.4, y: 1.5, w: 4.4, h: 2.4,
      fill: { color: P.navyMid }, line: { color: P.navyLight, width: 0.5 }, rectRadius: 0.06,
    });
    s.addShape("rect", { x: 0.4, y: 1.5, w: 0.035, h: 2.4, fill: { color: P.amber } });
    s.addText("Ramaiah Hospitals — 27 tests", {
      x: 0.65, y: 1.55, w: 4, h: 0.3,
      fontSize: 10.5, fontFace: F, bold: true, color: P.amber,
    });
    s.addText(
      [
        "Login flow: branding, credentials, auth guard (4)",
        "CC Agent: call desk, history, patients, appointments, performance, sidebar, sign-out (10)",
        "Supervisor: dashboard, team perf, live monitor, all data pages, settings (12)",
        "Auth setup with auto session unlock (1)",
      ].map(t => ({ text: t, options: { fontSize: 8.5, fontFace: FB, color: P.inkOnDark, bullet: { code: "25B8" }, paraSpaceAfter: 5, breakLine: true } })),
      { x: 0.65, y: 1.9, w: 3.9, h: 1.8, valign: "top" }
    );

    // Global
    s.addShape("roundRect", {
      x: 5.1, y: 1.5, w: 4.5, h: 2.4,
      fill: { color: P.navyMid }, line: { color: P.navyLight, width: 0.5 }, rectRadius: 0.06,
    });
    s.addShape("rect", { x: 5.1, y: 1.5, w: 0.035, h: 2.4, fill: { color: P.blueLight } });
    s.addText("Global Hospital — 13 tests", {
      x: 5.35, y: 1.55, w: 4, h: 0.3,
      fontSize: 10.5, fontFace: F, bold: true, color: P.blueLight,
    });
    s.addText(
      [
        "CC Agent: landing, history, patients, appointments, performance, sidebar, sign-out (7)",
        "Supervisor: landing, patients, appointments, campaigns, settings (5)",
        "Auth setup with auto session unlock (1)",
      ].map(t => ({ text: t, options: { fontSize: 8.5, fontFace: FB, color: P.inkOnDark, bullet: { code: "25B8" }, paraSpaceAfter: 5, breakLine: true } })),
      { x: 5.35, y: 1.9, w: 4.0, h: 1.8, valign: "top" }
    );

    // Self-healing footer
    s.addShape("roundRect", {
      x: 0.4, y: 4.15, w: 9.2, h: 0.85,
      fill: { color: P.navyMid }, line: { color: P.navyLight, width: 0.5 }, rectRadius: 0.06,
    });
    s.addText("Self-Healing", {
      x: 0.65, y: 4.2, w: 2, h: 0.25,
      fontSize: 9, fontFace: F, bold: true, color: P.emerald,
    });
    s.addText("Auto-clears session locks before login  |  Completes sign-out after tests  |  Runs against live EC2, not mocked  |  ~6 min on Woodpecker CI", {
      x: 0.65, y: 4.5, w: 8.5, h: 0.3,
      fontSize: 8, fontFace: FB, color: P.inkLight,
    });
    sn(s, 6);
  }

  // ─── SLIDE 7: CI/CD (Light) ───────────────────────────────────
  {
    const s = lightSlide(pptx);
    topLine(s, P.indigo);
    sectionHead(s, "CI/CD Pipeline", "Automated testing, report publishing, and team notifications");

    // Flow bar
    s.addShape("roundRect", {
      x: 0.5, y: 1.15, w: 9.0, h: 0.4,
      fill: { color: P.mist }, line: { color: P.silver, width: 0.5 }, rectRadius: 0.06,
    });
    s.addText("Azure DevOps   \u2192   Gitea Mirror   \u2192   Woodpecker Pipeline   \u2192   MinIO Reports   \u2192   Teams Alert", {
      x: 0.5, y: 1.15, w: 9.0, h: 0.4,
      fontSize: 9.5, fontFace: F, bold: true, color: P.indigo, align: "center", valign: "middle",
    });

    card(s, {
      x: 0.4, y: 1.75, w: 4.4, h: 1.7,
      title: "Frontend Pipeline", accent: P.blue,
      items: [
        "TypeScript typecheck (yarn tsc --noEmit)",
        "40 Playwright E2E tests against live EC2",
        "HTML report uploaded to MinIO (S3 plugin)",
        "Teams Adaptive Card with report link",
      ],
    });

    card(s, {
      x: 5.1, y: 1.75, w: 4.5, h: 1.7,
      title: "Sidecar Pipeline", accent: P.violet,
      items: [
        "Jest unit tests (npm ci + jest --ci)",
        "Teams notification on pass or fail",
        "Triggered on push or manual run",
      ],
    });

    card(s, {
      x: 0.4, y: 3.65, w: 9.2, h: 1.4,
      title: "Operations Dashboard", accent: P.teal,
      items: [
        "operations.healix360.net — Woodpecker CI with full build history and logs",
        "operations.healix360.net/reports/{run}/ — Playwright HTML reports with screenshots (basic auth protected)",
        "git.healix360.net — Gitea forge mirroring Azure DevOps every 15 minutes",
        "Teams 'Deployment updates' channel receives Adaptive Cards with pass/fail count and report link",
      ],
    });
    sn(s, 7);
  }

  // ─── SLIDE 8: Timeline (Light) ────────────────────────────────
  {
    const s = lightSlide(pptx);
    topLine(s, P.teal);
    sectionHead(s, "Development Timeline");

    const timeline = [
      { date: "Apr 6 Sun", title: "Onboarding Wizard", desc: "6-phase setup wizard, widget config, telephony/AI CRUD, team invite, clinic/doctor management", color: P.blue },
      { date: "Apr 7 Mon", title: "SIP & ACW Fixes", desc: "3-layer ACW protection, SIP disconnect guard, dispose agentId, setup wizard polish", color: P.teal },
      { date: "Apr 8 Tue", title: "Master Data", desc: "Dynamic clinic/doctor fetching, appointment form overhaul, Ramaiah 195 doctor seed", color: P.amber },
      { date: "Apr 9 Wed", title: "EC2 Deployment", desc: "Multi-tenant architecture, telephony dispatcher, Caddy host routing, 14 containers", color: P.indigo },
      { date: "Apr 10 Thu", title: "Defect Sprint", desc: "9 bugs fixed, 40 E2E tests, architecture docs, runbook, cross-tenant discovery", color: P.rose },
      { date: "Apr 11 Fri", title: "CI/CD Pipeline", desc: "Woodpecker + Gitea + MinIO, Teams notifications, defaultAgentId security patch", color: P.emerald },
    ];

    // Vertical line
    s.addShape("rect", { x: 1.25, y: 1.2, w: 0.02, h: 3.9, fill: { color: P.silver } });

    timeline.forEach((e, i) => {
      const y = 1.2 + i * 0.65;
      // Dot
      s.addShape("ellipse", {
        x: 1.18, y: y + 0.06, w: 0.16, h: 0.16,
        fill: { color: e.color }, line: { color: P.white, width: 2 },
      });
      // Date
      s.addText(e.date, {
        x: 1.55, y, w: 1.2, h: 0.22,
        fontSize: 7.5, fontFace: F, bold: true, color: e.color,
      });
      // Title
      s.addText(e.title, {
        x: 2.8, y, w: 1.8, h: 0.22,
        fontSize: 9.5, fontFace: F, bold: true, color: P.inkDark,
      });
      // Desc
      s.addText(e.desc, {
        x: 4.7, y, w: 4.8, h: 0.55,
        fontSize: 8, fontFace: FB, color: P.inkMid, valign: "top",
      });
    });
    sn(s, 8);
  }

  // ─── SLIDE 9: Closing (Dark) ──────────────────────────────────
  {
    const s = darkSlide(pptx);
    topLine(s, P.teal);

    s.addShape("rect", { x: 0.6, y: 1.6, w: 0.035, h: 1.8, fill: { color: P.teal } });

    s.addText("57 commits across 3 repositories", {
      x: 0.85, y: 1.6, w: 8, h: 0.6,
      fontSize: 28, fontFace: F, bold: true, color: P.white,
    });

    s.addText("From single-tenant VPS to multi-tenant EC2 with automated CI/CD,\n40 end-to-end tests, and a fully integrated operations dashboard.", {
      x: 0.85, y: 2.3, w: 7, h: 0.7,
      fontSize: 12, fontFace: FB, color: P.inkLight, lineSpacingMultiple: 1.4,
    });

    // Achievement pills
    const items = [
      { text: "Multi-Tenant EC2", color: P.blue },
      { text: "40 E2E Tests", color: P.emerald },
      { text: "CI/CD Pipeline", color: P.indigo },
      { text: "9 Bugs Fixed", color: P.rose },
      { text: "Teams Alerts", color: P.violet },
    ];
    items.forEach((a, i) => {
      const x = 0.85 + i * 1.7;
      s.addShape("roundRect", {
        x, y: 3.4, w: 1.5, h: 0.32,
        fill: { color: P.navyMid },
        line: { color: a.color, width: 1 },
        rectRadius: 0.16,
      });
      s.addText(a.text, {
        x, y: 3.4, w: 1.5, h: 0.32,
        fontSize: 8, fontFace: F, bold: true, color: a.color,
        align: "center", valign: "middle",
      });
    });

    s.addText("Satya Suman Sari  |  FortyTwo Platform", {
      x: 0.85, y: 4.8, w: 5, h: 0.25,
      fontSize: 8, fontFace: FB, color: P.inkLight,
    });
    sn(s, 9);
  }

  await pptx.writeFile({ fileName: "docs/weekly-update-apr06-11.pptx" });
  console.log("Generated: docs/weekly-update-apr06-11.pptx");
}

build().catch(err => { console.error(err); process.exit(1); });
