@zendir/ui 0.1.8 → 0.1.10

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.
Files changed (92) hide show
  1. package/dist/index.js +0 -169
  2. package/dist/index.js.map +1 -1
  3. package/dist/react/context/DisplaySettingsContext.js +0 -12
  4. package/dist/react/context/DisplaySettingsContext.js.map +1 -1
  5. package/dist/react/core/AstroIcon.js +1 -816
  6. package/dist/react/core/AstroIcon.js.map +1 -1
  7. package/dist/react/core/index.d.ts +0 -1
  8. package/dist/react/index.d.ts +2 -42
  9. package/dist/react/utils/index.js +0 -8
  10. package/dist/react/utils/index.js.map +1 -1
  11. package/dist/react.js +0 -169
  12. package/dist/react.js.map +1 -1
  13. package/package.json +1 -1
  14. package/dist/react/3d/EarthViewer.js +0 -836
  15. package/dist/react/3d/EarthViewer.js.map +0 -1
  16. package/dist/react/3d/SolarSystemViewer.js +0 -372
  17. package/dist/react/3d/SolarSystemViewer.js.map +0 -1
  18. package/dist/react/3d/ZenSpace3D.js +0 -1253
  19. package/dist/react/3d/ZenSpace3D.js.map +0 -1
  20. package/dist/react/3d/ZenSpace3DCesium.js +0 -186
  21. package/dist/react/3d/ZenSpace3DCesium.js.map +0 -1
  22. package/dist/react/3d/ZenSpace3DShaders.js +0 -94
  23. package/dist/react/3d/ZenSpace3DShaders.js.map +0 -1
  24. package/dist/react/3d/ZenSpace3DUtils.js +0 -213
  25. package/dist/react/3d/ZenSpace3DUtils.js.map +0 -1
  26. package/dist/react/3d/threeLoader.js +0 -18
  27. package/dist/react/3d/threeLoader.js.map +0 -1
  28. package/dist/react/cards/AccessCard.js +0 -410
  29. package/dist/react/cards/AccessCard.js.map +0 -1
  30. package/dist/react/cards/OrbitCard.js +0 -372
  31. package/dist/react/cards/OrbitCard.js.map +0 -1
  32. package/dist/react/cards/SpacecraftCard.js +0 -941
  33. package/dist/react/cards/SpacecraftCard.js.map +0 -1
  34. package/dist/react/cards/TelemetryCard.js +0 -742
  35. package/dist/react/cards/TelemetryCard.js.map +0 -1
  36. package/dist/react/cards/TelemetryStreamCard.js +0 -309
  37. package/dist/react/cards/TelemetryStreamCard.js.map +0 -1
  38. package/dist/react/charts/GroundTrackMap.js +0 -1123
  39. package/dist/react/charts/GroundTrackMap.js.map +0 -1
  40. package/dist/react/charts/GroundTrackMapLeaflet.js +0 -571
  41. package/dist/react/charts/GroundTrackMapLeaflet.js.map +0 -1
  42. package/dist/react/charts/groundTrackMapLeafletTiles.js +0 -11
  43. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +0 -1
  44. package/dist/react/charts/groundTrackMapLeafletUtils.js +0 -109
  45. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +0 -1
  46. package/dist/react/charts/unified/AstroChart.js +0 -1405
  47. package/dist/react/charts/unified/AstroChart.js.map +0 -1
  48. package/dist/react/charts/unified/PowerOverviewChart.js +0 -488
  49. package/dist/react/charts/unified/PowerOverviewChart.js.map +0 -1
  50. package/dist/react/charts/unified/domain.js +0 -3168
  51. package/dist/react/charts/unified/domain.js.map +0 -1
  52. package/dist/react/charts/unified/generators.js +0 -518
  53. package/dist/react/charts/unified/generators.js.map +0 -1
  54. package/dist/react/charts/unified/presets.js +0 -999
  55. package/dist/react/charts/unified/presets.js.map +0 -1
  56. package/dist/react/charts/unified/sync.js +0 -219
  57. package/dist/react/charts/unified/sync.js.map +0 -1
  58. package/dist/react/charts/unified/theme.js +0 -562
  59. package/dist/react/charts/unified/theme.js.map +0 -1
  60. package/dist/react/charts/unified/useChartStream.js +0 -226
  61. package/dist/react/charts/unified/useChartStream.js.map +0 -1
  62. package/dist/react/chatgpt/AppCard.js +0 -306
  63. package/dist/react/chatgpt/AppCard.js.map +0 -1
  64. package/dist/react/chatgpt/index.js +0 -166
  65. package/dist/react/chatgpt/index.js.map +0 -1
  66. package/dist/react/hooks/useSpacecraftPosition.js +0 -89
  67. package/dist/react/hooks/useSpacecraftPosition.js.map +0 -1
  68. package/dist/react/hooks/useTelemetry.js +0 -73
  69. package/dist/react/hooks/useTelemetry.js.map +0 -1
  70. package/dist/react/hooks/useZendirSession.js +0 -148
  71. package/dist/react/hooks/useZendirSession.js.map +0 -1
  72. package/dist/react/visualizations/EclipseTimerCard.js +0 -250
  73. package/dist/react/visualizations/EclipseTimerCard.js.map +0 -1
  74. package/dist/react/visualizations/LinkBudgetCard.js +0 -444
  75. package/dist/react/visualizations/LinkBudgetCard.js.map +0 -1
  76. package/dist/react/visualizations/NavBallCard.js +0 -243
  77. package/dist/react/visualizations/NavBallCard.js.map +0 -1
  78. package/dist/react/visualizations/PropulsionCard.js +0 -298
  79. package/dist/react/visualizations/PropulsionCard.js.map +0 -1
  80. package/dist/react/visualizations/SensorFootprintCard.js +0 -326
  81. package/dist/react/visualizations/SensorFootprintCard.js.map +0 -1
  82. package/dist/react/visualizations/ThermalHeatmapCard.js +0 -372
  83. package/dist/react/visualizations/ThermalHeatmapCard.js.map +0 -1
  84. package/dist/shaders/atmosphere.frag.js +0 -5
  85. package/dist/shaders/atmosphere.frag.js.map +0 -1
  86. package/dist/shaders/atmosphere.vert.js +0 -5
  87. package/dist/shaders/atmosphere.vert.js.map +0 -1
  88. package/dist/shaders/stars.frag.js +0 -5
  89. package/dist/shaders/stars.frag.js.map +0 -1
  90. package/dist/shaders/stars.vert.js +0 -5
  91. package/dist/shaders/stars.vert.js.map +0 -1
  92. package/dist/style.css +0 -143
