ethio-map-kit 0.1.2 → 0.1.3
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 +119 -1
- package/dist/components/EthiopiaMap.d.ts +11 -3
- package/dist/components/EthiopiaRegionServicesCard.d.ts +7 -1
- package/dist/components/EthiopiaRegionServicesPanel.d.ts +20 -0
- package/dist/ethio-map-kit.css +1 -1
- package/dist/ethio-map-kit.js +743 -580
- package/dist/ethio-map-kit.umd.cjs +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/types.d.ts +15 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -87,12 +87,42 @@ const data: RegionRecord<RegionDatum> = {
|
|
|
87
87
|
| `selectionAnimation` | `"pulse" \| "static" \| "none" \| "outline"` | Selected-region animation style. |
|
|
88
88
|
| `showLabels` | `boolean` | Show or hide region labels. |
|
|
89
89
|
| `showMarkers` | `boolean` | Show or hide location markers. |
|
|
90
|
+
| `showInMapStats` | `boolean` | Show or hide the selected region service overlay inside the map surface. |
|
|
90
91
|
| `regionColors` | `PartialRegionRecord<string>` | Override region colors. |
|
|
91
92
|
| `selectedRegionId` | `EthiopiaRegionId \| null` | Controlled selected region. |
|
|
92
93
|
| `defaultSelectedRegionId` | `EthiopiaRegionId \| null` | Initial selected region. |
|
|
93
94
|
| `onRegionSelect` | `(selection) => void` | Called when a region is selected or cleared. |
|
|
95
|
+
| `className` | `string` | Class applied to the map surface in the all-in-one `EthiopiaMap`. |
|
|
96
|
+
| `style` | `React.CSSProperties` | Inline style applied to the map surface in the all-in-one `EthiopiaMap`. Useful for height and width. |
|
|
94
97
|
| `terrainImageUrl` | `string` | Custom terrain image URL. |
|
|
95
98
|
|
|
99
|
+
## Sizing The Map
|
|
100
|
+
|
|
101
|
+
The map surface fills its own container and has a default minimum height. Use `className`, `style`, or your layout wrapper to control the rendered size.
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
<EthiopiaMap
|
|
105
|
+
data={defaultRegionData}
|
|
106
|
+
serviceStats={defaultRegionServiceStats}
|
|
107
|
+
className="w-full"
|
|
108
|
+
style={{ width: "100%", height: 640, minHeight: 640 }}
|
|
109
|
+
/>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
With composable components, size `EthiopiaMapSurface` directly:
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
<EthiopiaMapProvider data={defaultRegionData}>
|
|
116
|
+
<div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_320px]">
|
|
117
|
+
<EthiopiaMapSurface
|
|
118
|
+
className="w-full"
|
|
119
|
+
style={{ height: 620, minHeight: 620 }}
|
|
120
|
+
/>
|
|
121
|
+
<EthiopiaSelectedRegionCard />
|
|
122
|
+
</div>
|
|
123
|
+
</EthiopiaMapProvider>
|
|
124
|
+
```
|
|
125
|
+
|
|
96
126
|
## Composable Components
|
|
97
127
|
|
|
98
128
|
For custom layouts, wrap components with `EthiopiaMapProvider`.
|
|
@@ -104,13 +134,18 @@ import {
|
|
|
104
134
|
EthiopiaMapLegend,
|
|
105
135
|
EthiopiaSelectedRegionCard,
|
|
106
136
|
EthiopiaRegionServicesCard,
|
|
137
|
+
EthiopiaRegionServicesPanel,
|
|
107
138
|
EthiopiaLocationsPanel,
|
|
108
139
|
defaultRegionData,
|
|
140
|
+
defaultRegionServiceStats,
|
|
109
141
|
} from "ethio-map-kit";
|
|
110
142
|
|
|
111
143
|
export function Dashboard() {
|
|
112
144
|
return (
|
|
113
|
-
<EthiopiaMapProvider
|
|
145
|
+
<EthiopiaMapProvider
|
|
146
|
+
data={defaultRegionData}
|
|
147
|
+
serviceStats={defaultRegionServiceStats}
|
|
148
|
+
>
|
|
114
149
|
<EthiopiaMapSurface />
|
|
115
150
|
<EthiopiaMapLegend />
|
|
116
151
|
<EthiopiaSelectedRegionCard />
|
|
@@ -121,6 +156,88 @@ export function Dashboard() {
|
|
|
121
156
|
}
|
|
122
157
|
```
|
|
123
158
|
|
|
159
|
+
## Service Stats Layouts
|
|
160
|
+
|
|
161
|
+
Service stats can appear inside the map surface, outside the map, or in a standalone details page. Use either the in-map overlay or the external card unless you intentionally want both.
|
|
162
|
+
|
|
163
|
+
In-map overlay only:
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
<EthiopiaMapProvider
|
|
167
|
+
data={defaultRegionData}
|
|
168
|
+
serviceStats={defaultRegionServiceStats}
|
|
169
|
+
showInMapStats
|
|
170
|
+
>
|
|
171
|
+
<EthiopiaMapSurface />
|
|
172
|
+
<EthiopiaSelectedRegionCard />
|
|
173
|
+
</EthiopiaMapProvider>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
External service card only:
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
<EthiopiaMapProvider
|
|
180
|
+
data={defaultRegionData}
|
|
181
|
+
serviceStats={defaultRegionServiceStats}
|
|
182
|
+
showInMapStats={false}
|
|
183
|
+
>
|
|
184
|
+
<div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_320px]">
|
|
185
|
+
<EthiopiaMapSurface className="w-full" style={{ height: 620 }} />
|
|
186
|
+
<EthiopiaRegionServicesCard />
|
|
187
|
+
</div>
|
|
188
|
+
</EthiopiaMapProvider>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Customize the in-map overlay and its scroll list from `EthiopiaMapSurface`:
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
<EthiopiaMapSurface
|
|
195
|
+
inMapStatsClassName="my-map-stats"
|
|
196
|
+
inMapStatsStyle={{ maxHeight: 320 }}
|
|
197
|
+
inMapStatsListClassName="my-map-stats-list"
|
|
198
|
+
inMapStatsListStyle={{ maxHeight: 240 }}
|
|
199
|
+
/>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Opt in to incremental row rendering when a region has many indicators:
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
<EthiopiaRegionServicesCard
|
|
206
|
+
incrementalRows={{
|
|
207
|
+
enabled: true,
|
|
208
|
+
initialCount: 8,
|
|
209
|
+
step: 8,
|
|
210
|
+
}}
|
|
211
|
+
/>
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The same option works on the in-map overlay:
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
<EthiopiaMapSurface
|
|
218
|
+
incrementalRows={{
|
|
219
|
+
enabled: true,
|
|
220
|
+
initialCount: 8,
|
|
221
|
+
step: 8,
|
|
222
|
+
thresholdPx: 80,
|
|
223
|
+
}}
|
|
224
|
+
/>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
For server-rendered detail pages, fetch data in your app and pass it directly to the context-free panel. The package does not include Prisma, Next.js caching, route generation, ISR, or database fetching.
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
const services = await getCachedMapsData("afar", 2021, true);
|
|
231
|
+
|
|
232
|
+
return (
|
|
233
|
+
<EthiopiaRegionServicesPanel
|
|
234
|
+
regionName="Afar"
|
|
235
|
+
regionValue={34}
|
|
236
|
+
services={services.afar ?? []}
|
|
237
|
+
/>
|
|
238
|
+
);
|
|
239
|
+
```
|
|
240
|
+
|
|
124
241
|
## Exports
|
|
125
242
|
|
|
126
243
|
- `EthiopiaMap`
|
|
@@ -129,6 +246,7 @@ export function Dashboard() {
|
|
|
129
246
|
- `EthiopiaMapLegend`
|
|
130
247
|
- `EthiopiaSelectedRegionCard`
|
|
131
248
|
- `EthiopiaRegionServicesCard`
|
|
249
|
+
- `EthiopiaRegionServicesPanel`
|
|
132
250
|
- `EthiopiaLocationsPanel`
|
|
133
251
|
- `useEthiopiaMap`
|
|
134
252
|
- `useSelectedRegionId`
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type CSSProperties } from "react";
|
|
2
|
+
import type { EthiopiaMapProps, EthiopiaRegionId, EthiopiaServiceRowsIncrementalConfig } from "../types";
|
|
2
3
|
export interface EthiopiaMapSurfaceProps {
|
|
3
4
|
className?: string;
|
|
5
|
+
style?: CSSProperties;
|
|
4
6
|
svgText?: string;
|
|
5
7
|
svgUrl?: string;
|
|
6
8
|
terrainImageUrl?: string;
|
|
9
|
+
inMapStatsClassName?: string;
|
|
10
|
+
inMapStatsStyle?: CSSProperties;
|
|
11
|
+
inMapStatsListClassName?: string;
|
|
12
|
+
inMapStatsListStyle?: CSSProperties;
|
|
13
|
+
inMapStatsEmptyText?: string;
|
|
14
|
+
incrementalRows?: EthiopiaServiceRowsIncrementalConfig;
|
|
7
15
|
}
|
|
8
|
-
export declare function EthiopiaMapSurface({ className, svgText, svgUrl, terrainImageUrl, }: EthiopiaMapSurfaceProps): import("react").JSX.Element;
|
|
9
|
-
export declare function EthiopiaMap({ className, svgText, svgUrl, terrainImageUrl, ...providerProps }: EthiopiaMapProps): import("react").JSX.Element;
|
|
16
|
+
export declare function EthiopiaMapSurface({ className, style, svgText, svgUrl, terrainImageUrl, inMapStatsClassName, inMapStatsStyle, inMapStatsListClassName, inMapStatsListStyle, inMapStatsEmptyText, incrementalRows, }: EthiopiaMapSurfaceProps): import("react").JSX.Element;
|
|
17
|
+
export declare function EthiopiaMap({ className, style, svgText, svgUrl, terrainImageUrl, inMapStatsClassName, inMapStatsStyle, inMapStatsListClassName, inMapStatsListStyle, inMapStatsEmptyText, incrementalRows, ...providerProps }: EthiopiaMapProps): import("react").JSX.Element;
|
|
10
18
|
export declare function useSelectedRegionId(): EthiopiaRegionId | null;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
import type { EthiopiaServiceRowsIncrementalConfig } from "../types";
|
|
1
3
|
export interface EthiopiaRegionServicesCardProps {
|
|
2
4
|
className?: string;
|
|
5
|
+
style?: CSSProperties;
|
|
6
|
+
listClassName?: string;
|
|
7
|
+
listStyle?: CSSProperties;
|
|
3
8
|
emptyText?: string;
|
|
9
|
+
incrementalRows?: EthiopiaServiceRowsIncrementalConfig;
|
|
4
10
|
}
|
|
5
|
-
export declare function EthiopiaRegionServicesCard({ className, emptyText, }: EthiopiaRegionServicesCardProps): import("react").JSX.Element;
|
|
11
|
+
export declare function EthiopiaRegionServicesCard({ className, style, listClassName, listStyle, emptyText, incrementalRows, }: EthiopiaRegionServicesCardProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type CSSProperties } from "react";
|
|
2
|
+
import type { EthiopiaServiceRowsIncrementalConfig, ServiceStat } from "../types";
|
|
3
|
+
type ServicesPanelVariant = "card" | "overlay";
|
|
4
|
+
export interface EthiopiaRegionServicesPanelProps {
|
|
5
|
+
className?: string;
|
|
6
|
+
style?: CSSProperties;
|
|
7
|
+
listClassName?: string;
|
|
8
|
+
listStyle?: CSSProperties;
|
|
9
|
+
title?: string;
|
|
10
|
+
kicker?: string;
|
|
11
|
+
regionName?: string | null;
|
|
12
|
+
regionValue?: number | null;
|
|
13
|
+
services?: readonly ServiceStat[];
|
|
14
|
+
emptyText?: string;
|
|
15
|
+
variant?: ServicesPanelVariant;
|
|
16
|
+
incrementalRows?: EthiopiaServiceRowsIncrementalConfig;
|
|
17
|
+
getBarPercent?: (stat: ServiceStat) => number;
|
|
18
|
+
}
|
|
19
|
+
export declare function EthiopiaRegionServicesPanel({ className, style, listClassName, listStyle, title, kicker, regionName, regionValue, services, emptyText, variant, incrementalRows, getBarPercent, }: EthiopiaRegionServicesPanelProps): import("react").JSX.Element;
|
|
20
|
+
export {};
|
package/dist/ethio-map-kit.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.ethiopia-map-surface{--map-stroke: rgba(42, 73, 63, .42);--preview-base: #f7faf6;--region-shadow-rest: rgba(0, 0, 0, .3);--region-shadow-wall: rgba(0, 0, 0, .6);--region-shadow-mid: rgba(0, 0, 0, .42);--region-shadow-ambient: rgba(0, 0, 0, .3);--region-shadow-glow: rgba(23, 107, 84, .45);position:relative;min-height:520px;overflow:hidden;border:1px solid rgba(40,72,62,.22);border-radius:8px;background:linear-gradient(rgba(23,107,84,.06) 1px,transparent 1px),linear-gradient(90deg,rgba(23,107,84,.06) 1px,transparent 1px),#eef5ef;background-size:32px 32px}.ethiopia-map-surface.dark-mode{--map-stroke: rgba(238, 248, 244, .72);--preview-base: #102520;--region-shadow-rest: rgba(218, 229, 224, .28);--region-shadow-wall: rgba(218, 229, 224, .42);--region-shadow-mid: rgba(206, 221, 214, .3);--region-shadow-ambient: rgba(220, 234, 228, .22);--region-shadow-glow: rgba(222, 238, 231, .34);border-color:#c2ddd33d;background:linear-gradient(rgba(173,214,198,.07) 1px,transparent 1px),linear-gradient(90deg,rgba(173,214,198,.07) 1px,transparent 1px),#15201c}.ethiopia-map-surface.bars-mode{background:linear-gradient(rgba(23,107,84,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(23,107,84,.05) 1px,transparent 1px),#f7faf7}.ethiopia-map-surface.dark-mode.bars-mode{background:#15201c}.ethiopia-map-svg-host{position:absolute;top:0;right:0;bottom:0;left:0}.ethiopia-map-surface svg{display:block;width:100%;height:100%}.ethiopia-map-watermark{position:absolute;top:20px;left:20px;z-index:5;width:auto;max-height:64px;object-fit:contain;opacity:.82;pointer-events:none;-webkit-user-select:none;user-select:none}.ethiopia-map-surface .map-region{transition:fill .18s ease,stroke .18s ease,opacity .18s ease,filter .18s ease,transform .26s ease;transform-box:fill-box;transform-origin:center}.ethiopia-map-surface.zooming .map-region{transition:none!important}.ethiopia-map-surface.zooming .region-outline-layer{opacity:0}.ethiopia-map-surface.zooming .map-region.pulse,.ethiopia-map-surface.zooming .map-region.lifted,.ethiopia-map-surface.zooming .map-region.outline-only{animation-play-state:paused;filter:none!important}.ethiopia-map-surface.zooming text,.ethiopia-map-surface.zooming tspan{opacity:0!important;transition:none!important}.ethiopia-map-surface .map-region:hover,.ethiopia-map-surface .map-region.selected{stroke:#fff!important}.ethiopia-map-surface text,.ethiopia-map-surface tspan{pointer-events:none}.ethiopia-map-surface.dark-mode .map-region{stroke:#e2efe9a3!important}.ethiopia-map-surface .map-region.pulse,.ethiopia-map-surface .map-region.lifted{transform-box:fill-box;transform-origin:center bottom;will-change:transform,filter}.ethiopia-map-surface .map-region.pulse{animation:regionFloat 3s cubic-bezier(.34,1.4,.64,1) infinite}.ethiopia-map-surface .map-region.lifted{animation:regionLiftHold .62s cubic-bezier(.34,1.4,.64,1) forwards}.ethiopia-map-surface .map-region.outline-only{fill:#ffffff0f!important;filter:drop-shadow(0 0 10px rgba(23,107,84,.28))}.ethiopia-map-surface .region-outline-layer{pointer-events:none}.ethiopia-map-surface .selected-region-outline,.ethiopia-map-surface .hover-region-outline{filter:drop-shadow(0 0 8px rgba(23,107,84,.36))}.ethiopia-map-surface.terrain-mode .map-region{fill:#ffffff08!important;stroke:#1b231fb8!important;stroke-width:1.5px!important}.ethiopia-map-surface.terrain-mode .map-region.selected{fill:#ffffff09!important}.ethiopia-map-surface.focus-mode .map-region:not(.selected){opacity:.3!important;fill:var(--preview-base)!important;stroke:var(--map-stroke)!important;filter:none}.ethiopia-map-surface.light-mode.focus-mode .map-region:not(.selected){fill:#fff!important}.ethiopia-map-surface.terrain-mode.focus-mode .map-region:not(.selected){fill:#ffffff06!important;opacity:.24!important;stroke:#1b231f75!important}.ethiopia-map-surface.focus-mode .map-region.selected{opacity:1!important;stroke:#fff!important}.ethiopia-map-surface.focus-mode text,.ethiopia-map-surface.focus-mode tspan{opacity:.24!important}.ethiopia-map-panel{border:1px solid rgba(40,72,62,.18);border-radius:8px;background:#ffffffb8;padding:14px;color:#17231f}.ethiopia-map-panel h2,.ethiopia-map-panel p{margin:0}.ethiopia-map-kicker{color:#60736b;font-size:12px;font-weight:800;text-transform:uppercase}.ethiopia-map-panel-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:12px}.ethiopia-map-legend-list,.ethiopia-service-list,.ethiopia-location-list{display:grid;gap:8px}.ethiopia-map-legend-list{max-height:300px;overflow:auto;padding-right:4px}.ethiopia-region-services .ethiopia-service-list{max-height:320px;overflow:auto;padding-right:4px}.ethiopia-map-legend-row{display:grid;grid-template-columns:12px minmax(0,1fr) 42px;gap:9px;align-items:center;border:1px solid rgba(40,72,62,.16);border-radius:6px;background:#ffffffa3;padding:8px;color:inherit;cursor:pointer;text-align:left}.ethiopia-map-legend-row.active{border-color:#176b546b}.ethiopia-map-swatch{width:12px;height:26px;border-radius:4px}.ethiopia-map-legend-title-line,.ethiopia-service-copy,.ethiopia-selected-region-stats{display:flex;align-items:baseline;justify-content:space-between;gap:10px}.ethiopia-map-legend-bar{display:block;height:5px;overflow:hidden;border-radius:999px;background:#14221d14}.ethiopia-map-legend-bar-fill{display:block;height:100%}.ethiopia-selected-region-preview,.ethiopia-empty-state{display:grid;place-items:center;border:1px solid rgba(40,72,62,.14);border-radius:8px;color:#60736b}.ethiopia-selected-region-preview{--ethiopia-preview-base: #f7faf6;--ethiopia-preview-stroke: rgba(42, 73, 63, .16);--region-shadow-rest: rgba(0, 0, 0, .3);--region-shadow-wall: rgba(0, 0, 0, .6);--region-shadow-mid: rgba(0, 0, 0, .42);--region-shadow-ambient: rgba(0, 0, 0, .3);--region-shadow-glow: rgba(23, 107, 84, .45);height:190px;margin:14px 0 0;background:#f7faf6;overflow:hidden}.ethiopia-empty-state{min-height:104px}.dark-mode .ethiopia-selected-region-preview,.dark-theme .ethiopia-selected-region-preview{--ethiopia-preview-base: #102520;--ethiopia-preview-stroke: rgba(255, 255, 255, .12);--region-shadow-rest: rgba(218, 229, 224, .28);--region-shadow-wall: rgba(218, 229, 224, .42);--region-shadow-mid: rgba(206, 221, 214, .3);--region-shadow-ambient: rgba(220, 234, 228, .22);--region-shadow-glow: rgba(222, 238, 231, .34);background:#102520}.ethiopia-selected-region-preview-canvas{width:100%;height:100%}.ethiopia-selected-region-preview-canvas svg{display:block;width:100%;height:100%}.ethiopia-selected-region-preview .map-region{transform-box:fill-box;transform-origin:center}.ethiopia-selected-region-preview .map-region.selected{stroke:#fff!important}.ethiopia-selected-region-preview .map-region.pulse,.ethiopia-selected-region-preview .map-region.lifted{transform-box:fill-box;transform-origin:center bottom;will-change:transform,filter}.ethiopia-selected-region-preview .map-region.pulse{animation:regionFloat 3s cubic-bezier(.34,1.4,.64,1) infinite}.ethiopia-selected-region-preview .map-region.lifted{animation:regionLiftHold .62s cubic-bezier(.34,1.4,.64,1) forwards}.ethiopia-selected-region-preview .map-region.outline-only{fill:#ffffff0d!important;filter:drop-shadow(0 0 8px rgba(23,107,84,.22))}.ethiopia-selected-region-preview>.ethiopia-empty-state{min-height:0;border:0;background:transparent}.ethiopia-selected-region-stats{margin-top:12px}.ethiopia-selected-region-stats div{min-width:0;flex:1;border:1px solid rgba(40,72,62,.14);border-radius:6px;padding:9px}.ethiopia-selected-region-stats span,.ethiopia-location-item span{display:block;color:#60736b;font-size:12px;font-weight:800;text-transform:uppercase}.ethiopia-service-row,.ethiopia-location-item{border:1px solid rgba(40,72,62,.14);border-radius:6px;padding:9px}.ethiopia-service-comparison{margin-top:8px;font-size:12px;font-weight:800;text-transform:uppercase}.ethiopia-service-comparison.positive{color:#176b54}.ethiopia-service-comparison.negative{color:#9f2f2f}.map-stat-overlay{position:absolute;box-sizing:border-box;right:12px;top:14px;z-index:8;width:min(336px,calc(100% - 28px));padding:12px;border:1px solid rgba(38,72,60,.18);border-radius:8px;background:#ffffffbd;box-shadow:0 1px #ffffff94 inset,0 22px 70px #1c2d2724;color:#17231f;opacity:0;pointer-events:none;transform:translateY(-12px) scale(.98);transition:opacity .22s ease,transform .26s cubic-bezier(.22,1,.36,1)}@supports (backdrop-filter: blur(18px)){.map-stat-overlay{-webkit-backdrop-filter:blur(18px) saturate(1.18);backdrop-filter:blur(18px) saturate(1.18)}}.map-stat-overlay.visible{opacity:1;pointer-events:auto;transform:translateY(0) scale(1)}.dark-mode .map-stat-overlay{border-color:#d8f4e824;background:#0d1c19cc;color:#edf7f2}.map-stat-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:10px}.map-stat-heading h2{margin:0;font-size:22px;line-height:1.05}.map-stat-index{display:grid;place-items:center;min-width:40px;height:40px;border:1px solid rgba(23,107,84,.28);border-radius:8px;background:#176b541a;color:#176b54;font-size:17px;font-weight:900}.map-stat-list{display:grid;gap:7px;max-height:min(60vh,560px);overflow:auto;padding-right:5px}.map-stat-empty{padding:18px 12px;border:1px solid rgba(40,72,62,.14);border-radius:8px;background:#ffffff6b;color:#60736b;font-size:14px;line-height:1.45;text-align:center}.map-stat-row{padding:8px;border:1px solid rgba(40,72,62,.14);border-radius:8px;background:#ffffff7a;opacity:0;transform:translate(16px);animation:statSlideIn .52s cubic-bezier(.22,1,.36,1) forwards;animation-delay:var(--delay)}.dark-mode .map-stat-row{border-color:#e8f4ef24;background:#ffffff0f}.map-stat-copy{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-bottom:7px}.map-stat-copy span{color:#60736b;font-size:11px;font-weight:800;text-transform:uppercase}.dark-mode .map-stat-copy span{color:#9eb8ae}.map-stat-copy strong{color:inherit;font-size:15px;font-weight:900}.map-stat-comparison{display:inline-flex;align-items:center;max-width:100%;gap:6px;margin-bottom:9px;padding:5px 8px;border:1px solid rgba(40,72,62,.14);border-radius:8px;background:#ffffff80;color:#60736b}.dark-mode .map-stat-comparison{border-color:#e8f4ef24;background:#ffffff0f}.map-stat-comparison span{font-size:9px;font-weight:900;text-transform:uppercase}.map-stat-comparison strong{color:inherit;font-size:11px;font-weight:900;white-space:nowrap}.map-stat-comparison.positive{border-color:#176b543d;background:#176b541a;color:#176b54}.map-stat-comparison.negative{border-color:#b041373d;background:#b041371a;color:#9d342c}.map-stat-comparison.neutral{border-color:#626f693d;background:#626f691a;color:#626f69}.dark-mode .map-stat-comparison.positive{color:#8be0bf}.dark-mode .map-stat-comparison.negative{color:#ffaaa0}.dark-mode .map-stat-comparison.neutral{color:#b8c6bf}.map-stat-bar{height:8px;overflow:hidden;border:1px solid rgba(40,72,62,.14);border-radius:999px;background:#274b3f14}.map-stat-bar i{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,#176b549e,#176b54);transform-origin:left;animation:statBarGrow .72s cubic-bezier(.22,1,.36,1) both;animation-delay:calc(var(--delay) + .12s)}.bar-morph-track{fill:#15282214}.bar-morph-bar{filter:drop-shadow(0 8px 12px rgba(23,107,84,.14))}.bar-row{opacity:1;transition:opacity .36s ease}.bar-row.visible{opacity:1!important}.bar-region-ghost{filter:drop-shadow(0 8px 18px rgba(28,45,39,.2))}.bar-morph-label,.bar-morph-value{fill:#17231f;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:24px;font-weight:800}.bar-morph-value{font-size:22px;text-anchor:end}.dark-mode .bar-morph-track{fill:#e8f4ef1f}.dark-mode .bar-morph-label,.dark-mode .bar-morph-value{fill:#edf7f2}@keyframes regionFloat{0%{transform:translateZ(0) scaleY(1);filter:drop-shadow(0 1px 2px var(--region-shadow-rest)) drop-shadow(0 0 6px var(--region-shadow-glow))}45%{transform:translate3d(-3px,-18px,0) scaleY(1.018);filter:drop-shadow(4px 22px 0 var(--region-shadow-wall)) drop-shadow(3px 18px 2px var(--region-shadow-mid)) drop-shadow(1px 8px 12px var(--region-shadow-ambient)) drop-shadow(0 0 14px var(--region-shadow-glow))}62%{transform:translate3d(-4px,-22px,0) scaleY(1.022);filter:drop-shadow(5px 26px 0 var(--region-shadow-wall)) drop-shadow(4px 20px 3px var(--region-shadow-mid)) drop-shadow(2px 10px 14px var(--region-shadow-ambient)) drop-shadow(0 0 18px var(--region-shadow-glow))}82%{transform:translate3d(-1px,-6px,0) scaleY(1.006);filter:drop-shadow(2px 8px 0 var(--region-shadow-mid)) drop-shadow(1px 6px 8px var(--region-shadow-ambient)) drop-shadow(0 0 10px var(--region-shadow-glow))}to{transform:translateZ(0) scaleY(1);filter:drop-shadow(0 1px 2px var(--region-shadow-rest)) drop-shadow(0 0 6px var(--region-shadow-glow))}}@keyframes regionLiftHold{0%{transform:translateZ(0) scaleY(1);filter:drop-shadow(0 1px 2px var(--region-shadow-rest)) drop-shadow(0 0 6px var(--region-shadow-glow))}70%{transform:translate3d(-4px,-22px,0) scaleY(1.022);filter:drop-shadow(5px 26px 0 var(--region-shadow-wall)) drop-shadow(4px 20px 3px var(--region-shadow-mid)) drop-shadow(2px 10px 14px var(--region-shadow-ambient)) drop-shadow(0 0 18px var(--region-shadow-glow))}to{transform:translate3d(-4px,-22px,0) scaleY(1.022);filter:drop-shadow(5px 26px 0 var(--region-shadow-wall)) drop-shadow(4px 20px 3px var(--region-shadow-mid)) drop-shadow(2px 10px 14px var(--region-shadow-ambient)) drop-shadow(0 0 18px var(--region-shadow-glow))}}@keyframes statSlideIn{to{opacity:1;transform:translate(0)}}@keyframes statBarGrow{0%{transform:scaleX(0)}to{transform:scaleX(1)}}.react-demo-shell{display:grid;grid-template-columns:minmax(0,1fr) 360px;gap:18px;min-height:100vh;padding:18px;background:#e8eee8;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.react-demo-shell.dark-theme{background:#111c18}.react-demo-map,.react-demo-sidebar{display:grid;gap:14px;align-content:start}.react-demo-sidebar{max-height:calc(100vh - 36px);overflow:auto;padding-right:2px}.react-demo-header{display:flex;align-items:flex-start;justify-content:space-between;gap:20px}.react-demo-map h1{margin:0;color:#17231f;font-size:44px;line-height:.95}.dark-theme .react-demo-map h1{color:#edf7f2}.react-demo-mode-switcher,.react-demo-selection-switcher{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;max-width:520px}.react-demo-selection-switcher{justify-self:end;max-width:none}.react-demo-mode-switcher button,.react-demo-selection-switcher button{border:1px solid rgba(38,83,69,.22);border-radius:6px;background:#ffffffc7;color:#17231f;cursor:pointer;font:inherit;font-size:13px;font-weight:800;padding:9px 11px}.react-demo-mode-switcher button.active,.react-demo-selection-switcher button.active{border-color:#176b54;background:#176b54;color:#fff}.dark-theme .react-demo-mode-switcher button,.dark-theme .react-demo-selection-switcher button{border-color:#e8f4ef33;background:#ffffff14;color:#edf7f2}.dark-theme .react-demo-mode-switcher button.active,.dark-theme .react-demo-selection-switcher button.active{border-color:#6dc7a8;background:#6dc7a8;color:#10201a}.react-demo-map .ethiopia-map-surface{height:calc(100vh - 128px)}.dark-theme .ethiopia-map-panel{border-color:#e8f4ef29;background:#ffffff14;color:#edf7f2}.dark-theme .ethiopia-map-kicker,.dark-theme .ethiopia-selected-region-stats span,.dark-theme .ethiopia-location-item span{color:#9eb8ae}.dark-theme .ethiopia-map-legend-row,.dark-theme .ethiopia-service-row,.dark-theme .ethiopia-location-item,.dark-theme .ethiopia-selected-region-stats div,.dark-theme .ethiopia-selected-region-preview,.dark-theme .ethiopia-empty-state{border-color:#e8f4ef24;background:#ffffff0f}@media(max-width:900px){.react-demo-shell{grid-template-columns:1fr}.react-demo-header{display:grid}.react-demo-mode-switcher{justify-content:flex-start}.react-demo-selection-switcher{justify-self:start}}
|
|
1
|
+
.ethiopia-map-surface{--map-stroke: rgba(42, 73, 63, .42);--preview-base: #f7faf6;--region-shadow-rest: rgba(0, 0, 0, .3);--region-shadow-wall: rgba(0, 0, 0, .6);--region-shadow-mid: rgba(0, 0, 0, .42);--region-shadow-ambient: rgba(0, 0, 0, .3);--region-shadow-glow: rgba(23, 107, 84, .45);position:relative;min-height:520px;overflow:hidden;border:1px solid rgba(40,72,62,.22);border-radius:8px;background:linear-gradient(rgba(23,107,84,.06) 1px,transparent 1px),linear-gradient(90deg,rgba(23,107,84,.06) 1px,transparent 1px),#eef5ef;background-size:32px 32px}.ethiopia-map-surface.dark-mode{--map-stroke: rgba(238, 248, 244, .72);--preview-base: #102520;--region-shadow-rest: rgba(218, 229, 224, .28);--region-shadow-wall: rgba(218, 229, 224, .42);--region-shadow-mid: rgba(206, 221, 214, .3);--region-shadow-ambient: rgba(220, 234, 228, .22);--region-shadow-glow: rgba(222, 238, 231, .34);border-color:#c2ddd33d;background:linear-gradient(rgba(173,214,198,.07) 1px,transparent 1px),linear-gradient(90deg,rgba(173,214,198,.07) 1px,transparent 1px),#15201c}.ethiopia-map-surface.bars-mode{background:linear-gradient(rgba(23,107,84,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(23,107,84,.05) 1px,transparent 1px),#f7faf7}.ethiopia-map-surface.dark-mode.bars-mode{background:#15201c}.ethiopia-map-svg-host{position:absolute;top:0;right:0;bottom:0;left:0}.ethiopia-map-surface svg{display:block;width:100%;height:100%}.ethiopia-map-watermark{position:absolute;top:20px;left:20px;z-index:5;width:auto;max-height:64px;object-fit:contain;opacity:.82;pointer-events:none;-webkit-user-select:none;user-select:none}.ethiopia-map-surface .map-region{transition:fill .18s ease,stroke .18s ease,opacity .18s ease,filter .18s ease,transform .26s ease;transform-box:fill-box;transform-origin:center}.ethiopia-map-surface.zooming .map-region{transition:none!important}.ethiopia-map-surface.zooming .region-outline-layer{opacity:0}.ethiopia-map-surface.zooming .map-region.pulse,.ethiopia-map-surface.zooming .map-region.lifted,.ethiopia-map-surface.zooming .map-region.outline-only{animation-play-state:paused;filter:none!important}.ethiopia-map-surface .map-region:hover,.ethiopia-map-surface .map-region.selected{stroke:#fff!important}.ethiopia-map-surface text,.ethiopia-map-surface tspan{pointer-events:none}.ethiopia-map-surface.dark-mode .map-region{stroke:#e2efe9a3!important}.ethiopia-map-surface .map-region.pulse,.ethiopia-map-surface .map-region.lifted{transform-box:fill-box;transform-origin:center bottom;will-change:transform,filter}.ethiopia-map-surface .map-region.pulse{animation:regionFloat 3s cubic-bezier(.34,1.4,.64,1) infinite}.ethiopia-map-surface .map-region.lifted{animation:regionLiftHold .62s cubic-bezier(.34,1.4,.64,1) forwards}.ethiopia-map-surface .map-region.outline-only{fill:#ffffff0f!important;filter:drop-shadow(0 0 10px rgba(23,107,84,.28))}.ethiopia-map-surface .region-outline-layer{pointer-events:none}.ethiopia-map-surface .selected-region-outline,.ethiopia-map-surface .hover-region-outline{filter:drop-shadow(0 0 8px rgba(23,107,84,.36))}.ethiopia-map-surface.terrain-mode .map-region{fill:#ffffff08!important;stroke:#1b231fb8!important;stroke-width:1.5px!important}.ethiopia-map-surface.terrain-mode .map-region.selected{fill:#ffffff09!important}.ethiopia-map-surface.focus-mode .map-region:not(.selected){opacity:.3!important;fill:var(--preview-base)!important;stroke:var(--map-stroke)!important;filter:none}.ethiopia-map-surface.light-mode.focus-mode .map-region:not(.selected){fill:#fff!important}.ethiopia-map-surface.terrain-mode.focus-mode .map-region:not(.selected){fill:#ffffff06!important;opacity:.24!important;stroke:#1b231f75!important}.ethiopia-map-surface.focus-mode .map-region.selected{opacity:1!important;stroke:#fff!important}.ethiopia-map-surface.focus-mode text,.ethiopia-map-surface.focus-mode tspan{opacity:.24!important}.ethiopia-map-panel{border:1px solid rgba(40,72,62,.18);border-radius:8px;background:#ffffffb8;padding:14px;color:#17231f}.ethiopia-map-panel h2,.ethiopia-map-panel p{margin:0}.ethiopia-map-kicker{color:#60736b;font-size:12px;font-weight:800;text-transform:uppercase}.ethiopia-map-panel-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:12px}.ethiopia-map-legend-list,.ethiopia-service-list,.ethiopia-location-list{display:grid;gap:8px}.ethiopia-service-list,.map-stat-list{scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:rgba(23,107,84,.42) rgba(23,107,84,.08)}.ethiopia-service-list::-webkit-scrollbar,.map-stat-list::-webkit-scrollbar{width:8px}.ethiopia-service-list::-webkit-scrollbar-track,.map-stat-list::-webkit-scrollbar-track{background:#176b5414;border-radius:999px}.ethiopia-service-list::-webkit-scrollbar-thumb,.map-stat-list::-webkit-scrollbar-thumb{background:#176b546b;border-radius:999px}.ethiopia-map-legend-list{max-height:300px;overflow:auto;padding-right:4px}.ethiopia-region-services .ethiopia-service-list{max-height:320px;overflow:auto;padding-right:4px}.ethiopia-map-legend-row{display:grid;grid-template-columns:12px minmax(0,1fr) 42px;gap:9px;align-items:center;border:1px solid rgba(40,72,62,.16);border-radius:6px;background:#ffffffa3;padding:8px;color:inherit;cursor:pointer;text-align:left}.ethiopia-map-legend-row.active{border-color:#176b546b}.ethiopia-map-swatch{width:12px;height:26px;border-radius:4px}.ethiopia-map-legend-title-line,.ethiopia-service-copy,.ethiopia-selected-region-stats{display:flex;align-items:baseline;justify-content:space-between;gap:10px}.ethiopia-map-legend-bar{display:block;height:5px;overflow:hidden;border-radius:999px;background:#14221d14}.ethiopia-map-legend-bar-fill{display:block;height:100%}.ethiopia-selected-region-preview,.ethiopia-empty-state{display:grid;place-items:center;border:1px solid rgba(40,72,62,.14);border-radius:8px;color:#60736b}.ethiopia-selected-region-preview{--ethiopia-preview-base: #f7faf6;--ethiopia-preview-stroke: rgba(42, 73, 63, .16);--region-shadow-rest: rgba(0, 0, 0, .3);--region-shadow-wall: rgba(0, 0, 0, .6);--region-shadow-mid: rgba(0, 0, 0, .42);--region-shadow-ambient: rgba(0, 0, 0, .3);--region-shadow-glow: rgba(23, 107, 84, .45);height:190px;margin:14px 0 0;background:#f7faf6;overflow:hidden}.ethiopia-empty-state{min-height:104px}.dark-mode .ethiopia-selected-region-preview,.dark-theme .ethiopia-selected-region-preview{--ethiopia-preview-base: #102520;--ethiopia-preview-stroke: rgba(255, 255, 255, .12);--region-shadow-rest: rgba(218, 229, 224, .28);--region-shadow-wall: rgba(218, 229, 224, .42);--region-shadow-mid: rgba(206, 221, 214, .3);--region-shadow-ambient: rgba(220, 234, 228, .22);--region-shadow-glow: rgba(222, 238, 231, .34);background:#102520}.ethiopia-selected-region-preview-canvas{width:100%;height:100%}.ethiopia-selected-region-preview-canvas svg{display:block;width:100%;height:100%}.ethiopia-selected-region-preview .map-region{transform-box:fill-box;transform-origin:center}.ethiopia-selected-region-preview .map-region.selected{stroke:#fff!important}.ethiopia-selected-region-preview .map-region.pulse,.ethiopia-selected-region-preview .map-region.lifted{transform-box:fill-box;transform-origin:center bottom;will-change:transform,filter}.ethiopia-selected-region-preview .map-region.pulse{animation:regionFloat 3s cubic-bezier(.34,1.4,.64,1) infinite}.ethiopia-selected-region-preview .map-region.lifted{animation:regionLiftHold .62s cubic-bezier(.34,1.4,.64,1) forwards}.ethiopia-selected-region-preview .map-region.outline-only{fill:#ffffff0d!important;filter:drop-shadow(0 0 8px rgba(23,107,84,.22))}.ethiopia-selected-region-preview>.ethiopia-empty-state{min-height:0;border:0;background:transparent}.ethiopia-selected-region-stats{margin-top:12px}.ethiopia-selected-region-stats div{min-width:0;flex:1;border:1px solid rgba(40,72,62,.14);border-radius:6px;padding:9px}.ethiopia-selected-region-stats span,.ethiopia-location-item span{display:block;color:#60736b;font-size:12px;font-weight:800;text-transform:uppercase}.ethiopia-service-row,.ethiopia-location-item{border:1px solid rgba(40,72,62,.14);border-radius:6px;padding:9px}.ethiopia-service-comparison{margin-top:8px;font-size:12px;font-weight:800;text-transform:uppercase}.ethiopia-service-comparison.positive{color:#176b54}.ethiopia-service-comparison.negative{color:#9f2f2f}.ethiopia-service-show-more,.map-stat-show-more{width:100%;border:1px solid rgba(23,107,84,.22);border-radius:6px;background:#176b5414;color:#176b54;cursor:pointer;font:inherit;font-size:12px;font-weight:900;padding:8px 10px;text-transform:uppercase}.ethiopia-service-show-more:hover,.map-stat-show-more:hover{background:#176b5421}.ethiopia-service-scroll-sentinel,.map-stat-scroll-sentinel{display:grid;place-items:center;min-height:26px;width:100%;border:1px dashed rgba(23,107,84,.22);border-radius:6px;background:#176b540d;color:#176b54;font-size:11px;font-weight:900;letter-spacing:0;text-transform:uppercase}.dark-theme .ethiopia-service-scroll-sentinel,.dark-mode .map-stat-scroll-sentinel{border-color:#8be0bf38;background:#8be0bf12;color:#8be0bf}.dark-theme .ethiopia-service-show-more,.dark-mode .map-stat-show-more{border-color:#8be0bf33;background:#8be0bf1a;color:#8be0bf}.dark-theme .ethiopia-service-show-more:hover,.dark-mode .map-stat-show-more:hover{background:#8be0bf29}.map-stat-overlay{position:absolute;box-sizing:border-box;right:12px;top:14px;z-index:8;width:min(336px,calc(100% - 28px));max-height:calc(100% - 28px);display:flex;flex-direction:column;padding:12px;border:1px solid rgba(38,72,60,.18);border-radius:8px;background:#ffffffbd;box-shadow:0 1px #ffffff94 inset,0 22px 70px #1c2d2724;color:#17231f;opacity:0;pointer-events:none;transform:translateY(-12px) scale(.98);transition:opacity .22s ease,transform .26s cubic-bezier(.22,1,.36,1)}@supports (backdrop-filter: blur(18px)){.map-stat-overlay{-webkit-backdrop-filter:blur(18px) saturate(1.18);backdrop-filter:blur(18px) saturate(1.18)}}.map-stat-overlay.visible{opacity:1;pointer-events:auto;transform:translateY(0) scale(1)}.dark-mode .map-stat-overlay{border-color:#d8f4e824;background:#0d1c19cc;color:#edf7f2}.map-stat-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:10px}.map-stat-heading h2{margin:0;font-size:22px;line-height:1.05}.map-stat-index{display:grid;place-items:center;min-width:40px;height:40px;border:1px solid rgba(23,107,84,.28);border-radius:8px;background:#176b541a;color:#176b54;font-size:17px;font-weight:900}.map-stat-list{display:grid;gap:7px;flex:1;min-height:0;max-height:none;overflow:auto;padding-right:5px}.map-stat-empty{padding:18px 12px;border:1px solid rgba(40,72,62,.14);border-radius:8px;background:#ffffff6b;color:#60736b;font-size:14px;line-height:1.45;text-align:center}.map-stat-row{padding:8px;border:1px solid rgba(40,72,62,.14);border-radius:8px;background:#ffffff7a;opacity:0;transform:translate(16px);animation:statSlideIn .52s cubic-bezier(.22,1,.36,1) forwards;animation-delay:var(--delay)}.dark-mode .map-stat-row{border-color:#e8f4ef24;background:#ffffff0f}.map-stat-copy{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-bottom:7px}.map-stat-copy span{color:#60736b;font-size:11px;font-weight:800;text-transform:uppercase}.dark-mode .map-stat-copy span{color:#9eb8ae}.map-stat-copy strong{color:inherit;font-size:15px;font-weight:900}.map-stat-comparison{display:inline-flex;align-items:center;max-width:100%;gap:6px;margin-bottom:9px;padding:5px 8px;border:1px solid rgba(40,72,62,.14);border-radius:8px;background:#ffffff80;color:#60736b}.dark-mode .map-stat-comparison{border-color:#e8f4ef24;background:#ffffff0f}.map-stat-comparison span{font-size:9px;font-weight:900;text-transform:uppercase}.map-stat-comparison strong{color:inherit;font-size:11px;font-weight:900;white-space:nowrap}.map-stat-comparison.positive{border-color:#176b543d;background:#176b541a;color:#176b54}.map-stat-comparison.negative{border-color:#b041373d;background:#b041371a;color:#9d342c}.map-stat-comparison.neutral{border-color:#626f693d;background:#626f691a;color:#626f69}.dark-mode .map-stat-comparison.positive{color:#8be0bf}.dark-mode .map-stat-comparison.negative{color:#ffaaa0}.dark-mode .map-stat-comparison.neutral{color:#b8c6bf}.map-stat-bar{height:8px;overflow:hidden;border:1px solid rgba(40,72,62,.14);border-radius:999px;background:#274b3f14}.map-stat-bar i{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,#176b549e,#176b54);transform-origin:left;animation:statBarGrow .72s cubic-bezier(.22,1,.36,1) both;animation-delay:calc(var(--delay) + .12s)}.bar-morph-track{fill:#15282214}.bar-morph-bar{filter:drop-shadow(0 8px 12px rgba(23,107,84,.14))}.bar-row{opacity:1;transition:opacity .36s ease}.bar-row.visible{opacity:1!important}.bar-region-ghost{filter:drop-shadow(0 8px 18px rgba(28,45,39,.2))}.bar-morph-label,.bar-morph-value{fill:#17231f;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:24px;font-weight:800}.bar-morph-value{font-size:22px;text-anchor:end}.dark-mode .bar-morph-track{fill:#e8f4ef1f}.dark-mode .bar-morph-label,.dark-mode .bar-morph-value{fill:#edf7f2}@keyframes regionFloat{0%{transform:translateZ(0) scaleY(1);filter:drop-shadow(0 1px 2px var(--region-shadow-rest)) drop-shadow(0 0 6px var(--region-shadow-glow))}45%{transform:translate3d(-3px,-18px,0) scaleY(1.018);filter:drop-shadow(4px 22px 0 var(--region-shadow-wall)) drop-shadow(3px 18px 2px var(--region-shadow-mid)) drop-shadow(1px 8px 12px var(--region-shadow-ambient)) drop-shadow(0 0 14px var(--region-shadow-glow))}62%{transform:translate3d(-4px,-22px,0) scaleY(1.022);filter:drop-shadow(5px 26px 0 var(--region-shadow-wall)) drop-shadow(4px 20px 3px var(--region-shadow-mid)) drop-shadow(2px 10px 14px var(--region-shadow-ambient)) drop-shadow(0 0 18px var(--region-shadow-glow))}82%{transform:translate3d(-1px,-6px,0) scaleY(1.006);filter:drop-shadow(2px 8px 0 var(--region-shadow-mid)) drop-shadow(1px 6px 8px var(--region-shadow-ambient)) drop-shadow(0 0 10px var(--region-shadow-glow))}to{transform:translateZ(0) scaleY(1);filter:drop-shadow(0 1px 2px var(--region-shadow-rest)) drop-shadow(0 0 6px var(--region-shadow-glow))}}@keyframes regionLiftHold{0%{transform:translateZ(0) scaleY(1);filter:drop-shadow(0 1px 2px var(--region-shadow-rest)) drop-shadow(0 0 6px var(--region-shadow-glow))}70%{transform:translate3d(-4px,-22px,0) scaleY(1.022);filter:drop-shadow(5px 26px 0 var(--region-shadow-wall)) drop-shadow(4px 20px 3px var(--region-shadow-mid)) drop-shadow(2px 10px 14px var(--region-shadow-ambient)) drop-shadow(0 0 18px var(--region-shadow-glow))}to{transform:translate3d(-4px,-22px,0) scaleY(1.022);filter:drop-shadow(5px 26px 0 var(--region-shadow-wall)) drop-shadow(4px 20px 3px var(--region-shadow-mid)) drop-shadow(2px 10px 14px var(--region-shadow-ambient)) drop-shadow(0 0 18px var(--region-shadow-glow))}}@keyframes statSlideIn{to{opacity:1;transform:translate(0)}}@keyframes statBarGrow{0%{transform:scaleX(0)}to{transform:scaleX(1)}}.react-demo-shell{display:grid;grid-template-columns:minmax(0,1fr) 360px;gap:18px;min-height:100vh;padding:18px;background:#e8eee8;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.react-demo-shell.dark-theme{background:#111c18}.react-demo-map,.react-demo-sidebar{display:grid;gap:14px;align-content:start}.react-demo-sidebar{max-height:calc(100vh - 36px);overflow:auto;padding-right:2px}.react-demo-header{display:flex;align-items:flex-start;justify-content:space-between;gap:20px}.react-demo-map h1{margin:0;color:#17231f;font-size:44px;line-height:.95}.dark-theme .react-demo-map h1{color:#edf7f2}.react-demo-mode-switcher,.react-demo-selection-switcher{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;max-width:520px}.react-demo-selection-switcher{justify-self:end;max-width:none}.react-demo-mode-switcher button,.react-demo-selection-switcher button{border:1px solid rgba(38,83,69,.22);border-radius:6px;background:#ffffffc7;color:#17231f;cursor:pointer;font:inherit;font-size:13px;font-weight:800;padding:9px 11px}.react-demo-mode-switcher button.active,.react-demo-selection-switcher button.active{border-color:#176b54;background:#176b54;color:#fff}.dark-theme .react-demo-mode-switcher button,.dark-theme .react-demo-selection-switcher button{border-color:#e8f4ef33;background:#ffffff14;color:#edf7f2}.dark-theme .react-demo-mode-switcher button.active,.dark-theme .react-demo-selection-switcher button.active{border-color:#6dc7a8;background:#6dc7a8;color:#10201a}.react-demo-map .ethiopia-map-surface{height:calc(100vh - 128px)}.dark-theme .ethiopia-map-panel{border-color:#e8f4ef29;background:#ffffff14;color:#edf7f2}.dark-theme .ethiopia-map-kicker,.dark-theme .ethiopia-selected-region-stats span,.dark-theme .ethiopia-location-item span{color:#9eb8ae}.dark-theme .ethiopia-map-legend-row,.dark-theme .ethiopia-service-row,.dark-theme .ethiopia-location-item,.dark-theme .ethiopia-selected-region-stats div,.dark-theme .ethiopia-selected-region-preview,.dark-theme .ethiopia-empty-state{border-color:#e8f4ef24;background:#ffffff0f}@media(max-width:900px){.react-demo-shell{grid-template-columns:1fr}.react-demo-header{display:grid}.react-demo-mode-switcher{justify-content:flex-start}.react-demo-selection-switcher{justify-self:start}}
|