import React, { useState, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
import { useNavigate } from 'react-router-dom';
import MapBg from '../assets/images/intel_map_dfw_twilight.webp';
import IntelligenceSidePanel from './dashboard/IntelligenceSidePanel';
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

// ── 10 Hotspots — 5 Commercial + 5 Residential, DFW Metro ──
const hotspots = [
    // Commercial
    {
        id: 1, top: '22%', left: '58%',
        address: '8333 Douglas Ave, Dallas',
        type: 'Commercial',
        problem: 'Roof Membrane Uplift',
        gain: '+$8.5M',
        weather: 'Hail Expected',
        status: 'Urgent',
        specs: { built: '1998', maintenance: '5 yrs since last coating' },
        management: { name: 'Sterling Properties', contact: 'Sign in for contact details' },
        photos: [
            { id: 'c1-1', url: '/assets/images/properties/Apartment_Complex.jpg', caption: 'Exterior View' },
            { id: 'c1-2', url: '/assets/images/properties/Office_Roof_Top_View.jpg', caption: 'Roof Aerial' },
            { id: 'c1-3', url: '/assets/images/properties/Broken_Roof_Surface.jpg', caption: 'Membrane Damage' },
        ]
    },
    {
        id: 2, top: '35%', left: '38%',
        address: '5600 Tennyson Pkwy, Plano',
        type: 'Commercial',
        problem: 'Critical Membrane Failure',
        gain: '+$22.5M',
        weather: 'Clear',
        status: 'Monitoring',
        specs: { built: '1982', maintenance: '20 yrs since roof replacement' },
        management: { name: 'Goldman Group', contact: 'Sign in for contact details' },
        photos: [
            { id: 'c2-1', url: '/assets/images/properties/Warehouse_Roof_Aerial.jpg', caption: 'Aerial Survey' },
            { id: 'c2-2', url: '/assets/images/properties/Mall_Rooftop_HVAC_Units.jpg', caption: 'HVAC Systems' },
            { id: 'c2-3', url: '/assets/images/properties/Storm_Worn_Roof.jpg', caption: 'Surface Wear' },
            { id: 'c2-4', url: '/assets/images/properties/Cracked_Asphalt_Shingles.jpg', caption: 'Substrate Cracking' },
        ]
    },
    {
        id: 3, top: '48%', left: '72%',
        address: '1900 Preston Rd, Frisco',
        type: 'Commercial',
        problem: 'Ponding Water Accumulation',
        gain: '+$4.2M',
        weather: 'Storm Watch',
        status: 'Action Required',
        specs: { built: '2005', maintenance: '3 yrs since drainage check' },
        management: { name: 'Hillcrest Capital', contact: 'Sign in for contact details' },
        photos: [
            { id: 'c3-1', url: '/assets/images/properties/Apartment_Complex.jpg', caption: 'Building Exterior' },
            { id: 'c3-2', url: '/assets/images/properties/Mall_Rooftop_HVAC_Units.jpg', caption: 'Rooftop Overview' },
            { id: 'c3-3', url: '/assets/images/properties/Broken_Roof_Surface.jpg', caption: 'Ponding Damage' },
        ]
    },
    {
        id: 4, top: '62%', left: '28%',
        address: '2100 N Hwy 360, Grand Prairie',
        type: 'Commercial',
        problem: 'HVAC Penetration Leak',
        gain: '+$6.8M',
        weather: 'Windy',
        status: 'Monitoring',
        specs: { built: '1995', maintenance: '8 yrs since waterproofing' },
        management: { name: 'Apex Industrial Partners', contact: 'Sign in for contact details' },
        photos: [
            { id: 'c4-1', url: '/assets/images/properties/Warehouse_Roof_Aerial.jpg', caption: 'Facility Aerial' },
            { id: 'c4-2', url: '/assets/images/properties/Mall_Rooftop_HVAC_Units.jpg', caption: 'HVAC Penetration' },
            { id: 'c4-3', url: '/assets/images/properties/Cracked_Storm_Shingles.jpg', caption: 'Seal Failure' },
        ]
    },
    {
        id: 5, top: '15%', left: '20%',
        address: '401 Commerce St, Fort Worth',
        type: 'Commercial',
        problem: 'Flashing Deterioration',
        gain: '+$11.3M',
        weather: 'Hail Expected',
        status: 'Urgent',
        specs: { built: '1990', maintenance: '12 yrs since seal replacement' },
        management: { name: 'Tarrant Realty Holdings', contact: 'Sign in for contact details' },
        photos: [
            { id: 'c5-1', url: '/assets/images/properties/Office_Roof_Top_View.jpg', caption: 'Roof Survey' },
            { id: 'c5-2', url: '/assets/images/properties/Apartment_Complex.jpg', caption: 'Building Facade' },
            { id: 'c5-3', url: '/assets/images/properties/Curled_Aging_Shingles.jpg', caption: 'Flashing Wear' },
            { id: 'c5-4', url: '/assets/images/properties/Storm_Worn_Roof.jpg', caption: 'Wind Exposure' },
        ]
    },
    // Residential
    {
        id: 6, top: '55%', left: '50%',
        address: '4200 Beverly Dr, Highland Park',
        type: 'Residential',
        problem: 'Severe Hail Impact',
        gain: '+$1.1M',
        weather: 'Rain Soon',
        status: 'Action Required',
        specs: { roofSize: '62 sq', eventHistory: '8 yrs since last hail event' },
        owner: { fico: '715', profile: 'Early Adopter / Long-term value' },
        photos: [
            { id: 'r6-1', url: '/assets/images/properties/Luxury_Driveway_Residence.jpg', caption: 'Front Exterior' },
            { id: 'r6-2', url: '/assets/images/properties/Hail_Damaged_Shingles.jpg', caption: 'Hail Damage' },
            { id: 'r6-3', url: '/assets/images/properties/Cracked_Storm_Shingles.jpg', caption: 'Storm Damage' },
        ]
    },
    {
        id: 7, top: '72%', left: '65%',
        address: '3505 Lexington Ave, University Park',
        type: 'Residential',
        problem: 'Asphalt Shingle Loss',
        gain: '+$950K',
        weather: 'Windy',
        status: 'Low Priority',
        specs: { roofSize: '45 sq', eventHistory: 'High Wind Zone' },
        owner: { fico: '680', profile: 'First-time Buyer' },
        photos: [
            { id: 'r7-1', url: '/assets/images/properties/Modern_White_Suburban_Home.jpg', caption: 'Front View' },
            { id: 'r7-2', url: '/assets/images/properties/Cracked_Asphalt_Shingles.jpg', caption: 'Shingle Loss' },
            { id: 'r7-3', url: '/assets/images/properties/Roof_Inspection_Angle.jpg', caption: 'Drone Inspection' },
        ]
    },
    {
        id: 8, top: '40%', left: '15%',
        address: '7212 Covewood Dr, Garland',
        type: 'Residential',
        problem: 'Aging Composite Shingles',
        gain: '+$420K',
        weather: 'Clear',
        status: 'Low Priority',
        specs: { roofSize: '38 sq', eventHistory: 'No recent events' },
        owner: { fico: '740', profile: 'Long-term Owner' },
        photos: [
            { id: 'r8-1', url: '/assets/images/properties/Beige_Two_Story_House.jpg', caption: 'Street View' },
            { id: 'r8-2', url: '/assets/images/properties/Curled_Aging_Shingles.jpg', caption: 'Aging Shingles' },
        ]
    },
    {
        id: 9, top: '75%', left: '42%',
        address: '1520 Creekside Dr, Allen',
        type: 'Residential',
        problem: 'Ridge Cap Separation',
        gain: '+$780K',
        weather: 'Hail Expected',
        status: 'Urgent',
        specs: { roofSize: '55 sq', eventHistory: '2 hail events in 3 years' },
        owner: { fico: '695', profile: 'Insurance-motivated' },
        photos: [
            { id: 'r9-1', url: '/assets/images/properties/Brick_Front_Porch_Home.jpg', caption: 'Entryway' },
            { id: 'r9-2', url: '/assets/images/properties/Overlapping_Roof_Shingles.jpg', caption: 'Ridge Detail' },
            { id: 'r9-3', url: '/assets/images/properties/Hail_Damaged_Shingles.jpg', caption: 'Hail Damage' },
            { id: 'r9-4', url: '/assets/images/properties/Storm_Worn_Roof.jpg', caption: 'Worn Surface' },
        ]
    },
    {
        id: 10, top: '30%', left: '82%',
        address: '905 W Main St, Richardson',
        type: 'Residential',
        problem: 'Granule Loss Pattern',
        gain: '+$560K',
        weather: 'Storm Watch',
        status: 'Action Required',
        specs: { roofSize: '42 sq', eventHistory: '5 yrs since installation' },
        owner: { fico: '720', profile: 'Recently Purchased' },
        photos: [
            { id: 'r10-1', url: '/assets/images/properties/Red_Shingle_Cottage.jpg', caption: 'Cottage Exterior' },
            { id: 'r10-2', url: '/assets/images/properties/Residential_Roof_Texture.jpg', caption: 'Roof Texture' },
            { id: 'r10-3', url: '/assets/images/properties/Cracked_Asphalt_Shingles.jpg', caption: 'Granule Loss' },
        ]
    },
];

const FILTERS = ['All', 'Commercial', 'Residential', 'Storm Path'];
const STORM_WEATHER = ['Hail Expected', 'Storm Watch', 'Rain Soon'];

const metrics = [
    { label: 'Total Pipeline', value: 57.1, prefix: '$', suffix: 'M', color: 'text-blue-500', stamp: '\u25CF Active', stampClass: 'permit-stamp--accent' },
    { label: 'Active Alerts', value: 7, prefix: '', suffix: '', color: 'text-amber-500', stamp: '\u25B2 Monitoring', stampClass: 'permit-stamp--accent' },
    { label: 'Urgent', value: 3, prefix: '', suffix: '', color: 'text-red-500', stamp: '\u2715 Critical', stampClass: 'permit-stamp--danger' },
    { label: 'Avg Roof Age', value: 18, prefix: '', suffix: ' yrs', color: 'text-emerald-500', stamp: '\u2713 Assessed', stampClass: 'permit-stamp--verified' },
];

const isSpotVisible = (spot, filter) => {
    if (filter === 'All') return true;
    if (filter === 'Commercial') return spot.type === 'Commercial';
    if (filter === 'Residential') return spot.type === 'Residential';
    if (filter === 'Storm Path') return STORM_WEATHER.includes(spot.weather);
    return true;
};

const IntelligenceMap = () => {
    const navigate = useNavigate();
    const [activeSpot, setActiveSpot] = useState(null);
    const [activeFilter, setActiveFilter] = useState('All');
    const [hoveredSpot, setHoveredSpot] = useState(null);
    const [showRescheduleDialog, setShowRescheduleDialog] = useState(false);

    const sectionRef = useRef(null);
    const pinRefs = useRef([]);
    const metricRefs = useRef([]);
    const mapGlowRef = useRef(null);

    // Reschedule dialog timer
    useEffect(() => {
        const timer = setTimeout(() => setShowRescheduleDialog(true), 2500);
        return () => clearTimeout(timer);
    }, []);

    // GSAP: Staggered pin entrance + metric counters
    useEffect(() => {
        const ctx = gsap.context(() => {
            // Pin entrance
            const pins = pinRefs.current.filter(Boolean);
            pins.forEach(pin => gsap.set(pin, { opacity: 0, scale: 0, y: 20 }));

            gsap.to(pins, {
                opacity: 1, scale: 1, y: 0,
                duration: 0.6, stagger: 0.08,
                ease: 'back.out(1.7)',
                scrollTrigger: {
                    trigger: sectionRef.current,
                    start: 'top 70%',
                    toggleActions: 'play none none none',
                },
                onComplete: () => {
                    // Clear GSAP inline styles so CSS transitions take over
                    pins.forEach(pin => {
                        if (pin) gsap.set(pin, { clearProps: 'opacity,transform' });
                    });
                },
            });

            // Metric counters — proxy object approach
            metricRefs.current.forEach((el) => {
                if (!el) return;
                const target = parseFloat(el.dataset.target);
                const suffix = el.dataset.suffix || '';
                const prefix = el.dataset.prefix || '';
                const counter = { value: 0 };
                el.innerText = prefix + '0' + suffix;

                gsap.to(counter, {
                    value: target,
                    duration: 2,
                    ease: 'power1.out',
                    scrollTrigger: {
                        trigger: el,
                        start: 'top 85%',
                        toggleActions: 'play none none none',
                    },
                    onUpdate: () => {
                        const display = target % 1 !== 0
                            ? counter.value.toFixed(1)
                            : Math.ceil(counter.value).toString();
                        el.innerText = prefix + display + suffix;
                    },
                });
            });
        }, sectionRef);

        return () => ctx.revert();
    }, []);

    // Mouse-follow glow on map
    const handleMapMouseMove = (e) => {
        if (!mapGlowRef.current) return;
        const rect = e.currentTarget.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        mapGlowRef.current.style.background =
            `radial-gradient(350px circle at ${x}px ${y}px, rgba(6,182,212,0.08), transparent 60%)`;
    };

    const handleMapMouseLeave = () => {
        if (mapGlowRef.current) mapGlowRef.current.style.background = 'transparent';
    };

    return (
        <section
            ref={sectionRef}
            className="py-24 bg-zinc-100 dark:bg-zinc-900 border-t border-zinc-200 dark:border-white/5 relative overflow-hidden"
        >
            {/* Blueprint grid bg */}
            <div className="absolute inset-0 blueprint-grid-fine"></div>

            <div className="max-w-7xl mx-auto px-6 relative z-10">

                {/* ── Header ── */}
                <div className="mb-8 text-center max-w-4xl mx-auto">
                    <div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-cyan-500/10 dark:bg-cyan-400/10 border border-cyan-500/20 dark:border-cyan-400/20 mb-4">
                        <div className="w-1.5 h-1.5 bg-cyan-500 dark:bg-cyan-400 rounded-full animate-pulse"></div>
                        <span className="text-cyan-600 dark:text-cyan-400 text-xs font-mono font-bold uppercase tracking-widest">Live CRM Data Feed</span>
                    </div>
                    <h2 className="text-3xl md:text-5xl font-black text-zinc-900 dark:text-white mb-4 tracking-tight">
                        Hyper-Local Sales Intelligence
                    </h2>
                    <p className="text-zinc-500 dark:text-zinc-400 text-lg max-w-2xl mx-auto">
                        Our systems overlay live NOAA weather data with property value insights. Maximize revenue by targeting neighborhoods directly in the storm path.
                    </p>
                </div>

                {/* ── Filter Bar ── */}
                <div className="flex flex-wrap items-center justify-center gap-2 sm:gap-3 mb-8">
                    {FILTERS.map((filter) => (
                        <button
                            key={filter}
                            onClick={() => { setActiveFilter(filter); setActiveSpot(null); }}
                            className={`font-mono text-[10px] font-bold uppercase tracking-widest px-4 py-2 rounded-md border transition-all duration-200
                                ${activeFilter === filter
                                    ? 'bg-cyan-500/10 dark:bg-cyan-400/10 text-cyan-600 dark:text-cyan-400 border-cyan-500/30 dark:border-cyan-400/30'
                                    : 'bg-white dark:bg-white/5 text-zinc-500 dark:text-gray-500 border-zinc-200 dark:border-white/10 hover:text-zinc-900 dark:hover:text-white hover:border-zinc-400 dark:hover:border-white/20'
                                }
                            `}
                        >
                            {filter}
                        </button>
                    ))}
                </div>

                {/* ══════════════════════════════════════════════ */}
                {/* MAP CONTAINER — always dark (satellite image) */}
                {/* ══════════════════════════════════════════════ */}
                <div
                    className="relative w-full h-[400px] md:h-[550px] lg:h-[650px] bg-black rounded-2xl border border-zinc-300 dark:border-white/20 shadow-2xl overflow-hidden isolate ring-1 ring-zinc-200 dark:ring-white/10"
                    onMouseMove={handleMapMouseMove}
                    onMouseLeave={handleMapMouseLeave}
                >
                    {/* Map Background */}
                    <div className="absolute inset-0 bg-[#0f172a]">
                        <img
                            src={MapBg}
                            alt="DFW Metroplex Map Overlay"
                            className="w-full h-full object-cover opacity-60 mix-blend-luminosity"
                        />
                        <div className="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-20"></div>
                    </div>

                    {/* Mouse-follow glow */}
                    <div
                        ref={mapGlowRef}
                        className="absolute inset-0 pointer-events-none z-10 transition-[background] duration-150"
                    />

                    {/* Region Indicator — HUD */}
                    <div className="absolute top-4 left-4 z-30">
                        <div className="bg-slate-900/80 backdrop-blur-md text-white pl-3 pr-4 py-1.5 md:pl-4 md:pr-6 md:py-2 rounded-r-lg border-l-4 border-cyan-400 shadow-[0_0_15px_rgba(0,229,255,0.2)]">
                            <div className="text-[9px] md:text-[10px] text-cyan-400 font-bold uppercase tracking-widest mb-0.5">Active Region</div>
                            <div className="font-black text-sm md:text-lg leading-none">DFW Zone 2</div>
                        </div>
                    </div>

                    {/* Weather Widget */}
                    <div className="absolute top-0 right-0 w-full h-full bg-gradient-to-bl from-slate-900/80 via-transparent to-transparent pointer-events-none"></div>
                    <div className="absolute top-4 right-4 p-3 md:p-4 bg-black/60 backdrop-blur-md rounded-lg border border-white/10 max-w-[180px] md:max-w-xs z-30 hidden sm:block">
                        <div className="flex items-center gap-3 md:gap-4">
                            <div className="bg-white/10 p-1.5 md:p-2 rounded-full text-white">
                                <span className="text-xl md:text-2xl">{'\u26C8'}</span>
                            </div>
                            <div>
                                <div className="font-bold text-white text-xs md:text-sm">Severe Hail Watch</div>
                                <div className="text-[10px] md:text-xs text-cyan-400 animate-pulse">Approaching Tarrant County</div>
                                <div className="text-[9px] md:text-[10px] text-gray-500 font-mono mt-1">ETA: 15 MINS</div>
                            </div>
                        </div>
                    </div>

                    {/* ── Interactive Pins ── */}
                    {hotspots.map((spot, index) => {
                        const visible = isSpotVisible(spot, activeFilter);
                        const isDimmed = activeSpot && activeSpot.id !== spot.id;
                        const isCommercial = spot.type === 'Commercial';

                        return (
                            <div
                                key={spot.id}
                                ref={(el) => { pinRefs.current[index] = el; }}
                                className={`absolute group/pin z-20 cursor-pointer transition-all duration-300 ease-in-out
                                    ${!visible ? 'opacity-0 scale-0 pointer-events-none' : ''}
                                    ${visible && isDimmed ? 'opacity-30' : ''}
                                `}
                                style={{ top: spot.top, left: spot.left }}
                                onClick={() => setActiveSpot(activeSpot?.id === spot.id ? null : spot)}
                                onMouseEnter={() => setHoveredSpot(spot.id)}
                                onMouseLeave={() => setHoveredSpot(null)}
                            >
                                {/* Larger invisible touch target */}
                                <div className="absolute -inset-4 md:-inset-2" />

                                {/* Urgent Status Alert Pulse */}
                                {visible && spot.status === 'Urgent' && (
                                    <div className="absolute -inset-8 rounded-full bg-red-500/30 animate-ping" style={{ animationDuration: '1.5s' }} />
                                )}

                                {/* Radar Ripple */}
                                {visible && (
                                    <div className={`absolute ${isCommercial ? '-inset-5' : '-inset-4'} rounded-full animate-ping opacity-75 ${isCommercial ? 'bg-purple-500/20' : 'bg-cyan-400/20'
                                        }`} />
                                )}

                                {/* Selected glow ring */}
                                {activeSpot?.id === spot.id && (
                                    <div className={`absolute -inset-6 rounded-full blur-md animate-pulse ${isCommercial ? 'bg-purple-500/25' : 'bg-cyan-400/25'
                                        }`} />
                                )}

                                {/* Pin cluster */}
                                <div className="relative flex flex-col items-center">
                                    {/* Pin Head */}
                                    <div className={`${isCommercial ? 'w-4 h-4' : 'w-3 h-3'} rounded-full border-2 border-white shadow-lg relative z-10 transition-transform duration-200 group-hover/pin:scale-125 ${isCommercial
                                        ? 'bg-purple-500 shadow-[0_0_15px_rgba(168,85,247,0.6)]'
                                        : 'bg-cyan-400 shadow-[0_0_15px_rgba(0,229,255,0.6)]'
                                        }`} />

                                    {/* Pin Line */}
                                    <div className="w-[1px] h-6 md:h-8 bg-gradient-to-b from-white to-transparent opacity-50" />

                                    {/* Ground Shadow */}
                                    <div className="absolute bottom-0 left-1/2 -translate-x-1/2 w-5 h-1 bg-black/60 blur-sm rounded-[100%] translate-y-1" />
                                </div>

                                {/* Hover Tooltip */}
                                <div className={`absolute bottom-full left-1/2 -translate-x-1/2 mb-3 bg-slate-900/90 backdrop-blur-md text-[10px] font-mono px-3 py-2 rounded-lg border border-white/10 shadow-lg whitespace-nowrap pointer-events-none transition-all duration-200 z-30
                                    ${hoveredSpot === spot.id && activeSpot?.id !== spot.id ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-1'}
                                `}>
                                    <div className="font-bold text-white text-[11px]">{spot.address}</div>
                                    <div className={`font-bold mt-0.5 ${isCommercial ? 'text-purple-400' : 'text-cyan-400'}`}>
                                        {spot.gain}
                                    </div>
                                    <div className="absolute top-full left-1/2 -translate-x-1/2 w-2 h-2 bg-slate-900/90 border-r border-b border-white/10 rotate-45 -mt-1" />
                                </div>
                            </div>
                        );
                    })}

                    {/* Reschedule Dialog */}
                    {showRescheduleDialog && (
                        <div className="absolute bottom-6 left-1/2 transform -translate-x-1/2 md:left-6 md:translate-x-0 z-50 w-[90%] md:w-96">
                            <div className="bg-white/95 backdrop-blur-xl rounded-xl shadow-2xl p-5 md:p-6 border-l-4 border-red-600 animate-[slideUp_0.5s_ease-out]">
                                <div className="flex justify-between items-start mb-3">
                                    <div className="flex items-center gap-3">
                                        <div className="w-8 h-8 bg-red-100 rounded-full flex items-center justify-center text-red-600 font-bold text-lg">!</div>
                                        <h4 className="font-bold text-slate-900 text-sm uppercase tracking-wide">Schedule Conflict</h4>
                                    </div>
                                    <button onClick={() => setShowRescheduleDialog(false)} className="text-gray-400 hover:text-black">{'\u2715'}</button>
                                </div>
                                <p className="text-gray-600 text-sm mb-4 leading-relaxed">
                                    <strong>Heavy rainfall expected in Plano at 2:00 PM.</strong><br />
                                    This conflicts with the inspection at <span className="text-slate-900 font-semibold">Legacy West</span>.
                                </p>
                                <div className="flex gap-3">
                                    <button onClick={() => navigate('/login')} className="flex-1 bg-slate-900 text-white text-xs font-bold py-2.5 rounded hover:bg-slate-800 transition-colors uppercase tracking-wider">
                                        Reschedule
                                    </button>
                                    <button onClick={() => setShowRescheduleDialog(false)} className="flex-1 bg-gray-100 text-gray-600 text-xs font-bold py-2.5 rounded hover:bg-gray-200 transition-colors uppercase tracking-wider">
                                        Dismiss
                                    </button>
                                </div>
                            </div>
                        </div>
                    )}

                    {/* Desktop Side Panel */}
                    {activeSpot && (
                        <div className="hidden md:block">
                            <IntelligenceSidePanel
                                data={activeSpot}
                                onClose={() => setActiveSpot(null)}
                            />
                        </div>
                    )}
                </div>

                {/* ── Mobile Bottom Sheet ── */}
                {activeSpot && ReactDOM.createPortal(
                    <div className="md:hidden fixed inset-0 z-[9999]">
                        <div className="absolute inset-0 bg-black/40 backdrop-blur-sm" onClick={() => setActiveSpot(null)} />
                        <div data-lenis-prevent className="absolute bottom-0 left-0 right-0 max-h-[80vh] bg-white dark:bg-zinc-900 rounded-t-2xl border-t border-zinc-200 dark:border-white/10 overflow-y-auto overscroll-contain animate-[slideUpSheet_0.3s_ease-out] shadow-2xl touch-pan-y">
                            {/* Sheet header */}
                            <div className="sticky top-0 bg-white dark:bg-zinc-900 px-6 pt-4 pb-2 border-b border-zinc-100 dark:border-white/5 z-10">
                                <div className="w-10 h-1 bg-zinc-300 dark:bg-white/20 rounded-full mx-auto mb-3" />
                                <div className="flex justify-between items-center">
                                    <div className="flex items-center gap-2">
                                        <div className={`w-2 h-2 rounded-full ${activeSpot.type === 'Commercial' ? 'bg-purple-500' : 'bg-cyan-400'}`} />
                                        <h3 className="font-bold text-zinc-900 dark:text-white text-sm">{activeSpot.address}</h3>
                                    </div>
                                    <button onClick={() => setActiveSpot(null)} className="text-zinc-400 hover:text-zinc-900 dark:hover:text-white p-1">{'\u2715'}</button>
                                </div>
                            </div>
                            <IntelligenceSidePanel
                                data={activeSpot}
                                onClose={() => setActiveSpot(null)}
                                variant="sheet"
                            />
                        </div>
                    </div>,
                    document.body
                )}

                {/* ── Aggregate Metrics ── */}
                <div className="grid grid-cols-2 md:grid-cols-4 gap-4 mt-8">
                    {metrics.map((m, i) => (
                        <div key={i} className="bg-white dark:bg-white/5 p-5 rounded-xl border border-zinc-200 dark:border-white/10 relative overflow-hidden hover:-translate-y-1 transition-transform duration-200">
                            <div className="measure-ticks measure-ticks-top absolute top-0 left-3 right-3 h-2.5"></div>
                            <div className="text-[10px] font-mono font-bold uppercase tracking-widest text-zinc-400 dark:text-gray-500 mb-1">
                                {m.label}
                            </div>
                            <div
                                ref={(el) => { metricRefs.current[i] = el; }}
                                data-target={m.value}
                                data-suffix={m.suffix}
                                data-prefix={m.prefix}
                                className={`text-3xl font-mono font-bold ${m.color} tracking-tight`}
                            >
                                {m.prefix}0{m.suffix}
                            </div>
                            <div className="mt-3 pt-2 border-t border-zinc-100 dark:border-white/5">
                                <span className={`permit-stamp ${m.stampClass}`}>{m.stamp}</span>
                            </div>
                            <div className="measure-ticks absolute bottom-0 left-3 right-3 h-2.5"></div>
                        </div>
                    ))}
                </div>
            </div>

            <style>{`
                @keyframes slideUp {
                    from { opacity: 0; transform: translate(-50%, 20px); }
                    to { opacity: 1; transform: translate(-50%, 0); }
                }
                @media (min-width: 768px) {
                    @keyframes slideUp {
                        from { opacity: 0; transform: translateY(20px); }
                        to { opacity: 1; transform: translateY(0); }
                    }
                }
            `}</style>
        </section>
    );
};

export default IntelligenceMap;
