root = Card([healthSummary, quarterSelector, activeProjectsSection, overdueMilestonesSection, budgetSection, utilizationSection, risksSection, upcomingDeadlinesSection, deliveryPaceSection, blockedItemsSection, actionsSection], "card", "column", "l")
healthSummary = Callout("success", "Portfolio Health", "12 of 15 projects on track; 2 at risk, 1 critical — overall status: Green with caveats")
quarterSelector = Card([quarterLabel, quarterSelect], "clear", "row", "m", "center")
quarterLabel = TextContent("Select Quarter:", "small-heavy")
quarterSelect = Select("quarter", quarterOptions, "Q3 2025", null, "small")
quarterOptions = [optQ2, optQ3, optQ4, optQ1]
optQ2 = SelectItem("Q2 2025", "Q2 2025")
optQ3 = SelectItem("Q3 2025", "Q3 2025")
optQ4 = SelectItem("Q4 2025", "Q4 2025")
optQ1 = SelectItem("Q1 2026", "Q1 2026")
activeProjectsSection = Card([activeProjectsHeader, activeProjectsTable], "sunk", "column", "m")
activeProjectsHeader = Heading("Active Projects", "h3")
activeProjectsTable = Table([projNameCol, projOwnerCol, projDeadlineCol, projHealthCol])
projNameCol = Col("Project", ["Apollo", "Artemis", "Orion", "Voyager", "Pioneer", "Mariner", "Viking", "Galileo", "Cassini", "Juno", "New Horizons", "Parker", "Lucy", "Psyche", "Europa Clipper"])
projOwnerCol = Col("Owner", ["S. Chen", "M. Patel", "R. Kim", "A. Gupta", "J. Rivera", "T. Nguyen", "L. Okafor", "D. Silva", "K. Johansson", "P. Dubois", "N. Kowalski", "H. Andersson", "F. Rossi", "E. Müller", "Y. Tanaka"])
projDeadlineCol = Col("Deadline", ["2025-09-15", "2025-10-01", "2025-08-30", "2025-11-15", "2025-09-30", "2025-10-20", "2025-08-15", "2025-12-01", "2025-09-20", "2025-10-10", "2025-11-30", "2025-09-10", "2025-12-15", "2026-01-15", "2026-02-28"])
projHealthCol = Col("Health", ["Green", "Green", "Yellow", "Green", "Red", "Green", "Yellow", "Green", "Green", "Yellow", "Green", "Red", "Green", "Green", "Yellow"])
overdueMilestonesSection = Card([overdueHeader, overdueTable], "sunk", "column", "m")
overdueHeader = Heading("Overdue Milestones", "h3")
overdueTable = Table([msProjectCol, msNameCol, msDueCol, msDaysLateCol])
msProjectCol = Col("Project", ["Orion", "Pioneer", "Viking", "Parker"])
msNameCol = Col("Milestone", ["Design Review", "Integration Test", "Security Audit", "Launch Readiness"])
msDueCol = Col("Original Due", ["2025-07-20", "2025-07-25", "2025-07-15", "2025-07-10"])
msDaysLateCol = Col("Days Late", [18, 13, 23, 28])
budgetSection = Card([budgetHeader, budgetChart], "sunk", "column", "m")
budgetHeader = Heading("Budget: Spent vs Allocation", "h3")
budgetChart = HorizontalBarChart(budgetLabels, [budgetAllocatedSeries, budgetSpentSeries], "grouped", "USD (k)", "Project")
budgetLabels = ["Apollo", "Artemis", "Orion", "Voyager", "Pioneer", "Mariner", "Viking", "Galileo", "Cassini", "Juno", "New Horizons", "Parker", "Lucy", "Psyche", "Europa Clipper"]
budgetAllocatedSeries = Series("Allocated", [1200, 950, 800, 1500, 600, 700, 550, 1100, 900, 650, 1300, 400, 850, 750, 2000])
budgetSpentSeries = Series("Spent", [780, 620, 510, 980, 410, 490, 380, 720, 580, 420, 890, 310, 540, 480, 1100])
utilizationSection = Card([utilHeader, utilChart], "sunk", "column", "m")
utilHeader = Heading("Team Utilization (%)", "h3")
utilChart = BarChart(utilLabels, [utilSeries], "grouped", "Team", "Utilization %")
utilLabels = ["Frontend", "Backend", "DevOps", "QA", "Design", "Data", "Mobile", "Security"]
utilSeries = Series("Utilization", [82, 78, 65, 71, 88, 74, 79, 68])
risksSection = Card([risksHeader, risksTable], "sunk", "column", "m")
risksHeader = Heading("Risks by Severity", "h3")
risksTable = Table([riskProjectCol, riskDescCol, riskSeverityCol, riskMitigationCol])
riskProjectCol = Col("Project", ["Pioneer", "Parker", "Orion", "Viking", "Europa Clipper", "Apollo", "Cassini"])
riskDescCol = Col("Risk", ["Key engineer leaving", "Vendor delay", "Scope creep", "Technical debt", "Regulatory change", "Budget overrun", "Integration complexity"])
riskSeverityCol = Col("Severity", ["Critical", "Critical", "High", "High", "High", "Medium", "Medium"])
riskMitigationCol = Col("Mitigation", ["Knowledge transfer started", "Alternate vendor identified", "Change control enforced", "Refactor sprint planned", "Legal review underway", "Forecast revised", "Architecture review scheduled"])
upcomingDeadlinesSection = Card([upcomingHeader, upcomingTable], "sunk", "column", "m")
upcomingHeader = Heading("Deadlines: Next 2 Weeks", "h3")
upcomingTable = Table([udProjectCol, udMilestoneCol, udDateCol, udStatusCol])
udProjectCol = Col("Project", ["Viking", "Apollo", "Parker", "Orion", "Mariner", "Galileo", "Juno"])
udMilestoneCol = Col("Milestone", ["Beta Release", "UAT Complete", "Launch Readiness", "Design Review", "Performance Test", "Security Scan", "Documentation"])
udDateCol = Col("Date", ["2025-08-10", "2025-08-12", "2025-08-14", "2025-08-15", "2025-08-16", "2025-08-18", "2025-08-20"])
udStatusCol = Col("Status", ["At Risk", "On Track", "Critical", "At Risk", "On Track", "On Track", "At Risk"])
deliveryPaceSection = Card([paceHeader, paceChart], "sunk", "column", "m")
paceHeader = Heading("Delivery Pace: Last 6 Sprints", "h3")
paceChart = LineChart(paceLabels, [velocitySeries, committedSeries], "natural", "Sprint", "Story Points")
paceLabels = ["Sprint 18", "Sprint 19", "Sprint 20", "Sprint 21", "Sprint 22", "Sprint 23"]
velocitySeries = Series("Velocity", [320, 345, 310, 360, 335, 350])
committedSeries = Series("Committed", [340, 350, 330, 370, 350, 360])
blockedItemsSection = Card([blockedHeader, blockedTable], "sunk", "column", "m")
blockedHeader = Heading("Blocked Work Items", "h3")
blockedTable = Table([blockedProjectCol, blockedItemCol, blockedReasonCol, blockedSinceCol])
blockedProjectCol = Col("Project", ["Pioneer", "Parker", "Orion", "Voyager", "Cassini"])
blockedItemCol = Col("Work Item", ["API Integration", "Third-party SDK", "Database Migration", "UI Framework Upgrade", "Contract Testing"])
blockedReasonCol = Col("Blocker", ["Waiting on vendor API", "License renewal pending", "Schema conflicts", "Breaking changes", "Environment unavailable"])
blockedSinceCol = Col("Days Blocked", [12, 8, 15, 5, 10])
actionsSection = Card([actionsHeader, exportBtn, requestPeopleForm, archiveDialog], "clear", "column", "m")
actionsHeader = Heading("Actions", "h3")
exportBtn = Button("Export Portfolio Review", ["export"], "primary")
requestPeopleForm = Form("request-people", requestButtons, [projectSelectField, peopleCountField, reasonField])
projectSelectField = FormControl("Project", projectSelect, "Select project needing resources")
projectSelect = Select("project", projectOptions, "Choose project", null, "medium")
projectOptions = [projOptApollo, projOptArtemis, projOptOrion, projOptVoyager, projOptPioneer, projOptMariner, projOptViking, projOptGalileo, projOptCassini, projOptJuno, projOptNewHorizons, projOptParker, projOptLucy, projOptPsyche, projOptEuropa]
projOptApollo = SelectItem("Apollo", "Apollo")
projOptArtemis = SelectItem("Artemis", "Artemis")
projOptOrion = SelectItem("Orion", "Orion")
projOptVoyager = SelectItem("Voyager", "Voyager")
projOptPioneer = SelectItem("Pioneer", "Pioneer")
projOptMariner = SelectItem("Mariner", "Mariner")
projOptViking = SelectItem("Viking", "Viking")
projOptGalileo = SelectItem("Galileo", "Galileo")
projOptCassini = SelectItem("Cassini", "Cassini")
projOptJuno = SelectItem("Juno", "Juno")
projOptNewHorizons = SelectItem("New Horizons", "New Horizons")
projOptParker = SelectItem("Parker", "Parker")
projOptLucy = SelectItem("Lucy", "Lucy")
projOptPsyche = SelectItem("Psyche", "Psyche")
projOptEuropa = SelectItem("Europa Clipper", "Europa Clipper")
peopleCountField = FormControl("Additional People Needed", peopleInput, "Number of FTEs requested")
peopleInput = Input("people_count", "1", "number")
reasonField = FormControl("Justification", reasonTextarea, "Brief reason for request")
reasonTextarea = TextArea("justification", "Describe why additional people are needed...", 3)
requestButtons = Buttons([submitRequestBtn, cancelRequestBtn])
submitRequestBtn = Button("Submit Request", ["submit_people_request"], "primary")
cancelRequestBtn = Button("Cancel", null, "tertiary")
archiveDialog = AlertDialogBlock("Archive Finished Project", "Archive Project", "This will move the project to read-only archive. All data will be preserved but the project will no longer appear in active views. Continue?", "Archive", "Cancel", "destructive")