import { useEffect, useId, useMemo, useRef, useState, type CSSProperties } from "react"; import mapboxgl, { type GeoJSONSource, type LngLatBoundsLike, type MapboxGeoJSONFeature, type MapMouseEvent, } from "mapbox-gl"; import { CommandGlobe } from "./CommandGlobe"; import { getMapboxToken } from "../lib/env"; import type { MapSelection, ViewerMapEntity, ViewerMapFeature, ViewerMapLink, ViewerMapState } from "../lib/viewer-map"; type CommandMapProps = { entities: ViewerMapEntity[]; features: ViewerMapFeature[]; links?: ViewerMapLink[]; selectedEntity: MapSelection; onSelectEntity: (entityId: MapSelection) => void; worldSummary: ViewerMapState["worldSummary"] & { activeEventCount?: number; lastUpdatedLabel?: string; }; }; type GeoJsonFeatureProperties = { id: string; entityId: string; entityLabel: string; title: string; subtitle: string; category: string; importance: string; color: string; accent: string; selected: number; dimmed: number; interactive: number; }; type GeoJsonFeatureCollection = GeoJSON.FeatureCollection; type MapFeatureMouseEvent = MapMouseEvent & { features?: MapboxGeoJSONFeature[] }; const DEFAULT_CENTER: [number, number] = [41.8, 27.8]; const DEFAULT_ZOOM = 2.35; const FALLBACK_ENTITY: MapSelection = "all"; const MAP_STYLE = "mapbox://styles/mapbox/dark-v11"; const INTEL_HIDDEN_LAYERS = [ "road-label", "settlement-label", "settlement-subdivision-label", "airport-label", "poi-label", "transit-label", "natural-label", ]; const LAYER_LABELS: Record = { alliance_anchor: "Alliance Anchor", chokepoint: "Chokepoint", coalition_link: "Coalition Link", front: "Front", geospatial_anchor: "Geospatial Anchor", infrastructure: "Infrastructure", location: "Location", strategic_site: "Strategic Site", }; export function CommandMap({ entities, features, links = [], selectedEntity, onSelectEntity, worldSummary, }: CommandMapProps) { const mapContainerRef = useRef(null); const mapRef = useRef(null); const popupRef = useRef(null); const [interactiveReady, setInteractiveReady] = useState(false); const [mapError, setMapError] = useState(null); const mapId = useId().replace(/:/g, ""); const sourceId = `trenches-command-map-source-${mapId}`; const token = getMapboxToken(); const hasToken = typeof token === "string" && token.trim().length > 0; const entityLookup = useMemo( () => new Map(entities.map((entity) => [entity.id, entity])), [entities], ); const geoJson = useMemo(() => { const pointFeatures: GeoJSON.Feature[] = features.map((feature) => { const entity = entityLookup.get(feature.entityId); const isSelected = selectedEntity === FALLBACK_ENTITY || selectedEntity === feature.entityId; return { type: "Feature", id: feature.id, properties: { id: feature.id, entityId: feature.entityId, entityLabel: feature.entityName, title: feature.name, subtitle: feature.description, category: feature.layer, importance: feature.layer === "chokepoint" ? "critical" : feature.layer === "front" ? "high" : "medium", color: entity?.color ?? "#90d1ff", accent: entity?.accent ?? "#dff3fb", selected: isSelected ? 1 : 0, dimmed: isSelected ? 0 : 1, interactive: 1, }, geometry: { type: "Point", coordinates: [feature.longitude, feature.latitude], }, }; }); const linkFeatures: GeoJSON.Feature[] = links.map((link) => { const entity = entityLookup.get(link.fromAgentId); const isSelected = selectedEntity === FALLBACK_ENTITY || selectedEntity === link.fromAgentId || selectedEntity === link.toAgentId; const fromLabel = entityLookup.get(link.fromAgentId)?.displayName ?? link.fromAgentId; const toLabel = entityLookup.get(link.toAgentId)?.displayName ?? link.toAgentId; return { type: "Feature", id: link.id, properties: { id: link.id, entityId: link.fromAgentId, entityLabel: `${fromLabel} ↔ ${toLabel}`, title: "Coalition Link", subtitle: `${fromLabel} coordinated with ${toLabel}.`, category: "coalition_link", importance: "medium", color: entity?.color ?? "#90d1ff", accent: entity?.accent ?? "#dff3fb", selected: isSelected ? 1 : 0, dimmed: isSelected ? 0 : 1, interactive: 0, }, geometry: { type: "LineString", coordinates: [link.from, link.to], }, }; }); return { type: "FeatureCollection", features: [...linkFeatures, ...pointFeatures], }; }, [entityLookup, features, links, selectedEntity]); const focusFeatures = useMemo(() => { if (selectedEntity === FALLBACK_ENTITY) { return features; } return features.filter((feature) => feature.entityId === selectedEntity); }, [features, selectedEntity]); const focusLinks = useMemo(() => { if (selectedEntity === FALLBACK_ENTITY) { return links; } return links.filter((link) => link.fromAgentId === selectedEntity || link.toAgentId === selectedEntity); }, [links, selectedEntity]); const categorySummary = useMemo(() => { const counts = new Map(); for (const feature of focusFeatures) { counts.set(feature.layer, (counts.get(feature.layer) ?? 0) + 1); } return [...counts.entries()] .sort((left, right) => right[1] - left[1]) .slice(0, 5) .map(([layer, count]) => ({ layer, label: LAYER_LABELS[layer] ?? startCase(layer), count, })); }, [focusFeatures]); const selectedEntityMeta = useMemo(() => { if (selectedEntity === FALLBACK_ENTITY) { return { label: "All Entities", color: "linear-gradient(135deg, #87f8c1 0%, #6bb8ff 100%)", headline: "Viewer-wide synthesis of every actor footprint, infrastructure chain, coalition line, and chokepoint.", priorities: ["Cross-entity route awareness", "Coalition edges", "Escalation geography", "Foreign basing"], featureCount: features.length, foreignBaseCount: 0, }; } const entity = selectedEntity === FALLBACK_ENTITY ? undefined : entityLookup.get(selectedEntity as ViewerMapEntity["id"]); return { label: entity?.displayName ?? selectedEntity, color: entity?.color ?? "#90d1ff", headline: entity?.headline ?? "Monitor the mapped footprint and strategic posture.", priorities: entity?.priorities ?? [], featureCount: entity?.featureCount ?? focusFeatures.length, foreignBaseCount: entity?.foreignBaseCount ?? 0, }; }, [entityLookup, features.length, focusFeatures.length, selectedEntity]); useEffect(() => { if (!hasToken || !mapContainerRef.current || mapRef.current) { return; } setInteractiveReady(false); setMapError(null); mapboxgl.accessToken = token; let map: mapboxgl.Map; try { map = new mapboxgl.Map({ container: mapContainerRef.current, style: MAP_STYLE, center: DEFAULT_CENTER, zoom: DEFAULT_ZOOM, attributionControl: false, projection: "globe", }); } catch (error) { setMapError(error instanceof Error ? error.message : "Failed to initialize WebGL."); return; } mapRef.current = map; popupRef.current = new mapboxgl.Popup({ closeButton: false, closeOnClick: false, offset: 18, className: "command-map-popup", }); map.addControl(new mapboxgl.NavigationControl({ visualizePitch: true }), "bottom-right"); map.on("style.load", () => { applyIntelligenceTheme(map); map.setFog({ color: "rgba(1, 5, 8, 0.96)", "high-color": "rgba(9, 27, 39, 0.34)", "space-color": "rgba(2, 5, 8, 1)", "star-intensity": 0.08, range: [-1, 2], }); }); map.on("load", () => { setInteractiveReady(true); if (!map.getSource(sourceId)) { map.addSource(sourceId, { type: "geojson", data: geoJson, }); } map.addLayer({ id: `${sourceId}-lines`, type: "line", source: sourceId, filter: ["==", ["geometry-type"], "LineString"], paint: { "line-color": ["get", "color"], "line-width": ["case", ["==", ["get", "selected"], 1], 3.2, 1.8], "line-opacity": ["case", ["==", ["get", "selected"], 1], 0.9, 0.24], "line-blur": ["case", ["==", ["get", "selected"], 1], 0.28, 0.85], }, }); map.addLayer({ id: `${sourceId}-point-halo`, type: "circle", source: sourceId, filter: ["==", ["geometry-type"], "Point"], paint: { "circle-radius": ["case", ["==", ["get", "selected"], 1], 15, 9], "circle-color": ["get", "color"], "circle-opacity": ["case", ["==", ["get", "selected"], 1], 0.2, 0.05], "circle-blur": 0.58, }, }); map.addLayer({ id: `${sourceId}-points`, type: "circle", source: sourceId, filter: ["==", ["geometry-type"], "Point"], paint: { "circle-radius": [ "case", ["==", ["get", "importance"], "critical"], 6.8, ["==", ["get", "importance"], "high"], 5.9, 4.9, ], "circle-color": ["get", "color"], "circle-stroke-color": ["case", ["==", ["get", "selected"], 1], "#f8fdff", "rgba(255,255,255,0.42)"], "circle-stroke-width": ["case", ["==", ["get", "selected"], 1], 1.45, 0.8], "circle-opacity": ["case", ["==", ["get", "selected"], 1], 0.98, 0.34], }, }); map.addLayer({ id: `${sourceId}-labels`, type: "symbol", source: sourceId, filter: ["all", ["==", ["geometry-type"], "Point"], ["==", ["get", "selected"], 1]], layout: { "text-field": ["get", "title"], "text-size": 11, "text-offset": [0, 1.28], "text-anchor": "top", "text-font": ["DIN Pro Medium", "Arial Unicode MS Regular"], }, paint: { "text-color": "rgba(233, 244, 248, 0.92)", "text-halo-color": "rgba(4, 10, 15, 0.95)", "text-halo-width": 1.2, "text-opacity": 0.9, }, }); bindInteraction(map, popupRef.current, onSelectEntity); fitMapToSelection(map, focusFeatures, focusLinks); }); map.on("error", (event) => { const nextError = event.error; setMapError(nextError instanceof Error ? nextError.message : "Map rendering error."); }); return () => { popupRef.current?.remove(); popupRef.current = null; setInteractiveReady(false); setMapError(null); map.remove(); mapRef.current = null; }; }, [focusFeatures, focusLinks, geoJson, hasToken, onSelectEntity, sourceId, token]); useEffect(() => { const map = mapRef.current; if (!map) { return; } const source = map.getSource(sourceId) as GeoJSONSource | undefined; if (source) { source.setData(geoJson); } fitMapToSelection(map, focusFeatures, focusLinks); }, [focusFeatures, focusLinks, geoJson, sourceId]); return (

Viewer Layer

World Intelligence Layer

This is a spectator command surface. Agents do not receive this spatial synthesis in their observation payload.

{hasToken && !mapError ? (
) : !hasToken ? (
Mapbox token missing

Spatial viewer is ready, but the tile layer is offline.

Set NEXT_PUBLIC_MAPBOX_TOKEN to render the theater map. Entity footprints, coalition links, and viewer controls remain available.

Tracked footprints {features.length}
Coalition links {links.length}
) : ( )} {hasToken && mapError ? (
WebGL unavailable, globe fallback active
) : hasToken && !interactiveReady ? (
Initializing interactive globe
) : null}
Operator intelligence wall
{worldSummary.lastUpdatedLabel ? {worldSummary.lastUpdatedLabel} : null}
Legend Signals mark assets, fronts, chokepoints, and foreign basing. Lines trace active coalition edges.
{entities.map((entity) => ( ))}
); } function MetricCard({ label, value, tone, }: { label: string; value: string; tone: "neutral" | "warn" | "hot"; }) { return (
{label} {value}
); } function scoreTone(value: number): "neutral" | "warn" | "hot" { if (value >= 75) { return "hot"; } if (value >= 50) { return "warn"; } return "neutral"; } function applyIntelligenceTheme(map: mapboxgl.Map) { for (const layerId of INTEL_HIDDEN_LAYERS) { if (map.getLayer(layerId)) { map.setLayoutProperty(layerId, "visibility", "none"); } } const paintUpdates: Array<{ id: string; prop: string; value: string | number; }> = [ { id: "background", prop: "background-color", value: "#02070a" }, { id: "land", prop: "fill-color", value: "#071117" }, { id: "water", prop: "fill-color", value: "#040b10" }, { id: "waterway", prop: "line-color", value: "#0d2732" }, { id: "admin-0-boundary", prop: "line-color", value: "rgba(90, 150, 170, 0.18)" }, { id: "admin-1-boundary", prop: "line-color", value: "rgba(90, 150, 170, 0.1)" }, { id: "road-primary", prop: "line-color", value: "rgba(65, 96, 108, 0.16)" }, { id: "road-secondary-tertiary", prop: "line-color", value: "rgba(55, 78, 88, 0.1)" }, { id: "airport", prop: "circle-color", value: "rgba(120, 170, 188, 0.18)" }, { id: "country-label", prop: "text-color", value: "rgba(174, 204, 214, 0.38)" }, { id: "marine-label", prop: "text-color", value: "rgba(79, 121, 138, 0.32)" }, ]; for (const update of paintUpdates) { if (!map.getLayer(update.id)) { continue; } try { map.setPaintProperty(update.id, update.prop as never, update.value as never); } catch { continue; } } } function bindInteraction( map: mapboxgl.Map, popup: mapboxgl.Popup | null, onSelectEntity: (entityId: MapSelection) => void, ) { const interactiveLayers = map .getStyle() .layers?.filter((layer) => layer.id.endsWith("-points") || layer.id.endsWith("-lines")) .map((layer) => layer.id); if (!interactiveLayers || interactiveLayers.length === 0) { return; } for (const layerId of interactiveLayers) { map.on("mouseenter", layerId, () => { map.getCanvas().style.cursor = "pointer"; }); map.on("mouseleave", layerId, () => { map.getCanvas().style.cursor = ""; popup?.remove(); }); map.on("mousemove", layerId, (event) => { renderPopup(map, popup, event); }); map.on("click", layerId, (event) => { const feature = event.features?.[0]; if (!feature || !feature.properties) { return; } const properties = feature.properties as GeoJsonFeatureProperties; if (properties.interactive === 1) { onSelectEntity(properties.entityId as MapSelection); } }); } } function renderPopup(map: mapboxgl.Map, popup: mapboxgl.Popup | null, event: MapFeatureMouseEvent) { if (!popup) { return; } const feature = event.features?.[0]; if (!feature || !feature.properties) { popup.remove(); return; } const properties = feature.properties as GeoJsonFeatureProperties; popup .setLngLat(resolvePopupCoordinates(feature.geometry)) .setHTML(buildPopupMarkup(properties)) .addTo(map); } function buildPopupMarkup(properties: GeoJsonFeatureProperties) { return [ `
`, `${escapeHtml(LAYER_LABELS[properties.category] ?? startCase(properties.category))}`, `${escapeHtml(properties.title)}`, `

${escapeHtml(properties.entityLabel)}

`, properties.subtitle ? `

${escapeHtml(properties.subtitle)}

` : "", `
`, ].join(""); } function resolvePopupCoordinates(geometry: GeoJSON.Geometry): [number, number] { if (geometry.type === "Point") { return geometry.coordinates as [number, number]; } if (geometry.type === "LineString") { return (geometry.coordinates[0] as [number, number]) ?? DEFAULT_CENTER; } return DEFAULT_CENTER; } function fitMapToSelection(map: mapboxgl.Map, features: ViewerMapFeature[], links: ViewerMapLink[]) { const coordinates: Array<[number, number]> = [ ...features.map((feature) => [feature.longitude, feature.latitude] as [number, number]), ...links.flatMap((link) => [link.from, link.to]), ]; if (coordinates.length === 0) { map.easeTo({ center: DEFAULT_CENTER, zoom: DEFAULT_ZOOM, duration: 650 }); return; } if (coordinates.length === 1) { map.easeTo({ center: coordinates[0], zoom: 4.2, duration: 650 }); return; } const bounds = new mapboxgl.LngLatBounds(coordinates[0], coordinates[0]); for (const coordinate of coordinates.slice(1)) { bounds.extend(coordinate); } map.fitBounds(bounds as LngLatBoundsLike, { padding: { top: 80, right: 420, bottom: 80, left: 80 }, duration: 850, maxZoom: 5.3, }); } function startCase(value: string) { return value .replace(/[_-]+/g, " ") .replace(/\s+/g, " ") .trim() .replace(/\b\w/g, (char) => char.toUpperCase()); } function escapeHtml(value: string) { return value .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } function cssVarStyle(name: string, value: string): CSSProperties { return { [name]: value, } as CSSProperties; } export default CommandMap;