root = Card([header, alertsTitle, alertOne, alertTwo, alertThree, sep1, overviewTitle, loadProgress, kpiTable, sep2, genTitle, genPie, genNote, sep3, forecastTitle, forecastChart, forecastNote, sep4, plantsTitle, plantsTable, sep5, outagesTitle, outagesList, sep6, maintTitle, maintList, sep7, regionsTitle, regionTable, regionForm, sep8, curtailTitle, curtailForm, followUps], "card", "column", "xl")
header = CardHeader("Network Operations Console", "National grid · Live view · Last update 14:32")
alertsTitle = Heading("Live alerts", "h2")
alertOne = Alert("Frequency deviation", "Frequency held at 49.7 Hz in the South region; primary reserve dispatched.", "warning")
alertTwo = Alert("Corridor overload forecast", "North–East corridor forecast to reach 97% capacity at 19:00.", "info")
alertThree = Alert("Wind ramp-down expected", "Wind output forecast to fall by 1,900 MW between 22:00 and 02:00.", "warning")
sep1 = Separator("horizontal", true)
overviewTitle = Heading("Network at a glance", "h2")
loadProgress = Progress(84, "Load vs capacity — 42,180 MW of 50,000 MW (84%)")
kpiTable = Table([kpiMetric, kpiValue, kpiDetail])
kpiMetric = Col("Metric", ["System load", "Capacity in use", "Price per MWh", "Emissions today"])
kpiValue = Col("Value", ["42,180 MW", "84%", "£86.40", "128,400 t CO₂e"])
kpiDetail = Col("Detail", ["4.2% above forecast", "7,820 MW headroom", "▲ £3.10 since midnight", "380 g CO₂ / kWh"])
sep2 = Separator("horizontal", true)
genTitle = Heading("Generation mix", "h2")
genPie = PieChart(genLabels, genValues, "donut")
genLabels = ["Wind", "Gas", "Nuclear", "Solar", "Hydro", "Imports"]
genValues = [11800, 12400, 6800, 4200, 2600, 4380]
genNote = TextCallout("info", "Low-carbon share", "Wind, solar, hydro and nuclear cover 60% of current demand.")
sep3 = Separator("horizontal", true)
forecastTitle = Heading("Demand forecast — next 24 hours", "h2")
forecastChart = AreaChart(forecastLabels, [forecastSeries], "natural", "Time", "Demand (MW)")
forecastLabels = ["15:00", "18:00", "21:00", "00:00", "03:00", "06:00", "09:00", "12:00", "15:00"]
forecastSeries = Series("Forecast demand", [42180, 46800, 43900, 33400, 31800, 29600, 28900, 35200, 39800])
forecastNote = TextCallout("warning", "Peak watch", "Evening peak of 46,800 MW forecast at 18:00; reserve margin falls to 6.4%.")
sep4 = Separator("horizontal", true)
plantsTitle = Heading("Plant output & status", "h2")
plantsTable = Table([plantName, plantSource, plantOutput, plantStatus])
plantName = Col("Plant", ["Beacon Hill CCGT", "Harlech Point Wind", "Kingsmead Nuclear", "Severn Barrage Hydro", "Alder Solar Farm", "Rivenwood OCGT"])
plantSource = Col("Source", ["Gas", "Wind", "Nuclear", "Hydro", "Solar", "Gas"])
plantOutput = Col("Output (MW)", [1240, 860, 1210, 640, 420, 310])
plantStatus = Col("Status", ["Running", "Running", "Running", "Derated", "Running", "Standby"])
sep5 = Separator("horizontal", true)
outagesTitle = Heading("Active outages", "h2")
outagesList = ListBlock([outageOne, outageTwo, outageThree], "number")
outageOne = ListItem("Fender substation transformer fault", "South region · 34,000 customers · ETA 18:30")
outageTwo = ListItem("Osprey 132 kV cable damage", "East region · 12,400 customers · ETA 22:00")
outageThree = ListItem("Redmoor 66 kV planned line work", "West region · 8,900 customers · ETA tomorrow 06:00")
sep6 = Separator("horizontal", true)
maintTitle = Heading("Maintenance planned this month", "h2")
maintList = ListBlock([maintOne, maintTwo, maintThree, maintFour])
maintOne = ListItem("Beacon Hill CCGT — turbine inspection", "12 Jun · 2 days · Gas turbine 2")
maintTwo = ListItem("Kingsmead Nuclear — refuelling outage", "18 Jun · 9 days · Unit 1")
maintThree = ListItem("Alder Solar — inverter replacement", "23 Jun · 1 day · Inverter bank C")
maintFour = ListItem("Severn Barrage — gate servicing", "27 Jun · 3 days · Sluice gates 4–6")
sep7 = Separator("horizontal", true)
regionsTitle = Heading("Regional focus", "h2")
regionTable = Table([regionName, regionLoad, regionCap, regionStatus])
regionName = Col("Region", ["North", "South", "East", "West"])
regionLoad = Col("Load (MW)", [10480, 13740, 9820, 8140])
regionCap = Col("Capacity (MW)", [12000, 15500, 11000, 9500])
regionStatus = Col("Status", ["Stable", "Frequency watch", "Stable", "Overload watch"])
regionForm = Form("region-focus", regionButtons, [regionField])
regionField = FormControl("Show one region", regionSelect, "Narrows all console views to the selected region")
regionSelect = Select("region", [regionN, regionS, regionE, regionW], "All regions")
regionN = SelectItem("north", "North")
regionS = SelectItem("south", "South")
regionE = SelectItem("east", "East")
regionW = SelectItem("west", "West")
regionButtons = Buttons([regionApplyBtn, regionClearBtn])
regionApplyBtn = Button("Apply focus", null, "primary")
regionClearBtn = Button("Clear focus", null, "tertiary")
sep8 = Separator("horizontal", true)
curtailTitle = Heading("Order curtailment", "h2")
curtailForm = Form("curtailment", curtailButtons, [curtailPlantField, curtailMwField, curtailReasonField])
curtailPlantField = FormControl("Plant", curtailPlantSelect)
curtailPlantSelect = Select("plant", [curtailP1, curtailP2, curtailP3], "Select plant")
curtailP1 = SelectItem("beacon-hill", "Beacon Hill CCGT")
curtailP2 = SelectItem("harlech-point", "Harlech Point Wind")
curtailP3 = SelectItem("rivenwood", "Rivenwood OCGT")
curtailMwField = FormControl("Reduction", curtailMwSlider, "50–500 MW in 10 MW steps")
curtailMwSlider = Slider("reduction_mw", "discrete", 50, 500, 10, [100])
curtailReasonField = FormControl("Reason", curtailReasonInput, "Short reason for the control-room log")
curtailReasonInput = Input("reason", "e.g. Corridor overload relief")
curtailButtons = Buttons([orderBtn, cancelCurtailBtn])
orderBtn = Button("Order curtailment", null, "primary")
cancelCurtailBtn = Button("Cancel", null, "tertiary")
followUps = FollowUpBlock([fuFocus, fuAlerts, fuCurtail])
fuFocus = FollowUpItem("Focus on the South region")
fuAlerts = FollowUpItem("What triggered the frequency warning?")
fuCurtail = FollowUpItem("Prepare a curtailment order for Harlech Point Wind")