{"version":3,"file":"NoaaLidarControl-BFReBpTO.cjs","sources":["../src/lib/stac/StacSearcher.ts","../src/lib/results/FootprintLayer.ts","../src/lib/utils/helpers.ts","../src/lib/utils/converters.ts","../src/lib/gui/PanelBuilder.ts","../src/lib/core/NoaaLidarControl.ts"],"sourcesContent":["import type { StacSearchResponse, StacItem, CacheEntry } from '../core/types';\nimport prebuiltIndex from '../../data/stac-index.json';\n\nconst NOAA_STAC_CATALOG =\n  'https://noaa-nos-coastal-lidar-pds.s3.us-east-1.amazonaws.com/entwine/stac/catalog.json';\nconst EPT_BASE_URL = 'https://noaa-nos-coastal-lidar-pds.s3.amazonaws.com/entwine/geoid18';\nconst CACHE_KEY = 'noaa-lidar-stac-items';\nconst DEFAULT_CACHE_DURATION = 7 * 24 * 60 * 60 * 1000; // 7 days\n\n/**\n * NOAA STAC Catalog link structure.\n */\ninterface CatalogLink {\n  rel: string;\n  href: string;\n  type?: string;\n  title?: string;\n}\n\n/**\n * NOAA STAC Catalog structure.\n */\ninterface StacCatalog {\n  type: string;\n  id: string;\n  stac_version: string;\n  description: string;\n  links: CatalogLink[];\n}\n\n/**\n * Cached item index entry.\n */\ninterface CachedItem {\n  id: string;\n  title?: string;\n  bbox: [number, number, number, number];\n  eptUrl: string;\n  pointCount?: number;\n}\n\n/**\n * Pre-built index structure.\n */\ninterface PrebuiltIndex {\n  version: number;\n  generatedAt: string;\n  itemCount: number;\n  items: CachedItem[];\n}\n\n/**\n * Progress callback for rebuild operation.\n */\nexport type RebuildProgressCallback = (progress: number, total: number) => void;\n\n/**\n * Client for searching NOAA Coastal LiDAR EPT data from AWS Open Data.\n *\n * Uses a pre-built index for instant searches. The index can be rebuilt\n * to fetch the latest data from the NOAA STAC catalog.\n *\n * @example\n * ```typescript\n * const searcher = new StacSearcher();\n * const results = await searcher.searchByExtent(\n *   [-80.0, 32.0, -79.0, 33.0],\n *   25\n * );\n * ```\n */\nexport class StacSearcher {\n  private _catalogUrl: string;\n  private _eptBaseUrl: string;\n  private _cacheDuration: number;\n  private _items: CachedItem[] | null = null;\n\n  /**\n   * Creates a new StacSearcher instance.\n   *\n   * @param catalogUrl - URL to the NOAA STAC catalog.json\n   * @param eptBaseUrl - Base URL for EPT data\n   * @param cacheDuration - Cache duration in milliseconds\n   */\n  constructor(\n    catalogUrl: string = NOAA_STAC_CATALOG,\n    eptBaseUrl: string = EPT_BASE_URL,\n    cacheDuration: number = DEFAULT_CACHE_DURATION\n  ) {\n    this._catalogUrl = catalogUrl;\n    this._eptBaseUrl = eptBaseUrl;\n    this._cacheDuration = cacheDuration;\n  }\n\n  /**\n   * Gets the STAC catalog URL.\n   */\n  get baseUrl(): string {\n    return this._catalogUrl;\n  }\n\n  /**\n   * Gets the EPT base URL.\n   */\n  get eptBaseUrl(): string {\n    return this._eptBaseUrl;\n  }\n\n  /**\n   * Validates and clamps a bounding box to valid geographic coordinates.\n   */\n  private _validateBbox(\n    bbox: [number, number, number, number]\n  ): [number, number, number, number] {\n    const safeValue = (val: number, defaultVal: number, min: number, max: number): number => {\n      if (!Number.isFinite(val)) {\n        return defaultVal;\n      }\n      return Math.max(min, Math.min(max, val));\n    };\n\n    return [\n      safeValue(bbox[0], -180, -180, 180), // west\n      safeValue(bbox[1], -90, -90, 90), // south\n      safeValue(bbox[2], 180, -180, 180), // east\n      safeValue(bbox[3], 90, -90, 90), // north\n    ];\n  }\n\n  /**\n   * Loads items from the pre-built index or localStorage cache.\n   */\n  private _loadItems(): CachedItem[] {\n    // Check localStorage cache first (for rebuilt index)\n    const cached = this._getFromCache();\n    if (cached) {\n      return cached;\n    }\n\n    // Use pre-built index\n    const index = prebuiltIndex as PrebuiltIndex;\n    return index.items;\n  }\n\n  /**\n   * Fetches fresh data from the NOAA STAC catalog.\n   * This is a slow operation that fetches all items (1000+).\n   *\n   * @param onProgress - Optional progress callback\n   * @returns Promise resolving to fresh items\n   */\n  async rebuildIndex(onProgress?: RebuildProgressCallback): Promise<CachedItem[]> {\n    // Fetch catalog.json\n    const catalogResponse = await fetch(this._catalogUrl);\n    if (!catalogResponse.ok) {\n      throw new Error(`Failed to fetch NOAA STAC catalog: ${catalogResponse.status} ${catalogResponse.statusText}`);\n    }\n\n    const catalog: StacCatalog = await catalogResponse.json();\n\n    // Get all item links\n    const itemLinks = catalog.links.filter(\n      (link) => link.rel === 'item' || link.rel === 'child'\n    );\n\n    const total = itemLinks.length;\n\n    // Fetch items in batches\n    const items: CachedItem[] = [];\n    const batchSize = 50;\n\n    for (let i = 0; i < itemLinks.length; i += batchSize) {\n      const batch = itemLinks.slice(i, i + batchSize);\n      const batchPromises = batch.map(async (link) => {\n        try {\n          const itemUrl = new URL(link.href, this._catalogUrl).href;\n          const response = await fetch(itemUrl);\n          if (!response.ok) {\n            console.warn(`Failed to fetch item: ${itemUrl}`);\n            return null;\n          }\n\n          const item: StacItem = await response.json();\n\n          // Extract mission ID\n          const missionMatch = item.id.match(/(\\d+)$/);\n          const missionId = missionMatch ? missionMatch[1] : item.id;\n\n          // Build EPT URL\n          const eptUrl = `${this._eptBaseUrl}/${missionId}/ept.json`;\n\n          // Get bbox\n          const bbox: [number, number, number, number] =\n            item.bbox.length === 6\n              ? [item.bbox[0], item.bbox[1], item.bbox[3], item.bbox[4]]\n              : (item.bbox as [number, number, number, number]);\n\n          return {\n            id: item.id,\n            title: item.properties?.title || item.id,\n            bbox,\n            eptUrl,\n            pointCount: item.properties?.['pc:count'] || item.properties?.['pointcloud:count'],\n          };\n        } catch (error) {\n          console.warn(`Error processing item ${link.href}:`, error);\n          return null;\n        }\n      });\n\n      const batchResults = await Promise.all(batchPromises);\n      items.push(...(batchResults.filter((item) => item !== null) as CachedItem[]));\n\n      // Report progress\n      if (onProgress) {\n        onProgress(Math.min(i + batchSize, total), total);\n      }\n    }\n\n    // Cache the result\n    this._saveToCache(items);\n    this._items = items;\n\n    return items;\n  }\n\n  /**\n   * Gets cached items from localStorage.\n   */\n  private _getFromCache(): CachedItem[] | null {\n    try {\n      const cached = localStorage.getItem(CACHE_KEY);\n      if (!cached) return null;\n\n      const entry: CacheEntry<CachedItem[]> = JSON.parse(cached);\n      if (Date.now() > entry.expiresAt) {\n        localStorage.removeItem(CACHE_KEY);\n        return null;\n      }\n\n      return entry.data;\n    } catch {\n      return null;\n    }\n  }\n\n  /**\n   * Saves items to localStorage cache.\n   */\n  private _saveToCache(items: CachedItem[]): void {\n    try {\n      const entry: CacheEntry<CachedItem[]> = {\n        data: items,\n        timestamp: Date.now(),\n        expiresAt: Date.now() + this._cacheDuration,\n      };\n      localStorage.setItem(CACHE_KEY, JSON.stringify(entry));\n    } catch (error) {\n      console.warn('Failed to cache NOAA STAC items:', error);\n    }\n  }\n\n  /**\n   * Clears the cached items (localStorage cache only, not pre-built index).\n   */\n  clearCache(): void {\n    try {\n      localStorage.removeItem(CACHE_KEY);\n    } catch {\n      // Ignore localStorage errors\n    }\n    this._items = null;\n  }\n\n  /**\n   * Ensures items are loaded.\n   */\n  private _ensureLoaded(): CachedItem[] {\n    if (this._items) {\n      return this._items;\n    }\n\n    this._items = this._loadItems();\n    return this._items;\n  }\n\n  /**\n   * Searches by bounding box.\n   *\n   * @param bbox - Bounding box [west, south, east, north]\n   * @param limit - Maximum results (default: 50)\n   * @returns Promise resolving to search results\n   */\n  async searchByExtent(\n    bbox: [number, number, number, number],\n    limit: number = 50\n  ): Promise<StacSearchResponse> {\n    const items = this._ensureLoaded();\n\n    // Validate bbox\n    const [west, south, east, north] = this._validateBbox(bbox);\n\n    // Filter items that intersect with bbox\n    const matching = items.filter((item) => {\n      const [iWest, iSouth, iEast, iNorth] = item.bbox;\n      // Check for bbox intersection\n      return !(iEast < west || iWest > east || iNorth < south || iSouth > north);\n    });\n\n    // Sort by point count (descending) and limit\n    const sorted = matching\n      .sort((a, b) => (b.pointCount ?? 0) - (a.pointCount ?? 0))\n      .slice(0, limit);\n\n    // Convert to StacItem format for compatibility\n    const features: StacItem[] = sorted.map((item) => ({\n      id: item.id,\n      type: 'Feature',\n      stac_version: '1.0.0',\n      geometry: {\n        type: 'Polygon',\n        coordinates: [[\n          [item.bbox[0], item.bbox[1]],\n          [item.bbox[2], item.bbox[1]],\n          [item.bbox[2], item.bbox[3]],\n          [item.bbox[0], item.bbox[3]],\n          [item.bbox[0], item.bbox[1]],\n        ]],\n      },\n      bbox: item.bbox,\n      properties: {\n        datetime: null,\n        title: item.title,\n        'pc:count': item.pointCount,\n      },\n      links: [],\n      assets: {\n        data: {\n          href: item.eptUrl,\n          type: 'application/json',\n          title: 'EPT Index',\n        },\n      },\n      collection: 'noaa-coastal-lidar',\n    }));\n\n    return {\n      type: 'FeatureCollection',\n      features,\n      numberMatched: matching.length,\n      numberReturned: features.length,\n    };\n  }\n\n  /**\n   * Gets the EPT URL for a STAC item.\n   *\n   * @param item - STAC item\n   * @returns EPT URL\n   */\n  async getEptUrl(item: StacItem): Promise<string> {\n    const asset = item.assets.data;\n    if (!asset) {\n      throw new Error(`No data asset found for item ${item.id}`);\n    }\n    return asset.href;\n  }\n\n  /**\n   * Alias for getEptUrl for backward compatibility.\n   * @deprecated Use getEptUrl instead\n   */\n  async getCopcUrl(item: StacItem): Promise<string> {\n    return this.getEptUrl(item);\n  }\n\n  /**\n   * Gets all available items.\n   */\n  async getAllItems(): Promise<CachedItem[]> {\n    return this._ensureLoaded();\n  }\n\n  /**\n   * Gets the total count of items.\n   */\n  async getCount(): Promise<number> {\n    return this._ensureLoaded().length;\n  }\n\n  /**\n   * Gets information about the current index.\n   */\n  getIndexInfo(): { source: 'prebuilt' | 'cached'; itemCount: number; generatedAt?: string } {\n    const cached = this._getFromCache();\n    if (cached) {\n      return {\n        source: 'cached',\n        itemCount: cached.length,\n      };\n    }\n\n    const index = prebuiltIndex as PrebuiltIndex;\n    return {\n      source: 'prebuilt',\n      itemCount: index.itemCount,\n      generatedAt: index.generatedAt,\n    };\n  }\n}\n","import type { Map as MapLibreMap, GeoJSONSource } from 'maplibre-gl';\nimport type { UnifiedSearchItem } from '../core/types';\nimport type { Feature, FeatureCollection } from 'geojson';\n\n/**\n * Options for configuring the FootprintLayer\n */\nexport interface FootprintLayerOptions {\n  /** Fill color for unselected footprints */\n  fillColor?: string;\n  /** Fill color for selected footprints */\n  selectedFillColor?: string;\n  /** Outline color */\n  outlineColor?: string;\n  /** Outline width in pixels */\n  outlineWidth?: number;\n}\n\nconst DEFAULT_OPTIONS: Required<FootprintLayerOptions> = {\n  fillColor: 'rgba(0, 100, 200, 0.15)',\n  selectedFillColor: 'rgba(0, 150, 255, 0.4)',\n  outlineColor: 'rgba(0, 100, 200, 1)',\n  outlineWidth: 2,\n};\n\n/**\n * Manages display of LiDAR item footprints on the map.\n * Shows item boundaries with selection highlighting.\n *\n * @example\n * ```typescript\n * const footprintLayer = new FootprintLayer(map);\n * footprintLayer.setItems(searchResults);\n * footprintLayer.setSelectedIds(new Set(['item-1', 'item-2']));\n * footprintLayer.zoomToFootprints();\n * ```\n */\nexport class FootprintLayer {\n  private _map: MapLibreMap;\n  private _options: Required<FootprintLayerOptions>;\n  private _sourceId = 'noaa-lidar-footprints-source';\n  private _fillLayerId = 'noaa-lidar-footprints-fill';\n  private _outlineLayerId = 'noaa-lidar-footprints-outline';\n  private _selectedLayerId = 'noaa-lidar-footprints-selected';\n  private _items: UnifiedSearchItem[] = [];\n  private _selectedIds: Set<string> = new Set();\n  private _clickHandler?: (itemId: string) => void;\n  private _layersInitialized: boolean = false;\n\n  /**\n   * Creates a new FootprintLayer instance.\n   *\n   * @param map - MapLibre GL map instance\n   * @param options - Configuration options\n   */\n  constructor(map: MapLibreMap, options?: FootprintLayerOptions) {\n    this._map = map;\n    this._options = { ...DEFAULT_OPTIONS, ...options };\n\n    // Track if this is the first style load (to distinguish from style changes)\n    let isFirstStyleLoad = true;\n\n    // Initialize layers when map style is ready\n    const initLayers = () => {\n      if (!this._layersInitialized) {\n        this._initLayers();\n        this._setupInteraction();\n        // If items were set before init, update now\n        if (this._items.length > 0) {\n          this._updateLayer();\n        }\n      }\n    };\n\n    // Handle all style loads (initial and changes)\n    this._map.on('style.load', () => {\n      if (isFirstStyleLoad) {\n        // First style load - just initialize\n        isFirstStyleLoad = false;\n        initLayers();\n      } else {\n        // Style change - layers were removed, need to re-add\n        this._layersInitialized = false;\n        this._initLayers();\n        this._setupInteraction();\n        if (this._items.length > 0) {\n          this._updateLayer();\n        }\n      }\n    });\n\n    // If style is already loaded, initialize immediately\n    if (this._map.isStyleLoaded()) {\n      isFirstStyleLoad = false;\n      initLayers();\n    }\n  }\n\n  /**\n   * Sets the items to display as footprints.\n   *\n   * @param items - Unified search items to display\n   */\n  setItems(items: UnifiedSearchItem[]): void {\n    this._items = items;\n\n    // Try to render immediately, or poll until ready\n    this._tryRender();\n  }\n\n  /**\n   * Attempts to render footprints, polling if style isn't ready yet.\n   */\n  private _tryRender(attempts: number = 0): void {\n    // If layers are initialized, update immediately\n    if (this._layersInitialized && this._map.getSource(this._sourceId)) {\n      this._updateLayer();\n      return;\n    }\n\n    // If style is loaded, initialize layers and update\n    if (this._map.isStyleLoaded()) {\n      this._initLayers();\n      this._setupInteraction();\n      this._updateLayer();\n      return;\n    }\n\n    // Style not loaded yet - poll until ready (max ~2 seconds)\n    if (attempts < 120) {\n      requestAnimationFrame(() => this._tryRender(attempts + 1));\n    }\n  }\n\n  /**\n   * Gets the currently displayed items.\n   */\n  getItems(): UnifiedSearchItem[] {\n    return [...this._items];\n  }\n\n  /**\n   * Sets which items are selected (highlighted).\n   *\n   * @param ids - Set of selected item IDs\n   */\n  setSelectedIds(ids: Set<string>): void {\n    this._selectedIds = ids;\n    this._updateSelectedFilter();\n  }\n\n  /**\n   * Gets the currently selected item IDs.\n   */\n  getSelectedIds(): Set<string> {\n    return new Set(this._selectedIds);\n  }\n\n  /**\n   * Registers a click handler for footprint clicks.\n   *\n   * @param handler - Function called with item ID when a footprint is clicked\n   */\n  onClick(handler: (itemId: string) => void): void {\n    this._clickHandler = handler;\n  }\n\n  /**\n   * Clears all footprints from the map.\n   */\n  clear(): void {\n    this._items = [];\n    this._selectedIds.clear();\n    this._clearLayer();\n  }\n\n  /**\n   * Zooms the map to fit all footprints.\n   *\n   * @param padding - Padding in pixels (default: 50)\n   * @param duration - Animation duration in ms (default: 1000)\n   */\n  zoomToFootprints(padding: number = 50, duration: number = 1000): void {\n    if (this._items.length === 0) return;\n\n    let minX = Infinity,\n      minY = Infinity;\n    let maxX = -Infinity,\n      maxY = -Infinity;\n\n    for (const item of this._items) {\n      const [west, south, east, north] = item.bbox;\n      minX = Math.min(minX, west);\n      minY = Math.min(minY, south);\n      maxX = Math.max(maxX, east);\n      maxY = Math.max(maxY, north);\n    }\n\n    this._map.fitBounds(\n      [\n        [minX, minY],\n        [maxX, maxY],\n      ],\n      {\n        padding,\n        duration,\n      }\n    );\n  }\n\n  /**\n   * Zooms to a specific item.\n   *\n   * @param itemId - The item ID to zoom to\n   * @param padding - Padding in pixels (default: 50)\n   */\n  zoomToItem(itemId: string, padding: number = 50): void {\n    const item = this._items.find((i) => i.id === itemId);\n    if (!item) return;\n\n    const [west, south, east, north] = item.bbox;\n    this._map.fitBounds(\n      [\n        [west, south],\n        [east, north],\n      ],\n      {\n        padding,\n        duration: 500,\n      }\n    );\n  }\n\n  /**\n   * Shows/hides the footprint layers.\n   *\n   * @param visible - Whether layers should be visible\n   */\n  setVisibility(visible: boolean): void {\n    const visibility = visible ? 'visible' : 'none';\n    if (this._map.getLayer(this._fillLayerId)) {\n      this._map.setLayoutProperty(this._fillLayerId, 'visibility', visibility);\n    }\n    if (this._map.getLayer(this._selectedLayerId)) {\n      this._map.setLayoutProperty(this._selectedLayerId, 'visibility', visibility);\n    }\n    if (this._map.getLayer(this._outlineLayerId)) {\n      this._map.setLayoutProperty(this._outlineLayerId, 'visibility', visibility);\n    }\n  }\n\n  /**\n   * Cleans up resources and removes layers from the map.\n   */\n  destroy(): void {\n    this._removeLayers();\n    this._clickHandler = undefined;\n  }\n\n  private _initLayers(): void {\n    // Add source if it doesn't exist\n    if (!this._map.getSource(this._sourceId)) {\n      this._map.addSource(this._sourceId, {\n        type: 'geojson',\n        data: { type: 'FeatureCollection', features: [] },\n      });\n    }\n\n    // Add fill layer (unselected items) - show all by default\n    if (!this._map.getLayer(this._fillLayerId)) {\n      this._map.addLayer({\n        id: this._fillLayerId,\n        type: 'fill',\n        source: this._sourceId,\n        paint: {\n          'fill-color': this._options.fillColor,\n        },\n      });\n    }\n\n    // Add selected fill layer - initially hidden (no features selected)\n    if (!this._map.getLayer(this._selectedLayerId)) {\n      this._map.addLayer({\n        id: this._selectedLayerId,\n        type: 'fill',\n        source: this._sourceId,\n        paint: {\n          'fill-color': this._options.selectedFillColor,\n        },\n        filter: ['==', ['get', 'id'], ''],\n      });\n    }\n\n    // Add outline layer\n    if (!this._map.getLayer(this._outlineLayerId)) {\n      this._map.addLayer({\n        id: this._outlineLayerId,\n        type: 'line',\n        source: this._sourceId,\n        paint: {\n          'line-color': this._options.outlineColor,\n          'line-width': this._options.outlineWidth,\n        },\n      });\n    }\n\n    this._layersInitialized = true;\n  }\n\n  private _setupInteraction(): void {\n    // Hover effect\n    this._map.on('mouseenter', this._fillLayerId, () => {\n      this._map.getCanvas().style.cursor = 'pointer';\n    });\n\n    this._map.on('mouseleave', this._fillLayerId, () => {\n      this._map.getCanvas().style.cursor = '';\n    });\n\n    this._map.on('mouseenter', this._selectedLayerId, () => {\n      this._map.getCanvas().style.cursor = 'pointer';\n    });\n\n    this._map.on('mouseleave', this._selectedLayerId, () => {\n      this._map.getCanvas().style.cursor = '';\n    });\n\n    // Click handling\n    this._map.on('click', this._fillLayerId, (e) => {\n      if (e.features && e.features.length > 0 && this._clickHandler) {\n        const itemId = e.features[0].properties?.id;\n        if (itemId) {\n          this._clickHandler(itemId);\n        }\n      }\n    });\n\n    this._map.on('click', this._selectedLayerId, (e) => {\n      if (e.features && e.features.length > 0 && this._clickHandler) {\n        const itemId = e.features[0].properties?.id;\n        if (itemId) {\n          this._clickHandler(itemId);\n        }\n      }\n    });\n  }\n\n  private _updateLayer(): void {\n    // Wait for layers to be initialized\n    if (!this._layersInitialized) {\n      return;\n    }\n\n    // If source was removed (e.g., style change), re-initialize\n    if (!this._map.getSource(this._sourceId)) {\n      this._layersInitialized = false;\n      this._initLayers();\n      this._setupInteraction();\n    }\n\n    // Use bbox to create rectangular footprints\n    const features: Feature[] = this._items.map((item) => {\n      const [west, south, east, north] = item.bbox;\n      return {\n        type: 'Feature',\n        properties: {\n          id: item.id,\n          datetime: item.properties.datetime,\n          pointCount: item.properties.pointCount,\n          sourceType: item.sourceType,\n        },\n        geometry: {\n          type: 'Polygon',\n          coordinates: [[\n            [west, south],\n            [east, south],\n            [east, north],\n            [west, north],\n            [west, south],\n          ]],\n        },\n      };\n    });\n\n    const data: FeatureCollection = {\n      type: 'FeatureCollection',\n      features,\n    };\n\n    const source = this._map.getSource(this._sourceId) as GeoJSONSource;\n    if (source) {\n      source.setData(data);\n    }\n\n    // Update filters\n    this._updateSelectedFilter();\n  }\n\n  private _updateSelectedFilter(): void {\n    const selectedArray = Array.from(this._selectedIds);\n\n    // Update fill layer - show items not in selectedArray\n    if (this._map.getLayer(this._fillLayerId)) {\n      if (selectedArray.length === 0) {\n        // Show all features when nothing selected\n        this._map.setFilter(this._fillLayerId, null);\n      } else {\n        this._map.setFilter(this._fillLayerId, [\n          '!',\n          ['in', ['get', 'id'], ['literal', selectedArray]],\n        ]);\n      }\n    }\n\n    // Update selected filter - show items in selectedArray\n    if (this._map.getLayer(this._selectedLayerId)) {\n      if (selectedArray.length === 0) {\n        // Hide all when nothing selected\n        this._map.setFilter(this._selectedLayerId, ['==', ['get', 'id'], '']);\n      } else {\n        this._map.setFilter(this._selectedLayerId, [\n          'in',\n          ['get', 'id'],\n          ['literal', selectedArray],\n        ]);\n      }\n    }\n  }\n\n  private _clearLayer(): void {\n    const source = this._map.getSource(this._sourceId) as GeoJSONSource;\n    if (source) {\n      source.setData({ type: 'FeatureCollection', features: [] });\n    }\n  }\n\n  private _removeLayers(): void {\n    // Remove layers\n    [this._outlineLayerId, this._selectedLayerId, this._fillLayerId].forEach((id) => {\n      if (this._map.getLayer(id)) {\n        this._map.removeLayer(id);\n      }\n    });\n\n    // Remove source\n    if (this._map.getSource(this._sourceId)) {\n      this._map.removeSource(this._sourceId);\n    }\n  }\n}\n","/**\n * Clamps a value between a minimum and maximum.\n *\n * @param value - The value to clamp\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns The clamped value\n */\nexport function clamp(value: number, min: number, max: number): number {\n  return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Formats a number for display with appropriate precision.\n *\n * @param value - The value to format\n * @param decimals - Number of decimal places (default: 2)\n * @returns Formatted string\n */\nexport function formatNumber(value: number, decimals: number = 2): string {\n  if (value >= 1_000_000) {\n    return `${(value / 1_000_000).toFixed(1)}M`;\n  }\n  if (value >= 1_000) {\n    return `${(value / 1_000).toFixed(1)}K`;\n  }\n  return value.toFixed(decimals);\n}\n\n/**\n * Formats a point count for display.\n *\n * @param count - The point count\n * @returns Formatted string like \"11.4M pts\" or \"500K pts\"\n */\nexport function formatPointCount(count: number | undefined): string {\n  if (count === undefined || count === null) return '';\n  if (count >= 1_000_000) {\n    return `${(count / 1_000_000).toFixed(1)}M pts`;\n  }\n  if (count >= 1_000) {\n    return `${(count / 1_000).toFixed(0)}K pts`;\n  }\n  return `${count} pts`;\n}\n\n/**\n * Formats a bounding box for display.\n *\n * @param bbox - Bounding box [west, south, east, north]\n * @returns Formatted string\n */\nexport function formatBbox(bbox: [number, number, number, number]): string {\n  const [west, south, east, north] = bbox;\n  return `${west.toFixed(2)}, ${south.toFixed(2)} to ${east.toFixed(2)}, ${north.toFixed(2)}`;\n}\n\n/**\n * Generates a unique ID with optional prefix.\n *\n * @param prefix - Optional prefix\n * @returns Unique ID string\n */\nexport function generateId(prefix: string = 'id'): string {\n  return `${prefix}-${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Debounces a function call.\n *\n * @param fn - Function to debounce\n * @param delay - Delay in milliseconds\n * @returns Debounced function\n */\nexport function debounce<T extends (...args: unknown[]) => void>(\n  fn: T,\n  delay: number\n): (...args: Parameters<T>) => void {\n  let timeoutId: ReturnType<typeof setTimeout>;\n  return (...args: Parameters<T>) => {\n    clearTimeout(timeoutId);\n    timeoutId = setTimeout(() => fn(...args), delay);\n  };\n}\n\n/**\n * Throttles a function call.\n *\n * @param fn - Function to throttle\n * @param limit - Minimum time between calls in milliseconds\n * @returns Throttled function\n */\nexport function throttle<T extends (...args: unknown[]) => void>(\n  fn: T,\n  limit: number\n): (...args: Parameters<T>) => void {\n  let lastRun = 0;\n  return (...args: Parameters<T>) => {\n    const now = Date.now();\n    if (now - lastRun >= limit) {\n      lastRun = now;\n      fn(...args);\n    }\n  };\n}\n\n/**\n * Creates a CSS class name string from multiple class names.\n *\n * @param classNames - Class names (strings or falsy values)\n * @returns Combined class name string\n */\nexport function classNames(\n  ...classNames: (string | undefined | null | false)[]\n): string {\n  return classNames.filter(Boolean).join(' ');\n}\n\n/**\n * Truncates a string to a maximum length with ellipsis.\n *\n * @param str - String to truncate\n * @param maxLength - Maximum length\n * @returns Truncated string\n */\nexport function truncate(str: string, maxLength: number): string {\n  if (str.length <= maxLength) return str;\n  return str.substring(0, maxLength - 3) + '...';\n}\n\n/**\n * Extracts a short name from a STAC item ID.\n *\n * @param itemId - The full item ID\n * @param maxLength - Maximum length (default: 30)\n * @returns Shortened name\n */\nexport function getItemShortName(itemId: string, maxLength: number = 30): string {\n  // Remove common prefixes like DigitalCoast_mission_\n  let name = itemId.replace(/^DigitalCoast_mission_/, 'Mission ');\n  return truncate(name, maxLength);\n}\n\n/**\n * Extracts metadata string from a STAC item for display.\n *\n * @param item - STAC item\n * @returns Metadata string (point count and/or date)\n */\nexport function getItemMetadata(item: {\n  properties: {\n    datetime?: string | null;\n    start_datetime?: string;\n    end_datetime?: string;\n    'pointcloud:count'?: number;\n    'pc:count'?: number;\n    [key: string]: unknown;\n  };\n  bbox?: number[];\n}): string {\n  const parts: string[] = [];\n\n  // Try to get point count (check both property names)\n  const pointCount =\n    (item.properties['pc:count'] as number | undefined) ??\n    (item.properties['pointcloud:count'] as number | undefined);\n  if (pointCount !== undefined && pointCount !== null) {\n    parts.push(formatPointCount(pointCount));\n  }\n\n  // Try to get datetime (check datetime, start_datetime, end_datetime)\n  const datetime =\n    item.properties.datetime ||\n    item.properties.start_datetime ||\n    item.properties.end_datetime;\n  if (datetime) {\n    try {\n      const date = new Date(datetime);\n      const year = date.getFullYear();\n      if (!isNaN(year)) {\n        parts.push(String(year));\n      }\n    } catch {\n      // Ignore date parsing errors\n    }\n  }\n\n  return parts.length > 0 ? parts.join(' • ') : 'LiDAR Dataset';\n}\n\n/**\n * Extracts bounding box from a GeoJSON geometry.\n *\n * @param geometry - GeoJSON geometry\n * @returns Bounding box [west, south, east, north]\n */\nexport function getBboxFromGeometry(\n  geometry: GeoJSON.Geometry\n): [number, number, number, number] {\n  let minX = Infinity,\n    minY = Infinity;\n  let maxX = -Infinity,\n    maxY = -Infinity;\n\n  const processCoordinates = (coords: number[]) => {\n    minX = Math.min(minX, coords[0]);\n    minY = Math.min(minY, coords[1]);\n    maxX = Math.max(maxX, coords[0]);\n    maxY = Math.max(maxY, coords[1]);\n  };\n\n  const traverse = (coords: unknown) => {\n    if (Array.isArray(coords)) {\n      if (typeof coords[0] === 'number') {\n        processCoordinates(coords as number[]);\n      } else {\n        coords.forEach(traverse);\n      }\n    }\n  };\n\n  if ('coordinates' in geometry) {\n    traverse(geometry.coordinates);\n  }\n\n  return [minX, minY, maxX, maxY];\n}\n","import type { StacItem, EptFeature, UnifiedSearchItem } from '../core/types';\nimport { getBboxFromGeometry, formatPointCount } from './helpers';\n\n/**\n * Converts a STAC item to a unified search item.\n *\n * @param item - STAC item from NOAA Coastal LiDAR catalog\n * @returns Unified search item\n */\nexport function stacToUnified(item: StacItem): UnifiedSearchItem {\n  // Handle both 4-element and 6-element bboxes\n  const bbox: [number, number, number, number] =\n    item.bbox.length === 6\n      ? [item.bbox[0], item.bbox[1], item.bbox[3], item.bbox[4]]\n      : (item.bbox as [number, number, number, number]);\n\n  // Extract point count (both property names are used)\n  const pointCount =\n    (item.properties['pc:count'] as number | undefined) ??\n    (item.properties['pointcloud:count'] as number | undefined);\n\n  // Clean up item name - remove NOAA prefixes\n  const name =\n    (item.properties.title as string | undefined) ??\n    item.id.replace(/^DigitalCoast_mission_/, 'Mission ');\n\n  return {\n    id: item.id,\n    type: 'Feature',\n    geometry: item.geometry,\n    bbox,\n    properties: {\n      name,\n      pointCount,\n      datetime: item.properties.datetime,\n    },\n    sourceType: 'ept', // NOAA data is always EPT\n    originalItem: item,\n  };\n}\n\n/**\n * Converts an EPT feature to a unified search item.\n *\n * @param feature - EPT feature from boundaries\n * @returns Unified search item\n */\nexport function eptToUnified(feature: EptFeature): UnifiedSearchItem {\n  const bbox: [number, number, number, number] =\n    feature.bbox ?? (getBboxFromGeometry(feature.geometry) as [number, number, number, number]);\n\n  return {\n    id: feature.properties.name, // Use name as ID\n    type: 'Feature',\n    geometry: feature.geometry,\n    bbox,\n    properties: {\n      name: feature.properties.name,\n      pointCount: feature.properties.count,\n      url: feature.properties.url,\n      datetime: null, // EPT doesn't have datetime\n    },\n    sourceType: 'ept',\n    originalItem: feature,\n  };\n}\n\n/**\n * Extracts the short display name from a unified item.\n *\n * @param item - Unified search item\n * @param maxLength - Maximum length (default: 30)\n * @returns Short display name\n */\nexport function getUnifiedItemName(item: UnifiedSearchItem, maxLength: number = 30): string {\n  let name = item.properties.name;\n  if (name.length > maxLength) {\n    return name.substring(0, maxLength - 3) + '...';\n  }\n  return name;\n}\n\n/**\n * Gets metadata string for a unified item.\n *\n * @param item - Unified search item\n * @returns Metadata string\n */\nexport function getUnifiedItemMetadata(item: UnifiedSearchItem): string {\n  const parts: string[] = [];\n\n  if (item.properties.pointCount) {\n    parts.push(formatPointCount(item.properties.pointCount));\n  }\n\n  if (item.properties.datetime) {\n    try {\n      const year = new Date(item.properties.datetime).getFullYear();\n      if (!isNaN(year)) parts.push(String(year));\n    } catch {\n      // Ignore date parsing errors\n    }\n  }\n\n  // Always EPT for NOAA data\n  parts.push('EPT');\n\n  return parts.join(' \\u2022 '); // Unicode bullet\n}\n","import type { UnifiedSearchItem, NoaaLidarState } from '../core/types';\nimport { formatPointCount, getItemShortName, formatBbox, getUnifiedItemMetadata } from '../utils';\nimport {\n  getClassificationName,\n  COLORMAP_NAMES,\n  COLORMAP_LABELS,\n  getColormap,\n} from 'maplibre-gl-lidar';\nimport type { ColormapName, ColorRangeConfig } from 'maplibre-gl-lidar';\n\n/**\n * ASPRS Standard LiDAR Classification Colors (RGB)\n */\nconst CLASSIFICATION_COLORS: { [key: number]: [number, number, number] } = {\n  0: [128, 128, 128], // Never Classified (gray)\n  1: [128, 128, 128], // Unassigned (gray)\n  2: [139, 90, 43], // Ground (brown)\n  3: [34, 139, 34], // Low Vegetation (light green)\n  4: [0, 128, 0], // Medium Vegetation (medium green)\n  5: [0, 100, 0], // High Vegetation (dark green)\n  6: [255, 165, 0], // Building (orange)\n  7: [255, 0, 0], // Low Point (Noise) (red)\n  8: [128, 128, 128], // Reserved (gray)\n  9: [0, 0, 255], // Water (blue)\n  10: [255, 255, 0], // Rail (yellow)\n  11: [128, 128, 128], // Road Surface (gray)\n  12: [128, 128, 128], // Reserved (gray)\n  13: [255, 255, 0], // Wire - Guard (yellow)\n  14: [255, 255, 0], // Wire - Conductor (yellow)\n  15: [128, 0, 128], // Transmission Tower (purple)\n  16: [255, 255, 0], // Wire - Connector (yellow)\n  17: [192, 192, 192], // Bridge Deck (light gray)\n  18: [255, 69, 0], // High Noise (orange-red)\n  19: [160, 82, 45], // Overhead Structure (sienna)\n  20: [173, 216, 230], // Ignored Ground (light blue)\n  21: [245, 245, 220], // Snow (beige)\n  22: [210, 180, 140], // Temporal Exclusion (tan)\n};\n\n/**\n * Callbacks for panel interactions\n */\nexport interface PanelCallbacks {\n  onSearchByExtent: () => void;\n  onStartDrawing: () => void;\n  onStopDrawing: () => void;\n  onSearchByDrawn: () => void;\n  onClearDrawn: () => void;\n  onItemSelect: (item: UnifiedSearchItem) => void;\n  onItemLoad: (item: UnifiedSearchItem) => void;\n  onLoadSelected: () => void;\n  onCopySignedUrls: () => void;\n  onDownloadSelected: () => void;\n  onClearResults: () => void;\n  onUnloadItem: (itemId: string) => void;\n  onClearLoaded: () => void;\n  onPointSizeChange: (size: number) => void;\n  onOpacityChange: (opacity: number) => void;\n  onColorSchemeChange: (scheme: string) => void;\n  onZOffsetChange: (offset: number) => void;\n  onPickableChange: (pickable: boolean) => void;\n  onElevationRangeChange: (range: [number, number] | null) => void;\n  onClassificationToggle: (classificationCode: number, visible: boolean) => void;\n  onClassificationShowAll: () => void;\n  onClassificationHideAll: () => void;\n  onColormapChange: (colormap: ColormapName) => void;\n  onColorRangeChange: (config: ColorRangeConfig) => void;\n  onShowMetadata?: (itemId: string) => void;\n  onCrossSectionPanel?: () => HTMLElement | null;\n  onRebuildIndex?: (onProgress: (progress: number, total: number) => void) => Promise<void>;\n  getIndexInfo?: () => { source: string; itemCount: number; generatedAt?: string };\n}\n\n/**\n * Builds and manages the control panel UI.\n */\nexport class PanelBuilder {\n  private _callbacks: PanelCallbacks;\n  private _state: NoaaLidarState;\n  private _container: HTMLElement | null = null;\n\n  // Section references for updates\n  private _searchSection: HTMLElement | null = null;\n  private _resultsSection: HTMLElement | null = null;\n  private _loadedSection: HTMLElement | null = null;\n  private _vizSection: HTMLElement | null = null;\n  private _crossSectionSection: HTMLElement | null = null;\n\n  // New UI element references for point picking, elevation filter, and classification\n  private _pickableCheckbox: HTMLInputElement | null = null;\n  private _elevationCheckbox: HTMLInputElement | null = null;\n  private _elevationSliderContainer: HTMLElement | null = null;\n  private _elevationRangeValue: HTMLElement | null = null;\n  private _elevationMinInput: HTMLInputElement | null = null;\n  private _elevationMaxInput: HTMLInputElement | null = null;\n  private _elevationTrackFill: HTMLElement | null = null;\n  private _classificationLegendContainer: HTMLElement | null = null;\n  private _classificationCheckboxes: Map<number, HTMLInputElement> = new Map();\n\n  // Colormap and color range UI elements\n  private _colormapContainer: HTMLElement | null = null;\n  private _colormapSelect: HTMLSelectElement | null = null;\n  private _colorbarCanvas: HTMLCanvasElement | null = null;\n  private _colorbarMinLabel: HTMLElement | null = null;\n  private _colorbarMaxLabel: HTMLElement | null = null;\n  private _colorRangeModePercentile: HTMLInputElement | null = null;\n  private _colorRangeModeAbsolute: HTMLInputElement | null = null;\n  private _percentileLowSlider: HTMLInputElement | null = null;\n  private _percentileHighSlider: HTMLInputElement | null = null;\n  private _absoluteMinSlider: HTMLInputElement | null = null;\n  private _absoluteMaxSlider: HTMLInputElement | null = null;\n  private _percentileRangeValue: HTMLElement | null = null;\n  private _absoluteRangeValue: HTMLElement | null = null;\n  private _percentileTrackFill: HTMLElement | null = null;\n  private _absoluteTrackFill: HTMLElement | null = null;\n  private _percentileSliderContainer: HTMLElement | null = null;\n  private _absoluteSliderContainer: HTMLElement | null = null;\n  private _currentColormap: ColormapName = 'viridis';\n  private _currentColorRangeConfig: ColorRangeConfig = {\n    mode: 'percentile',\n    percentileLow: 2,\n    percentileHigh: 98,\n  };\n  private _dataBounds: { min: number; max: number } = { min: 0, max: 100 };\n  private _computedBounds: { min: number; max: number } | null = null;\n\n  constructor(callbacks: PanelCallbacks, state: NoaaLidarState) {\n    this._callbacks = callbacks;\n    this._state = state;\n  }\n\n  /**\n   * Builds and returns the panel content element.\n   */\n  build(): HTMLElement {\n    this._container = document.createElement('div');\n    this._container.className = 'noaa-lidar-panel-content';\n\n    // Search section\n    this._searchSection = this._buildSearchSection();\n    this._container.appendChild(this._searchSection);\n\n    // Results section\n    this._resultsSection = this._buildResultsSection();\n    this._container.appendChild(this._resultsSection);\n\n    // Loaded datasets section\n    this._loadedSection = this._buildLoadedSection();\n    this._container.appendChild(this._loadedSection);\n\n    // Visualization section\n    this._vizSection = this._buildVisualizationSection();\n    this._container.appendChild(this._vizSection);\n\n    // Cross-section section (embedded from LidarControl)\n    this._crossSectionSection = this._buildCrossSectionSection();\n    if (this._crossSectionSection) {\n      this._container.appendChild(this._crossSectionSection);\n    }\n\n    return this._container;\n  }\n\n  /**\n   * Updates the panel with new state.\n   */\n  updateState(state: NoaaLidarState): void {\n    this._state = state;\n\n    // Update search section\n    if (this._searchSection) {\n      this._updateSearchSection();\n    }\n\n    // Update results section\n    if (this._resultsSection) {\n      this._updateResultsSection();\n    }\n\n    // Update loaded section\n    if (this._loadedSection) {\n      this._updateLoadedSection();\n    }\n\n    // Update visualization section (sync sliders with lidar control state)\n    if (this._vizSection) {\n      this._updateVisualizationSection();\n    }\n  }\n\n  private _buildSearchSection(): HTMLElement {\n    const section = document.createElement('div');\n    section.className = 'noaa-lidar-section noaa-lidar-search-section';\n\n    const header = document.createElement('div');\n    header.className = 'noaa-lidar-section-header';\n    header.textContent = 'Search';\n    section.appendChild(header);\n\n    const content = document.createElement('div');\n    content.className = 'noaa-lidar-section-content';\n\n    // Search buttons row\n    const buttonsRow = document.createElement('div');\n    buttonsRow.className = 'noaa-lidar-button-row';\n\n    const extentBtn = document.createElement('button');\n    extentBtn.className = 'noaa-lidar-btn noaa-lidar-btn-primary';\n    extentBtn.textContent = 'Search Map Extent';\n    extentBtn.addEventListener('click', () => this._callbacks.onSearchByExtent());\n    buttonsRow.appendChild(extentBtn);\n\n    const drawBtn = document.createElement('button');\n    drawBtn.className = 'noaa-lidar-btn noaa-lidar-btn-secondary';\n    drawBtn.id = 'noaa-lidar-draw-btn';\n    drawBtn.textContent = 'Draw Rectangle';\n    drawBtn.addEventListener('click', () => {\n      if (this._state.isDrawing) {\n        this._callbacks.onStopDrawing();\n      } else {\n        this._callbacks.onStartDrawing();\n      }\n    });\n    buttonsRow.appendChild(drawBtn);\n\n    content.appendChild(buttonsRow);\n\n    // Drawn bbox info\n    const bboxInfo = document.createElement('div');\n    bboxInfo.className = 'noaa-lidar-bbox-info';\n    bboxInfo.id = 'noaa-lidar-bbox-info';\n    bboxInfo.style.display = 'none';\n    content.appendChild(bboxInfo);\n\n    // Drawn bbox actions\n    const drawnActions = document.createElement('div');\n    drawnActions.className = 'noaa-lidar-button-row';\n    drawnActions.id = 'noaa-lidar-drawn-actions';\n    drawnActions.style.display = 'none';\n\n    const searchDrawnBtn = document.createElement('button');\n    searchDrawnBtn.className = 'noaa-lidar-btn noaa-lidar-btn-primary';\n    searchDrawnBtn.textContent = 'Search Drawn Area';\n    searchDrawnBtn.addEventListener('click', () => this._callbacks.onSearchByDrawn());\n    drawnActions.appendChild(searchDrawnBtn);\n\n    const clearDrawnBtn = document.createElement('button');\n    clearDrawnBtn.className = 'noaa-lidar-btn noaa-lidar-btn-danger';\n    clearDrawnBtn.textContent = 'Clear';\n    clearDrawnBtn.addEventListener('click', () => this._callbacks.onClearDrawn());\n    drawnActions.appendChild(clearDrawnBtn);\n\n    content.appendChild(drawnActions);\n\n    // Index info and refresh\n    const indexRow = document.createElement('div');\n    indexRow.className = 'noaa-lidar-index-row';\n\n    const indexInfo = document.createElement('span');\n    indexInfo.className = 'noaa-lidar-index-info';\n    indexInfo.id = 'noaa-lidar-index-info';\n    if (this._callbacks.getIndexInfo) {\n      const info = this._callbacks.getIndexInfo();\n      indexInfo.textContent = `${info.itemCount} datasets`;\n      indexInfo.title = info.generatedAt\n        ? `Index generated: ${new Date(info.generatedAt).toLocaleDateString()}`\n        : 'Using cached index';\n    }\n    indexRow.appendChild(indexInfo);\n\n    const refreshBtn = document.createElement('button');\n    refreshBtn.className = 'noaa-lidar-btn-link';\n    refreshBtn.textContent = 'Refresh Index';\n    refreshBtn.title = 'Fetch latest data from NOAA (takes a few minutes)';\n    refreshBtn.addEventListener('click', async () => {\n      if (this._callbacks.onRebuildIndex) {\n        refreshBtn.disabled = true;\n        refreshBtn.textContent = 'Refreshing...';\n        indexInfo.textContent = '0%';\n\n        try {\n          await this._callbacks.onRebuildIndex((progress, total) => {\n            const pct = Math.round((progress / total) * 100);\n            indexInfo.textContent = `${pct}%`;\n          });\n\n          if (this._callbacks.getIndexInfo) {\n            const info = this._callbacks.getIndexInfo();\n            indexInfo.textContent = `${info.itemCount} datasets`;\n          }\n          refreshBtn.textContent = 'Refresh Index';\n        } catch (err) {\n          indexInfo.textContent = 'Error';\n          refreshBtn.textContent = 'Retry';\n        }\n        refreshBtn.disabled = false;\n      }\n    });\n    indexRow.appendChild(refreshBtn);\n\n    content.appendChild(indexRow);\n\n    // Loading indicator\n    const loading = document.createElement('div');\n    loading.className = 'noaa-lidar-loading';\n    loading.id = 'noaa-lidar-search-loading';\n    loading.style.display = 'none';\n    loading.innerHTML = '<span class=\"noaa-lidar-spinner\"></span> Searching...';\n    content.appendChild(loading);\n\n    // Error message\n    const error = document.createElement('div');\n    error.className = 'noaa-lidar-error';\n    error.id = 'noaa-lidar-search-error';\n    error.style.display = 'none';\n    content.appendChild(error);\n\n    section.appendChild(content);\n    return section;\n  }\n\n  private _updateSearchSection(): void {\n    // Update draw button\n    const drawBtn = document.getElementById('noaa-lidar-draw-btn');\n    if (drawBtn) {\n      drawBtn.textContent = this._state.isDrawing ? 'Cancel Drawing' : 'Draw Rectangle';\n      drawBtn.className = this._state.isDrawing\n        ? 'noaa-lidar-btn noaa-lidar-btn-danger'\n        : 'noaa-lidar-btn noaa-lidar-btn-secondary';\n    }\n\n    // Update bbox info\n    const bboxInfo = document.getElementById('noaa-lidar-bbox-info');\n    const drawnActions = document.getElementById('noaa-lidar-drawn-actions');\n    if (bboxInfo && drawnActions) {\n      if (this._state.drawnBbox) {\n        bboxInfo.textContent = `Drawn area: ${formatBbox(this._state.drawnBbox)}`;\n        bboxInfo.style.display = 'block';\n        drawnActions.style.display = 'flex';\n      } else {\n        bboxInfo.style.display = 'none';\n        drawnActions.style.display = 'none';\n      }\n    }\n\n    // Update loading indicator\n    const loading = document.getElementById('noaa-lidar-search-loading');\n    if (loading) {\n      loading.style.display = this._state.isSearching ? 'flex' : 'none';\n    }\n\n    // Update error message\n    const error = document.getElementById('noaa-lidar-search-error');\n    if (error) {\n      if (this._state.searchError) {\n        error.textContent = this._state.searchError;\n        error.style.display = 'block';\n      } else {\n        error.style.display = 'none';\n      }\n    }\n  }\n\n  private _buildResultsSection(): HTMLElement {\n    const section = document.createElement('div');\n    section.className = 'noaa-lidar-section noaa-lidar-results-section';\n\n    const header = document.createElement('div');\n    header.className = 'noaa-lidar-section-header';\n    header.innerHTML = 'Results <span id=\"noaa-lidar-results-count\"></span>';\n    section.appendChild(header);\n\n    const content = document.createElement('div');\n    content.className = 'noaa-lidar-section-content';\n\n    // Results list\n    const list = document.createElement('div');\n    list.className = 'noaa-lidar-results-list';\n    list.id = 'noaa-lidar-results-list';\n    content.appendChild(list);\n\n    // Actions row 1 - Load and Clear\n    const actionsRow = document.createElement('div');\n    actionsRow.className = 'noaa-lidar-button-row';\n    actionsRow.id = 'noaa-lidar-results-actions';\n    actionsRow.style.display = 'none';\n\n    const loadSelectedBtn = document.createElement('button');\n    loadSelectedBtn.className = 'noaa-lidar-btn noaa-lidar-btn-primary';\n    loadSelectedBtn.id = 'noaa-lidar-load-selected-btn';\n    loadSelectedBtn.textContent = 'Load Selected';\n    loadSelectedBtn.addEventListener('click', () => this._callbacks.onLoadSelected());\n    actionsRow.appendChild(loadSelectedBtn);\n\n    const clearResultsBtn = document.createElement('button');\n    clearResultsBtn.className = 'noaa-lidar-btn noaa-lidar-btn-secondary';\n    clearResultsBtn.textContent = 'Clear';\n    clearResultsBtn.addEventListener('click', () => this._callbacks.onClearResults());\n    actionsRow.appendChild(clearResultsBtn);\n\n    content.appendChild(actionsRow);\n\n    // Actions row 2 - Copy URLs and Download\n    const actionsRow2 = document.createElement('div');\n    actionsRow2.className = 'noaa-lidar-button-row';\n    actionsRow2.id = 'noaa-lidar-results-actions-2';\n    actionsRow2.style.display = 'none';\n\n    const copyUrlsBtn = document.createElement('button');\n    copyUrlsBtn.className = 'noaa-lidar-btn noaa-lidar-btn-secondary';\n    copyUrlsBtn.id = 'noaa-lidar-copy-urls-btn';\n    copyUrlsBtn.textContent = 'Copy Signed URLs';\n    copyUrlsBtn.title = 'Copy signed COPC URLs of selected items to clipboard';\n    copyUrlsBtn.addEventListener('click', () => this._callbacks.onCopySignedUrls());\n    actionsRow2.appendChild(copyUrlsBtn);\n\n    const downloadBtn = document.createElement('button');\n    downloadBtn.className = 'noaa-lidar-btn noaa-lidar-btn-secondary';\n    downloadBtn.id = 'noaa-lidar-download-btn';\n    downloadBtn.textContent = 'Download Selected';\n    downloadBtn.title = 'Download selected COPC files';\n    downloadBtn.addEventListener('click', () => this._callbacks.onDownloadSelected());\n    actionsRow2.appendChild(downloadBtn);\n\n    content.appendChild(actionsRow2);\n    section.appendChild(content);\n\n    return section;\n  }\n\n  private _updateResultsSection(): void {\n    const countSpan = document.getElementById('noaa-lidar-results-count');\n    const list = document.getElementById('noaa-lidar-results-list');\n    const actions = document.getElementById('noaa-lidar-results-actions');\n    const actions2 = document.getElementById('noaa-lidar-results-actions-2');\n    const loadBtn = document.getElementById('noaa-lidar-load-selected-btn');\n    const copyUrlsBtn = document.getElementById('noaa-lidar-copy-urls-btn');\n    const downloadBtn = document.getElementById('noaa-lidar-download-btn');\n\n    if (!list) return;\n\n    // Update count\n    if (countSpan) {\n      if (this._state.searchResults.length > 0) {\n        const total = this._state.totalMatched ?? this._state.searchResults.length;\n        countSpan.textContent = `(${this._state.searchResults.length} of ${total})`;\n      } else {\n        countSpan.textContent = '';\n      }\n    }\n\n    // Clear and rebuild list\n    list.innerHTML = '';\n\n    if (this._state.searchResults.length === 0) {\n      if (actions) actions.style.display = 'none';\n      if (actions2) actions2.style.display = 'none';\n      return;\n    }\n\n    // Show actions\n    if (actions) actions.style.display = 'flex';\n    if (actions2) actions2.style.display = 'flex';\n\n    // Update load button\n    const selectedCount = this._state.selectedItems.size;\n    if (loadBtn) {\n      loadBtn.textContent = selectedCount > 0 ? `Load Selected (${selectedCount})` : 'Load Selected';\n      (loadBtn as HTMLButtonElement).disabled = selectedCount === 0;\n    }\n\n    // Update copy URLs button\n    if (copyUrlsBtn) {\n      copyUrlsBtn.textContent = selectedCount > 0 ? `Copy Signed URLs (${selectedCount})` : 'Copy Signed URLs';\n      (copyUrlsBtn as HTMLButtonElement).disabled = selectedCount === 0;\n    }\n\n    // Update download button\n    if (downloadBtn) {\n      downloadBtn.textContent = selectedCount > 0 ? `Download Selected (${selectedCount})` : 'Download Selected';\n      (downloadBtn as HTMLButtonElement).disabled = selectedCount === 0;\n    }\n\n    // Build result items\n    for (const item of this._state.searchResults) {\n      const isSelected = this._state.selectedItems.has(item.id);\n      const isLoaded = this._state.loadedItems.has(item.id);\n\n      const itemEl = document.createElement('div');\n      itemEl.className = `noaa-lidar-result-item${isSelected ? ' selected' : ''}${isLoaded ? ' loaded' : ''}`;\n\n      // Checkbox\n      const checkbox = document.createElement('input');\n      checkbox.type = 'checkbox';\n      checkbox.checked = isSelected;\n      checkbox.disabled = isLoaded;\n      checkbox.addEventListener('change', () => this._callbacks.onItemSelect(item));\n      itemEl.appendChild(checkbox);\n\n      // Item info\n      const info = document.createElement('div');\n      info.className = 'noaa-lidar-result-info';\n\n      const name = document.createElement('div');\n      name.className = 'noaa-lidar-result-name';\n      name.textContent = getItemShortName(item.id);\n      name.title = item.id;\n      info.appendChild(name);\n\n      const meta = document.createElement('div');\n      meta.className = 'noaa-lidar-result-meta';\n      meta.textContent = getUnifiedItemMetadata(item);\n      info.appendChild(meta);\n\n      itemEl.appendChild(info);\n\n      // Load button\n      if (!isLoaded) {\n        const loadItemBtn = document.createElement('button');\n        loadItemBtn.className = 'noaa-lidar-btn-icon';\n        loadItemBtn.title = 'Load this dataset';\n        loadItemBtn.innerHTML = '+';\n        loadItemBtn.addEventListener('click', (e) => {\n          e.stopPropagation();\n          this._callbacks.onItemLoad(item);\n        });\n        itemEl.appendChild(loadItemBtn);\n      } else {\n        const loadedBadge = document.createElement('span');\n        loadedBadge.className = 'noaa-lidar-loaded-badge';\n        loadedBadge.textContent = 'Loaded';\n        itemEl.appendChild(loadedBadge);\n      }\n\n      list.appendChild(itemEl);\n    }\n  }\n\n  private _buildLoadedSection(): HTMLElement {\n    const section = document.createElement('div');\n    section.className = 'noaa-lidar-section noaa-lidar-loaded-section';\n    section.id = 'noaa-lidar-loaded-section';\n    section.style.display = 'none';\n\n    const header = document.createElement('div');\n    header.className = 'noaa-lidar-section-header';\n    header.innerHTML = 'Loaded <span id=\"noaa-lidar-loaded-count\"></span>';\n    section.appendChild(header);\n\n    const content = document.createElement('div');\n    content.className = 'noaa-lidar-section-content';\n\n    // Loaded list\n    const list = document.createElement('div');\n    list.className = 'noaa-lidar-loaded-list';\n    list.id = 'noaa-lidar-loaded-list';\n    content.appendChild(list);\n\n    // Clear all button\n    const clearBtn = document.createElement('button');\n    clearBtn.className = 'noaa-lidar-btn noaa-lidar-btn-secondary noaa-lidar-btn-full';\n    clearBtn.textContent = 'Clear All';\n    clearBtn.addEventListener('click', () => this._callbacks.onClearLoaded());\n    content.appendChild(clearBtn);\n\n    section.appendChild(content);\n    return section;\n  }\n\n  private _updateLoadedSection(): void {\n    const section = document.getElementById('noaa-lidar-loaded-section');\n    const countSpan = document.getElementById('noaa-lidar-loaded-count');\n    const list = document.getElementById('noaa-lidar-loaded-list');\n\n    if (!section || !list) return;\n\n    const loadedCount = this._state.loadedItems.size;\n\n    if (loadedCount === 0) {\n      section.style.display = 'none';\n      return;\n    }\n\n    section.style.display = 'block';\n\n    if (countSpan) {\n      countSpan.textContent = `(${loadedCount})`;\n    }\n\n    // Rebuild list\n    list.innerHTML = '';\n\n    for (const [itemId, info] of this._state.loadedItems) {\n      const itemEl = document.createElement('div');\n      itemEl.className = 'noaa-lidar-loaded-item';\n\n      const nameEl = document.createElement('div');\n      nameEl.className = 'noaa-lidar-loaded-name';\n      nameEl.textContent = getItemShortName(itemId);\n      nameEl.title = itemId;\n      itemEl.appendChild(nameEl);\n\n      const pointsEl = document.createElement('div');\n      pointsEl.className = 'noaa-lidar-loaded-points';\n      pointsEl.textContent = formatPointCount(info.pointCount);\n      itemEl.appendChild(pointsEl);\n\n      // Info button for showing metadata (use internal point cloud ID, not NOAA item ID)\n      if (this._callbacks.onShowMetadata) {\n        const infoBtn = document.createElement('button');\n        infoBtn.className = 'noaa-lidar-btn-icon noaa-lidar-btn-info';\n        infoBtn.title = 'Show metadata';\n        infoBtn.innerHTML = 'ⓘ';\n        infoBtn.addEventListener('click', () => this._callbacks.onShowMetadata!(info.id));\n        itemEl.appendChild(infoBtn);\n      }\n\n      const removeBtn = document.createElement('button');\n      removeBtn.className = 'noaa-lidar-btn-icon noaa-lidar-btn-remove';\n      removeBtn.title = 'Unload this dataset';\n      removeBtn.innerHTML = '&times;';\n      removeBtn.addEventListener('click', () => this._callbacks.onUnloadItem(itemId));\n      itemEl.appendChild(removeBtn);\n\n      list.appendChild(itemEl);\n    }\n  }\n\n  private _updateVisualizationSection(): void {\n    const lidarState = this._state.lidarState;\n    if (!lidarState) return;\n\n    // Sync z-offset slider with lidar control state\n    const zOffsetSlider = document.getElementById('noaa-lidar-zoffset-slider') as HTMLInputElement;\n    const zOffsetValue = document.getElementById('noaa-lidar-zoffset-value');\n    if (zOffsetSlider && lidarState.zOffset !== undefined) {\n      // Only update if value differs to avoid triggering unnecessary events\n      if (parseFloat(zOffsetSlider.value) !== lidarState.zOffset) {\n        zOffsetSlider.value = String(lidarState.zOffset);\n        if (zOffsetValue) {\n          zOffsetValue.textContent = `${Math.round(lidarState.zOffset)}m`;\n        }\n      }\n    }\n\n    // Sync point size slider\n    const sizeSlider = document.getElementById('noaa-lidar-size-slider') as HTMLInputElement;\n    const sizeValue = document.getElementById('noaa-lidar-size-value');\n    if (sizeSlider && lidarState.pointSize !== undefined) {\n      if (parseFloat(sizeSlider.value) !== lidarState.pointSize) {\n        sizeSlider.value = String(lidarState.pointSize);\n        if (sizeValue) {\n          sizeValue.textContent = String(lidarState.pointSize);\n        }\n      }\n    }\n\n    // Sync opacity slider\n    const opacitySlider = document.getElementById('noaa-lidar-opacity-slider') as HTMLInputElement;\n    const opacityValue = document.getElementById('noaa-lidar-opacity-value');\n    if (opacitySlider && lidarState.opacity !== undefined) {\n      if (parseFloat(opacitySlider.value) !== lidarState.opacity) {\n        opacitySlider.value = String(lidarState.opacity);\n        if (opacityValue) {\n          opacityValue.textContent = String(lidarState.opacity);\n        }\n      }\n    }\n\n    // Sync computed bounds FIRST (actual values from percentile calculation)\n    // This must happen before updating data bounds so slider values use correct computed bounds\n    if (lidarState.computedColorBounds !== undefined) {\n      this._computedBounds = lidarState.computedColorBounds;\n    }\n\n    // Sync color scheme dropdown\n    const colorSelect = document.getElementById('noaa-lidar-color-select') as HTMLSelectElement;\n    if (colorSelect && lidarState.colorScheme !== undefined) {\n      // colorScheme can be a string or an object - only sync if it's a simple string type\n      const scheme = typeof lidarState.colorScheme === 'string' ? lidarState.colorScheme : null;\n      if (scheme) {\n        if (colorSelect.value !== scheme) {\n          colorSelect.value = scheme;\n        }\n        this._updateClassificationLegendVisibility(scheme);\n        this._updateColormapVisibility(scheme);\n        // Update data bounds when scheme changes (uses _computedBounds if available)\n        this._updateDataBoundsForScheme(scheme);\n      }\n    }\n\n    // Sync colormap dropdown\n    if (lidarState.colormap !== undefined) {\n      this.setColormap(lidarState.colormap);\n    }\n\n    // Sync color range config\n    if (lidarState.colorRange !== undefined) {\n      this.setColorRangeConfig(lidarState.colorRange);\n    }\n\n    // Update colorbar labels based on current config\n    this._updateColorbarLabels();\n\n    // Sync pickable checkbox\n    if (this._pickableCheckbox && lidarState.pickable !== undefined) {\n      if (this._pickableCheckbox.checked !== lidarState.pickable) {\n        this._pickableCheckbox.checked = lidarState.pickable;\n      }\n    }\n\n    // Sync elevation filter state\n    if (this._elevationCheckbox && lidarState.elevationRange !== undefined) {\n      const hasFilter = lidarState.elevationRange !== null;\n      if (this._elevationCheckbox.checked !== hasFilter) {\n        this._elevationCheckbox.checked = hasFilter;\n        if (this._elevationSliderContainer) {\n          this._elevationSliderContainer.style.display = hasFilter ? 'flex' : 'none';\n        }\n      }\n      if (hasFilter && lidarState.elevationRange) {\n        const [min, max] = lidarState.elevationRange;\n        if (this._elevationMinInput) {\n          this._elevationMinInput.value = String(min);\n        }\n        if (this._elevationMaxInput) {\n          this._elevationMaxInput.value = String(max);\n        }\n        if (this._elevationRangeValue) {\n          this._elevationRangeValue.textContent = `${Math.round(min)} - ${Math.round(max)}`;\n        }\n        this._updateElevationTrackFill();\n      }\n    }\n\n    // Update classification legend if classifications changed\n    if (lidarState.availableClassifications) {\n      this.updateClassificationLegend();\n    }\n  }\n\n  private _buildVisualizationSection(): HTMLElement {\n    const section = document.createElement('div');\n    section.className = 'noaa-lidar-section noaa-lidar-viz-section';\n    section.id = 'noaa-lidar-viz-section';\n    section.style.display = 'none';\n\n    const header = document.createElement('div');\n    header.className = 'noaa-lidar-section-header';\n    header.textContent = 'Visualization';\n    section.appendChild(header);\n\n    const content = document.createElement('div');\n    content.className = 'noaa-lidar-section-content';\n\n    // Color scheme dropdown\n    const colorRow = document.createElement('div');\n    colorRow.className = 'noaa-lidar-control-row';\n\n    const colorLabel = document.createElement('label');\n    colorLabel.textContent = 'Color By';\n    colorRow.appendChild(colorLabel);\n\n    const colorSelect = document.createElement('select');\n    colorSelect.className = 'noaa-lidar-select';\n    colorSelect.id = 'noaa-lidar-color-select';\n    ['elevation', 'intensity', 'classification', 'rgb'].forEach((scheme) => {\n      const option = document.createElement('option');\n      option.value = scheme;\n      option.textContent = scheme === 'rgb' ? 'RGB' : scheme.charAt(0).toUpperCase() + scheme.slice(1);\n      colorSelect.appendChild(option);\n    });\n    colorSelect.addEventListener('change', () => {\n      this._callbacks.onColorSchemeChange(colorSelect.value);\n      this._updateClassificationLegendVisibility(colorSelect.value);\n      this._updateColormapVisibility(colorSelect.value);\n      this._updateDataBoundsForScheme(colorSelect.value);\n    });\n    colorRow.appendChild(colorSelect);\n\n    content.appendChild(colorRow);\n\n    // Classification legend (shown only when classification color scheme is selected)\n    content.appendChild(this._buildClassificationLegend());\n\n    // Colormap section (shown only for elevation/intensity color schemes)\n    content.appendChild(this._buildColormapSection());\n\n    // Point size slider\n    const sizeRow = document.createElement('div');\n    sizeRow.className = 'noaa-lidar-control-row';\n\n    const sizeLabel = document.createElement('label');\n    sizeLabel.textContent = 'Point Size';\n    sizeRow.appendChild(sizeLabel);\n\n    const sizeSlider = document.createElement('input');\n    sizeSlider.type = 'range';\n    sizeSlider.className = 'noaa-lidar-slider';\n    sizeSlider.id = 'noaa-lidar-size-slider';\n    sizeSlider.min = '0.5';\n    sizeSlider.max = '10';\n    sizeSlider.step = '0.5';\n    sizeSlider.value = '2';\n    sizeSlider.addEventListener('input', () => {\n      this._callbacks.onPointSizeChange(parseFloat(sizeSlider.value));\n      sizeValue.textContent = sizeSlider.value;\n    });\n    sizeRow.appendChild(sizeSlider);\n\n    const sizeValue = document.createElement('span');\n    sizeValue.className = 'noaa-lidar-slider-value';\n    sizeValue.id = 'noaa-lidar-size-value';\n    sizeValue.textContent = '2';\n    sizeRow.appendChild(sizeValue);\n\n    content.appendChild(sizeRow);\n\n    // Opacity slider\n    const opacityRow = document.createElement('div');\n    opacityRow.className = 'noaa-lidar-control-row';\n\n    const opacityLabel = document.createElement('label');\n    opacityLabel.textContent = 'Opacity';\n    opacityRow.appendChild(opacityLabel);\n\n    const opacitySlider = document.createElement('input');\n    opacitySlider.type = 'range';\n    opacitySlider.className = 'noaa-lidar-slider';\n    opacitySlider.id = 'noaa-lidar-opacity-slider';\n    opacitySlider.min = '0.1';\n    opacitySlider.max = '1';\n    opacitySlider.step = '0.1';\n    opacitySlider.value = '1';\n    opacitySlider.addEventListener('input', () => {\n      this._callbacks.onOpacityChange(parseFloat(opacitySlider.value));\n      opacityValue.textContent = opacitySlider.value;\n    });\n    opacityRow.appendChild(opacitySlider);\n\n    const opacityValue = document.createElement('span');\n    opacityValue.className = 'noaa-lidar-slider-value';\n    opacityValue.id = 'noaa-lidar-opacity-value';\n    opacityValue.textContent = '1';\n    opacityRow.appendChild(opacityValue);\n\n    content.appendChild(opacityRow);\n\n    // Z Offset slider (to adjust for absolute elevation) - moved up, right after opacity\n    const zOffsetRow = document.createElement('div');\n    zOffsetRow.className = 'noaa-lidar-control-row';\n\n    const zOffsetLabel = document.createElement('label');\n    zOffsetLabel.textContent = 'Z Offset';\n    zOffsetLabel.title = 'Vertical offset to adjust for absolute elevation (negative values bring points down)';\n    zOffsetRow.appendChild(zOffsetLabel);\n\n    const zOffsetSlider = document.createElement('input');\n    zOffsetSlider.type = 'range';\n    zOffsetSlider.className = 'noaa-lidar-slider';\n    zOffsetSlider.id = 'noaa-lidar-zoffset-slider';\n    zOffsetSlider.min = '-3000';\n    zOffsetSlider.max = '0';\n    zOffsetSlider.step = '50';\n    zOffsetSlider.value = '0';\n    zOffsetSlider.addEventListener('input', () => {\n      const offset = parseFloat(zOffsetSlider.value);\n      this._callbacks.onZOffsetChange(offset);\n      zOffsetValue.textContent = `${Math.round(offset)}m`;\n    });\n    zOffsetRow.appendChild(zOffsetSlider);\n\n    const zOffsetValue = document.createElement('span');\n    zOffsetValue.className = 'noaa-lidar-slider-value noaa-lidar-slider-value-wide';\n    zOffsetValue.id = 'noaa-lidar-zoffset-value';\n    zOffsetValue.textContent = '0m';\n    zOffsetRow.appendChild(zOffsetValue);\n\n    content.appendChild(zOffsetRow);\n\n    // Enable point picking checkbox\n    content.appendChild(this._buildPickableCheckbox());\n\n    // Elevation filter checkbox with dual range slider\n    content.appendChild(this._buildElevationFilter());\n\n    section.appendChild(content);\n    return section;\n  }\n\n  /**\n   * Shows/hides the visualization section.\n   */\n  showVisualizationSection(show: boolean): void {\n    const section = document.getElementById('noaa-lidar-viz-section');\n    if (section) {\n      section.style.display = show ? 'block' : 'none';\n    }\n\n    // Show/hide the cross-section section\n    // If showing and the section doesn't exist yet, try to create it now\n    // (LidarControl should be initialized by now)\n    if (show && !this._crossSectionSection && this._container) {\n      this._crossSectionSection = this._buildCrossSectionSection();\n      if (this._crossSectionSection) {\n        this._container.appendChild(this._crossSectionSection);\n      }\n    }\n\n    if (this._crossSectionSection) {\n      this._crossSectionSection.style.display = show ? 'block' : 'none';\n    }\n  }\n\n  /**\n   * Builds the cross-section section that embeds the panel from LidarControl.\n   * This may return null if the LidarControl hasn't been initialized yet.\n   */\n  private _buildCrossSectionSection(): HTMLElement | null {\n    if (!this._callbacks.onCrossSectionPanel) return null;\n\n    const panel = this._callbacks.onCrossSectionPanel();\n    if (!panel) return null;\n\n    const section = document.createElement('div');\n    section.className = 'noaa-lidar-section noaa-lidar-crosssection-section';\n    section.id = 'noaa-lidar-crosssection-section';\n    section.style.display = 'none'; // Hidden until data is loaded\n\n    // Collapsible header\n    const header = document.createElement('div');\n    header.className = 'noaa-lidar-section-header noaa-lidar-section-collapsible';\n    header.innerHTML = '<span class=\"noaa-lidar-section-toggle\">▶</span> Cross-Section';\n    header.style.cursor = 'pointer';\n\n    // Collapsible body\n    const body = document.createElement('div');\n    body.className = 'noaa-lidar-section-body';\n    body.style.display = 'none';\n    body.appendChild(panel);\n\n    // Toggle handler\n    header.addEventListener('click', () => {\n      const toggle = header.querySelector('.noaa-lidar-section-toggle');\n      if (body.style.display === 'none') {\n        body.style.display = 'block';\n        if (toggle) toggle.textContent = '▼';\n      } else {\n        body.style.display = 'none';\n        if (toggle) toggle.textContent = '▶';\n      }\n    });\n\n    section.appendChild(header);\n    section.appendChild(body);\n\n    return section;\n  }\n\n  /**\n   * Builds the point picking checkbox.\n   */\n  private _buildPickableCheckbox(): HTMLElement {\n    const group = document.createElement('div');\n    group.className = 'noaa-lidar-checkbox-row';\n\n    const checkbox = document.createElement('input');\n    checkbox.type = 'checkbox';\n    checkbox.id = 'noaa-lidar-pickable-checkbox';\n    checkbox.checked = this._state.lidarState?.pickable ?? false;\n    this._pickableCheckbox = checkbox;\n\n    const label = document.createElement('label');\n    label.htmlFor = 'noaa-lidar-pickable-checkbox';\n    label.textContent = 'Enable point picking';\n\n    checkbox.addEventListener('change', () => {\n      this._callbacks.onPickableChange(checkbox.checked);\n    });\n\n    group.appendChild(checkbox);\n    group.appendChild(label);\n\n    return group;\n  }\n\n  /**\n   * Builds the elevation filter controls with checkbox and dual-thumb range slider.\n   */\n  private _buildElevationFilter(): HTMLElement {\n    const group = document.createElement('div');\n    group.className = 'noaa-lidar-checkbox-group';\n\n    // Checkbox row\n    const checkboxRow = document.createElement('div');\n    checkboxRow.className = 'noaa-lidar-checkbox-row';\n\n    const checkbox = document.createElement('input');\n    checkbox.type = 'checkbox';\n    checkbox.id = 'noaa-lidar-elevation-checkbox';\n    checkbox.checked = false;\n    this._elevationCheckbox = checkbox;\n\n    const label = document.createElement('label');\n    label.htmlFor = 'noaa-lidar-elevation-checkbox';\n    label.textContent = 'Elevation Filter';\n\n    checkboxRow.appendChild(checkbox);\n    checkboxRow.appendChild(label);\n    group.appendChild(checkboxRow);\n\n    // Dual range slider container (hidden by default)\n    const sliderContainer = document.createElement('div');\n    sliderContainer.className = 'noaa-lidar-dual-range-row';\n    sliderContainer.style.display = 'none';\n    this._elevationSliderContainer = sliderContainer;\n\n    // Get elevation bounds from loaded point clouds\n    const bounds = this._getElevationBounds();\n\n    // Label\n    const rangeLabel = document.createElement('label');\n    rangeLabel.textContent = 'Range (m)';\n    sliderContainer.appendChild(rangeLabel);\n\n    // Dual range slider wrapper\n    const sliderWrapper = document.createElement('div');\n    sliderWrapper.className = 'noaa-lidar-dual-range-slider';\n\n    // Track background\n    const track = document.createElement('div');\n    track.className = 'noaa-lidar-dual-range-track';\n    sliderWrapper.appendChild(track);\n\n    // Track fill (colored portion between thumbs)\n    const trackFill = document.createElement('div');\n    trackFill.className = 'noaa-lidar-dual-range-fill';\n    this._elevationTrackFill = trackFill;\n    sliderWrapper.appendChild(trackFill);\n\n    // Min slider (lower thumb)\n    const minInput = document.createElement('input');\n    minInput.type = 'range';\n    minInput.className = 'noaa-lidar-dual-range-input noaa-lidar-dual-range-min';\n    minInput.min = String(bounds.min);\n    minInput.max = String(bounds.max);\n    minInput.step = '1';\n    minInput.value = String(bounds.min);\n    this._elevationMinInput = minInput;\n    sliderWrapper.appendChild(minInput);\n\n    // Max slider (upper thumb)\n    const maxInput = document.createElement('input');\n    maxInput.type = 'range';\n    maxInput.className = 'noaa-lidar-dual-range-input noaa-lidar-dual-range-max';\n    maxInput.min = String(bounds.min);\n    maxInput.max = String(bounds.max);\n    maxInput.step = '1';\n    maxInput.value = String(bounds.max);\n    this._elevationMaxInput = maxInput;\n    sliderWrapper.appendChild(maxInput);\n\n    sliderContainer.appendChild(sliderWrapper);\n\n    // Range value display\n    const rangeValue = document.createElement('span');\n    rangeValue.className = 'noaa-lidar-dual-range-value';\n    rangeValue.textContent = `${bounds.min} - ${bounds.max}`;\n    this._elevationRangeValue = rangeValue;\n    sliderContainer.appendChild(rangeValue);\n\n    group.appendChild(sliderContainer);\n\n    // Event handlers\n    const updateElevationRange = () => {\n      if (checkbox.checked) {\n        const min = parseFloat(minInput.value);\n        const max = parseFloat(maxInput.value);\n        this._callbacks.onElevationRangeChange([min, max]);\n      }\n    };\n\n    const updateDisplay = () => {\n      const min = parseFloat(minInput.value);\n      const max = parseFloat(maxInput.value);\n      rangeValue.textContent = `${Math.round(min)} - ${Math.round(max)}`;\n      this._updateElevationTrackFill();\n    };\n\n    minInput.addEventListener('input', () => {\n      const minVal = parseFloat(minInput.value);\n      const maxVal = parseFloat(maxInput.value);\n      // Ensure min doesn't exceed max\n      if (minVal > maxVal) {\n        minInput.value = maxInput.value;\n      }\n      updateDisplay();\n      updateElevationRange();\n    });\n\n    maxInput.addEventListener('input', () => {\n      const minVal = parseFloat(minInput.value);\n      const maxVal = parseFloat(maxInput.value);\n      // Ensure max doesn't go below min\n      if (maxVal < minVal) {\n        maxInput.value = minInput.value;\n      }\n      updateDisplay();\n      updateElevationRange();\n    });\n\n    checkbox.addEventListener('change', () => {\n      sliderContainer.style.display = checkbox.checked ? 'flex' : 'none';\n      if (checkbox.checked) {\n        // Update bounds when enabling filter\n        const newBounds = this._getElevationBounds();\n        minInput.min = String(newBounds.min);\n        minInput.max = String(newBounds.max);\n        minInput.value = String(newBounds.min);\n        maxInput.min = String(newBounds.min);\n        maxInput.max = String(newBounds.max);\n        maxInput.value = String(newBounds.max);\n        updateDisplay();\n        // Apply current range\n        updateElevationRange();\n      } else {\n        this._callbacks.onElevationRangeChange(null);\n      }\n    });\n\n    // Initialize track fill position\n    this._updateElevationTrackFill();\n\n    return group;\n  }\n\n  /**\n   * Updates the elevation range slider track fill position.\n   */\n  private _updateElevationTrackFill(): void {\n    if (!this._elevationMinInput || !this._elevationMaxInput || !this._elevationTrackFill) return;\n\n    const min = parseFloat(this._elevationMinInput.min);\n    const max = parseFloat(this._elevationMinInput.max);\n    const minVal = parseFloat(this._elevationMinInput.value);\n    const maxVal = parseFloat(this._elevationMaxInput.value);\n\n    const range = max - min;\n    if (range <= 0) return;\n\n    const leftPercent = ((minVal - min) / range) * 100;\n    const rightPercent = ((max - maxVal) / range) * 100;\n\n    this._elevationTrackFill.style.left = `${leftPercent}%`;\n    this._elevationTrackFill.style.right = `${rightPercent}%`;\n  }\n\n  /**\n   * Gets elevation bounds from loaded point clouds.\n   */\n  private _getElevationBounds(): { min: number; max: number } {\n    if (!this._state.lidarState?.pointClouds || this._state.lidarState.pointClouds.length === 0) {\n      return { min: 0, max: 100 };\n    }\n\n    let minZ = Infinity;\n    let maxZ = -Infinity;\n\n    for (const pc of this._state.lidarState.pointClouds) {\n      if (pc.bounds) {\n        minZ = Math.min(minZ, pc.bounds.minZ);\n        maxZ = Math.max(maxZ, pc.bounds.maxZ);\n      }\n    }\n\n    // Round to nice values\n    minZ = Math.floor(minZ);\n    maxZ = Math.ceil(maxZ);\n\n    // Return reasonable defaults if no valid bounds found\n    if (!isFinite(minZ) || !isFinite(maxZ)) {\n      return { min: 0, max: 100 };\n    }\n\n    return { min: minZ, max: maxZ };\n  }\n\n  /**\n   * Builds the classification legend with toggleable visibility.\n   */\n  private _buildClassificationLegend(): HTMLElement {\n    const container = document.createElement('div');\n    container.className = 'noaa-lidar-classification-legend';\n    container.style.display = 'none'; // Hidden by default, shown when classification scheme is selected\n    this._classificationLegendContainer = container;\n\n    // Header with Show All / Hide All buttons\n    const header = document.createElement('div');\n    header.className = 'noaa-lidar-classification-header';\n\n    const showAllBtn = document.createElement('button');\n    showAllBtn.type = 'button';\n    showAllBtn.className = 'noaa-lidar-btn-small';\n    showAllBtn.textContent = 'Show All';\n    showAllBtn.addEventListener('click', () => this._callbacks.onClassificationShowAll());\n\n    const hideAllBtn = document.createElement('button');\n    hideAllBtn.type = 'button';\n    hideAllBtn.className = 'noaa-lidar-btn-small';\n    hideAllBtn.textContent = 'Hide All';\n    hideAllBtn.addEventListener('click', () => this._callbacks.onClassificationHideAll());\n\n    header.appendChild(showAllBtn);\n    header.appendChild(hideAllBtn);\n    container.appendChild(header);\n\n    // Legend items list\n    const list = document.createElement('div');\n    list.className = 'noaa-lidar-classification-list';\n    list.id = 'noaa-lidar-classification-list';\n\n    // Build legend items from available classifications\n    this._rebuildClassificationList(list);\n\n    container.appendChild(list);\n    return container;\n  }\n\n  /**\n   * Rebuilds the classification list items.\n   */\n  private _rebuildClassificationList(listContainer: HTMLElement): void {\n    listContainer.innerHTML = '';\n    this._classificationCheckboxes.clear();\n\n    const availableClassifications = this._state.lidarState?.availableClassifications;\n    const hiddenClassifications = this._state.lidarState?.hiddenClassifications || new Set<number>();\n\n    if (!availableClassifications || availableClassifications.size === 0) {\n      const placeholder = document.createElement('div');\n      placeholder.className = 'noaa-lidar-classification-empty';\n      placeholder.textContent = 'Loading classifications...';\n      listContainer.appendChild(placeholder);\n      return;\n    }\n\n    // Sort classifications by code\n    const sortedCodes = Array.from(availableClassifications).sort((a, b) => a - b);\n\n    for (const code of sortedCodes) {\n      const item = document.createElement('div');\n      item.className = 'noaa-lidar-classification-item';\n\n      const checkbox = document.createElement('input');\n      checkbox.type = 'checkbox';\n      checkbox.id = `noaa-lidar-class-${code}`;\n      checkbox.checked = !hiddenClassifications.has(code);\n      checkbox.addEventListener('change', () => {\n        this._callbacks.onClassificationToggle(code, checkbox.checked);\n      });\n      this._classificationCheckboxes.set(code, checkbox);\n\n      const swatch = document.createElement('span');\n      swatch.className = 'noaa-lidar-classification-swatch';\n      const color = CLASSIFICATION_COLORS[code] || [128, 128, 128];\n      swatch.style.backgroundColor = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;\n\n      const label = document.createElement('label');\n      label.htmlFor = `noaa-lidar-class-${code}`;\n      label.className = 'noaa-lidar-classification-label';\n      label.textContent = getClassificationName(code);\n\n      item.appendChild(checkbox);\n      item.appendChild(swatch);\n      item.appendChild(label);\n      listContainer.appendChild(item);\n    }\n  }\n\n  /**\n   * Updates visibility of the classification legend based on color scheme.\n   */\n  private _updateClassificationLegendVisibility(colorScheme: string): void {\n    if (this._classificationLegendContainer) {\n      this._classificationLegendContainer.style.display =\n        colorScheme === 'classification' ? 'block' : 'none';\n    }\n  }\n\n  /**\n   * Updates the classification legend checkboxes.\n   */\n  updateClassificationLegend(): void {\n    const list = document.getElementById('noaa-lidar-classification-list');\n    if (list) {\n      this._rebuildClassificationList(list);\n    }\n  }\n\n  /**\n   * Builds the colormap section with dropdown, colorbar, and color range controls.\n   */\n  private _buildColormapSection(): HTMLElement {\n    const container = document.createElement('div');\n    container.className = 'noaa-lidar-colormap-section';\n    container.style.display = 'none'; // Hidden by default\n    this._colormapContainer = container;\n\n    // Colormap dropdown row\n    const colormapRow = document.createElement('div');\n    colormapRow.className = 'noaa-lidar-control-row';\n\n    const colormapLabel = document.createElement('label');\n    colormapLabel.textContent = 'Colormap';\n    colormapRow.appendChild(colormapLabel);\n\n    const colormapSelect = document.createElement('select');\n    colormapSelect.className = 'noaa-lidar-select';\n    colormapSelect.id = 'noaa-lidar-colormap-select';\n\n    // Add colormap options\n    for (const name of COLORMAP_NAMES) {\n      const option = document.createElement('option');\n      option.value = name;\n      option.textContent = COLORMAP_LABELS[name] || name;\n      colormapSelect.appendChild(option);\n    }\n    colormapSelect.value = this._currentColormap;\n    this._colormapSelect = colormapSelect;\n\n    colormapSelect.addEventListener('change', () => {\n      this._currentColormap = colormapSelect.value as ColormapName;\n      this._updateColorbar();\n      this._callbacks.onColormapChange(this._currentColormap);\n    });\n    colormapRow.appendChild(colormapSelect);\n\n    container.appendChild(colormapRow);\n\n    // Colorbar container with min/max labels\n    const colorbarContainer = document.createElement('div');\n    colorbarContainer.className = 'noaa-lidar-colorbar-container';\n\n    // Min label\n    const minLabel = document.createElement('span');\n    minLabel.className = 'noaa-lidar-colorbar-label noaa-lidar-colorbar-min';\n    minLabel.textContent = '0';\n    this._colorbarMinLabel = minLabel;\n    colorbarContainer.appendChild(minLabel);\n\n    // Colorbar canvas\n    const colorbarCanvas = document.createElement('canvas');\n    colorbarCanvas.className = 'noaa-lidar-colorbar-canvas';\n    colorbarCanvas.width = 200;\n    colorbarCanvas.height = 16;\n    this._colorbarCanvas = colorbarCanvas;\n    colorbarContainer.appendChild(colorbarCanvas);\n\n    // Max label\n    const maxLabel = document.createElement('span');\n    maxLabel.className = 'noaa-lidar-colorbar-label noaa-lidar-colorbar-max';\n    maxLabel.textContent = '100';\n    this._colorbarMaxLabel = maxLabel;\n    colorbarContainer.appendChild(maxLabel);\n\n    container.appendChild(colorbarContainer);\n\n    // Color range controls\n    container.appendChild(this._buildColorRangeControls());\n\n    // Initialize colorbar\n    this._updateColorbar();\n\n    return container;\n  }\n\n  /**\n   * Builds the color range controls with mode toggle and sliders.\n   */\n  private _buildColorRangeControls(): HTMLElement {\n    const container = document.createElement('div');\n    container.className = 'noaa-lidar-color-range-section';\n\n    // Header with label and reset button\n    const header = document.createElement('div');\n    header.className = 'noaa-lidar-color-range-header';\n\n    const label = document.createElement('span');\n    label.textContent = 'Color Range';\n    header.appendChild(label);\n\n    const resetBtn = document.createElement('button');\n    resetBtn.type = 'button';\n    resetBtn.className = 'noaa-lidar-btn-small';\n    resetBtn.textContent = 'Reset';\n    resetBtn.addEventListener('click', () => this._resetColorRange());\n    header.appendChild(resetBtn);\n\n    container.appendChild(header);\n\n    // Mode toggle (Percentile / Absolute)\n    const modeRow = document.createElement('div');\n    modeRow.className = 'noaa-lidar-color-range-mode';\n\n    const percentileOption = document.createElement('label');\n    percentileOption.className = 'noaa-lidar-radio-option';\n    const percentileRadio = document.createElement('input');\n    percentileRadio.type = 'radio';\n    percentileRadio.name = 'noaa-lidar-color-range-mode';\n    percentileRadio.value = 'percentile';\n    percentileRadio.checked = true;\n    percentileRadio.id = 'noaa-lidar-color-range-percentile';\n    this._colorRangeModePercentile = percentileRadio;\n    percentileOption.appendChild(percentileRadio);\n    percentileOption.appendChild(document.createTextNode(' Percentile'));\n\n    const absoluteOption = document.createElement('label');\n    absoluteOption.className = 'noaa-lidar-radio-option';\n    const absoluteRadio = document.createElement('input');\n    absoluteRadio.type = 'radio';\n    absoluteRadio.name = 'noaa-lidar-color-range-mode';\n    absoluteRadio.value = 'absolute';\n    absoluteRadio.id = 'noaa-lidar-color-range-absolute';\n    this._colorRangeModeAbsolute = absoluteRadio;\n    absoluteOption.appendChild(absoluteRadio);\n    absoluteOption.appendChild(document.createTextNode(' Absolute'));\n\n    modeRow.appendChild(percentileOption);\n    modeRow.appendChild(absoluteOption);\n    container.appendChild(modeRow);\n\n    // Event listeners for mode change\n    percentileRadio.addEventListener('change', () => this._onColorRangeModeChange());\n    absoluteRadio.addEventListener('change', () => this._onColorRangeModeChange());\n\n    // Percentile slider container\n    container.appendChild(this._buildPercentileSliders());\n\n    // Absolute slider container\n    container.appendChild(this._buildAbsoluteSliders());\n\n    return container;\n  }\n\n  /**\n   * Builds the percentile range sliders.\n   */\n  private _buildPercentileSliders(): HTMLElement {\n    const container = document.createElement('div');\n    container.className = 'noaa-lidar-dual-range-row';\n    container.id = 'noaa-lidar-percentile-slider-container';\n    this._percentileSliderContainer = container;\n\n    const label = document.createElement('label');\n    label.textContent = 'Range (%)';\n    container.appendChild(label);\n\n    // Dual range slider wrapper\n    const sliderWrapper = document.createElement('div');\n    sliderWrapper.className = 'noaa-lidar-dual-range-slider';\n\n    // Track background\n    const track = document.createElement('div');\n    track.className = 'noaa-lidar-dual-range-track';\n    sliderWrapper.appendChild(track);\n\n    // Track fill\n    const trackFill = document.createElement('div');\n    trackFill.className = 'noaa-lidar-dual-range-fill';\n    this._percentileTrackFill = trackFill;\n    sliderWrapper.appendChild(trackFill);\n\n    // Min slider\n    const minInput = document.createElement('input');\n    minInput.type = 'range';\n    minInput.className = 'noaa-lidar-dual-range-input noaa-lidar-dual-range-min';\n    minInput.min = '0';\n    minInput.max = '100';\n    minInput.step = '1';\n    minInput.value = '2';\n    this._percentileLowSlider = minInput;\n    sliderWrapper.appendChild(minInput);\n\n    // Max slider\n    const maxInput = document.createElement('input');\n    maxInput.type = 'range';\n    maxInput.className = 'noaa-lidar-dual-range-input noaa-lidar-dual-range-max';\n    maxInput.min = '0';\n    maxInput.max = '100';\n    maxInput.step = '1';\n    maxInput.value = '98';\n    this._percentileHighSlider = maxInput;\n    sliderWrapper.appendChild(maxInput);\n\n    container.appendChild(sliderWrapper);\n\n    // Range value display\n    const rangeValue = document.createElement('span');\n    rangeValue.className = 'noaa-lidar-dual-range-value';\n    rangeValue.textContent = '2% - 98%';\n    this._percentileRangeValue = rangeValue;\n    container.appendChild(rangeValue);\n\n    // Event handlers\n    minInput.addEventListener('input', () => this._onPercentileSliderChange());\n    maxInput.addEventListener('input', () => this._onPercentileSliderChange());\n\n    // Initialize track fill\n    this._updatePercentileTrackFill();\n\n    return container;\n  }\n\n  /**\n   * Builds the absolute range sliders.\n   */\n  private _buildAbsoluteSliders(): HTMLElement {\n    const container = document.createElement('div');\n    container.className = 'noaa-lidar-dual-range-row';\n    container.id = 'noaa-lidar-absolute-slider-container';\n    container.style.display = 'none'; // Hidden by default (percentile mode is default)\n    this._absoluteSliderContainer = container;\n\n    const label = document.createElement('label');\n    label.textContent = 'Range';\n    container.appendChild(label);\n\n    // Dual range slider wrapper\n    const sliderWrapper = document.createElement('div');\n    sliderWrapper.className = 'noaa-lidar-dual-range-slider';\n\n    // Track background\n    const track = document.createElement('div');\n    track.className = 'noaa-lidar-dual-range-track';\n    sliderWrapper.appendChild(track);\n\n    // Track fill\n    const trackFill = document.createElement('div');\n    trackFill.className = 'noaa-lidar-dual-range-fill';\n    this._absoluteTrackFill = trackFill;\n    sliderWrapper.appendChild(trackFill);\n\n    // Min slider\n    const minInput = document.createElement('input');\n    minInput.type = 'range';\n    minInput.className = 'noaa-lidar-dual-range-input noaa-lidar-dual-range-min';\n    minInput.min = String(this._dataBounds.min);\n    minInput.max = String(this._dataBounds.max);\n    minInput.step = '0.01';\n    minInput.value = String(this._dataBounds.min);\n    this._absoluteMinSlider = minInput;\n    sliderWrapper.appendChild(minInput);\n\n    // Max slider\n    const maxInput = document.createElement('input');\n    maxInput.type = 'range';\n    maxInput.className = 'noaa-lidar-dual-range-input noaa-lidar-dual-range-max';\n    maxInput.min = String(this._dataBounds.min);\n    maxInput.max = String(this._dataBounds.max);\n    maxInput.step = '0.01';\n    maxInput.value = String(this._dataBounds.max);\n    this._absoluteMaxSlider = maxInput;\n    sliderWrapper.appendChild(maxInput);\n\n    container.appendChild(sliderWrapper);\n\n    // Range value display (current selected values)\n    const rangeValue = document.createElement('span');\n    rangeValue.className = 'noaa-lidar-dual-range-value';\n    rangeValue.textContent = `${this._formatValue(this._dataBounds.min)} - ${this._formatValue(this._dataBounds.max)}`;\n    this._absoluteRangeValue = rangeValue;\n    container.appendChild(rangeValue);\n\n    // Event handlers\n    minInput.addEventListener('input', () => this._onAbsoluteSliderChange());\n    maxInput.addEventListener('input', () => this._onAbsoluteSliderChange());\n\n    // Initialize track fill\n    this._updateAbsoluteTrackFill();\n\n    return container;\n  }\n\n  /**\n   * Updates colormap section visibility based on color scheme.\n   */\n  private _updateColormapVisibility(colorScheme: string): void {\n    if (this._colormapContainer) {\n      const showColormap = colorScheme === 'elevation' || colorScheme === 'intensity';\n      this._colormapContainer.style.display = showColormap ? 'block' : 'none';\n    }\n  }\n\n  /**\n   * Updates data bounds based on the current color scheme.\n   */\n  private _updateDataBoundsForScheme(scheme: string): void {\n    let bounds: { min: number; max: number };\n\n    if (scheme === 'elevation') {\n      bounds = this._getElevationBounds();\n    } else if (scheme === 'intensity') {\n      bounds = this._getIntensityBounds();\n    } else {\n      bounds = { min: 0, max: 100 };\n    }\n\n    this._dataBounds = bounds;\n    this._updateAbsoluteSliderBounds(bounds.min, bounds.max);\n    this._updateColorbarLabels();\n  }\n\n  /**\n   * Gets intensity bounds from loaded point clouds.\n   * Intensity values are normalized to 0-1 range during loading in maplibre-gl-lidar.\n   */\n  private _getIntensityBounds(): { min: number; max: number } {\n    // Intensity values are normalized to 0-1 range during loading\n    // This matches the behavior in maplibre-gl-lidar\n    return { min: 0, max: 1 };\n  }\n\n  /**\n   * Updates the absolute slider bounds.\n   * This sets the min/max range of the sliders and initializes values based on computed bounds or percentile.\n   */\n  private _updateAbsoluteSliderBounds(min: number, max: number): void {\n    // Calculate appropriate step based on range\n    const range = max - min;\n    let step = 1;\n    if (range <= 1) {\n      step = 0.01;\n    } else if (range <= 10) {\n      step = 0.1;\n    } else if (range <= 100) {\n      step = 1;\n    } else if (range <= 1000) {\n      step = 10;\n    } else {\n      step = 100;\n    }\n\n    // Use computed bounds if available, otherwise compute from percentile\n    let initialMin: number;\n    let initialMax: number;\n\n    if (this._computedBounds) {\n      initialMin = this._computedBounds.min;\n      initialMax = this._computedBounds.max;\n    } else {\n      initialMin = min + (range * this._currentColorRangeConfig.percentileLow) / 100;\n      initialMax = min + (range * this._currentColorRangeConfig.percentileHigh) / 100;\n    }\n\n    if (this._absoluteMinSlider) {\n      this._absoluteMinSlider.min = String(min);\n      this._absoluteMinSlider.max = String(max);\n      this._absoluteMinSlider.step = String(step);\n      this._absoluteMinSlider.value = String(initialMin);\n    }\n    if (this._absoluteMaxSlider) {\n      this._absoluteMaxSlider.min = String(min);\n      this._absoluteMaxSlider.max = String(max);\n      this._absoluteMaxSlider.step = String(step);\n      this._absoluteMaxSlider.value = String(initialMax);\n    }\n    if (this._absoluteRangeValue) {\n      this._absoluteRangeValue.textContent = `${this._formatValue(initialMin)} - ${this._formatValue(initialMax)}`;\n    }\n\n    this._updateAbsoluteTrackFill();\n\n    // Update config with computed values\n    this._currentColorRangeConfig.absoluteMin = initialMin;\n    this._currentColorRangeConfig.absoluteMax = initialMax;\n  }\n\n  /**\n   * Updates the absolute slider range label based on current slider values.\n   */\n  private _updateAbsoluteRangeLabel(): void {\n    if (!this._absoluteRangeValue) return;\n\n    const minVal = this._currentColorRangeConfig.absoluteMin ?? this._dataBounds.min;\n    const maxVal = this._currentColorRangeConfig.absoluteMax ?? this._dataBounds.max;\n    this._absoluteRangeValue.textContent = `${this._formatValue(minVal)} - ${this._formatValue(maxVal)}`;\n  }\n\n  /**\n   * Updates the colorbar min/max labels based on current config.\n   */\n  private _updateColorbarLabels(): void {\n    let minVal: number;\n    let maxVal: number;\n\n    if (this._currentColorRangeConfig.mode === 'percentile') {\n      // In percentile mode, use computed bounds if available, otherwise approximate\n      if (this._computedBounds) {\n        minVal = this._computedBounds.min;\n        maxVal = this._computedBounds.max;\n      } else {\n        const range = this._dataBounds.max - this._dataBounds.min;\n        minVal = this._dataBounds.min + (range * this._currentColorRangeConfig.percentileLow) / 100;\n        maxVal = this._dataBounds.min + (range * this._currentColorRangeConfig.percentileHigh) / 100;\n      }\n    } else {\n      // In absolute mode, use the slider values\n      minVal = this._currentColorRangeConfig.absoluteMin ?? this._dataBounds.min;\n      maxVal = this._currentColorRangeConfig.absoluteMax ?? this._dataBounds.max;\n    }\n\n    if (this._colorbarMinLabel) {\n      this._colorbarMinLabel.textContent = this._formatValue(minVal);\n    }\n    if (this._colorbarMaxLabel) {\n      this._colorbarMaxLabel.textContent = this._formatValue(maxVal);\n    }\n  }\n\n  /**\n   * Formats a value for display based on the data range (not the value itself).\n   * This matches the maplibre-gl-lidar behavior.\n   */\n  private _formatValue(value: number): string {\n    const range = this._dataBounds.max - this._dataBounds.min;\n    if (range <= 1) {\n      return value.toFixed(2); // For intensity (0-1), show 2 decimal places\n    } else if (range <= 10) {\n      return value.toFixed(1);\n    } else if (range <= 100) {\n      return value.toFixed(1);\n    } else {\n      return value.toFixed(0);\n    }\n  }\n\n  /**\n   * Updates the colorbar canvas with the current colormap gradient.\n   */\n  private _updateColorbar(): void {\n    if (!this._colorbarCanvas) return;\n\n    const ctx = this._colorbarCanvas.getContext('2d');\n    if (!ctx) return;\n\n    const width = this._colorbarCanvas.width;\n    const height = this._colorbarCanvas.height;\n\n    // Get colormap (array of RGB colors)\n    const colorRamp = getColormap(this._currentColormap);\n\n    // Create gradient\n    const gradient = ctx.createLinearGradient(0, 0, width, 0);\n\n    // Add color stops from the color ramp\n    const numColors = colorRamp.length;\n    for (let i = 0; i < numColors; i++) {\n      const t = i / (numColors - 1);\n      const color = colorRamp[i];\n      gradient.addColorStop(t, `rgb(${color[0]}, ${color[1]}, ${color[2]})`);\n    }\n\n    // Draw gradient\n    ctx.fillStyle = gradient;\n    ctx.fillRect(0, 0, width, height);\n  }\n\n  /**\n   * Handles color range mode change (percentile/absolute toggle).\n   */\n  private _onColorRangeModeChange(): void {\n    const isPercentile = this._colorRangeModePercentile?.checked ?? true;\n\n    // Show/hide appropriate slider container\n    if (this._percentileSliderContainer) {\n      this._percentileSliderContainer.style.display = isPercentile ? 'flex' : 'none';\n    }\n    if (this._absoluteSliderContainer) {\n      this._absoluteSliderContainer.style.display = isPercentile ? 'none' : 'flex';\n    }\n\n    // Sync values when switching modes\n    if (!isPercentile) {\n      // Switching from percentile to absolute\n      let computedMin: number;\n      let computedMax: number;\n\n      // Use actual computed bounds if available (from the library's percentile calculation)\n      if (this._computedBounds) {\n        computedMin = this._computedBounds.min;\n        computedMax = this._computedBounds.max;\n      } else {\n        // Fall back to linear interpolation\n        const range = this._dataBounds.max - this._dataBounds.min;\n        computedMin =\n          this._dataBounds.min + (range * this._currentColorRangeConfig.percentileLow) / 100;\n        computedMax =\n          this._dataBounds.min + (range * this._currentColorRangeConfig.percentileHigh) / 100;\n      }\n\n      // Update absolute slider values\n      if (this._absoluteMinSlider) {\n        this._absoluteMinSlider.value = String(computedMin);\n      }\n      if (this._absoluteMaxSlider) {\n        this._absoluteMaxSlider.value = String(computedMax);\n      }\n      this._updateAbsoluteTrackFill();\n\n      // Update config with computed values\n      this._currentColorRangeConfig.absoluteMin = computedMin;\n      this._currentColorRangeConfig.absoluteMax = computedMax;\n\n      // Update the slider range label\n      this._updateAbsoluteRangeLabel();\n    }\n    // When switching from absolute to percentile, keep the existing percentile values\n    // (don't recompute from absolute - just restore the previous percentile settings)\n\n    // Update config mode\n    this._currentColorRangeConfig.mode = isPercentile ? 'percentile' : 'absolute';\n\n    // Update colorbar labels\n    this._updateColorbarLabels();\n\n    this._emitColorRangeChange();\n  }\n\n  /**\n   * Handles percentile slider input changes.\n   */\n  private _onPercentileSliderChange(): void {\n    if (!this._percentileLowSlider || !this._percentileHighSlider) return;\n\n    let low = parseFloat(this._percentileLowSlider.value);\n    let high = parseFloat(this._percentileHighSlider.value);\n\n    // Ensure min doesn't exceed max\n    if (low > high) {\n      low = high;\n      this._percentileLowSlider.value = String(low);\n    }\n    // Ensure max doesn't go below min\n    if (high < low) {\n      high = low;\n      this._percentileHighSlider.value = String(high);\n    }\n\n    // Update display\n    if (this._percentileRangeValue) {\n      this._percentileRangeValue.textContent = `${Math.round(low)}% - ${Math.round(high)}%`;\n    }\n\n    this._updatePercentileTrackFill();\n\n    // Update config\n    this._currentColorRangeConfig.percentileLow = low;\n    this._currentColorRangeConfig.percentileHigh = high;\n\n    // Update colorbar labels\n    this._updateColorbarLabels();\n\n    this._emitColorRangeChange();\n  }\n\n  /**\n   * Handles absolute slider input changes.\n   */\n  private _onAbsoluteSliderChange(): void {\n    if (!this._absoluteMinSlider || !this._absoluteMaxSlider) return;\n\n    let min = parseFloat(this._absoluteMinSlider.value);\n    let max = parseFloat(this._absoluteMaxSlider.value);\n\n    // Ensure min doesn't exceed max\n    if (min > max) {\n      min = max;\n      this._absoluteMinSlider.value = String(min);\n    }\n    // Ensure max doesn't go below min\n    if (max < min) {\n      max = min;\n      this._absoluteMaxSlider.value = String(max);\n    }\n\n    // Update display\n    if (this._absoluteRangeValue) {\n      this._absoluteRangeValue.textContent = `${this._formatValue(min)} - ${this._formatValue(max)}`;\n    }\n\n    this._updateAbsoluteTrackFill();\n\n    // Update config\n    this._currentColorRangeConfig.absoluteMin = min;\n    this._currentColorRangeConfig.absoluteMax = max;\n\n    // Update colorbar labels\n    this._updateColorbarLabels();\n\n    this._emitColorRangeChange();\n  }\n\n  /**\n   * Updates the percentile slider track fill position.\n   */\n  private _updatePercentileTrackFill(): void {\n    if (!this._percentileLowSlider || !this._percentileHighSlider || !this._percentileTrackFill)\n      return;\n\n    const min = 0;\n    const max = 100;\n    const low = parseFloat(this._percentileLowSlider.value);\n    const high = parseFloat(this._percentileHighSlider.value);\n\n    const leftPercent = ((low - min) / (max - min)) * 100;\n    const rightPercent = ((max - high) / (max - min)) * 100;\n\n    this._percentileTrackFill.style.left = `${leftPercent}%`;\n    this._percentileTrackFill.style.right = `${rightPercent}%`;\n  }\n\n  /**\n   * Updates the absolute slider track fill position.\n   */\n  private _updateAbsoluteTrackFill(): void {\n    if (!this._absoluteMinSlider || !this._absoluteMaxSlider || !this._absoluteTrackFill) return;\n\n    const min = parseFloat(this._absoluteMinSlider.min);\n    const max = parseFloat(this._absoluteMinSlider.max);\n    const lowVal = parseFloat(this._absoluteMinSlider.value);\n    const highVal = parseFloat(this._absoluteMaxSlider.value);\n\n    const range = max - min;\n    if (range <= 0) return;\n\n    const leftPercent = ((lowVal - min) / range) * 100;\n    const rightPercent = ((max - highVal) / range) * 100;\n\n    this._absoluteTrackFill.style.left = `${leftPercent}%`;\n    this._absoluteTrackFill.style.right = `${rightPercent}%`;\n  }\n\n  /**\n   * Emits the current color range configuration.\n   */\n  private _emitColorRangeChange(): void {\n    this._callbacks.onColorRangeChange({ ...this._currentColorRangeConfig });\n  }\n\n  /**\n   * Resets color range to default percentile 2-98%.\n   */\n  private _resetColorRange(): void {\n    // Reset to percentile mode\n    if (this._colorRangeModePercentile) {\n      this._colorRangeModePercentile.checked = true;\n    }\n    if (this._colorRangeModeAbsolute) {\n      this._colorRangeModeAbsolute.checked = false;\n    }\n\n    // Show percentile slider, hide absolute\n    if (this._percentileSliderContainer) {\n      this._percentileSliderContainer.style.display = 'flex';\n    }\n    if (this._absoluteSliderContainer) {\n      this._absoluteSliderContainer.style.display = 'none';\n    }\n\n    // Reset percentile values\n    if (this._percentileLowSlider) {\n      this._percentileLowSlider.value = '2';\n    }\n    if (this._percentileHighSlider) {\n      this._percentileHighSlider.value = '98';\n    }\n    if (this._percentileRangeValue) {\n      this._percentileRangeValue.textContent = '2% - 98%';\n    }\n\n    // Update track fill\n    this._updatePercentileTrackFill();\n\n    // Reset config\n    this._currentColorRangeConfig = {\n      mode: 'percentile',\n      percentileLow: 2,\n      percentileHigh: 98,\n    };\n\n    this._emitColorRangeChange();\n  }\n\n  /**\n   * Sets the colormap dropdown value.\n   *\n   * @param colormap - Colormap name\n   */\n  setColormap(colormap: ColormapName): void {\n    this._currentColormap = colormap;\n    if (this._colormapSelect) {\n      this._colormapSelect.value = colormap;\n    }\n    this._updateColorbar();\n  }\n\n  /**\n   * Sets the color range configuration.\n   *\n   * @param config - Color range config\n   */\n  setColorRangeConfig(config: ColorRangeConfig): void {\n    this._currentColorRangeConfig = { ...config };\n\n    // Update mode toggle\n    if (this._colorRangeModePercentile) {\n      this._colorRangeModePercentile.checked = config.mode === 'percentile';\n    }\n    if (this._colorRangeModeAbsolute) {\n      this._colorRangeModeAbsolute.checked = config.mode === 'absolute';\n    }\n\n    // Show/hide slider containers\n    if (this._percentileSliderContainer) {\n      this._percentileSliderContainer.style.display = config.mode === 'percentile' ? 'flex' : 'none';\n    }\n    if (this._absoluteSliderContainer) {\n      this._absoluteSliderContainer.style.display = config.mode === 'absolute' ? 'flex' : 'none';\n    }\n\n    // Update percentile sliders\n    if (this._percentileLowSlider) {\n      this._percentileLowSlider.value = String(config.percentileLow);\n    }\n    if (this._percentileHighSlider) {\n      this._percentileHighSlider.value = String(config.percentileHigh);\n    }\n    if (this._percentileRangeValue) {\n      this._percentileRangeValue.textContent = `${Math.round(config.percentileLow)}% - ${Math.round(config.percentileHigh)}%`;\n    }\n    this._updatePercentileTrackFill();\n\n    // Update absolute sliders if values are provided\n    if (config.absoluteMin !== undefined && config.absoluteMax !== undefined) {\n      if (this._absoluteMinSlider) {\n        this._absoluteMinSlider.value = String(config.absoluteMin);\n      }\n      if (this._absoluteMaxSlider) {\n        this._absoluteMaxSlider.value = String(config.absoluteMax);\n      }\n      this._updateAbsoluteTrackFill();\n      this._updateAbsoluteRangeLabel();\n    }\n  }\n}\n","import type { IControl, Map as MapLibreMap, MapMouseEvent, GeoJSONSource } from 'maplibre-gl';\nimport { LidarControl } from 'maplibre-gl-lidar';\nimport type {\n  ColorScheme,\n  ColormapName,\n  ColorRangeConfig,\n  PointCloudFullMetadata,\n  ElevationProfile,\n} from 'maplibre-gl-lidar';\nimport type {\n  NoaaLidarControlOptions,\n  NoaaLidarState,\n  NoaaLidarControlEvent,\n  NoaaLidarEventHandler,\n  NoaaLidarEventData,\n  StacItem,\n  LoadedItemInfo,\n  UnifiedSearchItem,\n} from './types';\nimport { StacSearcher } from '../stac/StacSearcher';\nimport { FootprintLayer } from '../results/FootprintLayer';\nimport { PanelBuilder } from '../gui/PanelBuilder';\nimport { getItemShortName, stacToUnified } from '../utils';\n\nconst DEFAULT_OPTIONS: Required<\n  Omit<NoaaLidarControlOptions, 'className' | 'lidarControlOptions'>\n> = {\n  collapsed: true,\n  position: 'top-right',\n  title: 'NOAA Coastal LiDAR',\n  panelWidth: 380,\n  maxHeight: 500,\n  maxResults: 50,\n  showFootprints: true,\n  autoZoomToResults: true,\n  stacCatalogUrl:\n    'https://noaa-nos-coastal-lidar-pds.s3.us-east-1.amazonaws.com/entwine/stac/catalog.json',\n  cacheDuration: 7 * 24 * 60 * 60 * 1000, // 7 days\n};\n\n// Drawing layer IDs\nconst DRAW_SOURCE_ID = 'noaa-lidar-draw-source';\nconst DRAW_FILL_LAYER_ID = 'noaa-lidar-draw-fill';\nconst DRAW_LINE_LAYER_ID = 'noaa-lidar-draw-line';\n\n/**\n * A MapLibre GL control for searching and visualizing NOAA Coastal LiDAR data.\n *\n * @example\n * ```typescript\n * const control = new NoaaLidarControl({\n *   title: 'NOAA Coastal LiDAR',\n *   maxResults: 25,\n * });\n * map.addControl(control, 'top-right');\n *\n * // Search by map extent\n * await control.searchByExtent();\n *\n * // Load a selected item\n * control.loadItem(item);\n * ```\n */\nexport class NoaaLidarControl implements IControl {\n  private _map?: MapLibreMap;\n  private _mapContainer?: HTMLElement;\n  private _container?: HTMLElement;\n  private _panel?: HTMLElement;\n  private _options: Required<Omit<NoaaLidarControlOptions, 'className' | 'lidarControlOptions'>> &\n    Pick<NoaaLidarControlOptions, 'className' | 'lidarControlOptions'>;\n  private _state: NoaaLidarState;\n  private _eventHandlers: Map<NoaaLidarControlEvent, Set<NoaaLidarEventHandler>> = new Map();\n\n  // Core components\n  private _stacSearcher: StacSearcher;\n  private _footprintLayer?: FootprintLayer;\n  private _lidarControl?: LidarControl;\n  private _panelBuilder?: PanelBuilder;\n  private _initialized: boolean = false;\n\n  // Drawing state\n  private _drawStartPoint: { lng: number; lat: number } | null = null;\n  private _boundMouseDown?: (e: MapMouseEvent) => void;\n  private _boundMouseMove?: (e: MapMouseEvent) => void;\n  private _boundMouseUp?: (e: MapMouseEvent) => void;\n\n  // Track URL to item ID mapping for loaded items\n  private _urlToItemId: Map<string, string> = new Map();\n\n  /**\n   * Creates a new NoaaLidarControl instance.\n   *\n   * @param options - Configuration options\n   */\n  constructor(options?: Partial<NoaaLidarControlOptions>) {\n    this._options = { ...DEFAULT_OPTIONS, ...options };\n    this._stacSearcher = new StacSearcher(\n      this._options.stacCatalogUrl,\n      undefined,\n      this._options.cacheDuration\n    );\n    this._state = {\n      collapsed: this._options.collapsed,\n      panelWidth: this._options.panelWidth,\n      maxHeight: this._options.maxHeight,\n      dataSource: 'ept', // NOAA data is always EPT\n      searchMode: 'none',\n      isDrawing: false,\n      drawnBbox: null,\n      searchResults: [],\n      selectedItems: new Set(),\n      isSearching: false,\n      searchError: null,\n      totalMatched: null,\n      loadedItems: new Map(),\n      lidarState: null,\n    };\n  }\n\n  // ==================== IControl Implementation ====================\n\n  /**\n   * Called when the control is added to the map.\n   */\n  onAdd(map: MapLibreMap): HTMLElement {\n    this._map = map;\n    this._mapContainer = map.getContainer();\n\n    // Create UI immediately\n    this._container = this._createContainer();\n    this._panel = this._createPanel();\n    this._mapContainer.appendChild(this._panel);\n\n    // Initialize components after map style is ready\n    const initWhenReady = () => {\n      if (!this._initialized) this._initComponents();\n    };\n    if (map.isStyleLoaded()) {\n      initWhenReady();\n    } else {\n      map.once('style.load', initWhenReady);\n    }\n\n    this._setupEventListeners();\n\n    if (!this._state.collapsed) {\n      this._panel.classList.add('expanded');\n      requestAnimationFrame(() => this._updatePanelPosition());\n    }\n\n    return this._container;\n  }\n\n  /**\n   * Called when the control is removed from the map.\n   */\n  onRemove(): void {\n    // Cleanup drawing\n    this.stopDrawing();\n    this._removeDrawLayers();\n\n    // Cleanup components\n    this._footprintLayer?.destroy();\n\n    if (this._lidarControl && this._map) {\n      try {\n        this._map.removeControl(this._lidarControl);\n      } catch {\n        // Ignore errors\n      }\n    }\n\n    // Remove DOM elements\n    this._panel?.parentNode?.removeChild(this._panel);\n    this._container?.parentNode?.removeChild(this._container);\n\n    this._map = undefined;\n    this._mapContainer = undefined;\n    this._eventHandlers.clear();\n    this._initialized = false;\n  }\n\n  private _initComponents(): void {\n    if (!this._map || this._initialized) return;\n\n    try {\n      // Initialize drawing layers\n      this._initDrawLayers();\n\n      // Initialize FootprintLayer\n      this._footprintLayer = new FootprintLayer(this._map);\n      this._footprintLayer.onClick((itemId) => {\n        const item = this._state.searchResults.find((i) => i.id === itemId);\n        if (item) {\n          this.toggleItemSelection(item);\n        }\n      });\n\n      // Initialize LidarControl (collapsed - we use our own UI)\n      this._lidarControl = new LidarControl({\n        collapsed: true,\n        position: this._options.position,\n        ...this._options.lidarControlOptions,\n      });\n      this._map.addControl(this._lidarControl, this._options.position);\n\n      // Hide the LidarControl's toggle button since NoaaLidarControl provides its own UI\n      const lidarEl = (this._lidarControl as any)._container as HTMLElement;\n      if (lidarEl) lidarEl.style.display = 'none';\n\n      // Listen to lidar control state changes\n      this._lidarControl.on('statechange', (event) => {\n        this.setState({ lidarState: event.state });\n        // Show viz section when data is loaded\n        if (this._panelBuilder && this._state.loadedItems.size > 0) {\n          this._panelBuilder.showVisualizationSection(true);\n        }\n      });\n\n      this._initialized = true;\n    } catch (error) {\n      console.error('Error in _initComponents:', error);\n    }\n  }\n\n  private _initDrawLayers(): void {\n    if (!this._map) return;\n\n    // Add source\n    if (!this._map.getSource(DRAW_SOURCE_ID)) {\n      this._map.addSource(DRAW_SOURCE_ID, {\n        type: 'geojson',\n        data: { type: 'FeatureCollection', features: [] },\n      });\n    }\n\n    // Add fill layer\n    if (!this._map.getLayer(DRAW_FILL_LAYER_ID)) {\n      this._map.addLayer({\n        id: DRAW_FILL_LAYER_ID,\n        type: 'fill',\n        source: DRAW_SOURCE_ID,\n        paint: {\n          'fill-color': 'rgba(0, 120, 255, 0.1)',\n        },\n      });\n    }\n\n    // Add line layer\n    if (!this._map.getLayer(DRAW_LINE_LAYER_ID)) {\n      this._map.addLayer({\n        id: DRAW_LINE_LAYER_ID,\n        type: 'line',\n        source: DRAW_SOURCE_ID,\n        paint: {\n          'line-color': 'rgba(0, 120, 255, 0.8)',\n          'line-width': 2,\n          'line-dasharray': [3, 2],\n        },\n      });\n    }\n  }\n\n  private _removeDrawLayers(): void {\n    if (!this._map) return;\n\n    if (this._map.getLayer(DRAW_LINE_LAYER_ID)) {\n      this._map.removeLayer(DRAW_LINE_LAYER_ID);\n    }\n    if (this._map.getLayer(DRAW_FILL_LAYER_ID)) {\n      this._map.removeLayer(DRAW_FILL_LAYER_ID);\n    }\n    if (this._map.getSource(DRAW_SOURCE_ID)) {\n      this._map.removeSource(DRAW_SOURCE_ID);\n    }\n  }\n\n  private _updateDrawLayer(bbox: [number, number, number, number] | null): void {\n    if (!this._map) return;\n\n    const source = this._map.getSource(DRAW_SOURCE_ID) as GeoJSONSource;\n    if (!source) return;\n\n    if (!bbox) {\n      source.setData({ type: 'FeatureCollection', features: [] });\n      return;\n    }\n\n    const [west, south, east, north] = bbox;\n    source.setData({\n      type: 'FeatureCollection',\n      features: [\n        {\n          type: 'Feature',\n          properties: {},\n          geometry: {\n            type: 'Polygon',\n            coordinates: [\n              [\n                [west, south],\n                [east, south],\n                [east, north],\n                [west, north],\n                [west, south],\n              ],\n            ],\n          },\n        },\n      ],\n    });\n  }\n\n  // ==================== Public API ====================\n\n  /**\n   * Returns whether the control is fully initialized and ready.\n   */\n  isReady(): boolean {\n    return this._initialized && this._lidarControl !== undefined;\n  }\n\n  /**\n   * Gets the current control state.\n   */\n  getState(): NoaaLidarState {\n    return {\n      ...this._state,\n      selectedItems: new Set(this._state.selectedItems),\n      loadedItems: new Map(this._state.loadedItems),\n    };\n  }\n\n  /**\n   * Updates the control state.\n   *\n   * @param newState - Partial state to merge\n   */\n  setState(newState: Partial<NoaaLidarState>): void {\n    this._state = { ...this._state, ...newState };\n    this._panelBuilder?.updateState(this._state);\n    this._emit('statechange');\n  }\n\n  /**\n   * Toggles the panel open/closed.\n   */\n  toggle(): void {\n    this._state.collapsed = !this._state.collapsed;\n    if (this._panel) {\n      if (this._state.collapsed) {\n        this._panel.classList.remove('expanded');\n        this._emit('collapse');\n      } else {\n        this._panel.classList.add('expanded');\n        this._updatePanelPosition();\n        this._emit('expand');\n      }\n    }\n    this._emit('statechange');\n  }\n\n  /**\n   * Expands the panel.\n   */\n  expand(): void {\n    if (this._state.collapsed) this.toggle();\n  }\n\n  /**\n   * Collapses the panel.\n   */\n  collapse(): void {\n    if (!this._state.collapsed) this.toggle();\n  }\n\n  /**\n   * Registers an event handler.\n   *\n   * @param event - Event type\n   * @param handler - Handler function\n   */\n  on(event: NoaaLidarControlEvent, handler: NoaaLidarEventHandler): void {\n    if (!this._eventHandlers.has(event)) {\n      this._eventHandlers.set(event, new Set());\n    }\n    this._eventHandlers.get(event)!.add(handler);\n  }\n\n  /**\n   * Removes an event handler.\n   *\n   * @param event - Event type\n   * @param handler - Handler function\n   */\n  off(event: NoaaLidarControlEvent, handler: NoaaLidarEventHandler): void {\n    this._eventHandlers.get(event)?.delete(handler);\n  }\n\n  /**\n   * Gets the MapLibre GL map instance.\n   */\n  getMap(): MapLibreMap | undefined {\n    return this._map;\n  }\n\n  /**\n   * Gets the internal LidarControl instance.\n   */\n  getLidarControl(): LidarControl | undefined {\n    return this._lidarControl;\n  }\n\n  /**\n   * Gets the FootprintLayer instance.\n   */\n  getFootprintLayer(): FootprintLayer | undefined {\n    return this._footprintLayer;\n  }\n\n  // ==================== Search API ====================\n\n  /**\n   * Searches by the current map extent.\n   *\n   * @returns Promise resolving to search results\n   */\n  async searchByExtent(): Promise<UnifiedSearchItem[]> {\n    if (!this._map) throw new Error('Control not added to map');\n\n    const bounds = this._map.getBounds();\n    const bbox: [number, number, number, number] = [\n      bounds.getWest(),\n      bounds.getSouth(),\n      bounds.getEast(),\n      bounds.getNorth(),\n    ];\n\n    return this.searchByBbox(bbox);\n  }\n\n  /**\n   * Searches by a bounding box.\n   *\n   * @param bbox - Bounding box [west, south, east, north]\n   * @returns Promise resolving to search results\n   */\n  async searchByBbox(bbox: [number, number, number, number]): Promise<UnifiedSearchItem[]> {\n    // Wait for initialization if not ready (footprint layer needs to be created)\n    if (!this._initialized) {\n      await this._waitForInit();\n    }\n\n    this.setState({\n      isSearching: true,\n      searchError: null,\n      searchResults: [],\n      selectedItems: new Set(),\n    });\n    this._emit('searchstart');\n\n    try {\n      // Search NOAA STAC catalog\n      const response = await this._stacSearcher.searchByExtent(bbox, this._options.maxResults);\n      const items = response.features.map(stacToUnified);\n      const totalMatched = response.numberMatched ?? response.context?.matched ?? items.length;\n\n      this.setState({\n        isSearching: false,\n        searchResults: items,\n        totalMatched,\n      });\n\n      // Show footprints on map\n      if (this._options.showFootprints && this._footprintLayer) {\n        this._footprintLayer.setItems(items);\n        if (this._options.autoZoomToResults && items.length > 0) {\n          this._footprintLayer.zoomToFootprints();\n        }\n      }\n\n      this._emitWithData('searchcomplete', { items });\n      return items;\n    } catch (error) {\n      const err = error instanceof Error ? error : new Error(String(error));\n      this.setState({\n        isSearching: false,\n        searchError: err.message,\n      });\n      this._emitWithData('searcherror', { error: err });\n      throw err;\n    }\n  }\n\n  /**\n   * Starts bbox drawing mode.\n   */\n  startDrawing(): void {\n    if (!this._map) return;\n\n    // Ensure draw layers are initialized\n    if (!this._map.getSource(DRAW_SOURCE_ID)) {\n      this._initDrawLayers();\n    }\n\n    this.setState({ searchMode: 'draw', isDrawing: true });\n    this._emit('drawstart');\n\n    // Clear previous drawn bbox\n    this.clearDrawnBbox();\n\n    // Disable map interactions during drawing\n    this._map.dragPan.disable();\n    this._map.doubleClickZoom.disable();\n    this._map.getCanvas().style.cursor = 'crosshair';\n\n    this._boundMouseDown = (e: MapMouseEvent) => {\n      e.preventDefault();\n      this._drawStartPoint = { lng: e.lngLat.lng, lat: e.lngLat.lat };\n    };\n\n    this._boundMouseMove = (e: MapMouseEvent) => {\n      if (!this._drawStartPoint) return;\n\n      const west = Math.min(this._drawStartPoint.lng, e.lngLat.lng);\n      const east = Math.max(this._drawStartPoint.lng, e.lngLat.lng);\n      const south = Math.min(this._drawStartPoint.lat, e.lngLat.lat);\n      const north = Math.max(this._drawStartPoint.lat, e.lngLat.lat);\n\n      this._updateDrawLayer([west, south, east, north]);\n    };\n\n    this._boundMouseUp = (e: MapMouseEvent) => {\n      if (this._drawStartPoint) {\n        const west = Math.min(this._drawStartPoint.lng, e.lngLat.lng);\n        const east = Math.max(this._drawStartPoint.lng, e.lngLat.lng);\n        const south = Math.min(this._drawStartPoint.lat, e.lngLat.lat);\n        const north = Math.max(this._drawStartPoint.lat, e.lngLat.lat);\n\n        // Only create bbox if user actually dragged (not just clicked)\n        const minDrag = 0.0001; // Small threshold to detect actual drag\n        if (Math.abs(east - west) > minDrag || Math.abs(north - south) > minDrag) {\n          const bbox: [number, number, number, number] = [west, south, east, north];\n          this.setState({ drawnBbox: bbox, isDrawing: false });\n          this._updateDrawLayer(bbox);\n          this._emit('drawend');\n        }\n      }\n      this._drawStartPoint = null;\n      this.stopDrawing();\n    };\n\n    this._map.on('mousedown', this._boundMouseDown);\n    this._map.on('mousemove', this._boundMouseMove);\n    this._map.on('mouseup', this._boundMouseUp);\n  }\n\n  /**\n   * Stops bbox drawing mode.\n   */\n  stopDrawing(): void {\n    if (!this._map) return;\n\n    // Re-enable map interactions\n    this._map.dragPan.enable();\n    this._map.doubleClickZoom.enable();\n    this._map.getCanvas().style.cursor = '';\n\n    if (this._boundMouseDown) {\n      this._map.off('mousedown', this._boundMouseDown);\n      this._boundMouseDown = undefined;\n    }\n    if (this._boundMouseMove) {\n      this._map.off('mousemove', this._boundMouseMove);\n      this._boundMouseMove = undefined;\n    }\n    if (this._boundMouseUp) {\n      this._map.off('mouseup', this._boundMouseUp);\n      this._boundMouseUp = undefined;\n    }\n\n    this._drawStartPoint = null;\n    this.setState({ searchMode: 'none', isDrawing: false });\n  }\n\n  /**\n   * Clears the drawn bbox.\n   */\n  clearDrawnBbox(): void {\n    this.setState({ drawnBbox: null });\n    this._updateDrawLayer(null);\n  }\n\n  // ==================== Selection API ====================\n\n  /**\n   * Selects an item for visualization.\n   *\n   * @param item - The unified search item to select\n   */\n  selectItem(item: UnifiedSearchItem): void {\n    const newSelected = new Set(this._state.selectedItems);\n    newSelected.add(item.id);\n    this.setState({ selectedItems: newSelected });\n    this._footprintLayer?.setSelectedIds(newSelected);\n    this._emit('itemselect');\n  }\n\n  /**\n   * Deselects an item.\n   *\n   * @param item - The unified search item to deselect\n   */\n  deselectItem(item: UnifiedSearchItem): void {\n    const newSelected = new Set(this._state.selectedItems);\n    newSelected.delete(item.id);\n    this.setState({ selectedItems: newSelected });\n    this._footprintLayer?.setSelectedIds(newSelected);\n    this._emit('itemdeselect');\n  }\n\n  /**\n   * Toggles item selection.\n   *\n   * @param item - The unified search item to toggle\n   */\n  toggleItemSelection(item: UnifiedSearchItem): void {\n    if (this._state.selectedItems.has(item.id)) {\n      this.deselectItem(item);\n    } else {\n      this.selectItem(item);\n    }\n  }\n\n  /**\n   * Clears all selections.\n   */\n  clearSelection(): void {\n    this.setState({ selectedItems: new Set() });\n    this._footprintLayer?.setSelectedIds(new Set());\n  }\n\n  // ==================== Loading API ====================\n\n  /**\n   * Loads a unified search item's point cloud data for visualization.\n   *\n   * @param item - Unified search item to load\n   */\n  async loadItem(item: UnifiedSearchItem): Promise<void> {\n    // Wait for initialization if not ready\n    if (!this._initialized) {\n      await this._waitForInit();\n    }\n\n    if (!this._lidarControl) {\n      throw new Error('LiDAR control not available');\n    }\n\n    this._emit('loadstart');\n\n    // Set cursor to waiting\n    if (this._map) {\n      this._map.getCanvas().style.cursor = 'wait';\n    }\n\n    try {\n      // Get EPT URL from STAC item\n      const url = await this._stacSearcher.getEptUrl(item.originalItem as StacItem);\n\n      // Track URL to item ID mapping\n      this._urlToItemId.set(url, item.id);\n\n      const pointCloudInfo = await this._lidarControl.loadPointCloud(url);\n\n      // Create LoadedItemInfo with the item name\n      const info: LoadedItemInfo = {\n        ...pointCloudInfo,\n        name: getItemShortName(item.id),\n      };\n\n      const loadedItems = new Map(this._state.loadedItems);\n      loadedItems.set(item.id, info);\n      this.setState({ loadedItems });\n\n      // Show visualization section\n      if (this._panelBuilder) {\n        this._panelBuilder.showVisualizationSection(true);\n      }\n\n      this._emitWithData('loadcomplete', { pointCloud: info });\n    } catch (error) {\n      const err = error instanceof Error ? error : new Error(String(error));\n      this._emitWithData('loaderror', { error: err });\n      throw err;\n    } finally {\n      // Reset cursor\n      if (this._map) {\n        this._map.getCanvas().style.cursor = '';\n      }\n    }\n  }\n\n  /**\n   * Wait for the control to be initialized.\n   */\n  private _waitForInit(): Promise<void> {\n    return new Promise((resolve) => {\n      if (this._initialized) {\n        resolve();\n        return;\n      }\n\n      // Try to initialize now if map is ready\n      if (this._map && this._map.isStyleLoaded() && !this._initialized) {\n        this._initComponents();\n        if (this._initialized) {\n          resolve();\n          return;\n        }\n      }\n\n      let attempts = 0;\n      const maxAttempts = 100; // ~1.6 seconds at 60fps\n\n      const checkInit = () => {\n        if (this._initialized) {\n          resolve();\n          return;\n        }\n\n        attempts++;\n\n        // Try to force initialization if map appears ready\n        if (this._map && this._map.isStyleLoaded() && !this._initialized) {\n          this._initComponents();\n          if (this._initialized) {\n            resolve();\n            return;\n          }\n        }\n\n        if (attempts < maxAttempts) {\n          requestAnimationFrame(checkInit);\n        } else {\n          // Give up waiting and resolve anyway - search will work but footprints may not show\n          console.warn('NoaaLidarControl: Initialization timeout, proceeding without full initialization');\n          resolve();\n        }\n      };\n      checkInit();\n    });\n  }\n\n  /**\n   * Loads all selected items.\n   */\n  async loadSelectedItems(): Promise<void> {\n    const selectedItems = this._state.searchResults.filter((item) =>\n      this._state.selectedItems.has(item.id)\n    );\n\n    for (const item of selectedItems) {\n      if (!this._state.loadedItems.has(item.id)) {\n        try {\n          await this.loadItem(item);\n        } catch {\n          // Individual load failures are handled by loadItem\n        }\n      }\n    }\n  }\n\n  /**\n   * Unloads a specific item.\n   *\n   * @param itemId - The item ID to unload\n   */\n  unloadItem(itemId: string): void {\n    const info = this._state.loadedItems.get(itemId);\n    if (info) {\n      this._lidarControl?.unloadPointCloud(info.id);\n      const loadedItems = new Map(this._state.loadedItems);\n      loadedItems.delete(itemId);\n      this.setState({ loadedItems });\n\n      // Emit unload event\n      this._emitWithData('unload', { itemId });\n\n      // Hide visualization section if no items loaded\n      if (loadedItems.size === 0 && this._panelBuilder) {\n        this._panelBuilder.showVisualizationSection(false);\n      }\n    }\n  }\n\n  /**\n   * Clears all loaded items.\n   */\n  clearLoadedItems(): void {\n    // Emit unload events for each item before clearing\n    const itemIds = Array.from(this._state.loadedItems.keys());\n    this._lidarControl?.unloadPointCloud();\n    this.setState({ loadedItems: new Map() });\n    this._urlToItemId.clear();\n\n    // Emit unload event for each removed item\n    for (const itemId of itemIds) {\n      this._emitWithData('unload', { itemId });\n    }\n\n    // Hide visualization section\n    if (this._panelBuilder) {\n      this._panelBuilder.showVisualizationSection(false);\n    }\n  }\n\n  /**\n   * Clears search results and footprints.\n   */\n  clearResults(): void {\n    this._footprintLayer?.clear();\n    this.setState({\n      searchResults: [],\n      selectedItems: new Set(),\n      totalMatched: null,\n    });\n  }\n\n  // ==================== URL/Download API ====================\n\n  /**\n   * Gets URLs for the selected items.\n   *\n   * @returns Promise resolving to array of URLs\n   */\n  async getSignedUrls(): Promise<string[]> {\n    const selectedItems = this._state.searchResults.filter((item) =>\n      this._state.selectedItems.has(item.id)\n    );\n\n    const urls: string[] = [];\n    for (const item of selectedItems) {\n      try {\n        const url = await this._stacSearcher.getEptUrl(item.originalItem as StacItem);\n        urls.push(url);\n      } catch (error) {\n        console.error(`Failed to get URL for ${item.id}:`, error);\n      }\n    }\n\n    return urls;\n  }\n\n  /**\n   * Copies URLs for selected items to the clipboard.\n   */\n  async copySignedUrls(): Promise<void> {\n    const selectedCount = this._state.selectedItems.size;\n    if (selectedCount === 0) {\n      console.warn('No items selected to copy URLs');\n      return;\n    }\n\n    try {\n      const urls = await this.getSignedUrls();\n      if (urls.length === 0) {\n        console.warn('No URLs could be generated');\n        return;\n      }\n\n      const urlText = urls.join('\\n');\n      await navigator.clipboard.writeText(urlText);\n      console.log(`Copied ${urls.length} URL(s) to clipboard`);\n\n      // Show temporary success feedback\n      this._showNotification(`Copied ${urls.length} URL(s) to clipboard`);\n    } catch (error) {\n      console.error('Failed to copy URLs:', error);\n      this._showNotification('Failed to copy URLs', true);\n    }\n  }\n\n  /**\n   * Shows a temporary notification message.\n   */\n  private _showNotification(message: string, isError: boolean = false): void {\n    // Create notification element\n    const notification = document.createElement('div');\n    notification.className = `noaa-lidar-notification${isError ? ' error' : ''}`;\n    notification.textContent = message;\n\n    // Add to panel\n    if (this._panel) {\n      this._panel.appendChild(notification);\n\n      // Remove after 3 seconds\n      setTimeout(() => {\n        notification.remove();\n      }, 3000);\n    }\n  }\n\n  // ==================== Visualization API ====================\n\n  /**\n   * Sets the point size.\n   *\n   * @param size - Point size in pixels\n   */\n  setPointSize(size: number): void {\n    this._lidarControl?.setPointSize(size);\n  }\n\n  /**\n   * Sets the point cloud opacity.\n   *\n   * @param opacity - Opacity value (0-1)\n   */\n  setOpacity(opacity: number): void {\n    this._lidarControl?.setOpacity(opacity);\n  }\n\n  /**\n   * Sets the color scheme.\n   *\n   * @param scheme - Color scheme type\n   */\n  setColorScheme(scheme: ColorScheme): void {\n    this._lidarControl?.setColorScheme(scheme);\n  }\n\n  /**\n   * Sets the Z offset for vertical adjustment.\n   * Use negative values to bring point clouds down to ground level.\n   *\n   * @param offset - Z offset in meters\n   */\n  setZOffset(offset: number): void {\n    this._lidarControl?.setZOffset(offset);\n  }\n\n  /**\n   * Sets whether points are pickable (enables hover/click interactions).\n   *\n   * @param pickable - Whether points should be pickable\n   */\n  setPickable(pickable: boolean): void {\n    this._lidarControl?.setPickable(pickable);\n  }\n\n  /**\n   * Sets the elevation range filter.\n   *\n   * @param range - Elevation range [min, max] or null to clear\n   */\n  setElevationRange(range: [number, number] | null): void {\n    if (range) {\n      this._lidarControl?.setElevationRange(range[0], range[1]);\n    } else {\n      this._lidarControl?.clearElevationRange();\n    }\n  }\n\n  /**\n   * Sets visibility for a specific classification.\n   *\n   * @param code - Classification code\n   * @param visible - Whether to show the classification\n   */\n  setClassificationVisibility(code: number, visible: boolean): void {\n    this._lidarControl?.setClassificationVisibility(code, visible);\n  }\n\n  /**\n   * Shows all classifications (makes all visible).\n   */\n  showAllClassifications(): void {\n    this._lidarControl?.showAllClassifications();\n  }\n\n  /**\n   * Hides all classifications.\n   */\n  hideAllClassifications(): void {\n    this._lidarControl?.hideAllClassifications();\n  }\n\n  /**\n   * Sets the colormap for elevation/intensity coloring.\n   *\n   * @param colormap - Colormap name\n   */\n  setColormap(colormap: ColormapName): void {\n    this._lidarControl?.setColormap(colormap);\n  }\n\n  /**\n   * Gets the current colormap.\n   *\n   * @returns Current colormap name\n   */\n  getColormap(): ColormapName | undefined {\n    return this._lidarControl?.getColormap();\n  }\n\n  /**\n   * Sets the color range configuration.\n   *\n   * @param config - Color range configuration\n   */\n  setColorRange(config: ColorRangeConfig): void {\n    this._lidarControl?.setColorRange(config);\n  }\n\n  /**\n   * Gets the current color range configuration.\n   *\n   * @returns Current color range config\n   */\n  getColorRange(): ColorRangeConfig | undefined {\n    return this._lidarControl?.getColorRange();\n  }\n\n  // ==================== Metadata API ====================\n\n  /**\n   * Shows the metadata panel for a point cloud.\n   *\n   * @param itemId - Optional item ID. If not provided, uses the active point cloud.\n   */\n  showMetadata(itemId?: string): void {\n    const id = itemId ?? this._getActivePointCloudId();\n    if (id && this._lidarControl) {\n      this._lidarControl.showMetadataPanel(id);\n    }\n  }\n\n  /**\n   * Hides the metadata panel.\n   */\n  hideMetadata(): void {\n    this._lidarControl?.hideMetadataPanel();\n  }\n\n  /**\n   * Gets the full metadata for a point cloud.\n   *\n   * @param itemId - Optional item ID. If not provided, uses the active point cloud.\n   * @returns Full metadata or undefined if not available.\n   */\n  getMetadata(itemId?: string): PointCloudFullMetadata | undefined {\n    return this._lidarControl?.getFullMetadata(itemId);\n  }\n\n  /**\n   * Gets the active point cloud ID from the internal state.\n   *\n   * @returns Active point cloud ID or null.\n   */\n  private _getActivePointCloudId(): string | null {\n    if (!this._lidarControl) return null;\n    const state = this._lidarControl.getState();\n    return state.activePointCloudId ?? (state.pointClouds.length > 0 ? state.pointClouds[0].id : null);\n  }\n\n  // ==================== Cross-Section API ====================\n\n  /**\n   * Enables cross-section drawing mode.\n   * Users can click two points on the map to define a cross-section line.\n   */\n  enableCrossSection(): void {\n    this._lidarControl?.enableCrossSection();\n  }\n\n  /**\n   * Disables cross-section drawing mode.\n   */\n  disableCrossSection(): void {\n    this._lidarControl?.disableCrossSection();\n  }\n\n  /**\n   * Checks if cross-section drawing mode is enabled.\n   *\n   * @returns True if cross-section mode is active.\n   */\n  isCrossSectionEnabled(): boolean {\n    return this._lidarControl?.isCrossSectionEnabled() ?? false;\n  }\n\n  /**\n   * Sets the buffer distance for cross-section extraction.\n   *\n   * @param meters - Buffer distance in meters.\n   */\n  setCrossSectionBufferDistance(meters: number): void {\n    this._lidarControl?.setCrossSectionBufferDistance(meters);\n  }\n\n  /**\n   * Gets the current cross-section elevation profile.\n   *\n   * @returns Elevation profile data or null if no cross-section exists.\n   */\n  getCrossSectionProfile(): ElevationProfile | null {\n    return this._lidarControl?.getCrossSectionProfile() ?? null;\n  }\n\n  /**\n   * Clears the current cross-section line and profile.\n   */\n  clearCrossSection(): void {\n    this._lidarControl?.clearCrossSection();\n  }\n\n  /**\n   * Gets the cross-section panel element from the internal LidarControl.\n   * This can be used to embed the panel in custom UI.\n   *\n   * @returns HTMLElement containing the cross-section panel, or null.\n   */\n  getCrossSectionPanel(): HTMLElement | null {\n    if (!this._lidarControl) return null;\n    const panel = this._lidarControl.getCrossSectionPanel();\n    return panel ? panel.render() : null;\n  }\n\n  // ==================== Private Methods ====================\n\n  private _emit(event: NoaaLidarControlEvent): void {\n    const handlers = this._eventHandlers.get(event);\n    if (handlers) {\n      const eventData: NoaaLidarEventData = { type: event, state: this.getState() };\n      handlers.forEach((handler) => handler(eventData));\n    }\n  }\n\n  private _emitWithData(event: NoaaLidarControlEvent, data: Partial<NoaaLidarEventData>): void {\n    const handlers = this._eventHandlers.get(event);\n    if (handlers) {\n      const eventData: NoaaLidarEventData = { type: event, state: this.getState(), ...data };\n      handlers.forEach((handler) => handler(eventData));\n    }\n  }\n\n  private _createContainer(): HTMLElement {\n    const container = document.createElement('div');\n    container.className = `maplibregl-ctrl maplibregl-ctrl-group noaa-lidar-control${\n      this._options.className ? ` ${this._options.className}` : ''\n    }`;\n\n    const toggleBtn = document.createElement('button');\n    toggleBtn.className = 'noaa-lidar-control-toggle';\n    toggleBtn.type = 'button';\n    toggleBtn.setAttribute('aria-label', this._options.title);\n    toggleBtn.innerHTML = `\n      <span class=\"noaa-lidar-control-icon\">\n        <img\n          class=\"noaa-lidar-control-icon-image\"\n          src=\"https://cdn-icons-png.flaticon.com/512/2311/2311489.png\"\n          alt=\"\"\n          aria-hidden=\"true\"\n        />\n      </span>\n    `;\n    toggleBtn.addEventListener('click', () => this.toggle());\n\n    container.appendChild(toggleBtn);\n    return container;\n  }\n\n  private _createPanel(): HTMLElement {\n    const panel = document.createElement('div');\n    panel.className = 'noaa-lidar-control-panel';\n    panel.style.width = `${this._options.panelWidth}px`;\n    panel.style.maxHeight = `${this._options.maxHeight}px`;\n\n    // Header\n    const header = document.createElement('div');\n    header.className = 'noaa-lidar-control-header';\n\n    const title = document.createElement('span');\n    title.className = 'noaa-lidar-control-title';\n    title.textContent = this._options.title;\n\n    const closeBtn = document.createElement('button');\n    closeBtn.className = 'noaa-lidar-control-close';\n    closeBtn.type = 'button';\n    closeBtn.setAttribute('aria-label', 'Close panel');\n    closeBtn.innerHTML = '&times;';\n    closeBtn.addEventListener('click', () => this.collapse());\n\n    header.appendChild(title);\n    header.appendChild(closeBtn);\n\n    // Content via PanelBuilder\n    this._panelBuilder = new PanelBuilder(\n      {\n        onSearchByExtent: () => this.searchByExtent(),\n        onStartDrawing: () => this.startDrawing(),\n        onStopDrawing: () => this.stopDrawing(),\n        onSearchByDrawn: () => {\n          if (this._state.drawnBbox) {\n            this.searchByBbox(this._state.drawnBbox);\n          }\n        },\n        onClearDrawn: () => this.clearDrawnBbox(),\n        onItemSelect: (item) => this.toggleItemSelection(item),\n        onItemLoad: (item) => {\n          this.loadItem(item).catch(() => {\n            // Errors are handled via events\n          });\n        },\n        onLoadSelected: () => {\n          this.loadSelectedItems().catch(() => {\n            // Errors are handled via events\n          });\n        },\n        onCopySignedUrls: () => {\n          this.copySignedUrls().catch((err) => {\n            console.error('Failed to copy URLs:', err);\n          });\n        },\n        onDownloadSelected: () => {\n          // Download is not applicable for EPT data\n          console.warn('EPT data cannot be downloaded directly');\n        },\n        onClearResults: () => this.clearResults(),\n        onUnloadItem: (itemId) => this.unloadItem(itemId),\n        onClearLoaded: () => this.clearLoadedItems(),\n        onPointSizeChange: (size) => this.setPointSize(size),\n        onOpacityChange: (opacity) => this.setOpacity(opacity),\n        onColorSchemeChange: (scheme) => this.setColorScheme(scheme as ColorScheme),\n        onZOffsetChange: (offset) => this.setZOffset(offset),\n        onPickableChange: (pickable) => this.setPickable(pickable),\n        onElevationRangeChange: (range) => this.setElevationRange(range),\n        onClassificationToggle: (code, visible) => this.setClassificationVisibility(code, visible),\n        onClassificationShowAll: () => this.showAllClassifications(),\n        onClassificationHideAll: () => this.hideAllClassifications(),\n        onColormapChange: (colormap) => this.setColormap(colormap),\n        onColorRangeChange: (config) => this.setColorRange(config),\n        onShowMetadata: (itemId) => this.showMetadata(itemId),\n        onCrossSectionPanel: () => this.getCrossSectionPanel(),\n        onRebuildIndex: async (onProgress) => {\n          await this._stacSearcher.rebuildIndex(onProgress);\n        },\n        getIndexInfo: () => this._stacSearcher.getIndexInfo(),\n      },\n      this._state\n    );\n\n    const content = this._panelBuilder.build();\n\n    panel.appendChild(header);\n    panel.appendChild(content);\n\n    return panel;\n  }\n\n  private _setupEventListeners(): void {\n    // Click outside to close - but not if clicking in the map\n    const handleClickOutside = (e: MouseEvent) => {\n      const target = e.target as HTMLElement;\n      // Don't close if clicking inside the panel, container, or map canvas\n      if (\n        this._container?.contains(target) ||\n        this._panel?.contains(target) ||\n        this._mapContainer?.querySelector('.maplibregl-canvas')?.contains(target)\n      ) {\n        return;\n      }\n      // Don't close if clicking inside lidar popups (metadata panel, chart popup)\n      const lidarPopup = document.querySelector('.lidar-metadata-backdrop, .lidar-chart-popup-backdrop');\n      if (lidarPopup?.contains(target)) {\n        return;\n      }\n      // Also check if the click target itself is part of a lidar popup (by class)\n      // This handles cases where the popup closes before we can check containment\n      if (target.closest?.('.lidar-metadata-backdrop, .lidar-metadata-panel, .lidar-chart-popup-backdrop, .lidar-chart-popup')) {\n        return;\n      }\n      // Only collapse if panel is expanded and click is truly outside\n      if (!this._state.collapsed) {\n        this.collapse();\n      }\n    };\n\n    // Use capture phase to avoid conflicts\n    document.addEventListener('click', handleClickOutside, true);\n\n    // Update panel position on resize\n    window.addEventListener('resize', () => {\n      if (!this._state.collapsed) {\n        this._updatePanelPosition();\n      }\n    });\n\n    this._map?.on('resize', () => {\n      if (!this._state.collapsed) {\n        this._updatePanelPosition();\n      }\n    });\n  }\n\n  private _getControlPosition(): 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' {\n    const parent = this._container?.parentElement;\n    if (!parent) return 'top-right';\n\n    if (parent.classList.contains('maplibregl-ctrl-top-left')) return 'top-left';\n    if (parent.classList.contains('maplibregl-ctrl-top-right')) return 'top-right';\n    if (parent.classList.contains('maplibregl-ctrl-bottom-left')) return 'bottom-left';\n    if (parent.classList.contains('maplibregl-ctrl-bottom-right')) return 'bottom-right';\n\n    return 'top-right';\n  }\n\n  private _updatePanelPosition(): void {\n    if (!this._container || !this._panel || !this._mapContainer) return;\n\n    const button = this._container.querySelector('.noaa-lidar-control-toggle');\n    if (!button) return;\n\n    const buttonRect = button.getBoundingClientRect();\n    const mapRect = this._mapContainer.getBoundingClientRect();\n    const position = this._getControlPosition();\n\n    const buttonTop = buttonRect.top - mapRect.top;\n    const buttonBottom = mapRect.bottom - buttonRect.bottom;\n    const buttonLeft = buttonRect.left - mapRect.left;\n    const buttonRight = mapRect.right - buttonRect.right;\n\n    const panelGap = 5;\n\n    this._panel.style.top = '';\n    this._panel.style.bottom = '';\n    this._panel.style.left = '';\n    this._panel.style.right = '';\n\n    switch (position) {\n      case 'top-left':\n        this._panel.style.top = `${buttonTop + buttonRect.height + panelGap}px`;\n        this._panel.style.left = `${buttonLeft}px`;\n        break;\n      case 'top-right':\n        this._panel.style.top = `${buttonTop + buttonRect.height + panelGap}px`;\n        this._panel.style.right = `${buttonRight}px`;\n        break;\n      case 'bottom-left':\n        this._panel.style.bottom = `${buttonBottom + buttonRect.height + panelGap}px`;\n        this._panel.style.left = `${buttonLeft}px`;\n        break;\n      case 'bottom-right':\n        this._panel.style.bottom = `${buttonBottom + buttonRect.height + panelGap}px`;\n        this._panel.style.right = `${buttonRight}px`;\n        break;\n    }\n  }\n\n  getPanelElement(): HTMLElement | null {\n    return this._panel ?? null;\n  }\n}\n"],"names":["items","DEFAULT_OPTIONS","classNames","getClassificationName","COLORMAP_NAMES","COLORMAP_LABELS","getColormap","LidarControl","_a"],"mappings":"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"}