root = Card([header, healthBanner, projectTableSection, milestonesSection, budgetSection, utilizationSection, risksSection, deadlinesSection, paceSection, blockedSection, quarterSelector, actionsSection])
header = CardHeader("Q3 2025 Portfolio Review", "PMO dashboard · 14 active projects")
healthBanner = Callout("success", "Portfolio health: On track", "9 projects green, 3 amber, 2 red. One critical risk requires attention.")
projectTableSection = Card([projectHeading, projectTable], "sunk")
projectHeading = Heading("Active Projects", "h3")
projectTable = Table([projName, projOwner, projDeadline, projHealth])
projName = Col("Project", ["Atlas ERP", "Nimbus Cloud", "Vertex Mobile", "Orion Analytics", "Pulse CRM"])
projOwner = Col("Owner", ["M. Chen", "A. Patel", "S. Okafor", "L. Rodriguez", "J. Kim"])
projDeadline = Col("Deadline", ["2025-10-15", "2025-11-02", "2025-09-28", "2025-12-10", "2025-10-30"])
projHealth = Col("Health", ["Green", "Amber", "Red", "Green", "Amber"])
milestonesSection = Card([milestonesHeading, milestonesList], "sunk")
milestonesHeading = Heading("Overdue Milestones", "h3")
milestonesList = ListBlock([ms1, ms2, ms3], "number")
ms1 = ListItem("Atlas ERP — Data migration complete", "Due 2025-09-10 · 12 days overdue", null, "View")
ms2 = ListItem("Vertex Mobile — Beta signoff", "Due 2025-09-15 · 7 days overdue", null, "View")
ms3 = ListItem("Pulse CRM — API v2 freeze", "Due 2025-09-18 · 4 days overdue", null, "View")
budgetSection = Card([budgetHeading, budgetChart], "sunk")
budgetHeading = Heading("Budget Spent vs Allocation", "h3")
budgetChart = HorizontalBarChart(["Atlas ERP", "Nimbus Cloud", "Vertex Mobile", "Orion Analytics", "Pulse CRM"], [allocSeries, spentSeries], "grouped", "USD (k)", "Project")
allocSeries = Series("Allocated", [1500, 800, 1200, 900, 650])
spentSeries = Series("Spent", [1420, 610, 1180, 540, 690])
utilizationSection = Card([utilHeading, utilChart], "sunk")
utilHeading = Heading("Team Utilization", "h3")
utilChart = BarChart(["Design", "Eng Frontend", "Eng Backend", "QA", "Data"], [utilSeries], "grouped", "Team", "Utilization %")
utilSeries = Series("Utilization", [88, 92, 74, 81, 96])
risksSection = Card([risksHeading, risksTable], "sunk")
risksHeading = Heading("Open Risks", "h3")
risksTable = Table([riskName, riskSeverity, riskOwner])
riskName = Col("Risk", ["Vertex Mobile scope creep", "Nimbus Cloud vendor delay", "Atlas ERP data quality", "Pulse CRM churn spike"])
riskSeverity = Col("Severity", ["High", "High", "Medium", "Medium"])
riskOwner = Col("Owner", ["S. Okafor", "A. Patel", "M. Chen", "J. Kim"])
deadlinesSection = Card([deadlinesHeading, deadlinesList], "sunk")
deadlinesHeading = Heading("Deadlines in Next 14 Days", "h3")
deadlinesList = ListBlock([dl1, dl2, dl3], "number")
dl1 = ListItem("Orion Analytics — Model freeze", "2025-09-22 · in 4 days", null, "View")
dl2 = ListItem("Nimbus Cloud — UAT kickoff", "2025-09-26 · in 8 days", null, "View")
dl3 = ListItem("Atlas ERP — Go-live dry run", "2025-09-30 · in 12 days", null, "View")
paceSection = Card([paceHeading, paceChart], "sunk")
paceHeading = Heading("Delivery Pace — Last 6 Sprints", "h3")
paceChart = LineChart(["Sprint 1", "Sprint 2", "Sprint 3", "Sprint 4", "Sprint 5", "Sprint 6"], [committedSeries, deliveredSeries], "linear", "Sprint", "Story points")
committedSeries = Series("Committed", [320, 340, 310, 360, 330, 350])
deliveredSeries = Series("Delivered", [290, 335, 300, 345, 310, 340])
blockedSection = Card([blockedHeading, blockedList], "sunk")
blockedHeading = Heading("Blocked Work Items", "h3")
blockedList = ListBlock([bl1, bl2], "number")
bl1 = ListItem("Atlas ERP — ETL pipeline job", "Blocked on vendor API access · 3 days", null, "Unblock")
bl2 = ListItem("Vertex Mobile — Push notification service", "Blocked on security review · 5 days", null, "Unblock")
quarterSelector = Card([quarterHeading, quarterForm], "sunk")
quarterHeading = Heading("Select Review Period", "h3")
quarterForm = Form("quarter-select", quarterButtons, [quarterField])
quarterField = FormControl("Quarter", quarterSelect)
quarterSelect = Select("quarter", [q1, q2, q3, q4], "Choose a quarter")
q1 = SelectItem("2025-Q1", "Q1 2025")
q2 = SelectItem("2025-Q2", "Q2 2025")
q3 = SelectItem("2025-Q3", "Q3 2025")
q4 = SelectItem("2025-Q4", "Q4 2025")
quarterButtons = Buttons([applyBtn])
applyBtn = Button("Load Quarter", null, "primary")
actionsSection = Card([actionsHeading, actionButtons], "sunk")
actionsHeading = Heading("Portfolio Actions", "h3")
actionButtons = Buttons([requestPeopleBtn, exportBtn, archiveBtn])
requestPeopleBtn = Button("Request more people")
exportBtn = Button("Export review", null, "secondary")
archiveBtn = Button("Archive finished project", null, "tertiary")