root = Card([header, healthSummary, quarterSelector, sections, actionButtons])
header = CardHeader("PMO Portfolio Review", "Q2 2026 · 12 Active Projects · 84 Team Members")
healthSummary = TextContent("**Portfolio Health: 🟡 At Risk** — 3 projects critical, 2 over budget, 18% team over-utilization, 7 blocked items needing escalation.", "default")
quarterSelector = Form("quarter-selector", quarterButtons, [quarterField])
quarterField = FormControl("Quarter", quarterSelect, "Switch to view portfolio data for a different quarter")
quarterSelect = Select("quarter", quarterOptions, "Q2 2026", { required: true })
quarterOptions = [qo1, qo2, qo3, qo4]
qo1 = SelectItem("Q1-2026", "Q1 2026 (Jan–Mar)")
qo2 = SelectItem("Q2-2026", "Q2 2026 (Apr–Jun)")
qo3 = SelectItem("Q3-2026", "Q3 2026 (Jul–Sep)")
qo4 = SelectItem("Q4-2026", "Q4 2026 (Oct–Dec)")
quarterButtons = Buttons([quarterSubmit], "row")
quarterSubmit = Button("Apply Quarter", { type: "continue_conversation", context: "Show portfolio review for selected quarter" }, "primary")
sections = SectionBlock([secProjects, secMilestones, secBudget, secUtilization, secRisks, secDeadlines, secPace, secBlocked], false)
secProjects = SectionItem("projects", "Active Projects (12)", [projectsTable])
projectsTable = Table([colProjName, colOwner, colDeadline, colHealth, colStatus])
colProjName = Col("Project", projNames, "string")
colOwner = Col("Owner", projOwners, "string")
colDeadline = Col("Deadline", projDeadlines, "string")
colHealth = Col("Health", projHealth, "string")
colStatus = Col("Status", projStatus, "string")
projNames = ["Apollo Platform", "Orion Migration", "Nova Analytics", "Stellar Mobile", "Lunar CRM", "Solar API Gateway", "Comet Data Lake", "Nebula AI/ML", "Aurora Payments", "Zenith Reporting", "Horizon Integration", "Polaris Security"]
projOwners = ["S. Chen", "M. Rodriguez", "A. Patel", "J. Kim", "R. Thompson", "L. Wang", "D. Okafor", "K. Jensen", "P. Singh", "E. Mueller", "T. Nakamura", "F. Rossi"]
projDeadlines = ["2026-06-15", "2026-07-01", "2026-06-30", "2026-08-15", "2026-06-20", "2026-07-31", "2026-09-01", "2026-10-15", "2026-06-10", "2026-07-15", "2026-08-31", "2026-09-30"]
projHealth = ["🟢 Healthy", "🟡 At Risk", "🔴 Critical", "🟢 Healthy", "🔴 Critical", "🟡 At Risk", "🟢 Healthy", "🟡 At Risk", "🔴 Critical", "🟢 Healthy", "🟡 At Risk", "🟢 Healthy"]
projStatus = ["On Track", "Delayed", "Blocked", "On Track", "Blocked", "Delayed", "On Track", "Delayed", "Blocked", "On Track", "Delayed", "On Track"]
secMilestones = SectionItem("milestones", "Overdue Milestones (8)", [milestonesTable])
milestonesTable = Table([colMsProject, colMsName, colMsDue, colMsDaysOverdue, colMsOwner])
colMsProject = Col("Project", msProjects, "string")
colMsName = Col("Milestone", msNames, "string")
colMsDue = Col("Due Date", msDueDates, "string")
colMsDaysOverdue = Col("Days Overdue", msDaysOverdue, "number")
colMsOwner = Col("Owner", msOwners, "string")
msProjects = ["Orion Migration", "Nova Analytics", "Stellar Mobile", "Lunar CRM", "Solar API Gateway", "Comet Data Lake", "Nebula AI/ML", "Aurora Payments"]
msNames = ["Data Migration Complete", "Dashboard v2 Launch", "iOS App Store Submit", "User Acceptance Testing", "Auth Service GA", "ETL Pipeline Stabilize", "Model Training Complete", "PCI-DSS Audit Ready"]
msDueDates = ["2026-05-20", "2026-05-25", "2026-05-28", "2026-05-15", "2026-05-30", "2026-05-18", "2026-05-22", "2026-05-10"]
msDaysOverdue = [22, 17, 14, 27, 12, 24, 20, 32]
msOwners = ["M. Rodriguez", "A. Patel", "J. Kim", "R. Thompson", "L. Wang", "D. Okafor", "K. Jensen", "P. Singh"]
secBudget = SectionItem("budget", "Budget: Spent vs Allocation", [budgetChart, budgetTable])
budgetChart = HorizontalBarChart(budgetProjects, [budgetAllocatedSeries, budgetSpentSeries], "grouped", "Amount ($k)", "Project")
budgetProjects = ["Apollo Platform", "Orion Migration", "Nova Analytics", "Stellar Mobile", "Lunar CRM", "Solar API Gateway", "Comet Data Lake", "Nebula AI/ML", "Aurora Payments", "Zenith Reporting", "Horizon Integration", "Polaris Security"]
budgetAllocatedSeries = Series("Allocated ($k)", [850, 1200, 600, 950, 400, 700, 1100, 1500, 500, 300, 650, 800])
budgetSpentSeries = Series("Spent ($k)", [620, 1080, 580, 720, 390, 510, 890, 1420, 480, 210, 420, 560])
budgetTable = Table([colBProject, colBAllocated, colBSpent, colBRemaining, colBPercent])
colBProject = Col("Project", budgetProjects, "string")
colBAllocated = Col("Allocated ($k)", [850, 1200, 600, 950, 400, 700, 1100, 1500, 500, 300, 650, 800], "number")
colBSpent = Col("Spent ($k)", [620, 1080, 580, 720, 390, 510, 890, 1420, 480, 210, 420, 560], "number")
colBRemaining = Col("Remaining ($k)", [230, 120, 20, 230, 10, 190, 210, 80, 20, 90, 230, 240], "number")
colBPercent = Col("% Used", ["73%", "90%", "97%", "76%", "98%", "73%", "81%", "95%", "96%", "70%", "65%", "70%"], "string")
secUtilization = SectionItem("utilization", "Team Utilization", [utilChart, utilTable])
utilChart = BarChart(utilTeams, [utilAllocatedSeries, utilActualSeries], "grouped", "Team", "Utilization (%)")
utilTeams = ["Platform", "Mobile", "Data", "AI/ML", "Payments", "Security", "Integrations", "QA/DevOps"]
utilAllocatedSeries = Series("Allocated (%)", [85, 90, 95, 100, 80, 75, 88, 92])
utilActualSeries = Series("Actual (%)", [92, 105, 118, 125, 88, 82, 95, 108])
utilTable = Table([colUTeam, colUAllocated, colUActual, colUDelta, colUStatus])
colUTeam = Col("Team", utilTeams, "string")
colUAllocated = Col("Allocated %", [85, 90, 95, 100, 80, 75, 88, 92], "number")
colUActual = Col("Actual %", [92, 105, 118, 125, 88, 82, 95, 108], "number")
colUDelta = Col("Delta", [7, 15, 23, 25, 8, 7, 7, 16], "number")
colUStatus = Col("Status", ["⚠️ Over", "🔴 Critical", "🔴 Critical", "🔴 Critical", "⚠️ Over", "✅ OK", "⚠️ Over", "🔴 Critical"], "string")
secRisks = SectionItem("risks", "Top Risks by Severity (15)", [risksTable])
risksTable = Table([colRProject, colRDescription, colRSeverity, colRLikelihood, colRImpact, colRMitigation, colROwner])
colRProject = Col("Project", riskProjects, "string")
colRDescription = Col("Risk", riskDescriptions, "string")
colRSeverity = Col("Severity", riskSeverity, "string")
colRLikelihood = Col("Likelihood", riskLikelihood, "string")
colRImpact = Col("Impact", riskImpact, "string")
colRMitigation = Col("Mitigation", riskMitigation, "string")
colROwner = Col("Owner", riskOwners, "string")
riskProjects = ["Nova Analytics", "Lunar CRM", "Nebula AI/ML", "Orion Migration", "Aurora Payments", "Stellar Mobile", "Comet Data Lake", "Solar API Gateway", "Horizon Integration", "Polaris Security", "Apollo Platform", "Zenith Reporting", "Nova Analytics", "Orion Migration", "Nebula AI/ML"]
riskDescriptions = ["Key data engineer leaving", "PCI compliance gap", "GPU quota exhaustion", "Legacy data quality issues", "Third-party API deprecation", "iOS 18 compatibility", "Storage cost overrun", "Rate limit bottlenecks", "Partner SLA breach risk", "Pen test findings", "Scope creep from stakeholders", "Report perf degradation", "Model drift in production", "Vendor contract renewal", "Training data bias"]
riskSeverity = ["🔴 Critical", "🔴 Critical", "🔴 Critical", "🟠 High", "🟠 High", "🟠 High", "🟠 High", "🟡 Medium", "🟡 Medium", "🟡 Medium", "🟡 Medium", "🟡 Medium", "🟡 Medium", "🟢 Low", "🟢 Low"]
riskLikelihood = ["High", "High", "Medium", "High", "Medium", "High", "Medium", "Medium", "Low", "Medium", "Medium", "High", "Medium", "Low", "Low"]
riskImpact = ["High", "High", "High", "Medium", "High", "Medium", "Medium", "Medium", "Medium", "High", "Low", "Medium", "High", "Low", "Medium"]
riskMitigation = ["Hire contractor, cross-train", "Engage auditor, fast-track", "Request quota increase", "Data profiling sprint", "Negotiate extension", "Compatibility sprint", "Implement tiering", "Add caching layer", "Escalate to vendor", "Remediation sprint", "Change control board", "Query optimization", "Retrain pipeline", "Legal review initiated", "Bias audit scheduled"]
riskOwners = ["A. Patel", "R. Thompson", "K. Jensen", "M. Rodriguez", "P. Singh", "J. Kim", "D. Okafor", "L. Wang", "T. Nakamura", "F. Rossi", "S. Chen", "E. Mueller", "K. Jensen", "M. Rodriguez", "K. Jensen"]
secDeadlines = SectionItem("deadlines", "Deadlines in Next 2 Weeks (9)", [deadlinesList])
deadlinesList = ListBlock([dl1, dl2, dl3, dl4, dl5, dl6, dl7, dl8, dl9], "number")
dl1 = ListItem("Aurora Payments — PCI-DSS Audit Ready", "Due: 2026-06-10 · Owner: P. Singh · 🔴 Critical", null, null, { type: "continue_conversation", context: "Show details for Aurora Payments PCI-DSS milestone" })
dl2 = ListItem("Lunar CRM — User Acceptance Testing", "Due: 2026-06-15 · Owner: R. Thompson · 🔴 Critical", null, null, { type: "continue_conversation", context: "Show details for Lunar CRM UAT milestone" })
dl3 = ListItem("Apollo Platform — Phase 3 Release", "Due: 2026-06-15 · Owner: S. Chen · 🟢 Healthy", null, null, { type: "continue_conversation", context: "Show details for Apollo Platform Phase 3 release" })
dl4 = ListItem("Nova Analytics — Dashboard v2 Launch", "Due: 2026-06-20 · Owner: A. Patel · 🟡 At Risk", null, null, { type: "continue_conversation", context: "Show details for Nova Analytics Dashboard v2" })
dl5 = ListItem("Orion Migration — Cutover Weekend", "Due: 2026-06-22 · Owner: M. Rodriguez · 🟡 At Risk", null, null, { type: "continue_conversation", context: "Show details for Orion Migration cutover" })
dl6 = ListItem("Zenith Reporting — Executive Demo", "Due: 2026-06-25 · Owner: E. Mueller · 🟢 Healthy", null, null, { type: "continue_conversation", context: "Show details for Zenith Reporting executive demo" })
dl7 = ListItem("Stellar Mobile — Beta Test Complete", "Due: 2026-06-28 · Owner: J. Kim · 🟡 At Risk", null, null, { type: "continue_conversation", context: "Show details for Stellar Mobile beta test" })
dl8 = ListItem("Solar API Gateway — Load Test Pass", "Due: 2026-06-30 · Owner: L. Wang · 🟡 At Risk", null, null, { type: "continue_conversation", context: "Show details for Solar API Gateway load test" })
dl9 = ListItem("Comet Data Lake — Governance Review", "Due: 2026-07-01 · Owner: D. Okafor · 🟢 Healthy", null, null, { type: "continue_conversation", context: "Show details for Comet Data Lake governance review" })
secPace = SectionItem("pace", "Delivery Pace — Last 6 Sprints", [paceChart, paceTable])
paceChart = LineChart(sprintLabels, [pacePlannedSeries, paceDeliveredSeries, paceVelocitySeries], "natural", "Sprint", "Story Points")
sprintLabels = ["Sprint 18", "Sprint 19", "Sprint 20", "Sprint 21", "Sprint 22", "Sprint 23"]
pacePlannedSeries = Series("Planned", [420, 450, 480, 460, 500, 520])
paceDeliveredSeries = Series("Delivered", [395, 410, 430, 398, 445, 468])
paceVelocitySeries = Series("Velocity Trend", [395, 402, 412, 410, 417, 425])
paceTable = Table([colPSprint, colPPlanned, colPDelivered, colPVelocity, colPPercent])
colPSprint = Col("Sprint", sprintLabels, "string")
colPPlanned = Col("Planned", [420, 450, 480, 460, 500, 520], "number")
colPDelivered = Col("Delivered", [395, 410, 430, 398, 445, 468], "number")
colPVelocity = Col("Rolling Velocity", [395, 402, 412, 410, 417, 425], "number")
colPPercent = Col("% of Plan", ["94%", "91%", "90%", "87%", "89%", "90%"], "string")
secBlocked = SectionItem("blocked", "Blocked Work Items (7)", [blockedTable])
blockedTable = Table([colBProject, colBItem, colBBlocker, colBDaysBlocked, colBOwner, colBAction])
colBProject = Col("Project", blockedProjects, "string")
colBItem = Col("Work Item", blockedItems, "string")
colBBlocker = Col("Blocker", blockedBlockers, "string")
colBDaysBlocked = Col("Days Blocked", blockedDays, "number")
colBOwner = Col("Owner", blockedOwners, "string")
colBAction = Col("Action Needed", blockedActions, "string")
blockedProjects = ["Orion Migration", "Nova Analytics", "Lunar CRM", "Nebula AI/ML", "Aurora Payments", "Stellar Mobile", "Horizon Integration"]
blockedItems = ["Data validation scripts", "Dashboard API integration", "Salesforce connector", "GPU cluster access", "Payment provider sandbox", "TestFlight distribution", "Partner API credentials"]
blockedBlockers = ["Missing legacy schema docs", "Auth token expiry bug", "Vendor API rate limits", "Cloud quota request pending", "Compliance review backlog", "Apple review delay", "Legal contract negotiation"]
blockedDays = [14, 11, 18, 9, 22, 6, 13]
blockedOwners = ["M. Rodriguez", "A. Patel", "R. Thompson", "K. Jensen", "P. Singh", "J. Kim", "T. Nakamura"]
blockedActions = ["Escalate to Architecture", "Assign senior dev", "Engage vendor support", "Submit quota increase", "Escalate to Compliance", "Contact Apple Dev Relations", "Legal to expedite"]
actionButtons = Buttons([btnExport, btnRequestPeople, btnArchive], "row")
btnExport = Button("Export Review (PDF)", { type: "continue_conversation", context: "Export the current portfolio review as PDF" }, "primary")
btnRequestPeople = Button("Request More People", { type: "continue_conversation", context: "Open form to request additional team members for a project" }, "secondary")
btnArchive = Button("Archive Finished Project", { type: "continue_conversation", context: "Select and archive a completed project from the portfolio" }, "tertiary")