root = Card([header, healthSummary, toolbar, projectsCard, schedulesRow, metricsRow, riskRow, paceCard], "clear", "column", "l")
header = CardHeader("Portfolio Review", "Q3 2025 · PMO dashboard")
healthSummary = Callout("warning", "Portfolio health", "Overall delivery is stable, but Nimbus and Cloud infra need attention before month-end.")
toolbar = Card([quarterForm, exportActions, requestDialog, archiveDialog], "sunk", "row", "m")
quarterForm = Form("quarter-select", applyBtn, [quarterField])
applyBtn = Buttons([applyButton])
applyButton = Button("Apply", null, "primary")
quarterField = FormControl("Quarter", quarterSelect)
quarterSelect = Select("quarter", [q1, q2, q3, q4], "Select quarter", null, "Q3 2025")
q1 = SelectItem("q1", "Q1 2025")
q2 = SelectItem("q2", "Q2 2025")
q3 = SelectItem("q3", "Q3 2025")
q4 = SelectItem("q4", "Q4 2025")
exportActions = Buttons([exportButton])
exportButton = Button("Export review")
requestDialog = DialogBlock("Request staffing", "Request more people", "Tell us which project needs headcount and who you need.", [staffingForm], "outline")
staffingForm = Form("staffing", staffingButtons, [staffProjectField, roleField, countField])
staffingButtons = Buttons([staffingSubmit])
staffingSubmit = Button("Send request", null, "primary")
staffProjectField = FormControl("Project", staffProjectSelect)
staffProjectSelect = Select("project", [staffAtlas, staffNimbus, staffCore, staffCloud], "Pick a project")
staffAtlas = SelectItem("atlas", "Atlas")
staffNimbus = SelectItem("nimbus", "Nimbus")
staffCore = SelectItem("core", "Core migration")
staffCloud = SelectItem("cloud", "Cloud infra")
roleField = FormControl("Role", roleInput)
roleInput = Input("role", "e.g. Backend engineer")
countField = FormControl("Number of people", countInput)
countInput = Input("count", "e.g. 2", "number")
archiveDialog = AlertDialogBlock("Archive project", "Archive finished project?", "This moves the project to the archive and removes it from active view.", "Archive", "Cancel", "secondary")
projectsCard = Card([projectsHeader, projectsTable], "sunk", "column", "m")
projectsHeader = CardHeader("Active projects", "Owner · deadline · health")
projectsTable = Table([projectCol, ownerCol, deadlineCol, healthCol])
projectCol = Col("Project", ["Atlas", "Nimbus", "Core migration", "Cloud infra"])
ownerCol = Col("Owner", ["Sarah Chen", "Marcus Reid", "Priya Patel", "Tom Becker"])
deadlineCol = Col("Deadline", ["2025-09-15", "2025-09-30", "2025-10-10", "2025-08-28"])
healthCol = Col("Health", ["On track", "At risk", "On track", "Critical"])
schedulesRow = Card([overdueCard, deadlinesCard], "clear", "row", "m")
overdueCard = Card([overdueHeader, overdueList], "sunk", "column", "m")
overdueHeader = Heading("Overdue milestones", "h2")
overdueList = ListBlock([milestone1, milestone2, milestone3])
milestone1 = ListItem("Nimbus — API v2 spec", "Overdue by 18 days")
milestone2 = ListItem("Atlas — user onboarding flow", "Overdue by 12 days")
milestone3 = ListItem("Core migration — data cleanup", "Overdue by 6 days")
deadlinesCard = Card([deadlinesHeader, deadlinesList], "sunk", "column", "m")
deadlinesHeader = Heading("Deadlines in the next two weeks", "h2")
deadlinesList = ListBlock([deadline1, deadline2, deadline3, deadline4])
deadline1 = ListItem("Atlas — Beta sign-off", "Due Aug 14 · in 5 days")
deadline2 = ListItem("Cloud infra — Go-live review", "Due Aug 18 · in 9 days")
deadline3 = ListItem("Nimbus — UAT kickoff", "Due Aug 21 · in 12 days")
deadline4 = ListItem("Core migration — Pilot start", "Due Aug 23 · in 14 days")
metricsRow = Card([budgetCard, utilCard], "clear", "row", "m")
budgetCard = Card([budgetHeader, budgetChart], "sunk", "column", "m")
budgetHeader = Heading("Budget spent vs allocation", "h2")
budgetChart = BarChart(projectsShort, [spentSeries, allocatedSeries], "grouped", "Project", "USD (k)")
projectsShort = ["Atlas", "Nimbus", "Core", "Cloud"]
spentSeries = Series("Spent", [420, 310, 180, 275])
allocatedSeries = Series("Allocated", [600, 350, 250, 300])
utilCard = Card([utilHeader, utilAlex, utilMarie, utilSam, utilElena], "sunk", "column", "m")
utilHeader = Heading("Team utilization", "h2")
utilAlex = Progress(82, "Alex Kim — 82%")
utilMarie = Progress(95, "Marie Lopez — 95%")
utilSam = Progress(68, "Sam Okafor — 68%")
utilElena = Progress(74, "Elena Rossi — 74%")
riskRow = Card([risksCard, blockedCard], "clear", "row", "m")
risksCard = Card([risksHeader, risksTable], "sunk", "column", "m")
risksHeader = Heading("Open risks", "h2")
risksTable = Table([riskCol, likelihoodCol, impactCol, severityCol])
riskCol = Col("Risk", ["Key vendor may miss SLA", "Scope creep on Nimbus", "Single point of failure in infra", "Data privacy compliance gap"])
likelihoodCol = Col("Likelihood", ["High", "Medium", "Medium", "Low"])
impactCol = Col("Impact", ["High", "Medium", "High", "Medium"])
severityCol = Col("Severity", ["High", "Medium", "High", "Low"])
blockedCard = Card([blockedHeader, blockedList], "sunk", "column", "m")
blockedHeader = Heading("Blocked work items", "h2")
blockedList = ListBlock([blocked1, blocked2, blocked3])
blocked1 = ListItem("Checkout fails on mobile", "Waiting on design assets · 3 days")
blocked2 = ListItem("Atlas — SSO integration", "Awaiting vendor credentials · 5 days")
blocked3 = ListItem("Cloud infra — cost dashboards", "Blocked by data pipeline · 1 day")
paceCard = Card([paceHeader, paceChart], "sunk", "column", "m")
paceHeader = Heading("Delivery pace — last six sprints", "h2")
paceChart = LineChart(sprintLabels, [deliveredSeries, committedSeries], "natural", "Sprint", "Story points")
sprintLabels = ["S21", "S22", "S23", "S24", "S25", "S26"]
deliveredSeries = Series("Delivered", [28, 32, 30, 35, 41, 38])
committedSeries = Series("Committed", [30, 31, 34, 36, 38, 40])