root = Card([header, healthSummary, quarterSelector, activeProjects, overdueMilestones, budgetChart, utilizationChart, risksTable, upcomingDeadlines, deliveryPaceChart, blockedItems, actions])
header = CardHeader("Portfolio Review", "Q3 2025 — 12 active projects")
healthSummary = Callout("success", "Portfolio Health", "On track: 8 projects green, 3 yellow, 1 red — overall delivery confidence 82%")
quarterSelector = Form("quarter-select", quarterButtons, [quarterField])
quarterField = FormControl("Select Quarter", quarterSelect, "Switch to view a different quarter's portfolio")
quarterSelect = Select("quarter", quarterOptions, "Q3 2025")
quarterOptions = [q1, q2, q3, q4]
q1 = SelectItem("Q1 2025", "Q1 2025")
q2 = SelectItem("Q2 2025", "Q2 2025")
q3 = SelectItem("Q3 2025", "Q3 2025")
q4 = SelectItem("Q4 2025", "Q4 2025")
quarterButtons = Buttons([applyQuarterBtn])
applyQuarterBtn = Button("Apply", null, "primary")
activeProjects = Card([projectsHeading, projectsTable], "sunk")
projectsHeading = Heading("Active Projects", "h3")
projectsTable = Table([projName, projOwner, projDeadline, projHealth])
projName = Col("Project", ["Apollo CRM", "Orion Analytics", "Nova Mobile", "Titan Infrastructure", "Luna Payments", "Solar Dashboard", "Mercury API", "Venus Integration", "Mars Reporting", "Jupiter Security", "Saturn Compliance", "Neptune Migration"])
projOwner = Col("Owner", ["Sarah Chen", "Marcus Johnson", "Priya Patel", "David Kim", "Lisa Wang", "James Rodriguez", "Amanda Foster", "Robert Liu", "Emily Davis", "Michael Brown", "Jennifer Garcia", "Christopher Lee"])
projDeadline = Col("Deadline", ["2025-09-15", "2025-09-22", "2025-10-05", "2025-09-30", "2025-10-12", "2025-09-18", "2025-10-20", "2025-09-25", "2025-10-08", "2025-09-28", "2025-10-15", "2025-10-25"])
projHealth = Col("Health", ["Green", "Green", "Yellow", "Green", "Red", "Green", "Yellow", "Green", "Green", "Yellow", "Green", "Green"])
overdueMilestones = Card([milestonesHeading, milestonesTable], "sunk")
milestonesHeading = Heading("Overdue Milestones", "h3")
milestonesTable = Table([msProject, msMilestone, msDue, msDaysLate])
msProject = Col("Project", ["Orion Analytics", "Nova Mobile", "Titan Infrastructure", "Luna Payments"])
msMilestone = Col("Milestone", ["Data pipeline v2", "iOS beta release", "Cloud migration phase 1", "PCI-DSS audit prep"])
msDue = Col("Due Date", ["2025-08-20", "2025-08-25", "2025-08-15", "2025-08-28"])
msDaysLate = Col("Days Late", [25, 20, 30, 17])
budgetChart = Card([budgetHeading, budgetBarChart], "sunk")
budgetHeading = Heading("Budget Spent vs Allocation", "h3")
budgetBarChart = HorizontalBarChart(budgetLabels, budgetSeries, "grouped", "Project", "USD (thousands)")
budgetLabels = ["Apollo CRM", "Orion Analytics", "Nova Mobile", "Titan Infra", "Luna Payments", "Solar Dash", "Mercury API", "Venus Integr.", "Mars Report", "Jupiter Sec", "Saturn Comp", "Neptune Migr."]
budgetSeries = [budgetAllocated, budgetSpent]
budgetAllocated = Series("Allocated", [450, 380, 320, 520, 290, 210, 180, 240, 160, 350, 220, 410])
budgetSpent = Series("Spent", [312, 298, 285, 395, 267, 158, 142, 189, 112, 245, 154, 287])
utilizationChart = Card([utilHeading, utilRadialChart], "sunk")
utilHeading = Heading("Team Utilization", "h3")
utilRadialChart = RadialChart(utilLabels, utilValues)
utilLabels = ["Engineering", "Design", "QA", "DevOps", "Product", "Data"]
utilValues = [87, 72, 78, 91, 65, 83]
risksTable = Card([risksHeading, risksTableComp], "sunk")
risksHeading = Heading("Risks by Severity", "h3")
risksTableComp = Table([riskProject, riskDescription, riskSeverity, riskMitigation])
riskProject = Col("Project", ["Nova Mobile", "Titan Infrastructure", "Luna Payments", "Mercury API", "Jupiter Security", "Saturn Compliance"])
riskDescription = Col("Risk", ["iOS App Store rejection risk", "Cloud vendor SLA breach", "PCI-DSS scope creep", "Rate limit throttling", "Penetration test findings", "Audit timeline compression"])
riskSeverity = Col("Severity", ["High", "High", "Critical", "Medium", "High", "Medium"])
riskMitigation = Col("Mitigation", ["Pre-submission review", "Escalate to vendor exec", "Scope freeze + legal review", "Implement circuit breaker", "Remediation sprint planned", "Add 2 compliance engineers"])
upcomingDeadlines = Card([deadlinesHeading, deadlinesTable], "sunk")
deadlinesHeading = Heading("Deadlines — Next 2 Weeks", "h3")
deadlinesTable = Table([dlProject, dlMilestone, dlDate, dlStatus])
dlProject = Col("Project", ["Apollo CRM", "Solar Dashboard", "Venus Integration", "Mars Reporting", "Saturn Compliance"])
dlMilestone = Col("Milestone", ["GA release", "v3.2 launch", "Partner onboarding", "Executive demo", "Audit submission"])
dlDate = Col("Date", ["2025-09-15", "2025-09-18", "2025-09-22", "2025-09-25", "2025-09-28"])
dlStatus = Col("Status", ["On track", "At risk", "On track", "On track", "At risk"])
deliveryPaceChart = Card([paceHeading, paceLineChart], "sunk")
paceHeading = Heading("Delivery Pace — Last 6 Sprints", "h3")
paceLineChart = LineChart(paceLabels, paceSeries, "natural", "Sprint", "Story Points Delivered")
paceLabels = ["Sprint 18", "Sprint 19", "Sprint 20", "Sprint 21", "Sprint 22", "Sprint 23"]
paceSeries = [pacePlanned, paceActual]
pacePlanned = Series("Planned", [240, 260, 250, 270, 280, 290])
paceActual = Series("Delivered", [225, 248, 235, 262, 271, 278])
blockedItems = Card([blockedHeading, blockedList], "sunk")
blockedHeading = Heading("Blocked Work Items", "h3")
blockedList = ListBlock(blockedItemsData, "number")
blockedItemsData = [block1, block2, block3, block4, block5]
block1 = ListItem("Apollo CRM — Payment webhook retry logic", "Blocked on vendor API docs (Stripe)", null, "Escalate")
block2 = ListItem("Orion Analytics — Snowflake migration", "Waiting on infra team for warehouse provisioning", null, "Follow up")
block3 = ListItem("Nova Mobile — Push notification certs", "Apple Developer account access pending", null, "Request access")
block4 = ListItem("Titan Infrastructure — Terraform state lock", "Concurrent apply from CI/CD pipeline", null, "Investigate")
block5 = ListItem("Luna Payments — 3DS2 integration", "Sandbox environment down at processor", null, "Contact vendor")
actions = Buttons([exportBtn, requestPeopleBtn, archiveBtn], "row")
exportBtn = Button("Export Review", null, "primary")
requestPeopleBtn = Button("Request More People", null, "secondary")
archiveBtn = Button("Archive Project", null, "tertiary")