@@ -1,372 +0,0 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
2
- import { memo, useMemo } from "react";
3
- import { classNames, formatTemperature, safeNumber } from "../utils/index.js";
4
- import { useTheme } from "../theme/ThemeProvider.js";
5
- function getThermalStatus(temp, min, max) {
6
- if (temp === void 0 || !Number.isFinite(temp)) return { text: "--", level: "off" };
7
- if (temp < min) return { text: "COLD", level: "standby" };
8
- if (temp > max) return { text: "HOT", level: "critical" };
9
- return { text: "OK", level: "normal" };
10
- }
11
- const ThermalHeatmapCard = memo(function ThermalHeatmapCard2({
12
- components,
13
- averageTemperature,
14
- compact = false,
15
- loading = false,
16
- className = ""
17
- }) {
18
- const { tokens, theme, prefersReducedMotion } = useTheme();
19
- const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
20
- const cardBg = isTransparentTheme ? "transparent" : tokens.colors.background.surface;
21
- const cardGlass = isTransparentTheme ? {
22
- backdropFilter: "blur(12px)",
23
- WebkitBackdropFilter: "blur(12px)"
24
- } : {};
25
- const sortedComponents = useMemo(() => {
26
- if (!components) return [];
27
- return [...components].sort((a, b) => a.name.localeCompare(b.name));
28
- }, [components]);
29
- const hasWarning = useMemo(() => {
30
- if (!components) return false;
31
- return components.some((c) => {
32
- const temp = c.temperatureCelsius;
33
- return Number.isFinite(temp) && (temp < c.minSafeCelsius || temp > c.maxSafeCelsius);
34
- });
35
- }, [components]);
36
- const activeHeaterCount = useMemo(() => {
37
- if (!components) return 0;
38
- return components.filter((c) => c.heaterActive).length;
39
- }, [components]);
40
- const transitionDuration = prefersReducedMotion ? "0ms" : "200ms";
41
- const statusColors = {
42
- normal: "#6ed86e",
43
- caution: "#ffd54f",
44
- serious: "#ffa726",
45
- critical: "#e57373",
46
- off: "#90a4ae",
47
- standby: "#4fc3f7"
48
- };
49
- if (loading) {
50
- return /* @__PURE__ */ jsxs(
51
- "div",
52
- {
53
- className: classNames("zendir-thermal-heatmap-card", "loading", className),
54
- role: "article",
55
- "aria-busy": "true",
56
- "aria-label": "Loading thermal data",
57
- style: {
58
- backgroundColor: cardBg,
59
- ...cardGlass,
60
- border: "none",
61
- borderRadius: tokens.borderRadius.lg,
62
- padding: tokens.spacing.md,
63
- minHeight: 200
64
- },
65
- children: [
66
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 16 }, children: [
67
- /* @__PURE__ */ jsx("div", { style: { height: 24, width: "40%", backgroundColor: "rgba(255,255,255,0.1)", borderRadius: 4 } }),
68
- /* @__PURE__ */ jsx("div", { style: { height: 24, width: 60, backgroundColor: "rgba(255,255,255,0.1)", borderRadius: 4 } })
69
- ] }),
70
- /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8 }, children: [1, 2, 3, 4, 5, 6].map((i) => /* @__PURE__ */ jsx(
71
- "div",
72
- {
73
- style: {
74
- height: 64,
75
- backgroundColor: "rgba(255,255,255,0.06)",
76
- borderRadius: 8
77
- }
78
- },
79
- i
80
- )) })
81
- ]
82
- }
83
- );
84
- }
85
- if (!components || components.length === 0) {
86
- return /* @__PURE__ */ jsxs(
87
- "div",
88
- {
89
- className: classNames("zendir-thermal-heatmap-card", "empty", className),
90
- role: "article",
91
- "aria-label": "No thermal data",
92
- style: {
93
- backgroundColor: cardBg,
94
- ...cardGlass,
95
- border: "none",
96
- borderRadius: tokens.borderRadius.lg,
97
- padding: tokens.spacing.lg,
98
- textAlign: "center",
99
- color: tokens.colors.text.tertiary
100
- },
101
- children: [
102
- /* @__PURE__ */ jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "currentColor", style: { opacity: 0.5, marginBottom: 8 }, children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M10.5 2C12.433 2 14 3.567 14 5.5L14.0005 12.2576C15.2217 13.2664 16 14.7923 16 16.5C16 19.5376 13.5376 22 10.5 22C7.46243 22 5 19.5376 5 16.5C5 14.7919 5.77868 13.2656 7.00044 12.2568L7 5.5C7 3.567 8.567 2 10.5 2ZM10.5 4C9.7203 4 9.07955 4.59489 9.00687 5.35543L9 5.49987L9.0005 13.199L8.27384 13.799C7.47135 14.4616 7 15.4402 7 16.5C7 18.433 8.567 20 10.5 20C12.433 20 14 18.433 14 16.5C14 15.5111 13.5896 14.593 12.8828 13.9362L12.7268 13.7995L12.0006 13.1997L12 5.5C12 4.7203 11.4051 4.07955 10.6445 4.00687L10.5 4ZM11 5.5C11 5.22386 10.7761 5 10.5 5C10.2239 5 10 5.22386 10 5.5L10.0006 14.0499C8.85917 14.2813 8 15.2903 8 16.5C8 17.8807 9.11929 19 10.5 19C11.8807 19 13 17.8807 13 16.5C13 15.2907 12.1413 14.2819 11.0004 14.0501L11 5.5ZM20 11C20.5523 11 21 11.4477 21 12C21 12.5523 20.5523 13 20 13H17C16.4477 13 16 12.5523 16 12C16 11.4477 16.4477 11 17 11H20ZM19 9C19 8.44772 18.5523 8 18 8H17C16.4477 8 16 8.44772 16 9C16 9.55228 16.4477 10 17 10H18C18.5523 10 19 9.55228 19 9ZM20 5C20.5523 5 21 5.44772 21 6C21 6.55228 20.5523 7 20 7H17C16.4477 7 16 6.55228 16 6C16 5.44772 16.4477 5 17 5H20ZM19 3C19 2.44772 18.5523 2 18 2H17C16.4477 2 16 2.44772 16 3C16 3.55228 16.4477 4 17 4H18C18.5523 4 19 3.55228 19 3Z" }) }),
103
- /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: tokens.typography.body[2].fontSize }, children: "No thermal data available" })
104
- ]
105
- }
106
- );
107
- }
108
- const getTempColor = (temp, min, max) => {
109
- if (temp === void 0 || !Number.isFinite(temp)) return statusColors.off;
110
- const mid = (max + min) / 2;
111
- if (temp < min) return statusColors.standby;
112
- if (temp > max) return statusColors.critical;
113
- if (temp > mid + (max - mid) * 0.5) return statusColors.caution;
114
- return statusColors.normal;
115
- };
116
- const overallStatusColor = hasWarning ? statusColors.critical : statusColors.normal;
117
- return /* @__PURE__ */ jsxs(
118
- "article",
119
- {
120
- className: classNames("zendir-thermal-heatmap-card", className),
121
- "aria-label": "Spacecraft thermal status",
122
- style: {
123
- backgroundColor: cardBg,
124
- ...cardGlass,
125
- border: "none",
126
- borderRadius: tokens.borderRadius.lg,
127
- padding: tokens.spacing.md,
128
- fontFamily: tokens.typography.fontFamily.primary,
129
- color: tokens.colors.text.primary
130
- },
131
- children: [
132
- !compact && /* @__PURE__ */ jsxs(
133
- "header",
134
- {
135
- style: {
136
- display: "flex",
137
- justifyContent: "space-between",
138
- alignItems: "flex-start",
139
- marginBottom: tokens.spacing.md
140
- },
141
- children: [
142
- /* @__PURE__ */ jsxs("div", { children: [
143
- /* @__PURE__ */ jsx(
144
- "h3",
145
- {
146
- style: {
147
- margin: 0,
148
- fontSize: tokens.typography.fontSize.md,
149
- fontWeight: tokens.typography.fontWeight.semibold
150
- },
151
- children: "Thermal Status"
152
- }
153
- ),
154
- /* @__PURE__ */ jsxs(
155
- "p",
156
- {
157
- style: {
158
- margin: "2px 0 0 0",
159
- fontSize: tokens.typography.fontSize.xs,
160
- color: tokens.colors.text.tertiary
161
- },
162
- children: [
163
- components.length,
164
- " zones • Avg",
165
- " ",
166
- /* @__PURE__ */ jsx("span", { style: { fontFamily: tokens.typography.fontFamily.mono }, children: formatTemperature(averageTemperature) })
167
- ]
168
- }
169
- )
170
- ] }),
171
- /* @__PURE__ */ jsx(
172
- "span",
173
- {
174
- role: "status",
175
- style: {
176
- padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,
177
- borderRadius: tokens.borderRadius.sm,
178
- fontSize: tokens.typography.fontSize.xxs,
179
- // 0.625rem / 10px (AstroUXDS compact)
180
- fontWeight: tokens.typography.fontWeight.medium,
181
- // 500 (AstroUXDS medium)
182
- backgroundColor: `${overallStatusColor}20`,
183
- color: overallStatusColor
184
- },
185
- children: hasWarning ? "Warning" : "Nominal"
186
- }
187
- )
188
- ]
189
- }
190
- ),
191
- /* @__PURE__ */ jsx(
192
- "div",
193
- {
194
- style: {
195
- display: "grid",
196
- gridTemplateColumns: "repeat(3, 1fr)",
197
- gap: tokens.spacing.sm
198
- },
199
- children: sortedComponents.slice(0, compact ? 6 : 9).map((component) => {
200
- const color = getTempColor(
201
- component.temperatureCelsius,
202
- component.minSafeCelsius,
203
- component.maxSafeCelsius
204
- );
205
- const status = getThermalStatus(
206
- component.temperatureCelsius,
207
- component.minSafeCelsius,
208
- component.maxSafeCelsius
209
- );
210
- return /* @__PURE__ */ jsxs(
211
- "div",
212
- {
213
- style: {
214
- position: "relative",
215
- borderRadius: tokens.borderRadius.md,
216
- padding: tokens.spacing.sm,
217
- textAlign: "center",
218
- transition: `transform ${transitionDuration}`,
219
- backgroundColor: `${color}22`,
220
- borderLeft: `3px solid ${color}`
221
- },
222
- children: [
223
- component.heaterActive && /* @__PURE__ */ jsx(
224
- "div",
225
- {
226
- title: "Heater Active",
227
- style: {
228
- position: "absolute",
229
- top: 4,
230
- right: 4,
231
- width: 8,
232
- height: 8,
233
- backgroundColor: statusColors.caution,
234
- borderRadius: "50%",
235
- animation: prefersReducedMotion ? "none" : "heaterPulse 1s ease-in-out infinite"
236
- }
237
- }
238
- ),
239
- /* @__PURE__ */ jsx(
240
- "div",
241
- {
242
- style: {
243
- fontSize: tokens.typography.fontSize.xxs,
244
- // 0.625rem / 10px (AstroUXDS compact)
245
- color: tokens.colors.text.tertiary,
246
- overflow: "hidden",
247
- textOverflow: "ellipsis",
248
- whiteSpace: "nowrap",
249
- marginBottom: 2
250
- },
251
- children: component.name
252
- }
253
- ),
254
- /* @__PURE__ */ jsxs(
255
- "div",
256
- {
257
- style: {
258
- fontSize: tokens.typography.fontSize.lg,
259
- fontWeight: tokens.typography.fontWeight.bold,
260
- fontFamily: tokens.typography.fontFamily.mono,
261
- fontVariantNumeric: "tabular-nums",
262
- color
263
- },
264
- children: [
265
- safeNumber(component.temperatureCelsius, 0),
266
- "°"
267
- ]
268
- }
269
- ),
270
- /* @__PURE__ */ jsx(
271
- "div",
272
- {
273
- style: {
274
- fontSize: tokens.typography.fontSize.micro,
275
- // 0.5625rem / 9px (AstroUXDS micro)
276
- fontWeight: tokens.typography.fontWeight.medium,
277
- // 500 (AstroUXDS medium)
278
- color: statusColors[status.level] || statusColors.off
279
- },
280
- children: status.text
281
- }
282
- )
283
- ]
284
- },
285
- component.id
286
- );
287
- })
288
- }
289
- ),
290
- /* @__PURE__ */ jsxs(
291
- "div",
292
- {
293
- style: {
294
- marginTop: tokens.spacing.md,
295
- paddingTop: tokens.spacing.md,
296
- borderTop: `1px solid ${tokens.colors.border.muted}`
297
- },
298
- children: [
299
- /* @__PURE__ */ jsxs(
300
- "div",
301
- {
302
- style: {
303
- display: "flex",
304
- alignItems: "center",
305
- justifyContent: "space-between",
306
- fontSize: tokens.typography.fontSize.xxs
307
- // 0.625rem / 10px (AstroUXDS compact)
308
- },
309
- children: [
310
- /* @__PURE__ */ jsx("span", { style: { color: statusColors.standby }, children: "Cold" }),
311
- /* @__PURE__ */ jsx(
312
- "div",
313
- {
314
- style: {
315
- flex: 1,
316
- margin: `0 ${tokens.spacing.sm}`,
317
- height: 8,
318
- borderRadius: 4,
319
- background: `linear-gradient(to right, ${statusColors.standby}, ${statusColors.normal}, ${statusColors.caution}, ${statusColors.critical})`
320
- }
321
- }
322
- ),
323
- /* @__PURE__ */ jsx("span", { style: { color: statusColors.critical }, children: "Hot" })
324
- ]
325
- }
326
- ),
327
- activeHeaterCount > 0 && /* @__PURE__ */ jsxs(
328
- "div",
329
- {
330
- style: {
331
- display: "flex",
332
- justifyContent: "space-between",
333
- alignItems: "center",
334
- fontSize: tokens.typography.fontSize.xs,
335
- marginTop: tokens.spacing.sm
336
- },
337
- children: [
338
- /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "Active Heaters" }),
339
- /* @__PURE__ */ jsxs(
340
- "span",
341
- {
342
- style: {
343
- color: statusColors.caution,
344
- fontFamily: tokens.typography.fontFamily.mono
345
- },
346
- children: [
347
- activeHeaterCount,
348
- "/",
349
- components.length
350
- ]
351
- }
352
- )
353
- ]
354
- }
355
- )
356
- ]
357
- }
358
- ),
359
- /* @__PURE__ */ jsx("style", { children: `
360
- @keyframes heaterPulse {
361
- 0%, 100% { opacity: 1; }
362
- 50% { opacity: 0.5; }
363
- }
364
- ` })
365
- ]
366
- }
367
- );
368
- });
369
- export {
370
- ThermalHeatmapCard
371
- };
372
- //# sourceMappingURL=ThermalHeatmapCard.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ThermalHeatmapCard.js","sources":["../../../src/react/visualizations/ThermalHeatmapCard.tsx"],"sourcesContent":["/**\n * @zendir/ui - ThermalHeatmapCard Component\n * \n * Spacecraft thermal visualization with \"paper doll\" view showing\n * temperature of each component with color-coded ranges.\n * \n * AstroUXDS Compliance:\n * - Uses status colors appropriately (temperature = status indicator)\n * - Standby (cyan) = Too cold\n * - Normal (green) = Within cool range\n * - Caution (yellow) = Within warm range \n * - Critical (red) = Too hot\n * - Heater indicators use caution color per status semantics\n * \n * Features:\n * - Full null-safety with graceful fallbacks\n * - Color-coded temperature display\n * - Heater status indicators\n * - Loading and empty states\n */\n\nimport React, { memo, useMemo } from 'react';\nimport { useTheme } from '../theme';\nimport {\n safeNumber,\n formatTemperature,\n classNames,\n type StatusLevel,\n} from '../utils';\n\nexport interface ComponentThermal {\n id: string;\n name: string;\n /** Temperature in Celsius */\n temperatureCelsius: number;\n /** Minimum safe temperature */\n minSafeCelsius: number;\n /** Maximum safe temperature */\n maxSafeCelsius: number;\n /** Heater active status */\n heaterActive?: boolean;\n}\n\nexport interface ThermalHeatmapCardProps {\n /** Component thermal data */\n components?: ComponentThermal[];\n /** Average spacecraft temperature */\n averageTemperature?: number;\n /** Compact mode (fewer items) */\n compact?: boolean;\n /** Loading state */\n loading?: boolean;\n /** Custom class name */\n className?: string;\n}\n\n\n/**\n * Get status text and level\n */\nfunction getThermalStatus(\n temp: number | undefined,\n min: number,\n max: number\n): { text: string; level: StatusLevel } {\n if (temp === undefined || !Number.isFinite(temp)) return { text: '--', level: 'off' };\n if (temp < min) return { text: 'COLD', level: 'standby' };\n if (temp > max) return { text: 'HOT', level: 'critical' };\n return { text: 'OK', level: 'normal' };\n}\n\n/**\n * ThermalHeatmapCard - Displays spacecraft thermal status\n * \n * @example\n * ```tsx\n * <ThermalHeatmapCard\n * components={thermalComponents}\n * averageTemperature={22.5}\n * />\n * ```\n */\nexport const ThermalHeatmapCard = memo(function ThermalHeatmapCard({\n components,\n averageTemperature,\n compact = false,\n loading = false,\n className = '',\n}: ThermalHeatmapCardProps): React.ReactElement {\n const { tokens, theme, prefersReducedMotion } = useTheme();\n const isTransparentTheme = theme === 'transparent' || theme === 'transparent-bold' || theme === 'transparent-minimal';\n // Use transparent background with blur for transparent themes (matching Timeline)\n const cardBg = isTransparentTheme ? 'transparent' : tokens.colors.background.surface;\n const cardGlass = isTransparentTheme ? { \n backdropFilter: 'blur(12px)' as const, \n WebkitBackdropFilter: 'blur(12px)' as const,\n } : {};\n\n // Sort components by name\n const sortedComponents = useMemo(() => {\n if (!components) return [];\n return [...components].sort((a, b) => a.name.localeCompare(b.name));\n }, [components]);\n\n // Calculate overall status\n const hasWarning = useMemo(() => {\n if (!components) return false;\n return components.some((c) => {\n const temp = c.temperatureCelsius;\n return Number.isFinite(temp) && (temp < c.minSafeCelsius || temp > c.maxSafeCelsius);\n });\n }, [components]);\n\n // Count active heaters\n const activeHeaterCount = useMemo(() => {\n if (!components) return 0;\n return components.filter((c) => c.heaterActive).length;\n }, [components]);\n\n const transitionDuration = prefersReducedMotion ? '0ms' : '200ms';\n // Medium-soft status colors (readable, not too pale)\n const statusColors: Record<StatusLevel, string> = {\n normal: '#6ed86e',\n caution: '#ffd54f',\n serious: '#ffa726',\n critical: '#e57373',\n off: '#90a4ae',\n standby: '#4fc3f7',\n };\n\n // Loading state\n if (loading) {\n return (\n <div\n className={classNames('zendir-thermal-heatmap-card', 'loading', className)}\n role=\"article\"\n aria-busy=\"true\"\n aria-label=\"Loading thermal data\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n border: 'none',\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.md,\n minHeight: 200,\n }}\n >\n <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>\n <div style={{ height: 24, width: '40%', backgroundColor: 'rgba(255,255,255,0.1)', borderRadius: 4 }} />\n <div style={{ height: 24, width: 60, backgroundColor: 'rgba(255,255,255,0.1)', borderRadius: 4 }} />\n </div>\n <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8 }}>\n {[1, 2, 3, 4, 5, 6].map((i) => (\n <div\n key={i}\n style={{\n height: 64,\n backgroundColor: 'rgba(255,255,255,0.06)',\n borderRadius: 8,\n }}\n />\n ))}\n </div>\n </div>\n );\n }\n\n // Empty state\n if (!components || components.length === 0) {\n return (\n <div\n className={classNames('zendir-thermal-heatmap-card', 'empty', className)}\n role=\"article\"\n aria-label=\"No thermal data\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n border: 'none',\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.lg,\n textAlign: 'center',\n color: tokens.colors.text.tertiary,\n }}\n >\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"currentColor\" style={{ opacity: 0.5, marginBottom: 8 }}>\n <path fillRule=\"evenodd\" clipRule=\"evenodd\" d=\"M10.5 2C12.433 2 14 3.567 14 5.5L14.0005 12.2576C15.2217 13.2664 16 14.7923 16 16.5C16 19.5376 13.5376 22 10.5 22C7.46243 22 5 19.5376 5 16.5C5 14.7919 5.77868 13.2656 7.00044 12.2568L7 5.5C7 3.567 8.567 2 10.5 2ZM10.5 4C9.7203 4 9.07955 4.59489 9.00687 5.35543L9 5.49987L9.0005 13.199L8.27384 13.799C7.47135 14.4616 7 15.4402 7 16.5C7 18.433 8.567 20 10.5 20C12.433 20 14 18.433 14 16.5C14 15.5111 13.5896 14.593 12.8828 13.9362L12.7268 13.7995L12.0006 13.1997L12 5.5C12 4.7203 11.4051 4.07955 10.6445 4.00687L10.5 4ZM11 5.5C11 5.22386 10.7761 5 10.5 5C10.2239 5 10 5.22386 10 5.5L10.0006 14.0499C8.85917 14.2813 8 15.2903 8 16.5C8 17.8807 9.11929 19 10.5 19C11.8807 19 13 17.8807 13 16.5C13 15.2907 12.1413 14.2819 11.0004 14.0501L11 5.5ZM20 11C20.5523 11 21 11.4477 21 12C21 12.5523 20.5523 13 20 13H17C16.4477 13 16 12.5523 16 12C16 11.4477 16.4477 11 17 11H20ZM19 9C19 8.44772 18.5523 8 18 8H17C16.4477 8 16 8.44772 16 9C16 9.55228 16.4477 10 17 10H18C18.5523 10 19 9.55228 19 9ZM20 5C20.5523 5 21 5.44772 21 6C21 6.55228 20.5523 7 20 7H17C16.4477 7 16 6.55228 16 6C16 5.44772 16.4477 5 17 5H20ZM19 3C19 2.44772 18.5523 2 18 2H17C16.4477 2 16 2.44772 16 3C16 3.55228 16.4477 4 17 4H18C18.5523 4 19 3.55228 19 3Z\" />\n </svg>\n <p style={{ margin: 0, fontSize: tokens.typography.body[2].fontSize }}>No thermal data available</p>\n </div>\n );\n }\n\n const getTempColor = (temp: number | undefined, min: number, max: number) => {\n if (temp === undefined || !Number.isFinite(temp)) return statusColors.off;\n const mid = (max + min) / 2;\n if (temp < min) return statusColors.standby;\n if (temp > max) return statusColors.critical;\n if (temp > mid + (max - mid) * 0.5) return statusColors.caution;\n return statusColors.normal;\n };\n const overallStatusColor = hasWarning ? statusColors.critical : statusColors.normal;\n\n return (\n <article\n className={classNames('zendir-thermal-heatmap-card', className)}\n aria-label=\"Spacecraft thermal status\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n border: 'none',\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.md,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.primary,\n }}\n >\n {/* Header */}\n {!compact && (\n <header\n style={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n marginBottom: tokens.spacing.md,\n }}\n >\n <div>\n <h3\n style={{\n margin: 0,\n fontSize: tokens.typography.fontSize.md,\n fontWeight: tokens.typography.fontWeight.semibold,\n }}\n >\n Thermal Status\n </h3>\n <p\n style={{\n margin: '2px 0 0 0',\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n }}\n >\n {components.length} zones • Avg{' '}\n <span style={{ fontFamily: tokens.typography.fontFamily.mono }}>\n {formatTemperature(averageTemperature)}\n </span>\n </p>\n </div>\n <span\n role=\"status\"\n style={{\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\n borderRadius: tokens.borderRadius.sm,\n fontSize: tokens.typography.fontSize.xxs, // 0.625rem / 10px (AstroUXDS compact)\n fontWeight: tokens.typography.fontWeight.medium, // 500 (AstroUXDS medium)\n backgroundColor: `${overallStatusColor}20`,\n color: overallStatusColor,\n }}\n >\n {hasWarning ? 'Warning' : 'Nominal'}\n </span>\n </header>\n )}\n\n {/* Thermal Grid */}\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(3, 1fr)',\n gap: tokens.spacing.sm,\n }}\n >\n {sortedComponents.slice(0, compact ? 6 : 9).map((component) => {\n const color = getTempColor(\n component.temperatureCelsius,\n component.minSafeCelsius,\n component.maxSafeCelsius\n );\n const status = getThermalStatus(\n component.temperatureCelsius,\n component.minSafeCelsius,\n component.maxSafeCelsius\n );\n\n return (\n <div\n key={component.id}\n style={{\n position: 'relative',\n borderRadius: tokens.borderRadius.md,\n padding: tokens.spacing.sm,\n textAlign: 'center',\n transition: `transform ${transitionDuration}`,\n backgroundColor: `${color}22`,\n borderLeft: `3px solid ${color}`,\n }}\n >\n {/* Heater indicator */}\n {component.heaterActive && (\n <div\n title=\"Heater Active\"\n style={{\n position: 'absolute',\n top: 4,\n right: 4,\n width: 8,\n height: 8,\n backgroundColor: statusColors.caution,\n borderRadius: '50%',\n animation: prefersReducedMotion ? 'none' : 'heaterPulse 1s ease-in-out infinite',\n }}\n />\n )}\n\n {/* Component name */}\n <div\n style={{\n fontSize: tokens.typography.fontSize.xxs, // 0.625rem / 10px (AstroUXDS compact)\n color: tokens.colors.text.tertiary,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n marginBottom: 2,\n }}\n >\n {component.name}\n </div>\n\n {/* Temperature */}\n <div\n style={{\n fontSize: tokens.typography.fontSize.lg,\n fontWeight: tokens.typography.fontWeight.bold,\n fontFamily: tokens.typography.fontFamily.mono,\n fontVariantNumeric: 'tabular-nums',\n color,\n }}\n >\n {safeNumber(component.temperatureCelsius, 0)}°\n </div>\n\n {/* Status */}\n <div\n style={{\n fontSize: tokens.typography.fontSize.micro, // 0.5625rem / 9px (AstroUXDS micro)\n fontWeight: tokens.typography.fontWeight.medium, // 500 (AstroUXDS medium)\n color: statusColors[status.level] || statusColors.off,\n }}\n >\n {status.text}\n </div>\n </div>\n );\n })}\n </div>\n\n {/* Legend */}\n <div\n style={{\n marginTop: tokens.spacing.md,\n paddingTop: tokens.spacing.md,\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n fontSize: tokens.typography.fontSize.xxs, // 0.625rem / 10px (AstroUXDS compact)\n }}\n >\n <span style={{ color: statusColors.standby }}>Cold</span>\n <div\n style={{\n flex: 1,\n margin: `0 ${tokens.spacing.sm}`,\n height: 8,\n borderRadius: 4,\n background: `linear-gradient(to right, ${statusColors.standby}, ${statusColors.normal}, ${statusColors.caution}, ${statusColors.critical})`,\n }}\n />\n <span style={{ color: statusColors.critical }}>Hot</span>\n </div>\n\n {/* Active heaters */}\n {activeHeaterCount > 0 && (\n <div\n style={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n fontSize: tokens.typography.fontSize.xs,\n marginTop: tokens.spacing.sm,\n }}\n >\n <span style={{ color: tokens.colors.text.tertiary }}>Active Heaters</span>\n <span\n style={{\n color: statusColors.caution,\n fontFamily: tokens.typography.fontFamily.mono,\n }}\n >\n {activeHeaterCount}/{components.length}\n </span>\n </div>\n )}\n </div>\n\n {/* Keyframe animation */}\n <style>{`\n @keyframes heaterPulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n `}</style>\n </article>\n );\n});\n"],"names":["ThermalHeatmapCard"],"mappings":"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"}
@@ -1,5 +0,0 @@
1
- const atmosphereFragmentShader = "uniform vec3 uSunDirection;\n\nvarying vec3 vNormal;\nvarying vec3 vPosition;\nvarying vec3 vWorldPosition;\n\nvoid main() {\n // Base atmospheric scattering\n float viewIntensity = pow(0.65 - dot(vNormal, vec3(0.0, 0.0, 1.0)), 2.0);\n \n // Sun-facing glow (brighter on the side facing the sun)\n vec3 worldNormal = normalize(vWorldPosition);\n float sunFacing = dot(worldNormal, normalize(uSunDirection));\n float sunGlow = max(0.0, sunFacing) * 0.6 + 0.4; // 0.4-1.0 range\n \n // Terminator enhancement (glow at day/night boundary)\n float terminator = 1.0 - abs(sunFacing);\n float terminatorGlow = pow(terminator, 3.0) * 0.3;\n \n // Combine effects\n float totalIntensity = viewIntensity * sunGlow + terminatorGlow;\n \n // Atmosphere color (blue with slight orange on sun side)\n vec3 dayColor = vec3(0.3, 0.6, 1.0);\n vec3 sunsetColor = vec3(1.0, 0.5, 0.2);\n vec3 atmosphereColor = mix(dayColor, sunsetColor, pow(max(0.0, terminator), 4.0) * 0.3);\n \n gl_FragColor = vec4(atmosphereColor, 1.0) * totalIntensity;\n}\n";
2
- export {
3
- atmosphereFragmentShader as default
4
- };
5
- //# sourceMappingURL=atmosphere.frag.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"atmosphere.frag.js","sources":["../../src/shaders/atmosphere.frag?raw"],"sourcesContent":["export default \"uniform vec3 uSunDirection;\\n\\nvarying vec3 vNormal;\\nvarying vec3 vPosition;\\nvarying vec3 vWorldPosition;\\n\\nvoid main() {\\n // Base atmospheric scattering\\n float viewIntensity = pow(0.65 - dot(vNormal, vec3(0.0, 0.0, 1.0)), 2.0);\\n \\n // Sun-facing glow (brighter on the side facing the sun)\\n vec3 worldNormal = normalize(vWorldPosition);\\n float sunFacing = dot(worldNormal, normalize(uSunDirection));\\n float sunGlow = max(0.0, sunFacing) * 0.6 + 0.4; // 0.4-1.0 range\\n \\n // Terminator enhancement (glow at day/night boundary)\\n float terminator = 1.0 - abs(sunFacing);\\n float terminatorGlow = pow(terminator, 3.0) * 0.3;\\n \\n // Combine effects\\n float totalIntensity = viewIntensity * sunGlow + terminatorGlow;\\n \\n // Atmosphere color (blue with slight orange on sun side)\\n vec3 dayColor = vec3(0.3, 0.6, 1.0);\\n vec3 sunsetColor = vec3(1.0, 0.5, 0.2);\\n vec3 atmosphereColor = mix(dayColor, sunsetColor, pow(max(0.0, terminator), 4.0) * 0.3);\\n \\n gl_FragColor = vec4(atmosphereColor, 1.0) * totalIntensity;\\n}\\n\""],"names":[],"mappings":"AAAA,MAAA,2BAAe;"}
@@ -1,5 +0,0 @@
1
- const atmosphereVertexShader = "varying vec3 vNormal;\nvarying vec3 vPosition;\nvarying vec3 vWorldPosition;\n\nvoid main() {\n vNormal = normalize(mat3(modelViewMatrix) * normal);\n vPosition = position;\n vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n";
2
- export {
3
- atmosphereVertexShader as default
4
- };
5
- //# sourceMappingURL=atmosphere.vert.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"atmosphere.vert.js","sources":["../../src/shaders/atmosphere.vert?raw"],"sourcesContent":["export default \"varying vec3 vNormal;\\nvarying vec3 vPosition;\\nvarying vec3 vWorldPosition;\\n\\nvoid main() {\\n vNormal = normalize(mat3(modelViewMatrix) * normal);\\n vPosition = position;\\n vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;\\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\\n}\\n\""],"names":[],"mappings":"AAAA,MAAA,yBAAe;"}
@@ -1,5 +0,0 @@
1
- const starsFragmentShader = "uniform float time;\r\nvarying float vOpacity;\r\n\r\nvoid main() {\r\n float dist = length(gl_PointCoord - vec2(0.5));\r\n if (dist > 0.5) discard;\r\n\r\n float twinkle = sin(time * vOpacity * 3.0 + vOpacity * 10.0) * 0.3 + 0.7;\r\n float alpha = (1.0 - dist * 2.0) * twinkle;\r\n\r\n gl_FragColor = vec4(1.0, 1.0, 1.0, alpha);\r\n}\r\n\r\n\r\n\r\n\r\n";
2
- export {
3
- starsFragmentShader as default
4
- };
5
- //# sourceMappingURL=stars.frag.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stars.frag.js","sources":["../../src/shaders/stars.frag?raw"],"sourcesContent":["export default \"uniform float time;\\r\\nvarying float vOpacity;\\r\\n\\r\\nvoid main() {\\r\\n float dist = length(gl_PointCoord - vec2(0.5));\\r\\n if (dist > 0.5) discard;\\r\\n\\r\\n float twinkle = sin(time * vOpacity * 3.0 + vOpacity * 10.0) * 0.3 + 0.7;\\r\\n float alpha = (1.0 - dist * 2.0) * twinkle;\\r\\n\\r\\n gl_FragColor = vec4(1.0, 1.0, 1.0, alpha);\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\""],"names":[],"mappings":"AAAA,MAAA,sBAAe;"}
@@ -1,5 +0,0 @@
1
- const starsVertexShader = "attribute float opacity;\r\nvarying float vOpacity;\r\n\r\nvoid main() {\r\n vOpacity = opacity;\r\n vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);\r\n gl_PointSize = 3.0;\r\n gl_Position = projectionMatrix * mvPosition;\r\n}\r\n\r\n\r\n\r\n\r\n";
2
- export {
3
- starsVertexShader as default
4
- };
5
- //# sourceMappingURL=stars.vert.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stars.vert.js","sources":["../../src/shaders/stars.vert?raw"],"sourcesContent":["export default \"attribute float opacity;\\r\\nvarying float vOpacity;\\r\\n\\r\\nvoid main() {\\r\\n vOpacity = opacity;\\r\\n vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);\\r\\n gl_PointSize = 3.0;\\r\\n gl_Position = projectionMatrix * mvPosition;\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\""],"names":[],"mappings":"AAAA,MAAA,oBAAe;"}
package/dist/style.css DELETED
@@ -1,143 +0,0 @@
1
- /**
2
- * Zendir UI — Leaflet theme (hybrid / purple-hue)
3
- * Use with GroundTrackMap when mapProvider="leaflet".
4
- * Keeps map controls on-brand and minimizes third-party branding on the frontend.
5
- */
6
-
7
- /* Container: match SDK background and radius */
8
- .zendir-ground-track-map .leaflet-container {
9
- background: #0f1520;
10
- font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
11
- cursor: grab;
12
- }
13
-
14
- /* Zoom controls: visible and above overlays so scroll/zoom work */
15
- .zendir-ground-track-map .leaflet-control-zoom {
16
- z-index: 1000 !important;
17
- border: 1px solid rgba(157, 112, 255, 0.35) !important;
18
- border-radius: 8px;
19
- overflow: hidden;
20
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
21
- }
22
-
23
- .zendir-ground-track-map .leaflet-control-zoom a,
24
- .zendir-ground-track-map .leaflet-control-zoom a:hover {
25
- background: #181d2e !important;
26
- color: #e4e0f0 !important;
27
- width: 36px !important;
28
- height: 36px !important;
29
- line-height: 36px !important;
30
- font-size: 20px !important;
31
- font-weight: bold !important;
32
- border: none !important;
33
- cursor: pointer !important;
34
- }
35
-
36
- .zendir-ground-track-map .leaflet-control-zoom a:hover {
37
- background: rgba(157, 112, 255, 0.15) !important;
38
- color: #b794ff !important;
39
- }
40
-
41
- .zendir-ground-track-map .leaflet-control-zoom-in {
42
- border-bottom: 1px solid rgba(157, 112, 255, 0.15) !important;
43
- }
44
-
45
- /* Attribution: minimal, no Leaflet branding on frontend */
46
- .zendir-ground-track-map .leaflet-control-attribution {
47
- background: rgba(15, 21, 32, 0.85) !important;
48
- color: rgba(148, 163, 184, 0.7) !important;
49
- font-size: 10px !important;
50
- padding: 2px 6px !important;
51
- border-radius: 4px 0 0 0;
52
- border: none;
53
- margin: 0 !important;
54
- }
55
-
56
- /* Hide "Leaflet" link in attribution so only tile provider is shown */
57
- .zendir-ground-track-map .leaflet-control-attribution a[href*="leaflet"] {
58
- display: none !important;
59
- }
60
-
61
- .zendir-ground-track-map .leaflet-control-attribution a {
62
- color: rgba(157, 112, 255, 0.8) !important;
63
- }
64
-
65
- .zendir-ground-track-map .leaflet-control-attribution a:hover {
66
- color: #b794ff !important;
67
- }
68
-
69
- /* Popup / tooltip styling */
70
- .zendir-ground-track-map .leaflet-popup-content-wrapper {
71
- background: #181d2e;
72
- border: 1px solid rgba(157, 112, 255, 0.2);
73
- border-radius: 8px;
74
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
75
- }
76
-
77
- .zendir-ground-track-map .leaflet-popup-tip {
78
- background: #181d2e;
79
- }
80
-
81
- .zendir-ground-track-map .leaflet-popup-content {
82
- margin: 8px 12px;
83
- color: #e4e0f0;
84
- font-size: 12px;
85
- }
86
-
87
- /* Ensure map is interactive (scroll zoom, drag) */
88
- .zendir-ground-track-map-leaflet .leaflet-container {
89
- touch-action: none;
90
- }
91
- .zendir-ground-track-map .leaflet-pane,
92
- .zendir-ground-track-map .leaflet-tile-pane {
93
- pointer-events: auto;
94
- }
95
-
96
- /* Dragging cursor */
97
- .zendir-ground-track-map .leaflet-grab {
98
- cursor: grab;
99
- }
100
-
101
- .zendir-ground-track-map .leaflet-dragging .leaflet-grab {
102
- cursor: grabbing;
103
- }
104
-
105
- /* ── Custom SVG div icons ──────────────────────────────────────────────────── */
106
- .zendir-sat-icon,
107
- .zendir-station-icon {
108
- background: none !important;
109
- border: none !important;
110
- /* Let the inline SVG size itself naturally */
111
- overflow: visible;
112
- pointer-events: auto;
113
- cursor: pointer;
114
- }
115
-
116
- .zendir-sat-icon:hover svg,
117
- .zendir-station-icon:hover svg {
118
- filter: drop-shadow(0 0 6px currentColor);
119
- }
120
-
121
- /* Leaflet default icon reset (avoid blue pin override) */
122
- .zendir-sat-icon img,
123
- .zendir-station-icon img {
124
- display: none !important;
125
- }
126
-
127
- /* Tooltip (rich HTML) */
128
- .zendir-leaflet-tooltip {
129
- background: rgba(13, 19, 35, 0.95) !important;
130
- border: 1px solid rgba(157, 112, 255, 0.35) !important;
131
- border-radius: 6px !important;
132
- color: #e4e0f0 !important;
133
- font-size: 11px !important;
134
- font-family: 'Roboto', 'Inter', system-ui, sans-serif !important;
135
- padding: 5px 9px !important;
136
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45) !important;
137
- white-space: nowrap;
138
- pointer-events: none;
139
- }
140
-
141
- .zendir-leaflet-tooltip::before {
142
- border-top-color: rgba(157, 112, 255, 0.35) !important;
143
- }