map_view_vue3 0.0.0-stage → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,232 @@
1
- # Temporary Holding Version
1
+ # map_view_vue3
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 基于 Vue 3 + OpenLayers 的地图查看器组件,支持栅格图片、本地切片 XYZ、在线 XYZ、GeoJSON/SLD 数据加载,并提供坐标系切换、图层管理、拖拽加载等能力。
4
+
5
+ ## 目录结构
6
+
7
+ ```text
8
+ map_view_vue3/
9
+ ├─ map_view_vue3.js # ESM 构建产物
10
+ ├─ map_view_vue3.umd.cjs # UMD 构建产物
11
+ ├─ map_view_vue3.css # 组件样式
12
+ ├─ types/index.d.ts # TypeScript 类型声明
13
+ ├─ favicon.svg
14
+ └─ icons.svg
15
+ ```
16
+
17
+ ## 引入方式
18
+
19
+ ### 方式一:按需引入组件
20
+
21
+ ```ts
22
+ import { createApp } from 'vue'
23
+ import { MapViewVue3 } from './map_view_vue3/map_view_vue3.js'
24
+ import './map_view_vue3/map_view_vue3.css'
25
+
26
+ import App from './App.vue'
27
+
28
+ const app = createApp(App)
29
+ app.component('MapViewVue3', MapViewVue3)
30
+ app.mount('#app')
31
+ ```
32
+
33
+ ### 方式二:全局插件式注册
34
+
35
+ ```ts
36
+ import { createApp } from 'vue'
37
+ import MapViewVue3 from './map_view_vue3/map_view_vue3.js'
38
+ import './map_view_vue3/map_view_vue3.css'
39
+
40
+ import App from './App.vue'
41
+
42
+ const app = createApp(App)
43
+ app.use(MapViewVue3)
44
+ app.mount('#app')
45
+ ```
46
+
47
+ ## 基础用法
48
+
49
+ ```vue
50
+ <template>
51
+ <MapViewVue3
52
+ theme="light"
53
+ data-crs="EPSG:3857"
54
+ :zoom="4.2"
55
+ width="1000px"
56
+ height="800px"
57
+ map-background="#ffffff"
58
+ :auto-load="autoLoad"
59
+ @view-changed="onViewChanged"
60
+ @active-map-changed="onActiveMapChanged"
61
+ />
62
+ </template>
63
+
64
+ <script setup lang="ts">
65
+ import { ref } from 'vue'
66
+
67
+ const autoLoad = ref({
68
+ type: 'manifest',
69
+ url: 'http://localhost:7010/geojson/metadata.json',
70
+ baseUrl: 'http://localhost:7010/geojson'
71
+ })
72
+
73
+ function onViewChanged(state: { center: number[] | null; zoom: number | null; crs: string }) {
74
+ console.log('视野变化', state)
75
+ }
76
+
77
+ function onActiveMapChanged(payload: { id: number; name: string; kind: string }) {
78
+ console.log('当前地图变化', payload)
79
+ }
80
+ </script>
81
+ ```
82
+
83
+ ## Props
84
+
85
+ | 名称 | 类型 | 默认值 | 说明 |
86
+ | --- | --- | --- | --- |
87
+ | `theme` | `'light' \| 'dark'` | `'light'` | 明暗主题 |
88
+ | `dataCrs` | `string` | `'EPSG:3857'` | 初始数据坐标系 |
89
+ | `zoom` | `number` | `4.2` | 初始缩放级别 |
90
+ | `hidePanels` | `boolean` | `false` | 是否隐藏两侧面板 |
91
+ | `width` | `string \| number \| null` | `null` | 固定宽度,如 `'1000px'` |
92
+ | `height` | `string \| number \| null` | `null` | 固定高度,如 `'800px'` |
93
+ | `mapBackground` | `string \| null` | `null` | 地图画布背景色 |
94
+ | `autoLoad` | `AutoLoadConfig \| null` | `null` | 挂载后自动加载数据源 |
95
+
96
+ ## autoLoad 示例
97
+
98
+ ### 加载 GeoJSON 清单
99
+
100
+ ```ts
101
+ const autoLoad = {
102
+ type: 'manifest',
103
+ url: 'https://example.com/geojson/metadata.json',
104
+ baseUrl: 'https://example.com/geojson'
105
+ }
106
+ ```
107
+
108
+ ### 加载图片
109
+
110
+ ```ts
111
+ const autoLoad = {
112
+ type: 'image',
113
+ url: 'https://example.com/map.png',
114
+ worldFile: 'https://example.com/map.pgw',
115
+ crs: 'EPSG:3857',
116
+ name: '示例地图'
117
+ }
118
+ ```
119
+
120
+ ## 事件
121
+
122
+ | 事件名 | 参数 | 说明 |
123
+ | --- | --- | --- |
124
+ | `theme-changed` | `theme: 'light' \| 'dark'` | 主题切换 |
125
+ | `view-changed` | `{ center, zoom, crs }` | 视野变化 |
126
+ | `active-map-changed` | `{ id, name, kind }` | 当前地图切换 |
127
+ | `map-removed` | `{ id, name, kind }` | 地图删除 |
128
+ | `layer-removed` | `{ isGroup, name, layerCount, group }` | 图层删除 |
129
+ | `notify` | `{ message, type }` | 通知信息 |
130
+
131
+ ## 常用实例方法
132
+
133
+ 可以通过模板 `ref` 调用组件内部暴露的方法。
134
+
135
+ ```vue
136
+ <template>
137
+ <MapViewVue3 ref="viewer" />
138
+ <button @click="loadLayers">加载图层</button>
139
+ </template>
140
+
141
+ <script setup lang="ts">
142
+ import { ref } from 'vue'
143
+
144
+ const viewer = ref()
145
+
146
+ async function loadLayers() {
147
+ await viewer.value?.loadGeoJsonFromData([
148
+ {
149
+ name: '道路',
150
+ geojson: { type: 'FeatureCollection', features: [] },
151
+ sld: '<StyledLayerDescriptor></StyledLayerDescriptor>'
152
+ }
153
+ ])
154
+ }
155
+ </script>
156
+ ```
157
+
158
+ 常用方法包括:
159
+
160
+ | 方法 | 说明 |
161
+ | --- | --- |
162
+ | `waitViewerReady()` | 等待地图查看器初始化完成 |
163
+ | `loadImageFromUrl(options)` | 通过 URL 加载图片地图 |
164
+ | `addXyzLayer(options)` | 加载在线 XYZ 图层 |
165
+ | `loadGeoJsonFromFiles(files)` | 加载 GeoJSON / SLD 文件 |
166
+ | `loadGeoJsonFromManifest(manifest, baseUrl?)` | 通过 manifest 加载矢量数据 |
167
+ | `loadGeoJsonFromData(layers)` | 直接传入 GeoJSON / SLD 数据 |
168
+ | `fitActiveMap()` | 定位到当前地图 |
169
+ | `fitToExtent(extent, projection?)` | 定位到指定范围 |
170
+ | `getViewState()` | 获取当前视野状态 |
171
+ | `getActiveMapInfo()` | 获取当前地图信息 |
172
+ | `applyTheme(theme)` | 切换明暗主题 |
173
+ | `normalizeEpsg(value)` | 规范化 EPSG 代码 |
174
+
175
+ ## 数据格式说明
176
+
177
+ ### GeoJSON / SLD 目录
178
+
179
+ 支持按文件名主干配对的 `.geojson` / `.json` 与 `.sld` / `.xml` 文件。
180
+
181
+ ```text
182
+ layers/
183
+ ├─ roads.geojson
184
+ ├─ roads.sld
185
+ ├─ buildings.geojson
186
+ └─ buildings.sld
187
+ ```
188
+
189
+ ### manifest 示例
190
+
191
+ ```json
192
+ {
193
+ "layers": [
194
+ {
195
+ "name": "道路",
196
+ "geojson": "roads.geojson",
197
+ "sld": "roads.sld"
198
+ },
199
+ {
200
+ "name": "建筑",
201
+ "geojson": "buildings.geojson",
202
+ "sld": "buildings.sld"
203
+ }
204
+ ]
205
+ }
206
+ ```
207
+
208
+ 如果 `metadata.json` 存在,会用于图层排序和标题显示。
209
+
210
+ ## 注意事项
211
+
212
+ 1. 使用前请确保项目已引入 Vue 3。
213
+ 2. 本组件依赖 OpenLayers 与 proj4,构建产物中通常已经打包;如果你使用源码方式集成,请确保项目里已安装相关依赖。
214
+ 3. 加载远程 GeoJSON、图片或切片时,注意目标服务是否允许跨域访问。
215
+ 4. 如果使用本地切片目录,推荐按 `z/x/y.png` 的 XYZ 结构组织数据。
216
+ 5. 如需在线获取 EPSG 定义,需要能访问 `epsg.io`。
217
+
218
+ ## TypeScript
219
+
220
+ 类型声明位于 `types/index.d.ts`,可以直接使用:
221
+
222
+ ```ts
223
+ import type {
224
+ MapViewerProps,
225
+ MapViewerEmits,
226
+ MapViewerInstance
227
+ } from './map_view_vue3/types'
228
+ ```
229
+
230
+ ## 许可证
231
+
232
+ ISC
package/favicon.svg ADDED
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="48" height="46" fill="none" viewBox="0 0 48 46"><path fill="#863bff" d="M25.946 44.938c-.664.845-2.021.375-2.021-.698V33.937a2.26 2.26 0 0 0-2.262-2.262H10.287c-.92 0-1.456-1.04-.92-1.788l7.48-10.471c1.07-1.497 0-3.578-1.842-3.578H1.237c-.92 0-1.456-1.04-.92-1.788L10.013.474c.214-.297.556-.474.92-.474h28.894c.92 0 1.456 1.04.92 1.788l-7.48 10.471c-1.07 1.498 0 3.579 1.842 3.579h11.377c.943 0 1.473 1.088.89 1.83L25.947 44.94z" style="fill:#863bff;fill:color(display-p3 .5252 .23 1);fill-opacity:1"/><mask id="a" width="48" height="46" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha"><path fill="#000" d="M25.842 44.938c-.664.844-2.021.375-2.021-.698V33.937a2.26 2.26 0 0 0-2.262-2.262H10.183c-.92 0-1.456-1.04-.92-1.788l7.48-10.471c1.07-1.498 0-3.579-1.842-3.579H1.133c-.92 0-1.456-1.04-.92-1.787L9.91.473c.214-.297.556-.474.92-.474h28.894c.92 0 1.456 1.04.92 1.788l-7.48 10.471c-1.07 1.498 0 3.578 1.842 3.578h11.377c.943 0 1.473 1.088.89 1.832L25.843 44.94z" style="fill:#000;fill-opacity:1"/></mask><g mask="url(#a)"><g filter="url(#b)"><ellipse cx="5.508" cy="14.704" fill="#ede6ff" rx="5.508" ry="14.704" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -4.47 31.516)"/></g><g filter="url(#c)"><ellipse cx="10.399" cy="29.851" fill="#ede6ff" rx="10.399" ry="29.851" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -39.328 7.883)"/></g><g filter="url(#d)"><ellipse cx="5.508" cy="30.487" fill="#7e14ff" rx="5.508" ry="30.487" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.814 -25.913 -14.639)scale(1 -1)"/></g><g filter="url(#e)"><ellipse cx="5.508" cy="30.599" fill="#7e14ff" rx="5.508" ry="30.599" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.814 -32.644 -3.334)scale(1 -1)"/></g><g filter="url(#f)"><ellipse cx="5.508" cy="30.599" fill="#7e14ff" rx="5.508" ry="30.599" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -34.34 30.47)"/></g><g filter="url(#g)"><ellipse cx="14.072" cy="22.078" fill="#ede6ff" rx="14.072" ry="22.078" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="rotate(93.35 24.506 48.493)scale(-1 1)"/></g><g filter="url(#h)"><ellipse cx="3.47" cy="21.501" fill="#7e14ff" rx="3.47" ry="21.501" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.009 28.708 47.59)scale(-1 1)"/></g><g filter="url(#i)"><ellipse cx="3.47" cy="21.501" fill="#7e14ff" rx="3.47" ry="21.501" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.009 28.708 47.59)scale(-1 1)"/></g><g filter="url(#j)"><ellipse cx=".387" cy="8.972" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(39.51 .387 8.972)"/></g><g filter="url(#k)"><ellipse cx="47.523" cy="-6.092" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 47.523 -6.092)"/></g><g filter="url(#l)"><ellipse cx="41.412" cy="6.333" fill="#47bfff" rx="5.971" ry="9.665" style="fill:#47bfff;fill:color(display-p3 .2799 .748 1);fill-opacity:1" transform="rotate(37.892 41.412 6.333)"/></g><g filter="url(#m)"><ellipse cx="-1.879" cy="38.332" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 -1.88 38.332)"/></g><g filter="url(#n)"><ellipse cx="-1.879" cy="38.332" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 -1.88 38.332)"/></g><g filter="url(#o)"><ellipse cx="35.651" cy="29.907" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 35.651 29.907)"/></g><g filter="url(#p)"><ellipse cx="38.418" cy="32.4" fill="#47bfff" rx="5.971" ry="15.297" style="fill:#47bfff;fill:color(display-p3 .2799 .748 1);fill-opacity:1" transform="rotate(37.892 38.418 32.4)"/></g></g><defs><filter id="b" width="60.045" height="41.654" x="-19.77" y="16.149" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="c" width="90.34" height="51.437" x="-54.613" y="-7.533" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="d" width="79.355" height="29.4" x="-49.64" y="2.03" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="e" width="79.579" height="29.4" x="-45.045" y="20.029" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="f" width="79.579" height="29.4" x="-43.513" y="21.178" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="g" width="74.749" height="58.852" x="15.756" y="-17.901" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="h" width="61.377" height="25.362" x="23.548" y="2.284" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="i" width="61.377" height="25.362" x="23.548" y="2.284" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="j" width="56.045" height="63.649" x="-27.636" y="-22.853" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="k" width="54.814" height="64.646" x="20.116" y="-38.415" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="l" width="33.541" height="35.313" x="24.641" y="-11.323" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="m" width="54.814" height="64.646" x="-29.286" y="6.009" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="n" width="54.814" height="64.646" x="-29.286" y="6.009" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="o" width="54.814" height="64.646" x="8.244" y="-2.416" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="p" width="39.409" height="43.623" x="18.713" y="10.588" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter></defs></svg>
package/icons.svg ADDED
@@ -0,0 +1,24 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg">
2
+ <symbol id="bluesky-icon" viewBox="0 0 16 17">
3
+ <g clip-path="url(#bluesky-clip)"><path fill="#08060d" d="M7.75 7.735c-.693-1.348-2.58-3.86-4.334-5.097-1.68-1.187-2.32-.981-2.74-.79C.188 2.065.1 2.812.1 3.251s.241 3.602.398 4.13c.52 1.744 2.367 2.333 4.07 2.145-2.495.37-4.71 1.278-1.805 4.512 3.196 3.309 4.38-.71 4.987-2.746.608 2.036 1.307 5.91 4.93 2.746 2.72-2.746.747-4.143-1.747-4.512 1.702.189 3.55-.4 4.07-2.145.156-.528.397-3.691.397-4.13s-.088-1.186-.575-1.406c-.42-.19-1.06-.395-2.741.79-1.755 1.24-3.64 3.752-4.334 5.099"/></g>
4
+ <defs><clipPath id="bluesky-clip"><path fill="#fff" d="M.1.85h15.3v15.3H.1z"/></clipPath></defs>
5
+ </symbol>
6
+ <symbol id="discord-icon" viewBox="0 0 20 19">
7
+ <path fill="#08060d" d="M16.224 3.768a14.5 14.5 0 0 0-3.67-1.153c-.158.286-.343.67-.47.976a13.5 13.5 0 0 0-4.067 0c-.128-.306-.317-.69-.476-.976A14.4 14.4 0 0 0 3.868 3.77C1.546 7.28.916 10.703 1.231 14.077a14.7 14.7 0 0 0 4.5 2.306q.545-.748.965-1.587a9.5 9.5 0 0 1-1.518-.74q.191-.14.372-.293c2.927 1.369 6.107 1.369 8.999 0q.183.152.372.294-.723.437-1.52.74.418.838.963 1.588a14.6 14.6 0 0 0 4.504-2.308c.37-3.911-.63-7.302-2.644-10.309m-9.13 8.234c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.894 0 1.614.82 1.599 1.82.001 1-.705 1.82-1.6 1.82m5.91 0c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.893 0 1.614.82 1.599 1.82 0 1-.706 1.82-1.6 1.82"/>
8
+ </symbol>
9
+ <symbol id="documentation-icon" viewBox="0 0 21 20">
10
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="m15.5 13.333 1.533 1.322c.645.555.967.833.967 1.178s-.322.623-.967 1.179L15.5 18.333m-3.333-5-1.534 1.322c-.644.555-.966.833-.966 1.178s.322.623.966 1.179l1.534 1.321"/>
11
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M17.167 10.836v-4.32c0-1.41 0-2.117-.224-2.68-.359-.906-1.118-1.621-2.08-1.96-.599-.21-1.349-.21-2.848-.21-2.623 0-3.935 0-4.983.369-1.684.591-3.013 1.842-3.641 3.428C3 6.449 3 7.684 3 10.154v2.122c0 2.558 0 3.838.706 4.726q.306.383.713.671c.76.536 1.79.64 3.581.66"/>
12
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M3 10a2.78 2.78 0 0 1 2.778-2.778c.555 0 1.209.097 1.748-.047.48-.129.854-.503.982-.982.145-.54.048-1.194.048-1.749a2.78 2.78 0 0 1 2.777-2.777"/>
13
+ </symbol>
14
+ <symbol id="github-icon" viewBox="0 0 19 19">
15
+ <path fill="#08060d" fill-rule="evenodd" d="M9.356 1.85C5.05 1.85 1.57 5.356 1.57 9.694a7.84 7.84 0 0 0 5.324 7.44c.387.079.528-.168.528-.376 0-.182-.013-.805-.013-1.454-2.165.467-2.616-.935-2.616-.935-.349-.91-.864-1.143-.864-1.143-.71-.48.051-.48.051-.48.787.051 1.2.805 1.2.805.695 1.194 1.817.857 2.268.649.064-.507.27-.857.49-1.052-1.728-.182-3.545-.857-3.545-3.87 0-.857.31-1.558.8-2.104-.078-.195-.349-1 .077-2.078 0 0 .657-.208 2.14.805a7.5 7.5 0 0 1 1.946-.26c.657 0 1.328.092 1.946.26 1.483-1.013 2.14-.805 2.14-.805.426 1.078.155 1.883.078 2.078.502.546.799 1.247.799 2.104 0 3.013-1.818 3.675-3.558 3.87.284.247.528.714.528 1.454 0 1.052-.012 1.896-.012 2.156 0 .208.142.455.528.377a7.84 7.84 0 0 0 5.324-7.441c.013-4.338-3.48-7.844-7.773-7.844" clip-rule="evenodd"/>
16
+ </symbol>
17
+ <symbol id="social-icon" viewBox="0 0 20 20">
18
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M12.5 6.667a4.167 4.167 0 1 0-8.334 0 4.167 4.167 0 0 0 8.334 0"/>
19
+ <path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M2.5 16.667a5.833 5.833 0 0 1 8.75-5.053m3.837.474.513 1.035c.07.144.257.282.414.309l.93.155c.596.1.736.536.307.965l-.723.73a.64.64 0 0 0-.152.531l.207.903c.164.715-.213.991-.84.618l-.872-.52a.63.63 0 0 0-.577 0l-.872.52c-.624.373-1.003.094-.84-.618l.207-.903a.64.64 0 0 0-.152-.532l-.723-.729c-.426-.43-.289-.864.306-.964l.93-.156a.64.64 0 0 0 .412-.31l.513-1.034c.28-.562.735-.562 1.012 0"/>
20
+ </symbol>
21
+ <symbol id="x-icon" viewBox="0 0 19 19">
22
+ <path fill="#08060d" fill-rule="evenodd" d="M1.893 1.98c.052.072 1.245 1.769 2.653 3.77l2.892 4.114c.183.261.333.48.333.486s-.068.089-.152.183l-.522.593-.765.867-3.597 4.087c-.375.426-.734.834-.798.905a1 1 0 0 0-.118.148c0 .01.236.017.664.017h.663l.729-.83c.4-.457.796-.906.879-.999a692 692 0 0 0 1.794-2.038c.034-.037.301-.34.594-.675l.551-.624.345-.392a7 7 0 0 1 .34-.374c.006 0 .93 1.306 2.052 2.903l2.084 2.965.045.063h2.275c1.87 0 2.273-.003 2.266-.021-.008-.02-1.098-1.572-3.894-5.547-2.013-2.862-2.28-3.246-2.273-3.266.008-.019.282-.332 2.085-2.38l2-2.274 1.567-1.782c.022-.028-.016-.03-.65-.03h-.674l-.3.342a871 871 0 0 1-1.782 2.025c-.067.075-.405.458-.75.852a100 100 0 0 1-.803.91c-.148.172-.299.344-.99 1.127-.304.343-.32.358-.345.327-.015-.019-.904-1.282-1.976-2.808L6.365 1.85H1.8zm1.782.91 8.078 11.294c.772 1.08 1.413 1.973 1.425 1.984.016.017.241.02 1.05.017l1.03-.004-2.694-3.766L7.796 5.75 5.722 2.852l-1.039-.004-1.039-.004z" clip-rule="evenodd"/>
23
+ </symbol>
24
+ </svg>
@@ -0,0 +1,2 @@
1
+ :root,:host{--ol-background-color:white;--ol-accent-background-color:#f5f5f5;--ol-subtle-background-color:#80808040;--ol-partial-background-color:#ffffffbf;--ol-foreground-color:#333;--ol-subtle-foreground-color:#666;--ol-brand-color:#0af}.ol-box{box-sizing:border-box;border:1.5px solid var(--ol-background-color);background-color:var(--ol-partial-background-color);border-radius:2px}.ol-mouse-position{position:absolute;top:8px;right:8px}.ol-scale-line{background:var(--ol-partial-background-color);border-radius:4px;padding:2px;position:absolute;bottom:8px;left:8px}.ol-scale-line-inner{border:1px solid var(--ol-subtle-foreground-color);color:var(--ol-foreground-color);text-align:center;will-change:contents, width;border-top:none;margin:1px;font-size:10px;transition:all .25s}.ol-scale-bar{position:absolute;bottom:8px;left:8px}.ol-scale-bar-inner{display:flex}.ol-scale-step-marker{background-color:var(--ol-foreground-color);float:right;z-index:10;width:1px;height:15px}.ol-scale-step-text{z-index:11;color:var(--ol-foreground-color);text-shadow:-1.5px 0 var(--ol-partial-background-color), 0 1.5px var(--ol-partial-background-color), 1.5px 0 var(--ol-partial-background-color), 0 -1.5px var(--ol-partial-background-color);font-size:10px;position:absolute;bottom:-5px}.ol-scale-text{text-align:center;color:var(--ol-foreground-color);text-shadow:-1.5px 0 var(--ol-partial-background-color), 0 1.5px var(--ol-partial-background-color), 1.5px 0 var(--ol-partial-background-color), 0 -1.5px var(--ol-partial-background-color);font-size:12px;position:absolute;bottom:25px}.ol-scale-singlebar{z-index:9;box-sizing:border-box;border:1px solid var(--ol-foreground-color);height:10px;position:relative}.ol-scale-singlebar-even{background-color:var(--ol-subtle-foreground-color)}.ol-scale-singlebar-odd{background-color:var(--ol-background-color)}.ol-unsupported{display:none}.ol-viewport,.ol-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.ol-viewport canvas{all:unset;overflow:hidden}.ol-viewport{touch-action:pan-x pan-y}.ol-selectable{-webkit-touch-callout:default;-webkit-user-select:text;user-select:text}.ol-grabbing{cursor:-webkit-grabbing;cursor:-moz-grabbing;cursor:grabbing}.ol-grab{cursor:move;cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.ol-control{background-color:var(--ol-subtle-background-color);border-radius:4px;position:absolute}.ol-zoom{top:.5em;left:.5em}.ol-rotate{transition:opacity .25s linear,visibility linear;top:.5em;right:.5em}.ol-rotate.ol-hidden{opacity:0;visibility:hidden;transition:opacity .25s linear,visibility 0s linear .25s}.ol-zoom-extent{top:4.643em;left:.5em}.ol-full-screen{top:.5em;right:.5em}.ol-control button{color:var(--ol-subtle-foreground-color);font-weight:700;font-size:inherit;text-align:center;background-color:var(--ol-background-color);border:none;border-radius:2px;width:1.375em;height:1.375em;margin:1px;padding:0;line-height:.4em;text-decoration:none;display:block}.ol-control button::-moz-focus-inner{border:none;padding:0}.ol-zoom-extent button{line-height:1.4em}.ol-compass{will-change:transform;font-weight:400;display:block}.ol-touch .ol-control button{font-size:1.5em}.ol-touch .ol-zoom-extent{top:5.5em}.ol-control button:hover,.ol-control button:focus{outline:1px solid var(--ol-subtle-foreground-color);color:var(--ol-foreground-color);text-decoration:none}.ol-zoom .ol-zoom-in{border-radius:2px 2px 0 0}.ol-zoom .ol-zoom-out{border-radius:0 0 2px 2px}.ol-attribution{text-align:right;flex-flow:row-reverse;align-items:center;max-width:calc(100% - 1.3em);display:flex;bottom:.5em;right:.5em}.ol-attribution a{color:var(--ol-subtle-foreground-color);text-decoration:none}.ol-attribution ul{color:var(--ol-foreground-color);text-shadow:0 0 2px var(--ol-background-color);margin:0;padding:1px .5em;font-size:12px}.ol-attribution li{list-style:none;display:inline}.ol-attribution li:not(:last-child):after{content:" "}.ol-attribution img{max-height:2em;max-width:inherit;vertical-align:middle}.ol-attribution button{flex-shrink:0}.ol-attribution.ol-collapsed ul{display:none}.ol-attribution:not(.ol-collapsed){background:var(--ol-partial-background-color)}.ol-attribution.ol-uncollapsible{border-radius:4px 0 0;bottom:0;right:0}.ol-attribution.ol-uncollapsible img{max-height:1.6em;margin-top:-.2em}.ol-attribution.ol-uncollapsible button{display:none}.ol-zoomslider{height:200px;top:4.5em;left:.5em}.ol-zoomslider button{height:10px;position:relative}.ol-touch .ol-zoomslider{top:5.5em}.ol-overviewmap{bottom:.5em;left:.5em}.ol-overviewmap.ol-uncollapsible{border-radius:0 4px 0 0;bottom:0;left:0}.ol-overviewmap .ol-overviewmap-map,.ol-overviewmap button{display:block}.ol-overviewmap .ol-overviewmap-map{border:1px solid var(--ol-subtle-foreground-color);width:150px;height:150px}.ol-overviewmap:not(.ol-collapsed) button{position:absolute;bottom:0;left:0}.ol-overviewmap.ol-collapsed .ol-overviewmap-map,.ol-overviewmap.ol-uncollapsible button{display:none}.ol-overviewmap:not(.ol-collapsed){background:var(--ol-subtle-background-color)}.ol-overviewmap-box{border:1.5px dotted var(--ol-subtle-foreground-color)}.ol-overviewmap .ol-overviewmap-box:hover{cursor:move}.ol-overviewmap .ol-viewport:hover{cursor:pointer}.map-viewer-root{--bg:#0f1419;--panel:#171e26f2;--panel-solid:#171e26;--card:#1c2530;--field:#0e141b;--border:#2a3441;--text:#e8edf3;--muted:#9aa7b4;--accent:#3f8cff;--ok:#39c26d;--warn:#e8b339;--err:#ff6b6b;--radius:10px;--map-bg:#0b0f14;--tabs-bg:#141b23;--item-bg:#141b23;--btn2-bg:#2a3a4d;--btn2-bg-hover:#35485f;--chip-bg:#223450;--chip-border:#33517a;--chip-color:#bcd7ff;--chip-bg-hover:#2c4266;--hint-color:#8fbcff;--icon-hover-bg:#22304a;--toast-bg:#1c2530f2;--status-bg:#10151bd9;--ol-btn-bg:#1c2530dd;--drop-bg:#0b0f14cc;--drop-inner-bg:#12213a99;--shadow:0 8px 32px #00000080;--scroll-thumb:#2a3441}.map-viewer-root.light-theme{--bg:#dfe7ee;--panel:#fffffff2;--panel-solid:#fff;--card:#f2f6fa;--field:#fff;--border:#c9d4de;--text:#1c2833;--muted:#5a6b7b;--accent:#2f7bdb;--ok:#1e9e56;--warn:#b07d0a;--err:#d9534f;--map-bg:#e9eef3;--tabs-bg:#e4eaf0;--item-bg:#f7fafc;--btn2-bg:#dde5ec;--btn2-bg-hover:#cfdbe6;--chip-bg:#dbe8f8;--chip-border:#b3cdf0;--chip-color:#1d5cad;--chip-bg-hover:#c9ddf5;--hint-color:#1d6fd6;--icon-hover-bg:#e2e9f0;--toast-bg:#fffffff2;--status-bg:#fffffff0;--ol-btn-bg:#fffffff0;--drop-bg:#ebf1f7d9;--drop-inner-bg:#ffffffbf;--shadow:0 8px 32px #1e32462e;--scroll-thumb:#c3ced8}*{box-sizing:border-box}.map-viewer-root{background:var(--bg);height:100%;color:var(--text);margin:0;font-family:Segoe UI,Microsoft YaHei,system-ui,sans-serif;position:relative;overflow:hidden}#map{background:var(--map-bg);position:absolute;inset:0}.sidebar-resizer{top:12px;bottom:52px;left:calc(var(--sidebar-width,342px) + 6px);cursor:col-resize;z-index:11;border-radius:4px;width:10px;position:absolute}.sidebar-resizer:hover{background:#6699ff40}.map-loading-mask{z-index:5;background:var(--map-bg);opacity:.75;flex-direction:column;justify-content:center;align-items:center;gap:12px;display:flex;position:absolute;inset:0}.map-loading-spinner{border:3px solid var(--border);border-top-color:var(--accent);border-radius:50%;width:34px;height:34px;animation:.9s linear infinite map-loading-spin}.map-loading-text{color:var(--text);font-size:13px}@keyframes map-loading-spin{to{transform:rotate(360deg)}}#sidebar{width:var(--sidebar-width,342px);background:var(--panel);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid var(--border);box-shadow:var(--shadow);z-index:10;border-radius:14px;flex-direction:column;transition:transform .25s,opacity .25s;display:flex;position:absolute;top:12px;bottom:52px;left:12px}.map-viewer-root.sidebar-collapsed #sidebar{opacity:0;pointer-events:none;transform:translate(-115%)}#sidebar-open{z-index:9;background:var(--panel-solid);border:1px solid var(--border);width:38px;height:38px;color:var(--text);cursor:pointer;border-radius:10px;justify-content:center;align-items:center;font-size:18px;display:none;position:absolute;top:12px;left:12px}.map-viewer-root.sidebar-collapsed #sidebar-open{display:flex}#panel-right{background:var(--panel);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid var(--border);width:300px;box-shadow:var(--shadow);z-index:10;border-radius:14px;flex-direction:column;transition:transform .25s,opacity .25s;display:flex;position:absolute;top:12px;bottom:52px;right:12px}.map-viewer-root.panel-right-collapsed #panel-right{opacity:0;pointer-events:none;transform:translate(115%)}#panel-right-open{z-index:9;background:var(--panel-solid);border:1px solid var(--border);width:38px;height:38px;color:var(--text);cursor:pointer;border-radius:10px;justify-content:center;align-items:center;font-size:18px;display:none;position:absolute;top:12px;right:12px}.map-viewer-root.panel-right-collapsed #panel-right-open{display:flex}.sidebar-header{border-bottom:1px solid var(--border);flex:none;justify-content:space-between;align-items:center;padding:13px 14px 11px;display:flex}.brand{align-items:center;gap:10px;min-width:0;display:flex}.brand h1{white-space:nowrap;margin:0;font-size:15px}.brand p{color:var(--muted);margin:0;font-size:11px}.logo{font-size:22px}#sidebar-collapse,.header-actions button{border:1px solid var(--border);color:var(--muted);cursor:pointer;background:0 0;border-radius:7px;flex:none;justify-content:center;align-items:center;width:28px;height:28px;font-size:14px;transition:all .15s;display:flex}#sidebar-collapse:hover,.header-actions button:hover{color:var(--text);border-color:var(--accent)}.header-actions{flex:none;gap:6px;display:flex}.sidebar-body{flex-direction:column;flex:1;gap:12px;padding:12px 14px 16px;display:flex;overflow:auto}.sidebar-body::-webkit-scrollbar{width:8px}.sidebar-body::-webkit-scrollbar-thumb{background:var(--scroll-thumb);border-radius:4px}.block{background:var(--card);border:1px solid var(--border);border-radius:var(--radius);flex:none;padding:10px 12px}.block h2{color:var(--muted);letter-spacing:.05em;margin:0 0 8px;font-size:12px;font-weight:600}.tabs{background:var(--tabs-bg);border-radius:8px;flex-wrap:wrap;gap:4px;margin-bottom:10px;padding:4px;display:flex}.tab-btn{color:var(--muted);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:calc(33.33% - 3px);padding:7px 4px;font-size:12px;transition:all .15s}.tab-btn.active{background:var(--accent);color:#fff}.source-type-tabs .tab-btn,.source-tabs .tab-btn{flex:1}.tab-pane{display:none}.tab-pane.active{display:block}label{color:var(--muted);margin-bottom:6px;font-size:12px;display:block}input[type=text],input[type=number],select{background:var(--field);width:100%;color:var(--text);border:1px solid var(--border);border-radius:7px;outline:none;padding:7px 9px;font-family:inherit;font-size:13px}input:focus,select:focus{border-color:var(--accent)}.file-btn{background:var(--accent);color:#fff;cursor:pointer;border-radius:8px;justify-content:center;align-items:center;width:100%;margin:0 0 6px;padding:9px;font-size:13px;transition:all .15s;display:flex}.file-btn:hover{filter:brightness(1.12)}.file-name{color:var(--muted);word-break:break-all;min-height:15px;margin-bottom:8px;font-size:11.5px}.extent-grid{grid-template-columns:1fr 1fr;gap:6px;margin:8px 0 2px;display:grid}.grid-caption{color:var(--muted);margin:10px 0 0;font-size:11px;display:block}.extent-grid label{margin:0}.zoom-range{grid-template-columns:1fr 1fr;gap:6px;display:grid}.check{color:var(--text);cursor:pointer;align-items:center;gap:7px;margin:8px 0;font-size:12.5px;display:flex}.check input{width:auto;margin:0}.hint{color:var(--hint-color);min-height:0;margin:6px 0;font-size:11.5px;line-height:1.8}.chip{background:var(--chip-bg);color:var(--chip-color);border:1px solid var(--chip-border);cursor:pointer;border-radius:20px;margin:2px 3px 0 0;padding:2px 9px;font-size:11px;display:inline-block}.chip:hover{background:var(--chip-bg-hover)}.tip{color:var(--muted);margin:8px 0 0;font-size:11px;line-height:1.6}.primary-btn{color:#fff;cursor:pointer;background:linear-gradient(135deg,#3f8cff,#2f6fd8);border:none;border-radius:9px;flex:none;width:100%;padding:11px;font-size:14px;font-weight:600;transition:all .15s}.primary-btn:hover{filter:brightness(1.12)}.row{gap:6px;margin-bottom:6px;display:flex}.row select,.row input{flex:1;min-width:0}.mini-btn{background:var(--btn2-bg);color:var(--text);cursor:pointer;white-space:nowrap;border:none;border-radius:7px;padding:7px 12px;font-size:12px}.mini-btn:hover{background:var(--btn2-bg-hover)}.custom-crs{margin-top:8px}#map-list{flex-direction:column;gap:6px;margin:0;padding:0;list-style:none;display:flex}#map-list .empty{color:var(--muted);text-align:center;padding:10px 0;font-size:12px}.map-item{background:var(--item-bg);border:1px solid var(--border);cursor:pointer;border-radius:8px;justify-content:space-between;align-items:center;gap:6px;padding:7px 9px;transition:border-color .15s,background .15s;display:flex}.map-item:hover{border-color:var(--accent)}.map-item.active{border-color:var(--accent);background:var(--chip-bg)}.map-item.active .map-name{color:var(--accent)}.map-info{flex-direction:column;gap:2px;min-width:0;display:flex}.map-name{white-space:nowrap;text-overflow:ellipsis;font-size:12px;overflow:hidden}.map-meta{color:var(--muted);font-size:10.5px}.map-actions{flex:none;gap:2px;display:flex}.icon-btn{color:var(--muted);cursor:pointer;background:0 0;border:none;border-radius:5px;padding:4px 5px;font-size:13px}.icon-btn:hover{background:var(--icon-hover-bg);color:var(--text)}#statusbar{background:var(--status-bg);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-top:1px solid var(--border);z-index:10;height:34px;color:var(--muted);align-items:center;gap:20px;padding:0 14px;font-size:12px;display:flex;position:absolute;bottom:0;left:0;right:0}.status-seg{white-space:nowrap;align-items:center;min-width:0;display:flex}#status-info{margin-left:auto}#statusbar .ol-mouse-position{color:var(--text);font-variant-numeric:tabular-nums;font-size:12px;position:static}#statusbar .ol-scale-line{background:0 0;border:none;padding:0;position:static}#statusbar .ol-scale-line-inner{color:var(--muted);border-color:var(--muted);font-size:11px}.ol-zoom{left:calc(var(--sidebar-width,342px) + 24px);top:8px}.ol-fit-all{left:calc(var(--sidebar-width,342px) + 24px);top:84px}.ol-full-screen{left:calc(var(--sidebar-width,342px) + 24px);top:126px;right:auto}.ol-attribution{right:calc(var(--sidebar-width,342px) - 6px);bottom:42px}.map-viewer-root.sidebar-collapsed .ol-zoom,.map-viewer-root.sidebar-collapsed .ol-fit-all,.map-viewer-root.sidebar-collapsed .ol-full-screen{left:58px}.ol-control button{background:var(--ol-btn-bg);color:var(--text);border:1px solid var(--border);cursor:pointer;border-radius:6px;font-size:16px}.ol-zoom button,.ol-fit-all button,.ol-full-screen button{box-sizing:border-box;width:32px;height:32px;margin:1px}.ol-control button:hover{background:var(--accent);color:#fff}.ol-attribution{background:var(--status-bg)!important}.ol-attribution a,.ol-attribution ul{font-size:11px;color:var(--muted)!important}#drop-overlay{background:var(--drop-bg);z-index:25;justify-content:center;align-items:center;display:none;position:absolute;inset:0}#drop-overlay.show{display:flex}#drop-overlay>div{border:2px dashed var(--accent);color:var(--accent);background:var(--drop-inner-bg);border-radius:16px;padding:40px 60px;font-size:18px}#toast{background:var(--toast-bg);border:1px solid var(--border);color:var(--text);opacity:0;pointer-events:none;z-index:30;white-space:nowrap;text-overflow:ellipsis;border-radius:9px;max-width:72vw;padding:9px 16px;font-size:13px;transition:all .25s;position:absolute;top:16px;left:50%;overflow:hidden;transform:translate(-50%,-12px)}#toast.show{opacity:1;transform:translate(-50%)}#toast[data-type=ok]{border-color:var(--ok)}#toast[data-type=warn]{border-color:var(--warn)}#toast[data-type=err]{border-color:var(--err)}@media (width<=900px){#sidebar,#panel-right{width:calc(100vw - 24px)}}.dialog-overlay{z-index:25;background:#0a0e128c;justify-content:center;align-items:center;display:none;position:absolute;inset:0}.dialog-overlay.show{display:flex}.dialog{background:var(--panel-solid);border:1px solid var(--border);width:384px;max-width:calc(100vw - 24px);max-height:calc(100% - 24px);box-shadow:var(--shadow);border-radius:14px;flex-direction:column;display:flex}.dialog-header{border-bottom:1px solid var(--border);flex:none;justify-content:space-between;align-items:center;padding:13px 16px;display:flex}.dialog-header button{border:1px solid var(--border);color:var(--muted);cursor:pointer;background:0 0;border-radius:7px;justify-content:center;align-items:center;width:28px;height:28px;font-size:14px;transition:all .15s;display:flex}.dialog-header button:hover{color:var(--text);border-color:var(--accent)}.dialog-body{flex-direction:column;gap:12px;padding:12px 16px 16px;display:flex;overflow-y:auto}.dialog-body::-webkit-scrollbar{width:8px}.dialog-body::-webkit-scrollbar-thumb{background:var(--scroll-thumb);border-radius:4px}#view-crs-block{flex:none}#view-crs-block .row{margin-bottom:4px}#view-crs-block .row select{padding:5px 8px;font-size:12px}#view-crs-block .grid-caption{margin:5px 0 0}#view-crs-block .extent-grid{gap:4px;margin:5px 0 0}#view-crs-block .extent-grid input[type=number]{border-radius:6px;padding:4px 7px;font-size:11.5px}#layer-list-block{flex-direction:column;flex:auto;min-height:200px;display:flex;overflow:hidden}#layer-list-block h2{flex:none}#layer-list{flex-direction:column;flex:auto;gap:6px;min-height:0;margin:0;padding:0 2px 0 0;list-style:none;display:flex;overflow-y:auto}#layer-list::-webkit-scrollbar{width:8px}#layer-list::-webkit-scrollbar-thumb{background:var(--scroll-thumb);border-radius:4px}.layer-item{background:var(--item-bg);border:1px solid var(--border);border-radius:8px;justify-content:space-between;align-items:center;gap:6px;padding:7px 9px;transition:opacity .15s,border-color .15s,background .15s;display:flex}.layer-item.hidden-layer{opacity:.6}.layer-item:hover{border-color:var(--accent)}.layer-group{background:var(--chip-bg)}.layer-group .layer-name{font-weight:600}.layer-child{border-left:2px solid var(--accent);margin-left:14px}.layer-controls{flex:none;align-items:center;gap:2px;display:flex}.layer-fold{font-size:12px}.layer-info{flex-direction:column;gap:2px;min-width:0;display:flex}.layer-name{white-space:nowrap;text-overflow:ellipsis;font-size:12px;overflow:hidden}.layer-meta{color:var(--muted);font-size:10.5px}.map-detail{align-items:baseline;gap:8px;margin-bottom:7px;font-size:12px;display:flex}.map-detail:last-child{margin-bottom:0}.map-detail .detail-label{color:var(--muted);flex:none;width:74px}.map-detail span:last-child{word-break:break-all;color:var(--text)}.layer-list-title{justify-content:space-between;align-items:center;gap:8px;display:flex}.layer-summary{color:var(--text);background:var(--chip-bg);border:1px solid var(--chip-border);white-space:nowrap;border-radius:999px;padding:2px 6px;font-size:11px;font-weight:500}.layer-list-hint{color:var(--muted);margin:6px 0 0;font-size:12px}
2
+ /*$vite$:1*/