{"version":3,"file":"NasaEarthdataControl-CgZCipH0.cjs","names":[],"sources":["../src/lib/gibs/parseCapabilities.ts","../src/lib/gibs/search.ts","../src/lib/gibs/GibsClient.ts","../src/lib/gibs/tileUrl.ts","../src/lib/utils/helpers.ts","../src/lib/core/NasaEarthdataControl.ts"],"sourcesContent":["import type {\n  GibsCapabilities,\n  GibsLayer,\n  GibsLayerFormat,\n  GibsTimeDimension,\n  ParseOptions,\n} from \"./types\";\n\nconst FORMAT_MAP: Record<string, GibsLayerFormat> = {\n  \"image/png\": \"png\",\n  \"image/jpeg\": \"jpeg\",\n  \"application/vnd.mapbox-vector-tile\": \"mvt\",\n};\n\nconst MIME_MAP: Record<GibsLayerFormat, string> = {\n  png: \"image/png\",\n  jpeg: \"image/jpeg\",\n  mvt: \"application/vnd.mapbox-vector-tile\",\n};\n\n/**\n * Returns the direct child elements of a node matching a local tag name,\n * ignoring XML namespaces.\n */\nfunction childrenByLocalName(parent: Element, localName: string): Element[] {\n  const result: Element[] = [];\n  for (let i = 0; i < parent.children.length; i++) {\n    const child = parent.children[i];\n    if (child.localName === localName) {\n      result.push(child);\n    }\n  }\n  return result;\n}\n\n/**\n * Returns the text content of the first direct child element matching a local tag name.\n */\nfunction childText(parent: Element, localName: string): string | undefined {\n  const child = childrenByLocalName(parent, localName)[0];\n  return child?.textContent?.trim() || undefined;\n}\n\n/**\n * Parses the WGS84 bounding box of a layer element.\n */\nfunction parseBbox(\n  layerEl: Element,\n): [number, number, number, number] | undefined {\n  const bboxEl = childrenByLocalName(layerEl, \"WGS84BoundingBox\")[0];\n  if (!bboxEl) return undefined;\n\n  const lower = childText(bboxEl, \"LowerCorner\")?.split(/\\s+/).map(Number);\n  const upper = childText(bboxEl, \"UpperCorner\")?.split(/\\s+/).map(Number);\n  if (!lower || !upper || lower.length < 2 || upper.length < 2)\n    return undefined;\n  if ([...lower, ...upper].some((n) => Number.isNaN(n))) return undefined;\n\n  return [lower[0], lower[1], upper[0], upper[1]];\n}\n\n/**\n * Parses the Time dimension of a layer element, if present.\n */\nfunction parseTimeDimension(layerEl: Element): GibsTimeDimension | undefined {\n  const dimensions = childrenByLocalName(layerEl, \"Dimension\");\n  for (const dim of dimensions) {\n    if (childText(dim, \"Identifier\") !== \"Time\") continue;\n\n    const defaultValue = childText(dim, \"Default\");\n    if (!defaultValue) return undefined;\n\n    const values = childrenByLocalName(dim, \"Value\")\n      .map((v) => v.textContent?.trim())\n      .filter((v): v is string => Boolean(v));\n\n    return { default: defaultValue, values };\n  }\n  return undefined;\n}\n\n/**\n * Parses the first legend URL advertised in a layer's default style.\n */\nfunction parseLegendUrl(layerEl: Element): string | undefined {\n  const styles = childrenByLocalName(layerEl, \"Style\");\n  for (const style of styles) {\n    const legend = childrenByLocalName(style, \"LegendURL\")[0];\n    const href =\n      legend?.getAttribute(\"xlink:href\") ??\n      legend?.getAttributeNS(null, \"href\");\n    if (href) return href;\n  }\n  return undefined;\n}\n\n/**\n * Parses a single WMTS Layer element into a GibsLayer.\n * Returns undefined for layers that cannot be represented (missing\n * identifier, no tile resource template, or unsupported format).\n */\nfunction parseLayer(\n  layerEl: Element,\n  includeVector: boolean,\n): GibsLayer | undefined {\n  const id = childText(layerEl, \"Identifier\");\n  if (!id) return undefined;\n\n  const title = childText(layerEl, \"Title\") ?? id;\n\n  // Collect supported formats; prefer png > jpeg > mvt.\n  const formats = childrenByLocalName(layerEl, \"Format\")\n    .map((f) => FORMAT_MAP[f.textContent?.trim() ?? \"\"])\n    .filter((f): f is GibsLayerFormat => Boolean(f));\n  const format = ([\"png\", \"jpeg\", \"mvt\"] as const).find((f) =>\n    formats.includes(f),\n  );\n  if (!format) return undefined;\n  if (format === \"mvt\" && !includeVector) return undefined;\n\n  // Tile matrix set link, e.g. \"GoogleMapsCompatible_Level9\" -> maxZoom 9.\n  const tmsLink = childrenByLocalName(layerEl, \"TileMatrixSetLink\")[0];\n  const tileMatrixSet = tmsLink\n    ? childText(tmsLink, \"TileMatrixSet\")\n    : undefined;\n  if (!tileMatrixSet) return undefined;\n  const levelMatch = /Level(\\d+)$/.exec(tileMatrixSet);\n  const maxZoom = levelMatch ? parseInt(levelMatch[1], 10) : 9;\n\n  // Tile resource template. Only consider templates whose advertised format\n  // matches the chosen layer format, then prefer the template containing\n  // {Time} when the layer is time-enabled so dates can be substituted.\n  const resourceUrls = childrenByLocalName(layerEl, \"ResourceURL\").filter(\n    (r) => r.getAttribute(\"resourceType\") === \"tile\",\n  );\n  if (resourceUrls.length === 0) return undefined;\n\n  const selectedMime = MIME_MAP[format];\n  const formatMatched = resourceUrls.filter((r) => {\n    const mime = r.getAttribute(\"format\")?.trim().toLowerCase();\n    return !mime || mime === selectedMime;\n  });\n\n  const templates = (formatMatched.length > 0 ? formatMatched : resourceUrls)\n    .map((r) => r.getAttribute(\"template\"))\n    .filter((t): t is string => Boolean(t));\n  if (templates.length === 0) return undefined;\n\n  const time = parseTimeDimension(layerEl);\n  const resourceTemplate =\n    (time ? templates.find((t) => t.includes(\"{Time}\")) : undefined) ??\n    templates.find((t) => !t.includes(\"{Time}\")) ??\n    templates[0];\n\n  const extMatch = /\\.([a-z0-9]+)$/i.exec(resourceTemplate);\n  const fileExtension = extMatch\n    ? extMatch[1]\n    : format === \"jpeg\"\n      ? \"jpg\"\n      : format;\n\n  return {\n    id,\n    title,\n    // Platform/instrument prefix of the identifier, used for grouping\n    category: id.split(\"_\")[0],\n    format,\n    fileExtension,\n    tileMatrixSet,\n    maxZoom,\n    bbox: parseBbox(layerEl),\n    resourceTemplate,\n    time,\n    legendUrl: parseLegendUrl(layerEl),\n  };\n}\n\n/**\n * Parses a WMTS GetCapabilities XML document into a GibsCapabilities object.\n *\n * Layers without a usable tile resource template are skipped. Vector-tile\n * (MVT) layers are skipped unless `options.includeVector` is true.\n *\n * @param xml - The raw WMTSCapabilities.xml document text\n * @param options - Parse options\n * @returns Parsed capabilities with layers sorted by title\n */\nexport function parseCapabilities(\n  xml: string,\n  options?: ParseOptions,\n): GibsCapabilities {\n  const includeVector = options?.includeVector ?? false;\n\n  const doc = new DOMParser().parseFromString(xml, \"application/xml\");\n  const parserError = doc.getElementsByTagName(\"parsererror\")[0];\n  if (parserError) {\n    throw new Error(\n      `Failed to parse capabilities XML: ${parserError.textContent ?? \"unknown error\"}`,\n    );\n  }\n\n  const root = doc.documentElement;\n  const contents = childrenByLocalName(root, \"Contents\")[0];\n  if (!contents) {\n    throw new Error(\"Invalid capabilities document: missing Contents element\");\n  }\n\n  const layers: GibsLayer[] = [];\n  for (const layerEl of childrenByLocalName(contents, \"Layer\")) {\n    const layer = parseLayer(layerEl, includeVector);\n    if (layer) layers.push(layer);\n  }\n\n  layers.sort((a, b) => a.title.localeCompare(b.title));\n\n  return { layers, fetchedAt: Date.now() };\n}\n","import type { GibsLayer } from \"./types\";\n\n/**\n * Filters GIBS layers by a free-text query.\n *\n * Performs a case-insensitive substring match against the layer title and\n * identifier. An empty or whitespace-only query returns all layers.\n *\n * @param layers - The layers to search\n * @param query - The search query\n * @returns Layers whose title or identifier contains the query\n */\nexport function searchLayers(layers: GibsLayer[], query: string): GibsLayer[] {\n  const q = query.trim().toLowerCase();\n  if (!q) return layers;\n\n  return layers.filter(\n    (layer) =>\n      layer.title.toLowerCase().includes(q) ||\n      layer.id.toLowerCase().includes(q),\n  );\n}\n","import { parseCapabilities } from \"./parseCapabilities\";\nimport { searchLayers } from \"./search\";\nimport type { GibsCapabilities, GibsLayer } from \"./types\";\n\n/**\n * Default URL of the NASA GIBS WMTS capabilities document (EPSG:3857, \"best\" imagery).\n */\nexport const DEFAULT_CAPABILITIES_URL =\n  \"https://gibs.earthdata.nasa.gov/wmts/epsg3857/best/1.0.0/WMTSCapabilities.xml\";\n\n/**\n * Options for creating a GibsClient.\n */\nexport interface GibsClientOptions {\n  /**\n   * URL of the WMTS capabilities document.\n   * @default DEFAULT_CAPABILITIES_URL\n   */\n  url?: string;\n\n  /**\n   * Whether to include vector-tile (MVT) layers.\n   * @default false\n   */\n  includeVector?: boolean;\n}\n\n/**\n * Fetches, parses, and caches the NASA GIBS WMTS capabilities document.\n *\n * Concurrent calls to {@link GibsClient.getCapabilities} are deduplicated:\n * the document is fetched and parsed at most once unless `force` is passed.\n *\n * @example\n * ```typescript\n * const client = new GibsClient();\n * const { layers } = await client.getCapabilities();\n * const matches = client.search('temperature');\n * ```\n */\nexport class GibsClient {\n  private _url: string;\n  private _includeVector: boolean;\n  private _capabilities?: GibsCapabilities;\n  private _pending?: Promise<GibsCapabilities>;\n\n  /**\n   * Creates a new GibsClient.\n   *\n   * @param options - Client options\n   */\n  constructor(options?: GibsClientOptions) {\n    this._url = options?.url ?? DEFAULT_CAPABILITIES_URL;\n    this._includeVector = options?.includeVector ?? false;\n  }\n\n  /**\n   * Fetches and parses the capabilities document, caching the result.\n   *\n   * @param force - If true, refetch even if a cached result exists\n   * @returns The parsed capabilities\n   */\n  async getCapabilities(force = false): Promise<GibsCapabilities> {\n    if (this._capabilities && !force) return this._capabilities;\n    if (this._pending && !force) return this._pending;\n\n    this._pending = (async () => {\n      const response = await fetch(this._url);\n      if (!response.ok) {\n        throw new Error(\n          `Failed to fetch capabilities: ${response.status} ${response.statusText}`,\n        );\n      }\n      const xml = await response.text();\n      const capabilities = parseCapabilities(xml, {\n        includeVector: this._includeVector,\n      });\n      this._capabilities = capabilities;\n      return capabilities;\n    })();\n\n    try {\n      return await this._pending;\n    } finally {\n      this._pending = undefined;\n    }\n  }\n\n  /**\n   * Returns the cached capabilities, if already loaded.\n   */\n  getCachedCapabilities(): GibsCapabilities | undefined {\n    return this._capabilities;\n  }\n\n  /**\n   * Searches the cached layers by title or identifier.\n   * Returns an empty array if capabilities have not been loaded yet.\n   *\n   * @param query - The search query\n   */\n  search(query: string): GibsLayer[] {\n    return searchLayers(this._capabilities?.layers ?? [], query);\n  }\n\n  /**\n   * Looks up a cached layer by identifier.\n   *\n   * @param id - The layer identifier\n   */\n  getLayer(id: string): GibsLayer | undefined {\n    return this._capabilities?.layers.find((layer) => layer.id === id);\n  }\n}\n","import type { GibsLayer } from \"./types\";\n\n/**\n * Builds a MapLibre-compatible XYZ tile URL template from a GIBS layer.\n *\n * Substitutes {Time} with the given date (or the layer's default date),\n * {TileMatrixSet} with the layer's tile matrix set, and maps the WMTS\n * placeholders {TileMatrix}/{TileRow}/{TileCol} to {z}/{y}/{x}.\n *\n * @param layer - The GIBS layer to build a URL for\n * @param time - Optional ISO 8601 date overriding the layer's default date\n * @returns A tile URL template usable in a MapLibre raster source\n */\nexport function buildTileUrl(layer: GibsLayer, time?: string): string {\n  return layer.resourceTemplate\n    .replace(\"{Time}\", time ?? layer.time?.default ?? \"default\")\n    .replace(\"{TileMatrixSet}\", layer.tileMatrixSet)\n    .replace(\"{TileMatrix}\", \"{z}\")\n    .replace(\"{TileRow}\", \"{y}\")\n    .replace(\"{TileCol}\", \"{x}\");\n}\n","/**\n * Clamps a value between a minimum and maximum.\n *\n * @param value - The value to clamp\n * @param min - The minimum allowed value\n * @param max - The maximum allowed value\n * @returns The clamped value\n *\n * @example\n * ```typescript\n * clamp(5, 0, 10);  // returns 5\n * clamp(-5, 0, 10); // returns 0\n * clamp(15, 0, 10); // returns 10\n * ```\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 numeric value with appropriate decimal places based on step size.\n *\n * @param value - The value to format\n * @param step - The step size to determine decimal places\n * @returns The formatted value as a string\n *\n * @example\n * ```typescript\n * formatNumericValue(5, 1);     // returns \"5\"\n * formatNumericValue(0.5, 0.1); // returns \"0.5\"\n * formatNumericValue(0.55, 0.01); // returns \"0.55\"\n * ```\n */\nexport function formatNumericValue(value: number, step: number): string {\n  if (step === 0) return value.toString();\n  const decimals = Math.max(0, -Math.floor(Math.log10(step)));\n  return value.toFixed(decimals);\n}\n\n/**\n * Generates a unique ID string.\n *\n * @param prefix - Optional prefix for the ID\n * @returns A unique ID string\n *\n * @example\n * ```typescript\n * generateId('control'); // returns \"control-abc123\"\n * generateId();          // returns \"abc123\"\n * ```\n */\nexport function generateId(prefix?: string): string {\n  const id = Math.random().toString(36).substring(2, 9);\n  return prefix ? `${prefix}-${id}` : id;\n}\n\n/**\n * Debounces a function call.\n *\n * @param fn - The function to debounce\n * @param delay - The delay in milliseconds\n * @returns A debounced version of the function\n *\n * @example\n * ```typescript\n * const debouncedUpdate = debounce(() => updateMap(), 100);\n * window.addEventListener('resize', debouncedUpdate);\n * ```\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> | null = null;\n\n  return (...args: Parameters<T>) => {\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n    }\n    timeoutId = setTimeout(() => {\n      fn(...args);\n      timeoutId = null;\n    }, delay);\n  };\n}\n\n/**\n * Throttles a function call.\n *\n * @param fn - The function to throttle\n * @param limit - The minimum time between calls in milliseconds\n * @returns A throttled version of the function\n *\n * @example\n * ```typescript\n * const throttledScroll = throttle(() => handleScroll(), 100);\n * window.addEventListener('scroll', throttledScroll);\n * ```\n */\nexport function throttle<T extends (...args: unknown[]) => void>(\n  fn: T,\n  limit: number,\n): (...args: Parameters<T>) => void {\n  let inThrottle = false;\n\n  return (...args: Parameters<T>) => {\n    if (!inThrottle) {\n      fn(...args);\n      inThrottle = true;\n      setTimeout(() => {\n        inThrottle = false;\n      }, limit);\n    }\n  };\n}\n\n/**\n * Creates a CSS class string from an object of class names.\n *\n * @param classes - Object with class names as keys and boolean values\n * @returns A space-separated string of class names\n *\n * @example\n * ```typescript\n * classNames({ active: true, disabled: false, visible: true });\n * // returns \"active visible\"\n * ```\n */\nexport function classNames(classes: Record<string, boolean>): string {\n  return Object.entries(classes)\n    .filter(([, value]) => value)\n    .map(([key]) => key)\n    .join(\" \");\n}\n","import type {\n  IControl,\n  Map as MapLibreMap,\n  RasterTileSource,\n} from \"maplibre-gl\";\nimport { GibsClient, DEFAULT_CAPABILITIES_URL } from \"../gibs/GibsClient\";\nimport { buildTileUrl } from \"../gibs/tileUrl\";\nimport { searchLayers } from \"../gibs/search\";\nimport type { GibsCapabilities, GibsLayer } from \"../gibs/types\";\nimport { clamp, debounce } from \"../utils\";\nimport type {\n  NasaEarthdataControlOptions,\n  NasaEarthdataState,\n  NasaEarthdataEvent,\n  NasaEarthdataEventHandler,\n  NasaEarthdataEventPayload,\n  AddedLayerState,\n} from \"./types\";\n\n/**\n * Default options for the NasaEarthdataControl\n */\nconst DEFAULT_OPTIONS: Required<NasaEarthdataControlOptions> = {\n  collapsed: true,\n  position: \"top-right\",\n  title: \"NASA Earthdata\",\n  panelWidth: 320,\n  className: \"\",\n  capabilitiesUrl: DEFAULT_CAPABILITIES_URL,\n  includeVector: false,\n  showOpacity: true,\n  attribution:\n    '<a href=\"https://earthdata.nasa.gov/gibs\" target=\"_blank\">NASA EOSDIS GIBS</a>',\n  theme: \"auto\",\n};\n\n/**\n * Prefix used for source and layer ids added to the map\n */\nconst LAYER_ID_PREFIX = \"nasa-gibs-\";\n\n/**\n * Event handlers map type\n */\ntype EventHandlersMap = globalThis.Map<\n  NasaEarthdataEvent,\n  Set<NasaEarthdataEventHandler>\n>;\n\n/**\n * A MapLibre GL control for searching and adding NASA GIBS (Global Imagery\n * Browse Services) WMTS layers to the map.\n *\n * The control renders a collapsible button. When expanded, it fetches the\n * GIBS capabilities document, lets the user search the layer catalog, and\n * add/remove raster layers with per-layer date and opacity controls.\n *\n * @example\n * ```typescript\n * const control = new NasaEarthdataControl({\n *   title: 'NASA Earthdata',\n *   collapsed: false,\n * });\n * map.addControl(control, 'top-right');\n * control.on('layeradd', (e) => console.log('Added', e.layer?.id));\n * ```\n */\nexport class NasaEarthdataControl implements IControl {\n  private _map?: MapLibreMap;\n  private _mapContainer?: HTMLElement;\n  private _container?: HTMLElement;\n  private _panel?: HTMLElement;\n  private _options: Required<NasaEarthdataControlOptions>;\n  private _state: NasaEarthdataState;\n  private _eventHandlers: EventHandlersMap = new globalThis.Map();\n\n  private _client: GibsClient;\n  private _capabilities?: GibsCapabilities;\n  private _loading = false;\n  private _addedLayers: globalThis.Map<string, AddedLayerState> =\n    new globalThis.Map();\n\n  // Panel content elements\n  private _searchInput?: HTMLInputElement;\n  private _metaEl?: HTMLElement;\n  private _resultsEl?: HTMLElement;\n  private _addedEl?: HTMLElement;\n  private _insertSelect?: HTMLSelectElement;\n\n  // UI state: expanded category groups, open legends, insertion position\n  private _expandedCategories = new Set<string>();\n  private _openLegends = new Set<string>();\n  private _insertBefore = \"\";\n\n  // Panel positioning handlers\n  private _resizeHandler: (() => void) | null = null;\n  private _mapResizeHandler: (() => void) | null = null;\n  private _clickOutsideHandler: ((e: MouseEvent) => void) | null = null;\n\n  /**\n   * Creates a new NasaEarthdataControl instance.\n   *\n   * @param options - Configuration options for the control\n   */\n  constructor(options?: Partial<NasaEarthdataControlOptions>) {\n    this._options = { ...DEFAULT_OPTIONS, ...options };\n    this._state = {\n      collapsed: this._options.collapsed,\n      panelWidth: this._options.panelWidth,\n      query: \"\",\n      addedLayers: [],\n    };\n    this._client = new GibsClient({\n      url: this._options.capabilitiesUrl,\n      includeVector: this._options.includeVector,\n    });\n  }\n\n  /**\n   * Called when the control is added to the map.\n   * Implements the IControl interface.\n   *\n   * @param map - The MapLibre GL map instance\n   * @returns The control's container element\n   */\n  onAdd(map: MapLibreMap): HTMLElement {\n    this._map = map;\n    this._mapContainer = map.getContainer();\n    this._container = this._createContainer();\n    this._panel = this._createPanel();\n\n    // Append panel to map container for independent positioning (avoids overlap with other controls)\n    this._mapContainer.appendChild(this._panel);\n\n    // Setup event listeners for panel positioning and click-outside\n    this._setupEventListeners();\n\n    // Set initial panel state\n    if (!this._state.collapsed) {\n      this._panel.classList.add(\"expanded\");\n      this._loadCapabilities();\n      // Update position after control is added to DOM\n      requestAnimationFrame(() => {\n        this._updatePanelPosition();\n      });\n    }\n\n    return this._container;\n  }\n\n  /**\n   * Called when the control is removed from the map.\n   * Implements the IControl interface.\n   */\n  onRemove(): void {\n    // Remove all added GIBS layers and sources from the map\n    for (const layerId of Array.from(this._addedLayers.keys())) {\n      this._removeMapLayer(layerId);\n    }\n    this._addedLayers.clear();\n    this._state.addedLayers = [];\n\n    // Remove event listeners\n    if (this._resizeHandler) {\n      window.removeEventListener(\"resize\", this._resizeHandler);\n      this._resizeHandler = null;\n    }\n    if (this._mapResizeHandler && this._map) {\n      this._map.off(\"resize\", this._mapResizeHandler);\n      this._mapResizeHandler = null;\n    }\n    if (this._clickOutsideHandler) {\n      document.removeEventListener(\"click\", this._clickOutsideHandler);\n      this._clickOutsideHandler = null;\n    }\n\n    // Remove panel from map container\n    this._panel?.parentNode?.removeChild(this._panel);\n\n    // Remove button container from control stack\n    this._container?.parentNode?.removeChild(this._container);\n\n    this._map = undefined;\n    this._mapContainer = undefined;\n    this._container = undefined;\n    this._panel = undefined;\n    this._searchInput = undefined;\n    this._metaEl = undefined;\n    this._resultsEl = undefined;\n    this._addedEl = undefined;\n    this._insertSelect = undefined;\n    this._openLegends.clear();\n    this._eventHandlers.clear();\n  }\n\n  /**\n   * Gets the current state of the control.\n   *\n   * @returns The current control state\n   */\n  getState(): NasaEarthdataState {\n    return {\n      ...this._state,\n      addedLayers: this._state.addedLayers.map((l) => ({ ...l })),\n    };\n  }\n\n  /**\n   * Updates the control state. Changes to `addedLayers` are reconciled\n   * against the map: missing layers are added, extra layers are removed,\n   * and date/opacity changes are applied.\n   *\n   * @param newState - Partial state to merge with current state\n   */\n  setState(newState: Partial<NasaEarthdataState>): void {\n    if (\n      newState.collapsed !== undefined &&\n      newState.collapsed !== this._state.collapsed\n    ) {\n      if (newState.collapsed) {\n        this.collapse();\n      } else {\n        this.expand();\n      }\n    }\n\n    if (newState.panelWidth !== undefined) {\n      this._state.panelWidth = newState.panelWidth;\n      if (this._panel) {\n        this._panel.style.width = `${newState.panelWidth}px`;\n      }\n    }\n\n    if (newState.query !== undefined && newState.query !== this._state.query) {\n      this._state.query = newState.query;\n      if (this._searchInput) {\n        this._searchInput.value = newState.query;\n      }\n      this._renderResults();\n    }\n\n    let deferStateEmit = false;\n    if (newState.addedLayers) {\n      // Reconciliation needs the layer catalog; defer it until the\n      // capabilities are loaded so state restoration works before the\n      // panel is first expanded. An empty list needs no catalog data.\n      const desired = newState.addedLayers.map((l) => ({ ...l }));\n      if (desired.length === 0 || this._capabilities) {\n        this._reconcileAddedLayers(desired);\n      } else {\n        // Emit statechange only after reconciliation so listeners never\n        // see a stale addedLayers snapshot.\n        deferStateEmit = true;\n        void this.getCapabilities()\n          .then(() => {\n            this._reconcileAddedLayers(desired);\n            this._renderResults();\n            this._renderAddedSection();\n            this._emit(\"statechange\");\n          })\n          .catch((error: unknown) => {\n            const err =\n              error instanceof Error ? error : new Error(String(error));\n            this._emitError(err);\n          });\n      }\n    }\n\n    if (!deferStateEmit) {\n      this._emit(\"statechange\");\n    }\n  }\n\n  /**\n   * Toggles the collapsed state of the control panel.\n   */\n  toggle(): void {\n    this._state.collapsed = !this._state.collapsed;\n\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._loadCapabilities();\n        this._refreshInsertOptions();\n        this._emit(\"expand\");\n      }\n    }\n\n    this._emit(\"statechange\");\n  }\n\n  /**\n   * Expands the control panel.\n   */\n  expand(): void {\n    if (this._state.collapsed) {\n      this.toggle();\n    }\n  }\n\n  /**\n   * Collapses the control panel.\n   */\n  collapse(): void {\n    if (!this._state.collapsed) {\n      this.toggle();\n    }\n  }\n\n  /**\n   * Registers an event handler.\n   *\n   * @param event - The event type to listen for\n   * @param handler - The callback function\n   */\n  on(event: NasaEarthdataEvent, handler: NasaEarthdataEventHandler): 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 - The event type\n   * @param handler - The callback function to remove\n   */\n  off(event: NasaEarthdataEvent, handler: NasaEarthdataEventHandler): void {\n    this._eventHandlers.get(event)?.delete(handler);\n  }\n\n  /**\n   * Gets the map instance.\n   *\n   * @returns The MapLibre GL map instance or undefined if not added to a map\n   */\n  getMap(): MapLibreMap | undefined {\n    return this._map;\n  }\n\n  /**\n   * Gets the control container element.\n   *\n   * @returns The container element or undefined if not added to a map\n   */\n  getContainer(): HTMLElement | undefined {\n    return this._container;\n  }\n\n  /**\n   * Fetches and caches the GIBS capabilities document.\n   *\n   * @param force - If true, refetch even if cached\n   * @returns The parsed capabilities\n   */\n  async getCapabilities(force = false): Promise<GibsCapabilities> {\n    const capabilities = await this._client.getCapabilities(force);\n    this._capabilities = capabilities;\n    return capabilities;\n  }\n\n  /**\n   * Searches the loaded GIBS layers by title or identifier.\n   * Returns an empty array if the capabilities have not been loaded yet.\n   *\n   * @param query - The search query\n   * @returns Matching layers\n   */\n  search(query: string): GibsLayer[] {\n    return searchLayers(this._capabilities?.layers ?? [], query);\n  }\n\n  /**\n   * Gets the state of all layers currently added to the map.\n   *\n   * @returns Added layer states\n   */\n  getAddedLayers(): AddedLayerState[] {\n    return Array.from(this._addedLayers.values()).map((l) => ({ ...l }));\n  }\n\n  /**\n   * Adds a GIBS layer to the map as a raster source and layer.\n   * Requires the capabilities to be loaded (call getCapabilities() first\n   * when using the control programmatically).\n   *\n   * @param layerId - The GIBS layer identifier\n   * @param options - Optional date, opacity, visibility, and insertion position\n   */\n  addLayer(\n    layerId: string,\n    options?: {\n      date?: string;\n      opacity?: number;\n      visible?: boolean;\n      before?: string;\n      key?: string;\n    },\n  ): void {\n    if (!this._map) return;\n\n    const layer = this._client.getLayer(layerId);\n    if (!layer) {\n      this._emitError(\n        new Error(`Unknown GIBS layer: ${layerId} (capabilities not loaded?)`),\n      );\n      return;\n    }\n\n    const date = options?.date ?? layer.time?.default;\n    const opacity = clamp(options?.opacity ?? 1, 0, 1);\n    const visible = options?.visible ?? true;\n    const before = options?.before ?? this._insertBefore;\n\n    // Restoring a known instance key is a no-op if it is already on the map\n    if (options?.key && this._addedLayers.has(options.key)) return;\n    const key = options?.key ?? this._instanceKey(layer, date);\n    const mapId = LAYER_ID_PREFIX + key;\n\n    // Host applications that persist and restore layers may have already\n    // recreated the native source/layer from saved state. Reuse them when\n    // present instead of re-adding (which would throw on a duplicate id),\n    // and apply the requested opacity/visibility so control state and map\n    // agree.\n    if (!this._map.getSource(mapId)) {\n      this._map.addSource(mapId, {\n        type: \"raster\",\n        tiles: [buildTileUrl(layer, date)],\n        tileSize: 256,\n        maxzoom: layer.maxZoom,\n        attribution: this._options.attribution,\n      });\n    }\n    if (!this._map.getLayer(mapId)) {\n      this._map.addLayer(\n        {\n          id: mapId,\n          type: \"raster\",\n          source: mapId,\n          paint: { \"raster-opacity\": opacity },\n          layout: { visibility: visible ? \"visible\" : \"none\" },\n        },\n        before && this._map.getLayer(before) ? before : undefined,\n      );\n    } else {\n      this._map.setPaintProperty(mapId, \"raster-opacity\", opacity);\n      this._map.setLayoutProperty(\n        mapId,\n        \"visibility\",\n        visible ? \"visible\" : \"none\",\n      );\n    }\n\n    const added: AddedLayerState = { key, id: layerId, date, opacity, visible };\n    this._addedLayers.set(key, added);\n    this._syncAddedLayersState();\n    this._renderResults();\n    this._renderAddedSection();\n    this._refreshInsertOptions();\n    this._emit(\"layeradd\", { layer });\n    this._emit(\"statechange\");\n  }\n\n  /**\n   * Builds a unique instance key for a layer/date pair. Non-time layers can\n   * only be added once; time-enabled layers get one instance per addition,\n   * so a numeric suffix disambiguates repeated adds at the same date.\n   */\n  private _instanceKey(layer: GibsLayer, date?: string): string {\n    if (!layer.time) return layer.id;\n\n    const base = `${layer.id}@${date ?? layer.time.default}`;\n    if (!this._addedLayers.has(base)) return base;\n    let n = 2;\n    while (this._addedLayers.has(`${base}#${n}`)) n++;\n    return `${base}#${n}`;\n  }\n\n  /**\n   * Resolves an instance key or a GIBS layer identifier to instances.\n   * An exact key match wins; otherwise all instances of the layer match.\n   */\n  private _resolveInstances(keyOrId: string): AddedLayerState[] {\n    const exact = this._addedLayers.get(keyOrId);\n    if (exact) return [exact];\n    return Array.from(this._addedLayers.values()).filter(\n      (l) => l.id === keyOrId,\n    );\n  }\n\n  /**\n   * Removes added GIBS layer instances from the map. Pass an instance key\n   * to remove a single instance, or a GIBS layer identifier to remove all\n   * instances of that layer.\n   *\n   * @param keyOrId - An instance key or a GIBS layer identifier\n   */\n  removeLayer(keyOrId: string): void {\n    const instances = this._resolveInstances(keyOrId);\n    if (instances.length === 0) return;\n\n    for (const instance of instances) {\n      this._removeMapLayer(instance.key);\n      this._addedLayers.delete(instance.key);\n      this._openLegends.delete(instance.key);\n      this._emit(\"layerremove\", { layer: this._client.getLayer(instance.id) });\n    }\n    this._syncAddedLayersState();\n    this._renderResults();\n    this._renderAddedSection();\n    this._refreshInsertOptions();\n    this._emit(\"statechange\");\n  }\n\n  /**\n   * Changes the date of an added time-enabled layer instance.\n   *\n   * @param keyOrId - An instance key or a GIBS layer identifier\n   * @param date - The new ISO 8601 date\n   */\n  setLayerDate(keyOrId: string, date: string): void {\n    const added = this._resolveInstances(keyOrId)[0];\n    const layer = added ? this._client.getLayer(added.id) : undefined;\n    if (!this._map || !added || !layer) return;\n\n    added.date = date;\n    const mapId = LAYER_ID_PREFIX + added.key;\n    const source = this._map.getSource(mapId) as RasterTileSource | undefined;\n    const tiles = [buildTileUrl(layer, date)];\n\n    if (source && typeof source.setTiles === \"function\") {\n      source.setTiles(tiles);\n    } else {\n      // Fallback: re-create the source and layer\n      this._removeMapLayer(added.key);\n      this._addedLayers.delete(added.key);\n      this.addLayer(added.id, {\n        date,\n        opacity: added.opacity,\n        visible: added.visible,\n        key: added.key,\n      });\n      return;\n    }\n\n    this._syncAddedLayersState();\n    this._emit(\"statechange\");\n  }\n\n  /**\n   * Changes the opacity of an added layer instance.\n   *\n   * @param keyOrId - An instance key or a GIBS layer identifier\n   * @param opacity - The new opacity (0 to 1)\n   */\n  setLayerOpacity(keyOrId: string, opacity: number): void {\n    const added = this._resolveInstances(keyOrId)[0];\n    if (!this._map || !added) return;\n\n    added.opacity = clamp(opacity, 0, 1);\n    this._map.setPaintProperty(\n      LAYER_ID_PREFIX + added.key,\n      \"raster-opacity\",\n      added.opacity,\n    );\n    this._syncAddedLayersState();\n    this._emit(\"statechange\");\n  }\n\n  /**\n   * Toggles the visibility of an added layer instance on the map.\n   *\n   * @param keyOrId - An instance key or a GIBS layer identifier\n   * @param visible - Whether the layer should be visible\n   */\n  setLayerVisibility(keyOrId: string, visible: boolean): void {\n    const added = this._resolveInstances(keyOrId)[0];\n    if (!this._map || !added) return;\n\n    added.visible = visible;\n    this._map.setLayoutProperty(\n      LAYER_ID_PREFIX + added.key,\n      \"visibility\",\n      visible ? \"visible\" : \"none\",\n    );\n    this._syncAddedLayersState();\n    this._emit(\"statechange\");\n  }\n\n  /**\n   * Removes the map source and layer for an instance key, if present.\n   */\n  private _removeMapLayer(key: string): void {\n    if (!this._map) return;\n    const mapId = LAYER_ID_PREFIX + key;\n    if (this._map.getLayer(mapId)) {\n      this._map.removeLayer(mapId);\n    }\n    if (this._map.getSource(mapId)) {\n      this._map.removeSource(mapId);\n    }\n  }\n\n  /**\n   * Mirrors the internal added-layers map into the serializable state.\n   */\n  private _syncAddedLayersState(): void {\n    this._state.addedLayers = this.getAddedLayers();\n  }\n\n  /**\n   * Reconciles a desired added-layers list against the map:\n   * adds missing layers, removes extras, and applies date/opacity changes.\n   */\n  private _reconcileAddedLayers(desired: AddedLayerState[]): void {\n    const desiredKeys = new Set(desired.map((l) => l.key));\n\n    for (const existingKey of Array.from(this._addedLayers.keys())) {\n      if (!desiredKeys.has(existingKey)) {\n        this.removeLayer(existingKey);\n      }\n    }\n\n    for (const target of desired) {\n      const existing = this._addedLayers.get(target.key);\n      if (!existing) {\n        this.addLayer(target.id, {\n          date: target.date,\n          opacity: target.opacity,\n          visible: target.visible,\n          key: target.key,\n        });\n      } else {\n        if (target.date && target.date !== existing.date) {\n          this.setLayerDate(target.key, target.date);\n        }\n        if (\n          target.opacity !== undefined &&\n          target.opacity !== existing.opacity\n        ) {\n          this.setLayerOpacity(target.key, target.opacity);\n        }\n        if (\n          target.visible !== undefined &&\n          target.visible !== existing.visible\n        ) {\n          this.setLayerVisibility(target.key, target.visible);\n        }\n      }\n    }\n  }\n\n  /**\n   * Loads the capabilities document (once) and renders the results list.\n   */\n  private _loadCapabilities(): void {\n    if (this._capabilities || this._loading) return;\n\n    this._loading = true;\n    this._renderStatus(\"Loading NASA GIBS layer catalog…\");\n\n    this.getCapabilities()\n      .then(() => {\n        this._loading = false;\n        this._renderResults();\n        this._renderAddedSection();\n        this._refreshInsertOptions();\n        this._emit(\"capabilitiesload\");\n      })\n      .catch((error: unknown) => {\n        this._loading = false;\n        const err = error instanceof Error ? error : new Error(String(error));\n        this._renderStatus(\n          `Failed to load layer catalog: ${err.message}`,\n          true,\n        );\n        this._emitError(err);\n      });\n  }\n\n  /**\n   * Emits an event to all registered handlers.\n   *\n   * @param event - The event type to emit\n   * @param extra - Extra payload fields (layer, error)\n   */\n  private _emit(\n    event: NasaEarthdataEvent,\n    extra?: Partial<NasaEarthdataEventPayload>,\n  ): void {\n    const handlers = this._eventHandlers.get(event);\n    if (handlers) {\n      const eventData: NasaEarthdataEventPayload = {\n        type: event,\n        state: this.getState(),\n        ...extra,\n      };\n      handlers.forEach((handler) => handler(eventData));\n    }\n  }\n\n  /**\n   * Emits an 'error' event.\n   */\n  private _emitError(error: Error): void {\n    this._emit(\"error\", { error });\n  }\n\n  /**\n   * Returns the theme class for the configured theme, if explicit.\n   */\n  private _themeClass(): string {\n    if (this._options.theme === \"dark\") return \" ne-theme-dark\";\n    if (this._options.theme === \"light\") return \" ne-theme-light\";\n    return \"\";\n  }\n\n  /**\n   * Creates the main container element for the control.\n   * Contains a toggle button (29x29) matching navigation control size.\n   *\n   * @returns The container element\n   */\n  private _createContainer(): HTMLElement {\n    const container = document.createElement(\"div\");\n    container.className = `maplibregl-ctrl maplibregl-ctrl-group plugin-control maplibre-gl-nasa-earthdata${this._themeClass()}${\n      this._options.className ? ` ${this._options.className}` : \"\"\n    }`;\n\n    // Create toggle button (29x29 to match navigation control)\n    const toggleBtn = document.createElement(\"button\");\n    toggleBtn.className = \"plugin-control-toggle\";\n    toggleBtn.type = \"button\";\n    toggleBtn.setAttribute(\"aria-label\", this._options.title);\n    // Satellite-dish icon. A distinct, recognizable mark for NASA Earthdata's\n    // ground-station data access that avoids colliding with the generic globe\n    // icon used by core map functionality in host apps, and with the satellite\n    // icon used by the sibling NASA OPERA control.\n    toggleBtn.innerHTML = `\n      <span class=\"plugin-control-icon\">\n        <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n          <path d=\"M4 10a7.31 7.31 0 0 0 10 10Z\"/>\n          <path d=\"m9 15 3-3\"/>\n          <path d=\"M17 13a6 6 0 0 0-6-6\"/>\n          <path d=\"M21 13A10 10 0 0 0 11 3\"/>\n        </svg>\n      </span>\n    `;\n    toggleBtn.addEventListener(\"click\", () => this.toggle());\n\n    container.appendChild(toggleBtn);\n\n    return container;\n  }\n\n  /**\n   * Creates the panel element with header, search box, and results list.\n   * Panel is positioned as a dropdown below the toggle button.\n   *\n   * @returns The panel element\n   */\n  private _createPanel(): HTMLElement {\n    const panel = document.createElement(\"div\");\n    panel.className = `plugin-control-panel maplibre-gl-nasa-earthdata${this._themeClass()}`;\n    panel.style.width = `${this._options.panelWidth}px`;\n\n    // Create header with title and close button\n    const header = document.createElement(\"div\");\n    header.className = \"plugin-control-header\";\n\n    const title = document.createElement(\"span\");\n    title.className = \"plugin-control-title\";\n    title.textContent = this._options.title;\n\n    const closeBtn = document.createElement(\"button\");\n    closeBtn.className = \"plugin-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    // Create content area: search input, insert-before row, category list,\n    // and the added-layers management section\n    const content = document.createElement(\"div\");\n    content.className = \"plugin-control-content nasa-content\";\n\n    const search = document.createElement(\"input\");\n    search.className = \"plugin-control-input nasa-search\";\n    search.type = \"search\";\n    search.placeholder = \"Search layers (e.g. temperature)\";\n    search.setAttribute(\"aria-label\", \"Search NASA GIBS layers\");\n    search.value = this._state.query;\n    const onSearch = debounce(() => {\n      this._state.query = search.value;\n      this._renderResults();\n      this._emit(\"statechange\");\n    }, 250);\n    search.addEventListener(\"input\", onSearch);\n    this._searchInput = search;\n\n    // \"Insert before\" row: choose where new layers are inserted in the\n    // map's layer stack\n    const insertRow = document.createElement(\"div\");\n    insertRow.className = \"nasa-insert-row\";\n\n    const insertLabel = document.createElement(\"span\");\n    insertLabel.className = \"nasa-insert-label\";\n    insertLabel.textContent = \"Insert before\";\n\n    const insertSelect = document.createElement(\"select\");\n    insertSelect.className = \"nasa-insert-select\";\n    insertSelect.setAttribute(\"aria-label\", \"Insert new layers before\");\n    insertSelect.addEventListener(\"change\", () => {\n      this._insertBefore = insertSelect.value;\n    });\n    this._insertSelect = insertSelect;\n\n    insertRow.appendChild(insertLabel);\n    insertRow.appendChild(insertSelect);\n\n    const meta = document.createElement(\"div\");\n    meta.className = \"nasa-meta\";\n    this._metaEl = meta;\n\n    // Scrollable body holding the category groups and the added layers\n    const body = document.createElement(\"div\");\n    body.className = \"nasa-body\";\n\n    const results = document.createElement(\"div\");\n    results.className = \"nasa-results\";\n    this._resultsEl = results;\n\n    const added = document.createElement(\"div\");\n    added.className = \"nasa-added-section\";\n    this._addedEl = added;\n\n    body.appendChild(results);\n    body.appendChild(added);\n\n    content.appendChild(search);\n    content.appendChild(insertRow);\n    content.appendChild(meta);\n    content.appendChild(body);\n\n    panel.appendChild(header);\n    panel.appendChild(content);\n\n    // Resize handle on the panel's outer edge for adjusting the width by\n    // dragging. _updatePanelPosition() moves it to the correct side for the\n    // control corner (left edge when right-anchored, right edge when\n    // left-anchored).\n    const resizeHandle = document.createElement(\"div\");\n    resizeHandle.className = \"nasa-resize-handle\";\n    resizeHandle.setAttribute(\"aria-hidden\", \"true\");\n    resizeHandle.addEventListener(\"pointerdown\", (e) =>\n      this._startResize(e, resizeHandle),\n    );\n    panel.appendChild(resizeHandle);\n\n    return panel;\n  }\n\n  /**\n   * Returns the maximum panel width that fits the map container.\n   */\n  private _maxPanelWidth(): number {\n    return Math.max(\n      240,\n      (this._mapContainer?.getBoundingClientRect().width ?? window.innerWidth) -\n        20,\n    );\n  }\n\n  /**\n   * Clamps the panel width to the map container. Applied whenever the panel\n   * is (re)positioned so a saved width survives map shrinking.\n   */\n  private _applyPanelWidthBounds(): void {\n    if (!this._panel) return;\n    const width = Math.round(\n      clamp(this._state.panelWidth, 240, this._maxPanelWidth()),\n    );\n    this._state.panelWidth = width;\n    this._panel.style.width = `${width}px`;\n  }\n\n  /**\n   * Starts a panel width drag-resize. The drag direction is derived from\n   * the control corner so resizing works whether the panel is anchored to\n   * the left or the right edge of the map.\n   */\n  private _startResize(e: PointerEvent, handle: HTMLElement): void {\n    if (!this._panel) return;\n    e.preventDefault();\n\n    const startX = e.clientX;\n    const startWidth = this._panel.getBoundingClientRect().width;\n    // Right-anchored panels grow leftward, so invert the pointer delta\n    const anchoredRight = !this._getControlPosition().endsWith(\"left\");\n    const maxWidth = this._maxPanelWidth();\n\n    const onMove = (ev: PointerEvent) => {\n      const delta = anchoredRight ? startX - ev.clientX : ev.clientX - startX;\n      const width = Math.round(clamp(startWidth + delta, 240, maxWidth));\n      this._state.panelWidth = width;\n      if (this._panel) {\n        this._panel.style.width = `${width}px`;\n      }\n    };\n    const onEnd = (ev: PointerEvent) => {\n      handle.removeEventListener(\"pointermove\", onMove);\n      handle.removeEventListener(\"pointerup\", onEnd);\n      handle.removeEventListener(\"pointercancel\", onEnd);\n      if (handle.hasPointerCapture(ev.pointerId)) {\n        handle.releasePointerCapture(ev.pointerId);\n      }\n      this._panel?.classList.remove(\"nasa-resizing\");\n      this._emit(\"statechange\");\n    };\n\n    handle.setPointerCapture(e.pointerId);\n    handle.addEventListener(\"pointermove\", onMove);\n    handle.addEventListener(\"pointerup\", onEnd);\n    handle.addEventListener(\"pointercancel\", onEnd);\n    this._panel.classList.add(\"nasa-resizing\");\n  }\n\n  /**\n   * Shows a status message (loading or error) in the results area.\n   */\n  private _renderStatus(message: string, isError = false): void {\n    if (!this._resultsEl || !this._metaEl) return;\n    this._metaEl.textContent = \"\";\n    this._resultsEl.innerHTML = \"\";\n    const status = document.createElement(\"div\");\n    status.className = `nasa-status${isError ? \" nasa-status-error\" : \"\"}`;\n    status.textContent = message;\n    this._resultsEl.appendChild(status);\n  }\n\n  /**\n   * Groups layers by category, merging categories with fewer layers than\n   * the threshold into \"Other\". Returns entries sorted alphabetically\n   * with \"Other\" last.\n   */\n  private _groupByCategory(layers: GibsLayer[]): [string, GibsLayer[]][] {\n    const MIN_CATEGORY_SIZE = 3;\n    const all = this._capabilities?.layers ?? [];\n\n    // Count category sizes over the FULL catalog so a category does not\n    // flip into \"Other\" while filtering\n    const totals = new globalThis.Map<string, number>();\n    for (const layer of all) {\n      totals.set(layer.category, (totals.get(layer.category) ?? 0) + 1);\n    }\n\n    const groups = new globalThis.Map<string, GibsLayer[]>();\n    for (const layer of layers) {\n      const total = totals.get(layer.category) ?? 0;\n      const key = total >= MIN_CATEGORY_SIZE ? layer.category : \"Other\";\n      const group = groups.get(key);\n      if (group) {\n        group.push(layer);\n      } else {\n        groups.set(key, [layer]);\n      }\n    }\n\n    return Array.from(groups.entries()).sort(([a], [b]) => {\n      if (a === \"Other\") return 1;\n      if (b === \"Other\") return -1;\n      return a.localeCompare(b);\n    });\n  }\n\n  /**\n   * Renders the (filtered) layer catalog grouped by category.\n   */\n  private _renderResults(): void {\n    if (!this._resultsEl || !this._metaEl) return;\n    if (!this._capabilities) {\n      if (!this._loading) {\n        this._renderStatus(\"Expand the panel to load the layer catalog.\");\n      }\n      return;\n    }\n\n    const query = this._state.query.trim();\n    const matches = searchLayers(this._capabilities.layers, query);\n    const groups = this._groupByCategory(matches);\n\n    const layerWord = matches.length === 1 ? \"layer\" : \"layers\";\n    const categoryWord = groups.length === 1 ? \"category\" : \"categories\";\n    this._metaEl.textContent = `${matches.length} ${layerWord} in ${groups.length} ${categoryWord}`;\n\n    this._resultsEl.innerHTML = \"\";\n    if (matches.length === 0) {\n      const status = document.createElement(\"div\");\n      status.className = \"nasa-status\";\n      status.textContent = \"No layers match your search.\";\n      this._resultsEl.appendChild(status);\n      return;\n    }\n\n    for (const [category, layers] of groups) {\n      // While searching, auto-expand the matching categories\n      const expanded = query ? true : this._expandedCategories.has(category);\n      this._resultsEl.appendChild(\n        this._createCategoryGroup(category, layers, expanded),\n      );\n    }\n  }\n\n  /**\n   * Creates a collapsible category group with a count badge.\n   */\n  private _createCategoryGroup(\n    category: string,\n    layers: GibsLayer[],\n    expanded: boolean,\n  ): HTMLElement {\n    const group = document.createElement(\"div\");\n    group.className = \"nasa-category\";\n\n    const header = document.createElement(\"button\");\n    header.type = \"button\";\n    header.className = `nasa-category-header${expanded ? \" expanded\" : \"\"}`;\n    header.setAttribute(\"aria-expanded\", String(expanded));\n\n    const chevron = document.createElement(\"span\");\n    chevron.className = \"nasa-category-chevron\";\n    chevron.innerHTML = `\n      <svg viewBox=\"0 0 24 24\" width=\"12\" height=\"12\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n        <path d=\"M9 6l6 6-6 6\"/>\n      </svg>\n    `;\n\n    const name = document.createElement(\"span\");\n    name.className = \"nasa-category-name\";\n    name.textContent = category;\n\n    const count = document.createElement(\"span\");\n    count.className = \"nasa-category-count\";\n    count.textContent = String(layers.length);\n\n    header.appendChild(chevron);\n    header.appendChild(name);\n    header.appendChild(count);\n    header.addEventListener(\"click\", () => {\n      if (this._expandedCategories.has(category)) {\n        this._expandedCategories.delete(category);\n      } else {\n        this._expandedCategories.add(category);\n      }\n      this._renderResults();\n    });\n\n    group.appendChild(header);\n\n    if (expanded) {\n      const list = document.createElement(\"div\");\n      list.className = \"nasa-category-layers\";\n      list.setAttribute(\"role\", \"list\");\n\n      for (const layer of layers) {\n        list.appendChild(this._createLayerRow(layer));\n      }\n\n      group.appendChild(list);\n    }\n\n    return group;\n  }\n\n  /**\n   * Creates a single catalog layer row with title, badges, and an action\n   * button. Non-time layers toggle add/remove; time-enabled layers always\n   * offer \"Add\" so additional instances with different dates can be added.\n   * Per-layer controls live in the added-layers section.\n   */\n  private _createLayerRow(layer: GibsLayer): HTMLElement {\n    const instanceCount = Array.from(this._addedLayers.values()).filter(\n      (l) => l.id === layer.id,\n    ).length;\n    const added = instanceCount > 0;\n\n    const row = document.createElement(\"div\");\n    row.className = `nasa-layer-row${added ? \" nasa-layer-row-added\" : \"\"}`;\n    row.setAttribute(\"role\", \"listitem\");\n\n    const main = document.createElement(\"div\");\n    main.className = \"nasa-layer-main\";\n\n    const info = document.createElement(\"div\");\n    info.className = \"nasa-layer-info\";\n\n    const titleEl = document.createElement(\"div\");\n    titleEl.className = \"nasa-layer-title\";\n    titleEl.textContent = layer.title;\n    titleEl.title = layer.id;\n\n    const badges = document.createElement(\"div\");\n    badges.className = \"nasa-layer-badges\";\n    const formatBadge = document.createElement(\"span\");\n    formatBadge.className = \"nasa-badge\";\n    formatBadge.textContent = layer.format;\n    badges.appendChild(formatBadge);\n    if (layer.time) {\n      const timeBadge = document.createElement(\"span\");\n      timeBadge.className = \"nasa-badge nasa-badge-time\";\n      timeBadge.textContent = \"time\";\n      timeBadge.title = `Default date: ${layer.time.default}`;\n      badges.appendChild(timeBadge);\n    }\n    if (instanceCount > 1) {\n      const countBadge = document.createElement(\"span\");\n      countBadge.className = \"nasa-badge nasa-badge-time\";\n      countBadge.textContent = `${instanceCount} added`;\n      badges.appendChild(countBadge);\n    }\n\n    info.appendChild(titleEl);\n    info.appendChild(badges);\n\n    // Time-enabled layers can be added repeatedly (one instance per date),\n    // so their button always reads \"Add\"\n    const isRemove = added && !layer.time;\n    const actionBtn = document.createElement(\"button\");\n    actionBtn.type = \"button\";\n    actionBtn.className = `nasa-layer-action${isRemove ? \" nasa-layer-action-remove\" : \"\"}`;\n    actionBtn.textContent = isRemove ? \"Remove\" : \"Add\";\n    actionBtn.setAttribute(\n      \"aria-label\",\n      isRemove\n        ? `Remove layer ${layer.title}`\n        : added\n          ? `Add layer ${layer.title} for another date`\n          : `Add layer ${layer.title}`,\n    );\n    actionBtn.addEventListener(\"click\", () => {\n      if (!layer.time && this._resolveInstances(layer.id).length > 0) {\n        this.removeLayer(layer.id);\n      } else {\n        this.addLayer(layer.id);\n      }\n    });\n\n    main.appendChild(info);\n    main.appendChild(actionBtn);\n    row.appendChild(main);\n\n    return row;\n  }\n\n  /**\n   * Renders the \"Added layers\" management section: visibility checkbox,\n   * legend toggle, remove button, opacity slider, and date picker.\n   */\n  private _renderAddedSection(): void {\n    if (!this._addedEl) return;\n\n    this._addedEl.innerHTML = \"\";\n    if (this._addedLayers.size === 0) return;\n\n    const heading = document.createElement(\"div\");\n    heading.className = \"nasa-added-heading\";\n    heading.textContent = \"Added layers\";\n    this._addedEl.appendChild(heading);\n\n    for (const added of this._addedLayers.values()) {\n      const layer = this._client.getLayer(added.id);\n      if (layer) {\n        this._addedEl.appendChild(this._createAddedRow(layer, added));\n      }\n    }\n  }\n\n  /**\n   * Creates a management card for one added layer.\n   */\n  private _createAddedRow(\n    layer: GibsLayer,\n    added: AddedLayerState,\n  ): HTMLElement {\n    const card = document.createElement(\"div\");\n    card.className = \"nasa-added-card\";\n\n    // Header row: visibility checkbox, title, legend toggle, remove\n    const head = document.createElement(\"div\");\n    head.className = \"nasa-added-head\";\n\n    const visLabel = document.createElement(\"label\");\n    visLabel.className = \"nasa-added-vis\";\n    visLabel.title = \"Toggle layer visibility\";\n\n    const visCheckbox = document.createElement(\"input\");\n    visCheckbox.type = \"checkbox\";\n    visCheckbox.className = \"nasa-added-checkbox\";\n    visCheckbox.checked = added.visible;\n    visCheckbox.setAttribute(\n      \"aria-label\",\n      `Toggle visibility of ${layer.title}`,\n    );\n    visCheckbox.addEventListener(\"change\", () => {\n      this.setLayerVisibility(added.key, visCheckbox.checked);\n    });\n\n    const titleEl = document.createElement(\"span\");\n    titleEl.className = \"nasa-added-title\";\n    titleEl.textContent = layer.title;\n    titleEl.title = added.key;\n\n    visLabel.appendChild(visCheckbox);\n    visLabel.appendChild(titleEl);\n\n    // Date chip distinguishes multiple instances of the same time layer\n    let dateChip: HTMLElement | undefined;\n    if (layer.time && added.date) {\n      dateChip = document.createElement(\"span\");\n      dateChip.className = \"nasa-badge nasa-badge-time\";\n      dateChip.textContent = added.date.slice(0, 10);\n      visLabel.appendChild(dateChip);\n    }\n\n    const actions = document.createElement(\"div\");\n    actions.className = \"nasa-added-actions\";\n\n    if (layer.legendUrl) {\n      const legendBtn = document.createElement(\"button\");\n      legendBtn.type = \"button\";\n      legendBtn.className = `nasa-icon-button${\n        this._openLegends.has(added.key) ? \" active\" : \"\"\n      }`;\n      legendBtn.title = \"Toggle legend\";\n      legendBtn.setAttribute(\"aria-label\", `Toggle legend for ${layer.title}`);\n      legendBtn.innerHTML = `\n        <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n          <path d=\"M8 6h13M8 12h13M8 18h13\"/>\n          <rect x=\"3\" y=\"4.5\" width=\"3\" height=\"3\" rx=\"0.5\"/>\n          <rect x=\"3\" y=\"10.5\" width=\"3\" height=\"3\" rx=\"0.5\"/>\n          <rect x=\"3\" y=\"16.5\" width=\"3\" height=\"3\" rx=\"0.5\"/>\n        </svg>\n      `;\n      legendBtn.addEventListener(\"click\", () => {\n        if (this._openLegends.has(added.key)) {\n          this._openLegends.delete(added.key);\n        } else {\n          this._openLegends.add(added.key);\n        }\n        this._renderAddedSection();\n      });\n      actions.appendChild(legendBtn);\n    }\n\n    const removeBtn = document.createElement(\"button\");\n    removeBtn.type = \"button\";\n    removeBtn.className = \"nasa-icon-button nasa-icon-button-danger\";\n    removeBtn.title = \"Remove layer\";\n    removeBtn.setAttribute(\"aria-label\", `Remove layer ${layer.title}`);\n    removeBtn.innerHTML = `\n      <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n        <path d=\"M3 6h18M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2m3 0v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\"/>\n        <path d=\"M10 11v6M14 11v6\"/>\n      </svg>\n    `;\n    removeBtn.addEventListener(\"click\", () => {\n      this.removeLayer(added.key);\n    });\n    actions.appendChild(removeBtn);\n\n    head.appendChild(visLabel);\n    head.appendChild(actions);\n    card.appendChild(head);\n\n    // Opacity slider with live percentage readout\n    if (this._options.showOpacity) {\n      const opacityRow = document.createElement(\"label\");\n      opacityRow.className = \"nasa-control-label\";\n      opacityRow.textContent = \"Opacity\";\n\n      const opacityInput = document.createElement(\"input\");\n      opacityInput.type = \"range\";\n      opacityInput.className = \"nasa-opacity\";\n      opacityInput.min = \"0\";\n      opacityInput.max = \"1\";\n      opacityInput.step = \"0.05\";\n      opacityInput.value = String(added.opacity);\n      opacityInput.setAttribute(\"aria-label\", `Opacity for ${layer.title}`);\n\n      const opacityValue = document.createElement(\"span\");\n      opacityValue.className = \"nasa-opacity-value\";\n      opacityValue.textContent = `${Math.round(added.opacity * 100)}%`;\n\n      opacityInput.addEventListener(\"input\", () => {\n        const value = Number(opacityInput.value);\n        this.setLayerOpacity(added.key, value);\n        opacityValue.textContent = `${Math.round(value * 100)}%`;\n      });\n\n      opacityRow.appendChild(opacityInput);\n      opacityRow.appendChild(opacityValue);\n      card.appendChild(opacityRow);\n    }\n\n    // Date picker for time-enabled layers\n    if (layer.time) {\n      const dateLabel = document.createElement(\"label\");\n      dateLabel.className = \"nasa-control-label\";\n      dateLabel.textContent = \"Date\";\n\n      const dateInput = document.createElement(\"input\");\n      dateInput.type = \"date\";\n      dateInput.className = \"nasa-date\";\n      dateInput.value = (added.date ?? layer.time.default).slice(0, 10);\n      const range = this._timeRange(layer);\n      if (range.min) dateInput.min = range.min;\n      if (range.max) dateInput.max = range.max;\n      dateInput.addEventListener(\"change\", () => {\n        if (dateInput.value) {\n          this.setLayerDate(added.key, dateInput.value);\n          if (dateChip) {\n            dateChip.textContent = dateInput.value;\n          }\n        }\n      });\n\n      dateLabel.appendChild(dateInput);\n      card.appendChild(dateLabel);\n    }\n\n    // Legend image (GIBS horizontal legend SVG)\n    if (layer.legendUrl && this._openLegends.has(added.key)) {\n      const legend = document.createElement(\"img\");\n      legend.className = \"nasa-legend-image\";\n      legend.src = layer.legendUrl;\n      legend.alt = `Legend for ${layer.title}`;\n      legend.loading = \"lazy\";\n      card.appendChild(legend);\n    }\n\n    return card;\n  }\n\n  /**\n   * Refreshes the \"Insert before\" dropdown with the map's current layers.\n   */\n  private _refreshInsertOptions(): void {\n    if (!this._insertSelect || !this._map) return;\n\n    const layers = this._map.getStyle()?.layers ?? [];\n    const select = this._insertSelect;\n    select.innerHTML = \"\";\n\n    const topOption = document.createElement(\"option\");\n    topOption.value = \"\";\n    topOption.textContent = \"Top of map\";\n    select.appendChild(topOption);\n\n    for (const layer of layers) {\n      const option = document.createElement(\"option\");\n      option.value = layer.id;\n      option.textContent = layer.id;\n      select.appendChild(option);\n    }\n\n    // Restore the previous selection if the layer still exists\n    if (this._insertBefore && layers.some((l) => l.id === this._insertBefore)) {\n      select.value = this._insertBefore;\n    } else {\n      this._insertBefore = \"\";\n      select.value = \"\";\n    }\n  }\n\n  /**\n   * Derives the min/max selectable dates from a layer's time domain values.\n   */\n  private _timeRange(layer: GibsLayer): { min?: string; max?: string } {\n    const time = layer.time;\n    if (!time) return {};\n\n    let min: string | undefined;\n    let max: string | undefined;\n    for (const value of time.values) {\n      const [start, end] = value.split(\"/\");\n      const startDate = start?.slice(0, 10);\n      const endDate = (end ?? start)?.slice(0, 10);\n      if (startDate && (!min || startDate < min)) min = startDate;\n      if (endDate && (!max || endDate > max)) max = endDate;\n    }\n    const defaultDate = time.default.slice(0, 10);\n    if (!max || defaultDate > max) max = defaultDate;\n    return { min, max };\n  }\n\n  /**\n   * Setup event listeners for panel positioning and click-outside behavior.\n   */\n  private _setupEventListeners(): void {\n    // Click outside to close (check both container and panel since they're now separate).\n    // Ignore targets that are no longer connected to the DOM: clicking an\n    // Add/Remove button re-renders the results list, detaching the button\n    // before this document-level handler runs.\n    this._clickOutsideHandler = (e: MouseEvent) => {\n      const target = e.target as Node;\n      if (\n        this._container &&\n        this._panel &&\n        target.isConnected &&\n        !this._container.contains(target) &&\n        !this._panel.contains(target)\n      ) {\n        this.collapse();\n      }\n    };\n    document.addEventListener(\"click\", this._clickOutsideHandler);\n\n    // Update panel position on window resize\n    this._resizeHandler = () => {\n      if (!this._state.collapsed) {\n        this._updatePanelPosition();\n      }\n    };\n    window.addEventListener(\"resize\", this._resizeHandler);\n\n    // Update panel position on map resize (e.g., sidebar toggle)\n    this._mapResizeHandler = () => {\n      if (!this._state.collapsed) {\n        this._updatePanelPosition();\n      }\n    };\n    this._map?.on(\"resize\", this._mapResizeHandler);\n  }\n\n  /**\n   * Detect which corner the control is positioned in.\n   *\n   * @returns The position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n   */\n  private _getControlPosition():\n    | \"top-left\"\n    | \"top-right\"\n    | \"bottom-left\"\n    | \"bottom-right\" {\n    const parent = this._container?.parentElement;\n    if (!parent) return \"top-right\"; // Default\n\n    if (parent.classList.contains(\"maplibregl-ctrl-top-left\"))\n      return \"top-left\";\n    if (parent.classList.contains(\"maplibregl-ctrl-top-right\"))\n      return \"top-right\";\n    if (parent.classList.contains(\"maplibregl-ctrl-bottom-left\"))\n      return \"bottom-left\";\n    if (parent.classList.contains(\"maplibregl-ctrl-bottom-right\"))\n      return \"bottom-right\";\n\n    return \"top-right\"; // Default\n  }\n\n  /**\n   * Update the panel position based on button location and control corner.\n   * Positions the panel next to the button, expanding in the appropriate direction.\n   */\n  private _updatePanelPosition(): void {\n    if (!this._container || !this._panel || !this._mapContainer) return;\n\n    // Get the toggle button (first child of container)\n    const button = this._container.querySelector(\".plugin-control-toggle\");\n    if (!button) return;\n\n    // Keep the panel within the map even if it shrank since the width was set\n    this._applyPanelWidthBounds();\n\n    const buttonRect = button.getBoundingClientRect();\n    const mapRect = this._mapContainer.getBoundingClientRect();\n    const position = this._getControlPosition();\n\n    // Calculate button position relative to map container\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; // Gap between button and panel\n\n    // Reset all positioning\n    this._panel.style.top = \"\";\n    this._panel.style.bottom = \"\";\n    this._panel.style.left = \"\";\n    this._panel.style.right = \"\";\n\n    // Keep the resize handle on the panel's outer (growing) edge:\n    // right edge for left-anchored panels, left edge for right-anchored ones\n    this._panel\n      .querySelector(\".nasa-resize-handle\")\n      ?.classList.toggle(\"nasa-resize-handle-right\", position.endsWith(\"left\"));\n\n    switch (position) {\n      case \"top-left\":\n        // Panel expands down and to the right\n        this._panel.style.top = `${buttonTop + buttonRect.height + panelGap}px`;\n        this._panel.style.left = `${buttonLeft}px`;\n        break;\n\n      case \"top-right\":\n        // Panel expands down and to the left\n        this._panel.style.top = `${buttonTop + buttonRect.height + panelGap}px`;\n        this._panel.style.right = `${buttonRight}px`;\n        break;\n\n      case \"bottom-left\":\n        // Panel expands up and to the right\n        this._panel.style.bottom = `${buttonBottom + buttonRect.height + panelGap}px`;\n        this._panel.style.left = `${buttonLeft}px`;\n        break;\n\n      case \"bottom-right\":\n        // Panel expands up and to the left\n        this._panel.style.bottom = `${buttonBottom + buttonRect.height + panelGap}px`;\n        this._panel.style.right = `${buttonRight}px`;\n        break;\n    }\n  }\n}\n"],"mappings":"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"}