// The Universe · MASTER PLAN EXPLORER (Module 04) — FULL-SCREEN IMMERSIVE.
// The selected plan fills the entire screen as an edge-to-edge backdrop with
// pan / pinch / wheel zoom + double-tap reset. A translucent, collapsible glass
// library card floats over the plan; the header / lockup / EXPLORE-OVERVIEW pill
// float in a translucent top bar. Interactive gold pins (data-driven PINS{})
// overlay each plan — tap a pin to ease/zoom toward it and open an info popover.
// "Block Massing" swaps the flat image for the live interactive 3D GLB viewer
// (iframe) — orbit / zoom / tap-a-tower for info. This screen is SELF-CONTAINED
// and intentionally does NOT link into the separate Inventory flow.
//
// Matches index.html's 2560×1600 scaled-canvas convention.
// Component name PlanExplorerScreen · route 'masterplan-explorer'.
const MPX_PLANS = [
{ id:'ramp-ground', title:'Ramp Marking — Ground Floor Plan', tags:['GROUND FLOOR','PARKING'], cats:['Parking','Ground Floor'], img:'assets/masterplan/plans/ramp-ground.png?v=3', icon:'parking' },
{ id:'retail-zp', title:'Retail — Zoning & Parking — Basement 1 (Retail Parking)', tags:['BASEMENT 1','RETAIL','PARKING'], cats:['Retail','Parking'], img:'assets/masterplan/plans/retail-zoning-parking.png?v=2', icon:'bag' },
{ id:'retail-ground', title:'Retail Marking — Ground Floor', tags:['GROUND FLOOR','RETAIL'], cats:['Retail','Ground Floor'], img:'assets/masterplan/plans/retail-ground.png?v=2', icon:'tag' },
{ id:'retail-first', title:'Retail Marking — First Floor', tags:['FIRST FLOOR','RETAIL'], cats:['Retail','First Floor'], img:'assets/masterplan/plans/retail-first.png?v=2', icon:'stairs' },
{ id:'circ-ab', title:'Circulation — Tower A & B', tags:['MULTI-TOWER','CIRCULATION'], cats:['Circulation'], img:'assets/masterplan/plans/circulation-ab.png?v=2', icon:'circ' },
{ id:'circ-cdhij', title:'Circulation — Tower C, D, H, I & J', tags:['MULTI-TOWER','CIRCULATION'], cats:['Circulation'], img:'assets/masterplan/plans/circulation-cdhij.png?v=2', icon:'circ' },
{ id:'circ-efg', title:'Circulation — Tower E, F & G', tags:['MULTI-TOWER','CIRCULATION'], cats:['Circulation'], img:'assets/masterplan/plans/circulation-efg.png?v=2', icon:'circ' },
{ id:'block-massing', title:'Block Massing', tags:['MASTER PLAN','MASSING','3D'], cats:[], img:'assets/masterplan/plans/block-massing.png', icon:'massing' },
];
const MPX_FILTERS = ['All','Circulation','Retail','Parking','Ground Floor','First Floor'];
// ── pin accent palette by kind (matches inventory.jsx LM_KIND vocabulary) ──
const MPX_KIND = {
landscape:'#9bbf7a', social:'#c98a6a', wellness:'#7fa8c9', sport:'#c9a05e',
family:'#b59bd0', retail:'#d9b56b', entry:'#e0c48a', parking:'#9aa0a6',
context:'#c97f6a', tower:'#c9a05e', core:'#8fb1c9', plaza:'#9bbf7a', ramp:'#9aa0a6',
};
// compact line-glyphs (24-box, currentColor) — reused from inventory.jsx vocab
const MPX_PIN_GLYPH = {
landscape:'M5 18 Q9 9 12 14 Q15 9 19 18 M12 14 V7',
social:'M4 16 L12 6 L20 16 Z M9 16 V12 H15 V16',
wellness:'M4 14 Q8 10 12 14 T20 14 M4 18 Q8 14 12 18 T20 18',
sport:'M12 4 A8 8 0 1 0 12 20 A8 8 0 1 0 12 4 M4 12 H20 M12 4 Q7 12 12 20 Q17 12 12 4',
family:'M8 8 A2 2 0 1 0 8 7.9 M8 11 V17 M5 14 H11 M16 8 A2 2 0 1 0 16 7.9 M16 11 V17 M13 14 H19',
retail:'M5 9 H19 L18 19 H6 Z M8 9 V7 A4 4 0 0 1 16 7 V9',
entry:'M7 20 V7 H17 V20 M7 7 L12 4 L17 7 M13 13 H13.5',
parking:'M8 19 V6 H13 A4 4 0 0 1 13 14 H8',
context:'M6 18 V8 H10 V18 M14 18 V5 H18 V18 M4 18 H20',
core:'M12 3 V21 M3 12 H21 M6 6 L18 18 M18 6 L6 18',
plaza:'M4 20 H20 M7 20 V10 H17 V20 M10 10 V6 H14 V10',
ramp:'M4 19 L20 7 M4 19 H20 M11 13 V19',
tower:null, // towers draw a letter, not a glyph
};
// ── PINS — data-driven { planId: [ {x%,y%, label, sub, kind, detail[] } ] } ──
// Coords are PERCENT of the plan image (0–100). main-mp reuses inventory.jsx's
// LANDMARKS facts + the 10 towers; the others get sensible inferred pins.
const PINS = {
// ── MAIN MASTER PLAN — landmarks (from inventory LANDMARKS) + 10 towers ──
'main-mp': [
// landmarks
{ x:57, y:53, kind:'landscape', label:'Central Landscape Garden', sub:'4-acre podium green',
detail:['The gravitational core — a 4-acre landscaped garden every tower opens onto','Crystal garden, mound garden, flowering & seating gardens','Accent trees & terraced seating'] },
{ x:59, y:35, kind:'social', label:'The Clubhouse · G+1', sub:'L-shaped club · gym · pool',
detail:['Single L-shaped clubhouse anchoring the central area','G+1 clubhouse with gym & swimming pool','Banquet, café, library & co-working, indoor games, guest rooms'] },
{ x:53, y:42, kind:'wellness', label:'Swimming Pool & Jacuzzi', sub:'Central pool deck',
detail:['Swimming pool & jacuzzi in the central podium','Pool deck with clubhouse grand stair','Changing rooms at clubhouse'] },
{ x:74, y:21, kind:'sport', label:'Sports Court · Pickleball', sub:'Outdoor courts',
detail:['Outdoor pickleball court on the 2nd floor','Sports garden, running track & box cricket','Children’s playground'] },
{ x:41, y:83, kind:'retail', label:'High-Street Retail · G+1', sub:'47 shops',
detail:['G+1 high-street retail along the frontage','47 shops — 25 ground floor + 22 first floor','Merged corner shops; retail parking at basement'] },
{ x:57, y:91, kind:'entry', label:'Grand Arrival Foyer', sub:'Double-height entry',
detail:['Double-height foyer entry for blocks C–J','Entrance water feature & arrival court'] },
{ x:67, y:66, kind:'parking', label:'Parking · 3 Basements + GF', sub:'4 parking levels',
detail:['Four levels of parking — 3 basements + ground floor','Separate apartment & retail ramps'] },
{ x:74, y:34, kind:'context', label:'Stratum · Phase 1', sub:'Operational · adjacent',
detail:['Phase 1 (Stratum) is operational, right next door','Home to Reliance, Accenture, Citi, Siemens, Tech Mahindra & more','Proof the address already works'] },
// 10 towers (lettered pins) — positions from inventory TOWER_PT scaled to %
{ x:51, y:17, kind:'tower', tower:'E', label:'Tower E', sub:'Crown · 4 BHK + Penthouse', detail:['20 floors · 76 homes','Skyline · the largest homes','Pairs with Tower F'] },
{ x:67, y:21, kind:'tower', tower:'F', label:'Tower F', sub:'Crown · 4 BHK + Penthouse', detail:['20 floors · 76 homes','Skyline · the largest homes','Pairs with Tower E'] },
{ x:47, y:35, kind:'tower', tower:'D', label:'Tower D', sub:'West Court · 4 BHK', detail:['20 floors · 38 homes','Central-garden facing','Pairs with Tower C'] },
{ x:73, y:45, kind:'tower', tower:'G', label:'Tower G', sub:'Park Wing · 4 BHK', detail:['20 floors · 76 homes','Podium & sports-garden facing','Pairs with Tower H'] },
{ x:47, y:61, kind:'tower', tower:'C', label:'Tower C', sub:'West Court · 4 BHK', detail:['20 floors · 38 homes','Central-garden facing','Pairs with Tower D'] },
{ x:73, y:72, kind:'tower', tower:'H', label:'Tower H', sub:'Park Wing · 4 BHK', detail:['20 floors · 76 homes','Podium & sports-garden facing','Pairs with Tower G'] },
{ x:29, y:72, kind:'tower', tower:'B', label:'Tower B', sub:'North Edge · 4 BHK', detail:['21 floors · 84 homes','North · BRTS frontage','Pairs with Tower A'] },
{ x:35, y:72, kind:'tower', tower:'A', label:'Tower A', sub:'North Edge · 4 BHK', detail:['21 floors · 84 homes','North · BRTS frontage','Pairs with Tower B'] },
{ x:51, y:78, kind:'tower', tower:'J', label:'Tower J', sub:'Pool Court · 4 BHK', detail:['20 floors · 38 homes','Swimming-pool-deck facing','Pairs with Tower I'] },
{ x:63, y:78, kind:'tower', tower:'I', label:'Tower I', sub:'Pool Court · 4 BHK', detail:['20 floors · 38 homes','Swimming-pool-deck facing','Pairs with Tower J'] },
],
// ── RAMP MARKING — GROUND FLOOR ──
'ramp-ground': [
{ x:20, y:78, kind:'entry', label:'Apartment Ramp Entry', sub:'Resident vehicle access', detail:['Dedicated apartment vehicle ramp down to basements','Keeps resident & retail traffic separate'] },
{ x:78, y:74, kind:'ramp', label:'Retail Parking Ramp', sub:'Visitor / retail access', detail:['Separate ramp serving retail parking at Basement 1','Independent of the resident circulation core'] },
{ x:50, y:46, kind:'parking', label:'Ground-Floor Parking Bays', sub:'Surface stack', detail:['Marked ground-floor parking adjacent to the cores','Feeds the three basement levels below'] },
{ x:52, y:88, kind:'entry', label:'Arrival Drop-Off', sub:'Porte-cochère', detail:['Covered drop-off at the grand foyer','Pause-and-go lane keeps the ramp clear'] },
{ x:30, y:30, kind:'core', label:'North Circulation Core', sub:'Lift + stair', detail:['Vertical core linking GF to the parking basements'] },
{ x:72, y:36, kind:'core', label:'East Circulation Core', sub:'Lift + stair', detail:['Vertical core linking GF to the parking basements'] },
],
// ── RETAIL — ZONING & PARKING · BASEMENT 1 ──
'retail-zp': [
{ x:50, y:30, kind:'retail', label:'Retail Parking Zone', sub:'Basement 1', detail:['Dedicated retail parking floor, zoned away from resident bays','Direct lift access up to the high-street level'] },
{ x:24, y:58, kind:'ramp', label:'Retail Ramp In', sub:'Down ramp', detail:['Retail visitors descend via their own ramp','No overlap with apartment circulation'] },
{ x:76, y:60, kind:'ramp', label:'Retail Ramp Out', sub:'Up ramp', detail:['One-way exit ramp back to street level'] },
{ x:50, y:74, kind:'parking', label:'Visitor Bays', sub:'Marked stalls', detail:['Visitor & shopper parking allocation','Signage-led wayfinding to retail lifts'] },
{ x:38, y:42, kind:'core', label:'Retail Lift Core', sub:'To G+1 high street', detail:['Express retail core to ground & first-floor shops'] },
],
// ── RETAIL MARKING — GROUND FLOOR ──
'retail-ground': [
{ x:50, y:18, kind:'retail', label:'High-Street Frontage', sub:'25 ground shops', detail:['25 ground-floor shops along the high-street frontage','Active edge facing the BRTS / arrival road'] },
{ x:22, y:50, kind:'entry', label:'West Retail Entry', sub:'Pedestrian plaza', detail:['Shaded pedestrian entry into the retail spine'] },
{ x:78, y:50, kind:'entry', label:'East Retail Entry', sub:'Pedestrian plaza', detail:['Second pedestrian access from the east'] },
{ x:50, y:62, kind:'plaza', label:'Retail Plaza', sub:'Open court', detail:['Open plaza knitting the shopfronts together','Seating & landscape pause points'] },
{ x:50, y:90, kind:'parking', label:'Retail Drop-Off', sub:'Kerbside', detail:['Kerbside shopper drop-off at the frontage'] },
{ x:65, y:30, kind:'core', label:'Retail Lift / Stair', sub:'To first floor', detail:['Vertical link up to the 22 first-floor shops'] },
],
// ── RETAIL MARKING — FIRST FLOOR ──
'retail-first': [
{ x:50, y:20, kind:'retail', label:'First-Floor Shops', sub:'22 shops', detail:['22 first-floor shops above the high street','Merged corner units for anchor tenants'] },
{ x:28, y:52, kind:'core', label:'West Vertical Core', sub:'Lift + escalator', detail:['Connects first-floor retail to the ground plaza'] },
{ x:72, y:52, kind:'core', label:'East Vertical Core', sub:'Lift + escalator', detail:['Second vertical connection to ground level'] },
{ x:50, y:48, kind:'plaza', label:'Upper Galleria Walk', sub:'Connecting deck', detail:['Sheltered first-floor walkway linking the shops','Overlooks the retail plaza below'] },
{ x:50, y:82, kind:'social', label:'Café / F&B Cluster', sub:'Terrace edge', detail:['F&B cluster with a terrace overlooking the frontage'] },
],
// ── CIRCULATION plans — share a compact entry / drop-off / core set ──
'circ-ab': [
{ x:32, y:30, kind:'tower', tower:'A', label:'Tower A Core', sub:'North Edge', detail:['Resident lift & stair core for Tower A'] },
{ x:62, y:32, kind:'tower', tower:'B', label:'Tower B Core', sub:'North Edge', detail:['Resident lift & stair core for Tower B'] },
{ x:48, y:80, kind:'entry', label:'A&B Drop-Off', sub:'Arrival court', detail:['Shared arrival drop-off serving the A&B cluster'] },
{ x:48, y:55, kind:'plaza', label:'Cluster Court', sub:'Landscape link', detail:['Landscaped court linking both tower lobbies to the garden'] },
],
'circ-cdhij': [
{ x:30, y:34, kind:'tower', tower:'C', label:'Tower C Core', sub:'West Court', detail:['Resident lift & stair core for Tower C'] },
{ x:46, y:26, kind:'tower', tower:'D', label:'Tower D Core', sub:'West Court', detail:['Resident lift & stair core for Tower D'] },
{ x:70, y:38, kind:'tower', tower:'H', label:'Tower H Core', sub:'Park Wing', detail:['Resident lift & stair core for Tower H'] },
{ x:42, y:74, kind:'tower', tower:'J', label:'Tower J Core', sub:'Pool Court', detail:['Resident lift & stair core for Tower J'] },
{ x:62, y:76, kind:'tower', tower:'I', label:'Tower I Core', sub:'Pool Court', detail:['Resident lift & stair core for Tower I'] },
{ x:50, y:90, kind:'entry', label:'Shared Foyer Entry', sub:'Double-height', detail:['Double-height arrival foyer serving blocks C–J'] },
],
'circ-efg': [
{ x:34, y:28, kind:'tower', tower:'E', label:'Tower E Core', sub:'Crown', detail:['Resident lift & stair core for Tower E'] },
{ x:62, y:30, kind:'tower', tower:'F', label:'Tower F Core', sub:'Crown', detail:['Resident lift & stair core for Tower F'] },
{ x:78, y:54, kind:'tower', tower:'G', label:'Tower G Core', sub:'Park Wing', detail:['Resident lift & stair core for Tower G'] },
{ x:48, y:80, kind:'entry', label:'E&F Drop-Off', sub:'Arrival court', detail:['Shared arrival drop-off serving the crown cluster'] },
{ x:50, y:56, kind:'plaza', label:'Garden Link', sub:'To podium', detail:['Landscaped link from the lobbies into the central garden'] },
],
};
// ── INTERACTIVE MARKERS — the highlighted/dashed zones baked into each plan.
// Each marker draws a pulsing GLOW over its box + a numbered POINTER at the
// centre; tapping the pointer zooms into the zone and opens a centred info card.
// box {x,y,w,h} = percent of the plan image's contain-fit rect.
const MARKERS = {
'ramp-ground': [
{ num:1, color:'red', box:{x:49.03,y:31.58,w:2.00,h:9.76}, title:'Apartment Ramp',
sub:'Resident vehicle access', detail:['Dedicated apartment ramp down to the parking basements','Keeps resident traffic clear of the retail circulation'] },
{ num:2, color:'red', box:{x:37.71,y:57.00,w:2.14,h:11.14}, title:'Parking Ramp · West',
sub:'Ground → basement', detail:['West vehicle ramp linking the ground floor to basement parking','Feeds the western stack of parking bays'] },
{ num:3, color:'red', box:{x:52.69,y:57.64,w:8.22,h:2.67}, title:'Central Drive Aisle',
sub:'Ground-floor circulation', detail:['Primary ground-floor drive aisle through the parking field','Connects both ramps to the surface bays & cores'] },
],
'retail-zp': [
{ num:1, color:'magenta', box:{x:38.5,y:15.5,w:19.5,h:11.0}, title:'Retail · Plaza North',
sub:'High street · Units 1–2', detail:['Prime plaza-facing retail frontage along the north edge','Anchor shopfronts (Units 1 & 2) opening to the arrival plaza','Maximum footfall from the landscaped plaza'] },
{ num:2, color:'magenta', box:{x:52.5,y:34.0,w:6.8,h:14.0}, title:'Retail · Plaza East',
sub:'High street · Unit 3', detail:['East plaza-facing retail strip','Unit 3 — corner shop with dual frontage','Lift & stair access up to the first-floor shops'] },
{ num:3, color:'red', box:{x:53.59,y:49.10,w:5.74,h:4.46}, title:'Vehicle Ramp',
sub:'Ground → Basement-1 parking', detail:['Dedicated vehicle ramp down to Basement-1 parking','Separates retail-visitor & resident circulation','Two-way controlled access'] },
{ num:4, color:'magenta', box:{x:53.53,y:53.35,w:5.80,h:6.48}, title:'Retail · South Block',
sub:'High street · Plaza edge', detail:['Southern retail units completing the plaza spine','Rear-corridor service access','Continuous active frontage to the plaza'] },
{ num:5, color:'red', box:{x:75.84,y:27.84,w:1.90,h:13.28}, title:'Basement-1 Parking',
sub:'Retail parking zone', detail:['Dedicated retail / visitor parking at Basement 1','Marked bay rows with wide drive aisles','Direct lift cores up to the retail level'] },
{ num:6, color:'green', box:{x:89.23,y:15.09,w:5.14,h:5.42}, title:'Services & MEP',
sub:'Plant / utility zone', detail:['Mechanical, electrical & plumbing services zone','Segregated from public parking circulation','Supports the retail & basement levels'] },
],
'retail-ground': [
{ num:1, color:'gold', box:{x:44.0,y:10.5,w:28.0,h:11.5}, title:'High-Street Retail · North',
sub:'Ground-floor shops', detail:['The principal ground-floor retail frontage along the north edge','Continuous shopfronts opening to the landscaped boulevard','Highest-visibility units in the development'] },
{ num:2, color:'gold', box:{x:65.5,y:25.0,w:12.0,h:33.0}, title:'Retail Spine · East',
sub:'Ground-floor shops', detail:['Retail units lining the eastern edge of the podium','Direct frontage to the internal street & parking court','A mix of standard & corner-shop formats'] },
{ num:3, color:'teal', box:{x:40.5,y:20.5,w:6.0,h:8.0}, title:'Grand Arrival Court',
sub:'Drop-off & roundabout', detail:['Signature arrival roundabout & covered drop-off','Welcomes residents and retail visitors alike','Sets the address’s first impression'] },
{ num:4, color:'blue', box:{x:45.0,y:27.0,w:18.0,h:31.0}, title:'Surface Parking Court',
sub:'Ground-floor parking', detail:['Organised ground-floor parking field at the core','Wide drive aisles feeding the basement ramps','Screened from the retail frontage by landscape'] },
{ num:5, color:'gold', box:{x:47.0,y:62.0,w:12.5,h:6.0}, title:'Retail Plaza · South',
sub:'Shops & arrival', detail:['Southern retail cluster framing the secondary arrival','Café & convenience formats at the plaza edge','Pedestrian-friendly active frontage'] },
{ num:6, color:'green', box:{x:27.0,y:55.0,w:17.0,h:32.0}, title:'Garden Residences Wing',
sub:'Low-rise homes + garden', detail:['Intimate low-rise residential blocks in the south-west wing','Private landscaped garden & community lawn','The quietest, most green-fronted address in the scheme'] },
],
'retail-first': [
{ num:1, color:'gold', box:{x:47.5,y:13.8,w:30.0,h:13.0}, title:'First-Floor Retail · North',
sub:'First-floor shops', detail:['First-floor retail frontage above the high street','Larger-format units & showrooms','Linked to the ground floor by escalators & lifts'] },
{ num:2, color:'gold', box:{x:72.5,y:25.0,w:9.0,h:37.0}, title:'First-Floor Retail · East',
sub:'First-floor shops', detail:['Eastern first-floor retail wrapping the podium','Terraced units overlooking the amenity deck','Premium upper-level shop formats'] },
{ num:3, color:'blue', box:{x:55.5,y:35.5,w:10.0,h:8.0}, title:'Swimming Pool & Deck',
sub:'Amenity podium', detail:['Resort-style swimming pool & sun deck','Pool-side lounge and changing rooms','The heart of the first-floor amenity podium'] },
{ num:4, color:'green', box:{x:55.0,y:49.0,w:13.0,h:16.0}, title:'Central Lawn & Garden',
sub:'Open green', detail:['Expansive central lawn for events & play','Landscaped gardens framing the green','The development’s signature open space'] },
{ num:5, color:'purple', box:{x:47.0,y:70.0,w:25.0,h:9.0}, title:'Clubhouse & Amenities',
sub:'Indoor amenities', detail:['Clubhouse with gym, banquet & indoor games','Café, library & co-working lounges','Direct access from the amenity podium'] },
{ num:6, color:'red', box:{x:68.0,y:41.0,w:10.0,h:20.0}, title:'Running Track & Sports',
sub:'Active zone', detail:['Curved running / jogging track around the green','Outdoor fitness & sports pockets','Wraps the lawn for an active edge'] },
],
'circ-ab': [
{ num:1, color:'teal', box:{x:33,y:2,w:5,h:9}, title:'Site Entry · North Drive',
sub:'Vehicle entry', detail:['Main vehicular entry into the development from the north','Feeds the surface parking & basement ramps'] },
{ num:2, color:'blue', box:{x:40,y:30,w:24,h:28}, title:'Parking Circulation',
sub:'Surface parking court', detail:['One-way circulation loop through the surface parking','Aisles feed every core & the basement ramp'] },
{ num:3, color:'green', box:{x:28,y:52,w:7,h:7}, title:'Way to Basement',
sub:'Basement ramp', detail:['Ramp down to the basement parking levels','Branches off the main internal drive'] },
{ num:4, color:'magenta', box:{x:18,y:63,w:15,h:11}, title:'Tower B',
sub:'Residential core + lobby', detail:['Tower B lobby, entrance & residential core','Drop-off court at the tower forecourt','Direct lift access to all floors'] },
{ num:5, color:'magenta', box:{x:24,y:83,w:14,h:10}, title:'Tower A',
sub:'Residential core + lobby', detail:['Tower A lobby, entrance & residential core','Independent arrival within the garden wing','Direct lift access to all floors'] },
],
'circ-efg': [
{ num:1, color:'magenta', box:{x:37,y:13,w:11,h:13}, title:'Tower E',
sub:'Residential core + lobby', detail:['Tower E lobby & residential core','Entrance lobby off the north drive','Lift & stair access to all floors'] },
{ num:2, color:'magenta', box:{x:49,y:13,w:12,h:13}, title:'Tower F',
sub:'Residential core + lobby', detail:['Tower F lobby & residential core','Shares the north arrival with Tower E','Lift & stair access to all floors'] },
{ num:3, color:'magenta', box:{x:55,y:37,w:10,h:13}, title:'Tower G',
sub:'Residential core + lobby', detail:['Tower G lobby & residential core','Eastern arrival & drop-off','Lift & stair access to all floors'] },
{ num:4, color:'purple', box:{x:44,y:22,w:8,h:7}, title:'Double-Height Entrance Foyer',
sub:'Grand arrival', detail:['Double-height entrance foyer for the E–F cluster','A signature arrival volume','Connects lobby, drop-off & cores'] },
{ num:5, color:'red', box:{x:54,y:39,w:6,h:7}, title:'Drop-off Court',
sub:'Arrival', detail:['Covered drop-off serving Tower G','Pause-and-go lane keeps the drive clear'] },
{ num:6, color:'blue', box:{x:42,y:33,w:4,h:13}, title:'Way to Basement',
sub:'Basement ramp', detail:['Ramp down to basement parking','Separated from the resident drop-off'] },
],
'circ-cdhij': [
{ num:1, color:'magenta', box:{x:32,y:30,w:8,h:14}, title:'Tower D',
sub:'Residential core + lobby', detail:['Tower D lobby & residential core','West-court arrival','Lift & stair access to all floors'] },
{ num:2, color:'magenta', box:{x:32,y:45,w:8,h:13}, title:'Tower C',
sub:'Residential core + lobby', detail:['Tower C lobby & residential core','Pairs with Tower D on the west court','Lift & stair access to all floors'] },
{ num:3, color:'magenta', box:{x:35,y:61,w:10,h:9}, title:'Tower J',
sub:'Residential core + lobby', detail:['Tower J lobby & residential core','Pool-court arrival','Lift & stair access to all floors'] },
{ num:4, color:'magenta', box:{x:45,y:61,w:10,h:9}, title:'Tower I',
sub:'Residential core + lobby', detail:['Tower I lobby & residential core','Pairs with Tower J on the pool court','Lift & stair access to all floors'] },
{ num:5, color:'magenta', box:{x:57,y:55,w:9,h:14}, title:'Tower H',
sub:'Residential core + lobby', detail:['Tower H lobby & residential core','Park-wing arrival & drop-off','Lift & stair access to all floors'] },
{ num:6, color:'red', box:{x:45,y:55,w:10,h:6}, title:'Way to Basement & Drop-off',
sub:'Arrival + ramp', detail:['Central drop-off with the basement ramp alongside','Serves the C–J cluster','Keeps resident & service traffic ordered'] },
],
};
// circulation plans carry an animated coloured-arrow overlay (extracted from the artwork)
const CIRC = {
'circ-ab': { arrows:'assets/masterplan/plans/circulation-ab-arrows.png?v=1', glow:'rgba(70,185,105,0.95)' },
'circ-efg': { arrows:'assets/masterplan/plans/circulation-efg-arrows.png?v=1', glow:'rgba(72,130,235,0.95)' },
'circ-cdhij':{ arrows:'assets/masterplan/plans/circulation-cdhij-arrows.png?v=1', glow:'rgba(235,72,62,0.95)' },
};
// per-colour glow / pin palette
const MK_COLOR = {
red: { line:'rgba(229,57,53,0.92)', fill:'rgba(255,72,66,0.50)', pin:'#e5392f', ring:'rgba(229,57,53,0.40)', glow:'rgba(255,72,66,0.75)' },
magenta: { line:'rgba(206,42,150,0.94)', fill:'rgba(236,72,180,0.42)', pin:'#cf2c96', ring:'rgba(206,42,150,0.40)', glow:'rgba(236,72,180,0.70)' },
green: { line:'rgba(40,150,84,0.94)', fill:'rgba(70,180,110,0.42)', pin:'#239a54', ring:'rgba(40,150,84,0.40)', glow:'rgba(70,180,110,0.70)' },
gold: { line:'rgba(201,150,40,0.95)', fill:'rgba(232,180,70,0.40)', pin:'#c2922e', ring:'rgba(201,150,40,0.40)', glow:'rgba(235,185,80,0.72)' },
blue: { line:'rgba(70,120,210,0.93)', fill:'rgba(96,150,235,0.36)', pin:'#3f74d6', ring:'rgba(70,120,210,0.40)', glow:'rgba(110,160,240,0.70)' },
teal: { line:'rgba(28,150,160,0.93)', fill:'rgba(60,185,195,0.40)', pin:'#1f9aa6', ring:'rgba(28,150,160,0.40)', glow:'rgba(70,200,210,0.70)' },
purple: { line:'rgba(150,80,190,0.93)', fill:'rgba(178,110,215,0.36)', pin:'#9a52be', ring:'rgba(150,80,190,0.40)', glow:'rgba(190,120,225,0.70)' },
};
// ── inline plan-type glyphs (gold, simple, consistent · 24×24 viewBox) ──
function MpxGlyph({ type, size = 22, stroke = 'currentColor' }){
const P = { fill:'none', stroke, strokeWidth:1.6, strokeLinecap:'round', strokeLinejoin:'round' };
const G = {
parking: