@aparte/plugin-cards 0.0.0-stage → 0.29.1

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 (105) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -2
  3. package/dist/carousel-DwgHvriV.js +63 -0
  4. package/dist/carousel-DwgHvriV.js.map +1 -0
  5. package/dist/controls-BYUm4aRV.js +62 -0
  6. package/dist/controls-BYUm4aRV.js.map +1 -0
  7. package/dist/format-BFq79ydr.js +728 -0
  8. package/dist/format-BFq79ydr.js.map +1 -0
  9. package/dist/index.d.ts +30 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +120 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/items/icons.d.ts +12 -0
  14. package/dist/items/icons.d.ts.map +1 -0
  15. package/dist/items/index.d.ts +100 -0
  16. package/dist/items/index.d.ts.map +1 -0
  17. package/dist/items.js +698 -0
  18. package/dist/items.js.map +1 -0
  19. package/dist/kit/carousel.d.ts +17 -0
  20. package/dist/kit/carousel.d.ts.map +1 -0
  21. package/dist/kit/controls.d.ts +51 -0
  22. package/dist/kit/controls.d.ts.map +1 -0
  23. package/dist/kit/define.d.ts +201 -0
  24. package/dist/kit/define.d.ts.map +1 -0
  25. package/dist/kit/dom.d.ts +40 -0
  26. package/dist/kit/dom.d.ts.map +1 -0
  27. package/dist/kit/fence.d.ts +39 -0
  28. package/dist/kit/fence.d.ts.map +1 -0
  29. package/dist/kit/format.d.ts +49 -0
  30. package/dist/kit/format.d.ts.map +1 -0
  31. package/dist/kit/rating.d.ts +19 -0
  32. package/dist/kit/rating.d.ts.map +1 -0
  33. package/dist/kit/sparkline.d.ts +19 -0
  34. package/dist/kit/sparkline.d.ts.map +1 -0
  35. package/dist/kit/strings.d.ts +139 -0
  36. package/dist/kit/strings.d.ts.map +1 -0
  37. package/dist/link/icons.d.ts +16 -0
  38. package/dist/link/icons.d.ts.map +1 -0
  39. package/dist/link/index.d.ts +98 -0
  40. package/dist/link/index.d.ts.map +1 -0
  41. package/dist/link.js +387 -0
  42. package/dist/link.js.map +1 -0
  43. package/dist/media/icons.d.ts +28 -0
  44. package/dist/media/icons.d.ts.map +1 -0
  45. package/dist/media/index.d.ts +107 -0
  46. package/dist/media/index.d.ts.map +1 -0
  47. package/dist/media.js +610 -0
  48. package/dist/media.js.map +1 -0
  49. package/dist/order/icons.d.ts +49 -0
  50. package/dist/order/icons.d.ts.map +1 -0
  51. package/dist/order/index.d.ts +204 -0
  52. package/dist/order/index.d.ts.map +1 -0
  53. package/dist/order.js +1843 -0
  54. package/dist/order.js.map +1 -0
  55. package/dist/place/icons.d.ts +18 -0
  56. package/dist/place/icons.d.ts.map +1 -0
  57. package/dist/place/index.d.ts +207 -0
  58. package/dist/place/index.d.ts.map +1 -0
  59. package/dist/place.js +1456 -0
  60. package/dist/place.js.map +1 -0
  61. package/dist/plan/icons.d.ts +25 -0
  62. package/dist/plan/icons.d.ts.map +1 -0
  63. package/dist/plan/index.d.ts +153 -0
  64. package/dist/plan/index.d.ts.map +1 -0
  65. package/dist/plan.js +1191 -0
  66. package/dist/plan.js.map +1 -0
  67. package/dist/product/icons.d.ts +16 -0
  68. package/dist/product/icons.d.ts.map +1 -0
  69. package/dist/product/index.d.ts +133 -0
  70. package/dist/product/index.d.ts.map +1 -0
  71. package/dist/product.js +1245 -0
  72. package/dist/product.js.map +1 -0
  73. package/dist/rating-CHVajQ2b.js +35 -0
  74. package/dist/rating-CHVajQ2b.js.map +1 -0
  75. package/dist/score/icons.d.ts +35 -0
  76. package/dist/score/icons.d.ts.map +1 -0
  77. package/dist/score/index.d.ts +185 -0
  78. package/dist/score/index.d.ts.map +1 -0
  79. package/dist/score.js +1843 -0
  80. package/dist/score.js.map +1 -0
  81. package/dist/sparkline-C-cA9obz.js +56 -0
  82. package/dist/sparkline-C-cA9obz.js.map +1 -0
  83. package/dist/stats/icons.d.ts +19 -0
  84. package/dist/stats/icons.d.ts.map +1 -0
  85. package/dist/stats/index.d.ts +137 -0
  86. package/dist/stats/index.d.ts.map +1 -0
  87. package/dist/stats.js +1085 -0
  88. package/dist/stats.js.map +1 -0
  89. package/dist/stock/chart.d.ts +135 -0
  90. package/dist/stock/chart.d.ts.map +1 -0
  91. package/dist/stock/icons.d.ts +15 -0
  92. package/dist/stock/icons.d.ts.map +1 -0
  93. package/dist/stock/index.d.ts +195 -0
  94. package/dist/stock/index.d.ts.map +1 -0
  95. package/dist/stock.js +1013 -0
  96. package/dist/stock.js.map +1 -0
  97. package/dist/weather/conditions.d.ts +25 -0
  98. package/dist/weather/conditions.d.ts.map +1 -0
  99. package/dist/weather/icons.d.ts +12 -0
  100. package/dist/weather/icons.d.ts.map +1 -0
  101. package/dist/weather/index.d.ts +146 -0
  102. package/dist/weather/index.d.ts.map +1 -0
  103. package/dist/weather.js +1162 -0
  104. package/dist/weather.js.map +1 -0
  105. package/package.json +137 -3
@@ -0,0 +1,1162 @@
1
+ import { b as defineCard, q as str, r as word, e as el, p as num, t as toDate, k as formatUnit, m as glyph, f as formatDay, i as formatPercent, h as formatNumber, l as formatWhen, g as formatHour } from "./format-BFq79ydr.js";
2
+ import { s as sparkline } from "./sparkline-C-cA9obz.js";
3
+ const WEATHER_CONDITIONS = [
4
+ "clear",
5
+ "partly-cloudy",
6
+ "cloudy",
7
+ "fog",
8
+ "drizzle",
9
+ "rain",
10
+ "heavy-rain",
11
+ "sleet",
12
+ "snow",
13
+ "thunder",
14
+ "wind"
15
+ ];
16
+ function conditionFromWmo(code) {
17
+ const c = typeof code === "string" ? Number(code) : code;
18
+ if (typeof c !== "number" || !Number.isFinite(c)) return void 0;
19
+ if (c === 0) return "clear";
20
+ if (c === 1 || c === 2) return "partly-cloudy";
21
+ if (c === 3) return "cloudy";
22
+ if (c === 45 || c === 48) return "fog";
23
+ if (c >= 51 && c <= 55) return "drizzle";
24
+ if (c === 56 || c === 57 || c === 66 || c === 67) return "sleet";
25
+ if (c === 61 || c === 63 || c === 80 || c === 81) return "rain";
26
+ if (c === 65 || c === 82) return "heavy-rain";
27
+ if (c >= 71 && c <= 77 || c === 85 || c === 86) return "snow";
28
+ if (c >= 95 && c <= 99) return "thunder";
29
+ return void 0;
30
+ }
31
+ function conditionFromOpenWeather(id) {
32
+ const c = typeof id === "string" ? Number(id) : id;
33
+ if (typeof c !== "number" || !Number.isFinite(c)) return void 0;
34
+ if (c >= 200 && c < 300) return "thunder";
35
+ if (c >= 300 && c < 400) return "drizzle";
36
+ if (c === 511 || c >= 611 && c <= 616) return "sleet";
37
+ if (c >= 502 && c <= 504) return "heavy-rain";
38
+ if (c === 522 || c === 531) return "heavy-rain";
39
+ if (c >= 500 && c < 600) return "rain";
40
+ if (c >= 600 && c < 700) return "snow";
41
+ if (c === 771 || c === 781) return "wind";
42
+ if (c >= 700 && c < 800) return "fog";
43
+ if (c === 800) return "clear";
44
+ if (c === 801 || c === 802) return "partly-cloudy";
45
+ if (c === 803 || c === 804) return "cloudy";
46
+ return void 0;
47
+ }
48
+ const TEXT_MATCHES = [
49
+ [/thunder|storm|orage|lightning/i, "thunder"],
50
+ [/sleet|freezing|verglas|grésil|hail|grêle/i, "sleet"],
51
+ [/snow|neige|blizzard|flurr/i, "snow"],
52
+ [/heavy rain|downpour|torrential|forte pluie|averse forte|déluge/i, "heavy-rain"],
53
+ [/drizzle|bruine|crachin/i, "drizzle"],
54
+ [/rain|shower|pluie|pluvieux|averse/i, "rain"],
55
+ [/fog|mist|haze|brouillard|brume/i, "fog"],
56
+ [/partly|partial|scattered|few clouds|mostly sunny|éclaircie|partiellement|peu nuageux/i, "partly-cloudy"],
57
+ [/cloud|overcast|couvert|nuageux|gris/i, "cloudy"],
58
+ [/wind|gust|vent|rafale/i, "wind"],
59
+ [/clear|sunny|fair|soleil|ensoleillé|dégagé/i, "clear"]
60
+ ];
61
+ function conditionFromText(text) {
62
+ if (typeof text !== "string" || !text.trim()) return void 0;
63
+ const known = text.trim().toLowerCase().replace(/[\s_]+/g, "-");
64
+ if (WEATHER_CONDITIONS.includes(known)) return known;
65
+ for (const [re, condition] of TEXT_MATCHES) if (re.test(text)) return condition;
66
+ return void 0;
67
+ }
68
+ const CONDITION_WORDS = {
69
+ clear: { en: "Clear", fr: "Dégagé", de: "Klar", es: "Despejado", it: "Sereno", ja: "晴れ", ko: "맑음", pt: "Céu limpo", ru: "Ясно", zh: "晴" },
70
+ "partly-cloudy": { en: "Partly cloudy", fr: "Partiellement nuageux", de: "Teilweise bewölkt", es: "Parcialmente nublado", it: "Parzialmente nuvoloso", ja: "晴れ時々曇り", ko: "구름 조금", pt: "Parcialmente nublado", ru: "Переменная облачность", zh: "多云" },
71
+ cloudy: { en: "Cloudy", fr: "Couvert", de: "Bewölkt", es: "Nublado", it: "Nuvoloso", ja: "曇り", ko: "흐림", pt: "Nublado", ru: "Облачно", zh: "阴" },
72
+ fog: { en: "Fog", fr: "Brouillard", de: "Nebel", es: "Niebla", it: "Nebbia", ja: "霧", ko: "안개", pt: "Nevoeiro", ru: "Туман", zh: "雾" },
73
+ drizzle: { en: "Drizzle", fr: "Bruine", de: "Nieselregen", es: "Llovizna", it: "Pioviggine", ja: "霧雨", ko: "이슬비", pt: "Garoa", ru: "Морось", zh: "毛毛雨" },
74
+ rain: { en: "Rain", fr: "Pluie", de: "Regen", es: "Lluvia", it: "Pioggia", ja: "雨", ko: "비", pt: "Chuva", ru: "Дождь", zh: "雨" },
75
+ "heavy-rain": { en: "Heavy rain", fr: "Forte pluie", de: "Starkregen", es: "Lluvia intensa", it: "Pioggia forte", ja: "大雨", ko: "폭우", pt: "Chuva forte", ru: "Сильный дождь", zh: "大雨" },
76
+ sleet: { en: "Sleet", fr: "Pluie verglaçante", de: "Schneeregen", es: "Aguanieve", it: "Nevischio", ja: "みぞれ", ko: "진눈깨비", pt: "Granizo fino", ru: "Мокрый снег", zh: "雨夹雪" },
77
+ snow: { en: "Snow", fr: "Neige", de: "Schnee", es: "Nieve", it: "Neve", ja: "雪", ko: "눈", pt: "Neve", ru: "Снег", zh: "雪" },
78
+ thunder: { en: "Thunderstorm", fr: "Orage", de: "Gewitter", es: "Tormenta", it: "Temporale", ja: "雷雨", ko: "뇌우", pt: "Trovoada", ru: "Гроза", zh: "雷雨" },
79
+ wind: { en: "Windy", fr: "Venteux", de: "Windig", es: "Ventoso", it: "Ventoso", ja: "強風", ko: "바람", pt: "Ventoso", ru: "Ветрено", zh: "有风" }
80
+ };
81
+ const r = (n) => Math.round(n * 100) / 100;
82
+ const RAYS = Array.from({ length: 8 }, (_, i) => {
83
+ const a = i * Math.PI / 4;
84
+ return `M${r(32 + 16 * Math.cos(a))} ${r(32 + 16 * Math.sin(a))}L${r(32 + 22 * Math.cos(a))} ${r(32 + 22 * Math.sin(a))}`;
85
+ }).join("");
86
+ const SUN = `<g class="aparte-wx-sun-g"><path class="aparte-wx-rays" d="${RAYS}"/><circle class="aparte-wx-sun" cx="32" cy="32" r="11"/></g>`;
87
+ const MOON = `<g class="aparte-wx-moon-g"><path class="aparte-wx-moon" d="M38.5 16.5A16 16 0 1 0 47.5 44.5A12.5 12.5 0 0 1 38.5 16.5Z"/><circle class="aparte-wx-star" cx="48" cy="17" r="1.6"/><circle class="aparte-wx-star" cx="54" cy="27" r="1.1"/></g>`;
88
+ const CLOUD_PATH = "M22 46H46A9 9 0 0 0 47 28.06A13 13 0 0 0 22.4 25.1A10.5 10.5 0 0 0 22 46Z";
89
+ const cloud = (cls, transform = "") => `<path class="${cls}"${transform ? ` transform="${transform}"` : ""} d="${CLOUD_PATH}"/>`;
90
+ const behind = (night) => `<g transform="translate(-6.5 -6.5) scale(0.72)" class="aparte-wx-behind">${night ? MOON : SUN}</g>`;
91
+ const drops = (n, cls = "aparte-wx-drop") => {
92
+ const xs = n === 5 ? [19, 26, 33, 40, 47] : n === 4 ? [22, 29, 36, 43] : n === 2 ? [24, 32] : [24, 32, 40];
93
+ return `<g class="aparte-wx-fall">${xs.map((x, i) => `<path class="${cls}" style="--i:${i}" d="M${x} ${46 + i % 2 * 3}l-2.5 6"/>`).join("")}</g>`;
94
+ };
95
+ const dots = (n) => {
96
+ const xs = [22, 29, 36, 43];
97
+ return `<g class="aparte-wx-fall">${xs.map((x, i) => `<circle class="aparte-wx-drip" style="--i:${i}" cx="${x}" cy="${49 + i % 2 * 3}" r="1.8"/>`).join("")}</g>`;
98
+ };
99
+ const flakes = (xs) => `<g class="aparte-wx-drift-down">${xs.map((x, i) => `<g class="aparte-wx-flake" style="--i:${i}" transform="translate(${x} ${50 + i % 2 * 4})"><path d="M0 -3.2V3.2M-2.8 -1.6L2.8 1.6M-2.8 1.6L2.8 -1.6"/></g>`).join("")}</g>`;
100
+ const BOLT = '<path class="aparte-wx-bolt" d="M34.5 40 26 53h6.5l-3 10L41 48.5h-6.5l4.5-8.5z"/>';
101
+ const FOG = '<g class="aparte-wx-fog-g"><path class="aparte-wx-fog" d="M14 49H50M18 55H46M22 61H42"/></g>';
102
+ const WIND = '<g class="aparte-wx-wind-g"><path class="aparte-wx-wind" d="M9 25h26a6 6 0 1 0-6-6"/><path class="aparte-wx-wind" d="M9 33h37a6.5 6.5 0 1 1-6.5 6.5"/><path class="aparte-wx-wind" d="M9 41h18"/></g>';
103
+ function weatherIcon(condition, night = false) {
104
+ const up = "translate(0 -6)";
105
+ let body;
106
+ switch (condition) {
107
+ case "clear":
108
+ body = night ? MOON : SUN;
109
+ break;
110
+ case "partly-cloudy":
111
+ body = `${behind(night)}<g class="aparte-wx-drift">${cloud("aparte-wx-cloud", "translate(4 6)")}</g>`;
112
+ break;
113
+ case "cloudy":
114
+ body = `${cloud("aparte-wx-cloud-back", "translate(8 -5) scale(0.82)")}<g class="aparte-wx-drift">${cloud("aparte-wx-cloud", "translate(-2 4)")}</g>`;
115
+ break;
116
+ case "fog":
117
+ body = `${cloud("aparte-wx-cloud", "translate(0 -8)")}${FOG}`;
118
+ break;
119
+ case "drizzle":
120
+ body = `${cloud("aparte-wx-cloud", up)}${dots()}`;
121
+ break;
122
+ case "rain":
123
+ body = `${cloud("aparte-wx-cloud", up)}${drops(3)}`;
124
+ break;
125
+ case "heavy-rain":
126
+ body = `${cloud("aparte-wx-cloud-back", "translate(9 -12) scale(0.8)")}${cloud("aparte-wx-cloud aparte-wx-cloud--dark", up)}${drops(5)}`;
127
+ break;
128
+ case "sleet":
129
+ body = `${cloud("aparte-wx-cloud", up)}${drops(2)}${flakes([40])}`;
130
+ break;
131
+ case "snow":
132
+ body = `${cloud("aparte-wx-cloud", up)}${flakes([23, 32, 41])}`;
133
+ break;
134
+ case "thunder":
135
+ body = `${cloud("aparte-wx-cloud-back", "translate(9 -12) scale(0.8)")}${cloud("aparte-wx-cloud aparte-wx-cloud--dark", up)}${BOLT}`;
136
+ break;
137
+ case "wind":
138
+ body = WIND;
139
+ break;
140
+ }
141
+ return `<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" class="aparte-wx" data-condition="${condition}"${night ? ' data-night=""' : ""}>${body}</svg>`;
142
+ }
143
+ const weatherStyles = `/* =========================================
144
+ The weather card — @aparte/plugin-cards/weather
145
+ =========================================
146
+ Three variants of one card, chosen by \`data-variant\` on its root:
147
+ hero the sky behind the temperature, the stats, the next hours
148
+ compact one line on the card's surface, the sky as an edge
149
+ forecast a header on the sky, then the days, each with its range
150
+ Every colour is a \`--aparte-weather-*\` token: the glyphs' parts, the eleven skies by
151
+ day and by night. A theme repaints the weather by setting them.
152
+ */
153
+
154
+ /* Declared with no weight: core adds a renderer's sheet AFTER the app's CSS, so at equal
155
+ weight an app's own \`.aparte-weather-card { --aparte-weather-sky-clear: … }\` would lose. */
156
+ :where(.aparte-weather-card) {
157
+ /* The glyphs on the card's own surface. */
158
+ --aparte-weather-sun: #fbbf24;
159
+ --aparte-weather-sun-rays: #f59e0b;
160
+ --aparte-weather-moon: #c9ad5f;
161
+ --aparte-weather-star: #fde68a;
162
+ --aparte-weather-cloud: #c7d0dc;
163
+ --aparte-weather-cloud-back: #dfe5ed;
164
+ --aparte-weather-cloud-dark: #8794a7;
165
+ --aparte-weather-rain: #3b82f6;
166
+ --aparte-weather-snow: #6aa9ec;
167
+ --aparte-weather-bolt: #f5b80b;
168
+ --aparte-weather-fog: #98a3b3;
169
+ --aparte-weather-wind: #7f93ad;
170
+
171
+ /* The skies, by day. */
172
+ --aparte-weather-sky-clear: linear-gradient(160deg, #2a78dc 0%, #4fa7f0 55%, #7cc6f7 100%);
173
+ --aparte-weather-sky-partly-cloudy: linear-gradient(160deg, #3a7acb 0%, #6aa3dd 60%, #9cc4ea 100%);
174
+ --aparte-weather-sky-cloudy: linear-gradient(160deg, #56657a 0%, #75849a 60%, #8d9bb0 100%);
175
+ --aparte-weather-sky-fog: linear-gradient(160deg, #636e7d 0%, #808a98 60%, #9aa3af 100%);
176
+ --aparte-weather-sky-drizzle: linear-gradient(160deg, #4a6079 0%, #6a7f98 60%, #8396ac 100%);
177
+ --aparte-weather-sky-rain: linear-gradient(160deg, #364860 0%, #55687f 60%, #6c7f95 100%);
178
+ --aparte-weather-sky-heavy-rain: linear-gradient(160deg, #2a374b 0%, #445367 60%, #5a697d 100%);
179
+ --aparte-weather-sky-sleet: linear-gradient(160deg, #495b71 0%, #6a7f96 60%, #8ea2b8 100%);
180
+ --aparte-weather-sky-snow: linear-gradient(160deg, #557495 0%, #7e9cbd 60%, #a5bfd8 100%);
181
+ --aparte-weather-sky-thunder: linear-gradient(160deg, #26223c 0%, #3d375a 60%, #554d74 100%);
182
+ --aparte-weather-sky-wind: linear-gradient(160deg, #46719a 0%, #6b93b9 60%, #93b4d2 100%);
183
+
184
+ /* And by night. */
185
+ --aparte-weather-night-clear: linear-gradient(160deg, #081127 0%, #16224a 55%, #2b3a70 100%);
186
+ --aparte-weather-night-partly-cloudy: linear-gradient(160deg, #0f1834 0%, #1f2b52 60%, #38466f 100%);
187
+ --aparte-weather-night-cloudy: linear-gradient(160deg, #191f2b 0%, #2a3241 60%, #3c4556 100%);
188
+ --aparte-weather-night-fog: linear-gradient(160deg, #1f242d 0%, #333a45 60%, #484f5b 100%);
189
+ --aparte-weather-night-drizzle: linear-gradient(160deg, #18212f 0%, #2a3647 60%, #3c4a5e 100%);
190
+ --aparte-weather-night-rain: linear-gradient(160deg, #131b28 0%, #24303f 60%, #344255 100%);
191
+ --aparte-weather-night-heavy-rain: linear-gradient(160deg, #0e141f 0%, #1c2533 60%, #2b3647 100%);
192
+ --aparte-weather-night-sleet: linear-gradient(160deg, #1a2433 0%, #2d3a4d 60%, #425267 100%);
193
+ --aparte-weather-night-snow: linear-gradient(160deg, #1f2c42 0%, #33476a 60%, #4d6386 100%);
194
+ --aparte-weather-night-thunder: linear-gradient(160deg, #110e23 0%, #221d3d 60%, #352e55 100%);
195
+ --aparte-weather-night-wind: linear-gradient(160deg, #142236 0%, #243a58 60%, #395271 100%);
196
+
197
+ /* Text on a sky. */
198
+ --aparte-weather-on-sky: #ffffff;
199
+ --aparte-weather-on-sky-muted: rgb(255 255 255 / 0.8);
200
+ --aparte-weather-tile: rgb(255 255 255 / 0.14);
201
+ --aparte-weather-tile-border: rgb(255 255 255 / 0.18);
202
+ }
203
+
204
+ /* The glyphs drawn over a sky: white clouds, pale rain. */
205
+ .aparte-weather-card[data-variant="hero"][data-state="ready"],
206
+ .aparte-weather__forecast-head {
207
+ --aparte-weather-cloud: #ffffff;
208
+ --aparte-weather-moon: #f1e9c8;
209
+ --aparte-weather-cloud-back: rgb(255 255 255 / 0.62);
210
+ --aparte-weather-cloud-dark: #d3dae4;
211
+ --aparte-weather-rain: #bfdbfe;
212
+ --aparte-weather-snow: #ffffff;
213
+ --aparte-weather-fog: rgb(255 255 255 / 0.85);
214
+ --aparte-weather-wind: rgb(255 255 255 / 0.92);
215
+ --aparte-rich-card-spark: rgb(255 255 255 / 0.95);
216
+ }
217
+
218
+ /* ── The sky ─────────────────────────────────────────────────────────── */
219
+
220
+ .aparte-weather__sky {
221
+ position: absolute;
222
+ inset: 0;
223
+ z-index: -1;
224
+ background: var(--aparte-weather-sky-partly-cloudy);
225
+ }
226
+
227
+ .aparte-weather__sky::after {
228
+ content: "";
229
+ position: absolute;
230
+ inset: 0;
231
+ background: radial-gradient(120% 80% at 100% 0%, rgb(255 255 255 / 0.22), transparent 60%);
232
+ pointer-events: none;
233
+ }
234
+
235
+ .aparte-weather__sky[data-condition="clear"]::after {
236
+ background: radial-gradient(90% 70% at 92% 4%, rgb(255 223 130 / 0.45), transparent 62%);
237
+ }
238
+
239
+ .aparte-weather__sky[data-night]::after {
240
+ background:
241
+ radial-gradient(1.5px 1.5px at 18% 22%, rgb(255 255 255 / 0.8), transparent 100%),
242
+ radial-gradient(1px 1px at 34% 12%, rgb(255 255 255 / 0.7), transparent 100%),
243
+ radial-gradient(1.2px 1.2px at 62% 30%, rgb(255 255 255 / 0.6), transparent 100%),
244
+ radial-gradient(1px 1px at 78% 16%, rgb(255 255 255 / 0.7), transparent 100%),
245
+ radial-gradient(1.4px 1.4px at 48% 8%, rgb(255 255 255 / 0.5), transparent 100%);
246
+ }
247
+
248
+ .aparte-weather__sky[data-condition="clear"], .aparte-weather__accent[data-condition="clear"] { background: var(--aparte-weather-sky-clear); }
249
+ .aparte-weather__sky[data-condition="partly-cloudy"], .aparte-weather__accent[data-condition="partly-cloudy"] { background: var(--aparte-weather-sky-partly-cloudy); }
250
+ .aparte-weather__sky[data-condition="cloudy"], .aparte-weather__accent[data-condition="cloudy"] { background: var(--aparte-weather-sky-cloudy); }
251
+ .aparte-weather__sky[data-condition="fog"], .aparte-weather__accent[data-condition="fog"] { background: var(--aparte-weather-sky-fog); }
252
+ .aparte-weather__sky[data-condition="drizzle"], .aparte-weather__accent[data-condition="drizzle"] { background: var(--aparte-weather-sky-drizzle); }
253
+ .aparte-weather__sky[data-condition="rain"], .aparte-weather__accent[data-condition="rain"] { background: var(--aparte-weather-sky-rain); }
254
+ .aparte-weather__sky[data-condition="heavy-rain"], .aparte-weather__accent[data-condition="heavy-rain"] { background: var(--aparte-weather-sky-heavy-rain); }
255
+ .aparte-weather__sky[data-condition="sleet"], .aparte-weather__accent[data-condition="sleet"] { background: var(--aparte-weather-sky-sleet); }
256
+ .aparte-weather__sky[data-condition="snow"], .aparte-weather__accent[data-condition="snow"] { background: var(--aparte-weather-sky-snow); }
257
+ .aparte-weather__sky[data-condition="thunder"], .aparte-weather__accent[data-condition="thunder"] { background: var(--aparte-weather-sky-thunder); }
258
+ .aparte-weather__sky[data-condition="wind"], .aparte-weather__accent[data-condition="wind"] { background: var(--aparte-weather-sky-wind); }
259
+
260
+ .aparte-weather__sky[data-night][data-condition="clear"], .aparte-weather__accent[data-night][data-condition="clear"] { background: var(--aparte-weather-night-clear); }
261
+ .aparte-weather__sky[data-night][data-condition="partly-cloudy"], .aparte-weather__accent[data-night][data-condition="partly-cloudy"] { background: var(--aparte-weather-night-partly-cloudy); }
262
+ .aparte-weather__sky[data-night][data-condition="cloudy"], .aparte-weather__accent[data-night][data-condition="cloudy"] { background: var(--aparte-weather-night-cloudy); }
263
+ .aparte-weather__sky[data-night][data-condition="fog"], .aparte-weather__accent[data-night][data-condition="fog"] { background: var(--aparte-weather-night-fog); }
264
+ .aparte-weather__sky[data-night][data-condition="drizzle"], .aparte-weather__accent[data-night][data-condition="drizzle"] { background: var(--aparte-weather-night-drizzle); }
265
+ .aparte-weather__sky[data-night][data-condition="rain"], .aparte-weather__accent[data-night][data-condition="rain"] { background: var(--aparte-weather-night-rain); }
266
+ .aparte-weather__sky[data-night][data-condition="heavy-rain"], .aparte-weather__accent[data-night][data-condition="heavy-rain"] { background: var(--aparte-weather-night-heavy-rain); }
267
+ .aparte-weather__sky[data-night][data-condition="sleet"], .aparte-weather__accent[data-night][data-condition="sleet"] { background: var(--aparte-weather-night-sleet); }
268
+ .aparte-weather__sky[data-night][data-condition="snow"], .aparte-weather__accent[data-night][data-condition="snow"] { background: var(--aparte-weather-night-snow); }
269
+ .aparte-weather__sky[data-night][data-condition="thunder"], .aparte-weather__accent[data-night][data-condition="thunder"] { background: var(--aparte-weather-night-thunder); }
270
+ .aparte-weather__sky[data-night][data-condition="wind"], .aparte-weather__accent[data-night][data-condition="wind"] { background: var(--aparte-weather-night-wind); }
271
+
272
+ /* ── Hero ────────────────────────────────────────────────────────────── */
273
+
274
+ .aparte-weather-card[data-variant="hero"][data-state="ready"] {
275
+ color: var(--aparte-weather-on-sky);
276
+ border-color: rgb(0 0 0 / 0.06);
277
+ background: transparent;
278
+ box-shadow: 0 10px 30px -18px rgb(15 23 42 / 0.55);
279
+ text-shadow: 0 1px 2px rgb(0 0 0 / 0.16);
280
+ }
281
+
282
+ /* The card narrows on its own width, not the window's: a widget on a wide screen is as
283
+ narrow as a phone. On a drawn card (or its skeleton) only — a one-line state shrinks to
284
+ its words, and a size container cannot. */
285
+ .aparte-weather-card:is([data-state="ready"], [data-state="loading"]) {
286
+ container: aparte-weather / inline-size;
287
+ }
288
+
289
+ .aparte-weather__body {
290
+ display: grid;
291
+ gap: var(--aparte-space-6);
292
+ padding: var(--aparte-space-7) var(--aparte-space-8) var(--aparte-space-7);
293
+ }
294
+
295
+ .aparte-weather__head {
296
+ display: flex;
297
+ align-items: flex-start;
298
+ justify-content: space-between;
299
+ gap: var(--aparte-space-4);
300
+ }
301
+
302
+ .aparte-weather__place {
303
+ display: flex;
304
+ flex-direction: column;
305
+ gap: var(--aparte-space-1);
306
+ min-inline-size: 0;
307
+ }
308
+
309
+ .aparte-weather__location {
310
+ font-size: var(--aparte-font-size-lg);
311
+ font-weight: var(--aparte-font-weight-semibold);
312
+ letter-spacing: -0.01em;
313
+ overflow: hidden;
314
+ text-overflow: ellipsis;
315
+ white-space: nowrap;
316
+ }
317
+
318
+ .aparte-weather__when {
319
+ font-size: var(--aparte-font-size-sm);
320
+ color: var(--aparte-weather-on-sky-muted);
321
+ }
322
+
323
+ .aparte-weather-card[data-variant="hero"] .aparte-weather__icon {
324
+ --aparte-rich-card-glyph-size: 4.5rem;
325
+ margin-block: calc(var(--aparte-space-2) * -1) calc(var(--aparte-space-6) * -1);
326
+ margin-inline-end: calc(var(--aparte-space-2) * -1);
327
+ filter: drop-shadow(0 6px 10px rgb(0 0 0 / 0.18));
328
+ }
329
+
330
+ .aparte-weather__now {
331
+ display: flex;
332
+ align-items: center;
333
+ gap: var(--aparte-space-7);
334
+ }
335
+
336
+ .aparte-weather-card[data-variant="hero"] .aparte-weather__temp {
337
+ font-size: calc(3.75rem * var(--aparte-font-scale));
338
+ font-weight: 300;
339
+ line-height: 0.9;
340
+ letter-spacing: -0.045em;
341
+ }
342
+
343
+ .aparte-weather__now-text {
344
+ display: flex;
345
+ flex-direction: column;
346
+ gap: var(--aparte-space-2);
347
+ min-inline-size: 0;
348
+ }
349
+
350
+ .aparte-weather__summary {
351
+ font-size: var(--aparte-font-size-base);
352
+ font-weight: var(--aparte-font-weight-medium);
353
+ }
354
+
355
+ .aparte-weather__line {
356
+ display: flex;
357
+ flex-wrap: wrap;
358
+ column-gap: var(--aparte-space-5);
359
+ row-gap: var(--aparte-space-1);
360
+ font-size: var(--aparte-font-size-sm);
361
+ color: var(--aparte-weather-on-sky-muted);
362
+ }
363
+
364
+ .aparte-weather__range {
365
+ display: inline-flex;
366
+ gap: var(--aparte-space-4);
367
+ white-space: nowrap;
368
+ }
369
+
370
+ .aparte-weather__stats {
371
+ display: grid;
372
+ grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr));
373
+ gap: var(--aparte-space-3);
374
+ margin: 0;
375
+ }
376
+
377
+ .aparte-weather__stat {
378
+ display: flex;
379
+ flex-direction: column;
380
+ gap: var(--aparte-space-1);
381
+ padding: var(--aparte-space-3) var(--aparte-space-4);
382
+ border: var(--aparte-border-width) solid var(--aparte-weather-tile-border);
383
+ border-radius: var(--aparte-radius-lg);
384
+ background: var(--aparte-weather-tile);
385
+ backdrop-filter: blur(6px);
386
+ }
387
+
388
+ .aparte-weather__stat-label {
389
+ font-size: var(--aparte-font-size-2xs);
390
+ font-weight: var(--aparte-font-weight-semibold);
391
+ letter-spacing: 0.06em;
392
+ text-transform: uppercase;
393
+ color: var(--aparte-weather-on-sky-muted);
394
+ }
395
+
396
+ .aparte-weather__stat-value {
397
+ display: flex;
398
+ align-items: center;
399
+ gap: var(--aparte-space-2);
400
+ margin: 0;
401
+ font-size: var(--aparte-font-size-md);
402
+ font-weight: var(--aparte-font-weight-semibold);
403
+ white-space: nowrap;
404
+ }
405
+
406
+ .aparte-weather__wind-arrow {
407
+ display: inline-block;
408
+ font-size: var(--aparte-font-size-sm);
409
+ transform: rotate(var(--aparte-weather-wind-angle, 0deg));
410
+ }
411
+
412
+ /* Buttons on the sky: glass, not the surface's. */
413
+ .aparte-weather-card[data-variant="hero"][data-state="ready"] .aparte-rich-card__actions {
414
+ padding-inline: var(--aparte-space-8);
415
+ border-block-start-color: var(--aparte-weather-tile-border);
416
+ background: rgb(0 0 0 / 0.1);
417
+ }
418
+
419
+ .aparte-weather-card[data-variant="hero"][data-state="ready"] .aparte-rich-card__action {
420
+ border-color: var(--aparte-weather-tile-border);
421
+ background: var(--aparte-weather-tile);
422
+ color: var(--aparte-weather-on-sky);
423
+ text-shadow: none;
424
+ }
425
+
426
+ .aparte-weather-card[data-variant="hero"][data-state="ready"] .aparte-rich-card__action:hover {
427
+ background: rgb(255 255 255 / 0.24);
428
+ }
429
+
430
+ /* The next hours: a row of columns, the temperature's curve drawn above them. */
431
+ .aparte-weather__hourly {
432
+ --aparte-weather-hours: 8;
433
+ display: grid;
434
+ gap: var(--aparte-space-1);
435
+ padding-block-start: var(--aparte-space-5);
436
+ border-block-start: var(--aparte-border-width) solid var(--aparte-weather-tile-border);
437
+ overflow-x: auto;
438
+ scrollbar-width: none;
439
+ }
440
+
441
+ .aparte-weather__curve {
442
+ block-size: 1.75rem;
443
+ /* The curve's points sit over the middle of each column. */
444
+ padding-inline: calc(50% / var(--aparte-weather-hours));
445
+ min-inline-size: calc(var(--aparte-weather-hours) * 2.75rem);
446
+ box-sizing: border-box;
447
+ }
448
+
449
+ .aparte-weather__hours {
450
+ display: grid;
451
+ grid-auto-flow: column;
452
+ grid-auto-columns: minmax(2.75rem, 1fr);
453
+ margin: 0;
454
+ padding: 0;
455
+ list-style: none;
456
+ }
457
+
458
+ .aparte-weather__hour {
459
+ display: flex;
460
+ flex-direction: column;
461
+ align-items: center;
462
+ gap: var(--aparte-space-2);
463
+ }
464
+
465
+ .aparte-weather__hour-time {
466
+ font-size: var(--aparte-font-size-xs);
467
+ color: var(--aparte-weather-on-sky-muted);
468
+ white-space: nowrap;
469
+ }
470
+
471
+ .aparte-weather__hour-temp {
472
+ font-size: var(--aparte-font-size-md);
473
+ font-weight: var(--aparte-font-weight-semibold);
474
+ }
475
+
476
+ .aparte-weather__hour-rain {
477
+ margin-block: calc(var(--aparte-space-2) * -1);
478
+ font-size: var(--aparte-font-size-2xs);
479
+ font-weight: var(--aparte-font-weight-semibold);
480
+ color: #cfe5ff;
481
+ }
482
+
483
+ .aparte-weather__mini {
484
+ --aparte-rich-card-glyph-size: 1.6rem;
485
+ }
486
+
487
+ /* A small drawing stands still: only the big glyph moves. */
488
+ .aparte-weather__mini svg * {
489
+ animation: none !important;
490
+ }
491
+
492
+ /* ── Compact ─────────────────────────────────────────────────────────── */
493
+
494
+ .aparte-weather-card[data-variant="compact"] {
495
+ max-inline-size: 22rem;
496
+ }
497
+
498
+ .aparte-weather__accent {
499
+ position: absolute;
500
+ inset-block: 0;
501
+ inset-inline-start: 0;
502
+ inline-size: 4px;
503
+ }
504
+
505
+ .aparte-weather__compact {
506
+ display: flex;
507
+ align-items: center;
508
+ gap: var(--aparte-space-5);
509
+ padding: var(--aparte-space-4) var(--aparte-space-6) var(--aparte-space-4) calc(var(--aparte-space-6) + 4px);
510
+ }
511
+
512
+ .aparte-weather__compact .aparte-weather__icon {
513
+ --aparte-rich-card-glyph-size: 2.4rem;
514
+ }
515
+
516
+ .aparte-weather__compact .aparte-weather__temp {
517
+ font-size: var(--aparte-font-size-2xl);
518
+ font-weight: var(--aparte-font-weight-semibold);
519
+ letter-spacing: -0.03em;
520
+ line-height: 1;
521
+ }
522
+
523
+ .aparte-weather__compact-text {
524
+ display: flex;
525
+ flex-direction: column;
526
+ min-inline-size: 0;
527
+ flex: 1;
528
+ }
529
+
530
+ .aparte-weather__compact .aparte-weather__location {
531
+ font-size: var(--aparte-font-size-md);
532
+ }
533
+
534
+ .aparte-weather__compact .aparte-weather__summary {
535
+ font-size: var(--aparte-font-size-sm);
536
+ font-weight: var(--aparte-font-weight-normal);
537
+ color: var(--aparte-text-muted);
538
+ overflow: hidden;
539
+ text-overflow: ellipsis;
540
+ white-space: nowrap;
541
+ }
542
+
543
+ .aparte-weather__compact .aparte-weather__range {
544
+ flex-direction: column;
545
+ gap: 0;
546
+ font-size: var(--aparte-font-size-sm);
547
+ color: var(--aparte-text-muted);
548
+ text-align: end;
549
+ }
550
+
551
+ .aparte-weather__compact .aparte-weather__hi {
552
+ color: var(--aparte-text);
553
+ font-weight: var(--aparte-font-weight-semibold);
554
+ }
555
+
556
+ /* ── Forecast ────────────────────────────────────────────────────────── */
557
+
558
+ .aparte-weather__forecast-head {
559
+ position: relative;
560
+ isolation: isolate;
561
+ color: var(--aparte-weather-on-sky);
562
+ text-shadow: 0 1px 2px rgb(0 0 0 / 0.16);
563
+ }
564
+
565
+ .aparte-weather__forecast-head .aparte-weather__compact {
566
+ padding: var(--aparte-space-6) var(--aparte-space-7);
567
+ }
568
+
569
+ .aparte-weather__forecast-head .aparte-weather__icon {
570
+ --aparte-rich-card-glyph-size: 3.25rem;
571
+ }
572
+
573
+ .aparte-weather__forecast-head .aparte-weather__temp {
574
+ font-size: calc(2.25rem * var(--aparte-font-scale));
575
+ font-weight: 300;
576
+ }
577
+
578
+ .aparte-weather__forecast-head .aparte-weather__summary,
579
+ .aparte-weather__forecast-head .aparte-weather__range {
580
+ color: var(--aparte-weather-on-sky-muted);
581
+ }
582
+
583
+ .aparte-weather__forecast-head .aparte-weather__hi {
584
+ color: var(--aparte-weather-on-sky);
585
+ }
586
+
587
+ .aparte-weather__days {
588
+ margin: 0;
589
+ padding: var(--aparte-space-2) var(--aparte-space-7) var(--aparte-space-4);
590
+ list-style: none;
591
+ }
592
+
593
+ .aparte-weather__day {
594
+ display: grid;
595
+ grid-template-columns: minmax(3.25rem, auto) 1.75rem 2.25rem 2.25rem minmax(3rem, 1fr) 2.25rem;
596
+ align-items: center;
597
+ gap: var(--aparte-space-3);
598
+ padding-block: var(--aparte-space-3);
599
+ font-size: var(--aparte-font-size-md);
600
+ }
601
+
602
+ .aparte-weather__day + .aparte-weather__day {
603
+ border-block-start: var(--aparte-border-width) solid var(--aparte-border);
604
+ }
605
+
606
+ .aparte-weather__day-name {
607
+ font-weight: var(--aparte-font-weight-medium);
608
+ white-space: nowrap;
609
+ }
610
+
611
+ .aparte-weather__day-rain {
612
+ font-size: var(--aparte-font-size-xs);
613
+ font-weight: var(--aparte-font-weight-semibold);
614
+ color: var(--aparte-weather-rain);
615
+ }
616
+
617
+ .aparte-weather__day-low {
618
+ color: var(--aparte-text-muted);
619
+ text-align: end;
620
+ }
621
+
622
+ .aparte-weather__day-high {
623
+ font-weight: var(--aparte-font-weight-semibold);
624
+ }
625
+
626
+ .aparte-weather__bar {
627
+ position: relative;
628
+ block-size: 6px;
629
+ border-radius: var(--aparte-radius-full);
630
+ background: color-mix(in oklab, var(--aparte-text) 10%, transparent);
631
+ }
632
+
633
+ .aparte-weather__bar-fill {
634
+ position: absolute;
635
+ inset-block: 0;
636
+ inset-inline-start: var(--aparte-weather-bar-start, 0%);
637
+ inset-inline-end: calc(100% - var(--aparte-weather-bar-end, 100%));
638
+ border-radius: inherit;
639
+ background: linear-gradient(to right, var(--aparte-weather-bar-cold), var(--aparte-weather-bar-warm));
640
+ }
641
+
642
+ .aparte-weather__bar-fill:dir(rtl) {
643
+ background: linear-gradient(to left, var(--aparte-weather-bar-cold), var(--aparte-weather-bar-warm));
644
+ }
645
+
646
+ .aparte-weather__bar-now {
647
+ position: absolute;
648
+ inset-block-start: 50%;
649
+ inset-inline-start: calc(var(--aparte-weather-bar-at, 0%) - 5px);
650
+ inline-size: 10px;
651
+ block-size: 10px;
652
+ border: 2px solid var(--aparte-surface-1);
653
+ border-radius: var(--aparte-radius-full);
654
+ background: var(--aparte-text);
655
+ transform: translateY(-50%);
656
+ }
657
+
658
+ /* ── Loading ─────────────────────────────────────────────────────────── */
659
+
660
+ .aparte-weather-card[data-state="loading"] .aparte-weather__sk-place { inline-size: 7rem; }
661
+ .aparte-weather-card[data-state="loading"] .aparte-weather__sk-icon { inline-size: 3.5rem; block-size: 3.5rem; flex: none; }
662
+ .aparte-weather-card[data-state="loading"] .aparte-weather__sk-temp { inline-size: 5.5rem; block-size: 3.25rem; border-radius: var(--aparte-radius-lg); }
663
+ .aparte-weather-card[data-state="loading"] .aparte-weather__sk-summary { inline-size: 8rem; }
664
+ .aparte-weather-card[data-state="loading"] .aparte-weather__sk-stats {
665
+ display: grid;
666
+ grid-template-columns: repeat(3, 1fr);
667
+ gap: var(--aparte-space-3);
668
+ }
669
+ .aparte-weather-card[data-state="loading"] .aparte-weather__sk-stat { block-size: 3rem; border-radius: var(--aparte-radius-lg); }
670
+ .aparte-weather-card[data-state="loading"] .aparte-weather__compact .aparte-weather__sk-icon { inline-size: 2.6rem; block-size: 2.6rem; }
671
+ .aparte-weather-card[data-state="loading"] .aparte-weather__compact .aparte-weather__sk-temp { inline-size: 3rem; block-size: 1.75rem; }
672
+
673
+ /* ── The glyphs ──────────────────────────────────────────────────────── */
674
+
675
+ .aparte-wx .aparte-wx-sun { fill: var(--aparte-weather-sun); }
676
+ .aparte-wx .aparte-wx-rays {
677
+ fill: none;
678
+ stroke: var(--aparte-weather-sun-rays);
679
+ stroke-width: 3.2;
680
+ stroke-linecap: round;
681
+ transform-box: view-box;
682
+ transform-origin: 32px 32px;
683
+ /* Core's turn: its sheet is on every page a chat is on. */
684
+ animation: aparte-spin 60s linear infinite;
685
+ }
686
+ .aparte-wx .aparte-wx-moon { fill: var(--aparte-weather-moon); }
687
+ .aparte-wx .aparte-wx-star { fill: var(--aparte-weather-star); animation: aparte-weather-twinkle 3.2s ease-in-out infinite; }
688
+ .aparte-wx .aparte-wx-star + .aparte-wx-star { animation-delay: -1.6s; }
689
+ .aparte-wx .aparte-wx-cloud { fill: var(--aparte-weather-cloud); }
690
+ .aparte-wx .aparte-wx-cloud-back { fill: var(--aparte-weather-cloud-back); }
691
+ .aparte-wx .aparte-wx-cloud--dark { fill: var(--aparte-weather-cloud-dark); }
692
+ .aparte-wx .aparte-wx-drift { animation: aparte-weather-drift 7s ease-in-out infinite alternate; }
693
+ .aparte-wx .aparte-wx-drop {
694
+ fill: none;
695
+ stroke: var(--aparte-weather-rain);
696
+ stroke-width: 3;
697
+ stroke-linecap: round;
698
+ animation: aparte-weather-fall 1.3s ease-in infinite;
699
+ animation-delay: calc(var(--i, 0) * -0.45s);
700
+ }
701
+ .aparte-wx .aparte-wx-drip {
702
+ fill: var(--aparte-weather-rain);
703
+ animation: aparte-weather-fall 1.6s ease-in infinite;
704
+ animation-delay: calc(var(--i, 0) * -0.4s);
705
+ }
706
+ .aparte-wx .aparte-wx-flake path {
707
+ fill: none;
708
+ stroke: var(--aparte-weather-snow);
709
+ stroke-width: 1.8;
710
+ stroke-linecap: round;
711
+ animation: aparte-weather-snowfall 3.4s linear infinite;
712
+ }
713
+ .aparte-wx .aparte-wx-flake:nth-child(2) path { animation-delay: -1.1s; }
714
+ .aparte-wx .aparte-wx-flake:nth-child(3) path { animation-delay: -2.2s; }
715
+ .aparte-wx .aparte-wx-bolt { fill: var(--aparte-weather-bolt); animation: aparte-weather-flash 4.5s linear infinite; }
716
+ .aparte-wx .aparte-wx-fog, .aparte-wx .aparte-wx-wind {
717
+ fill: none;
718
+ stroke-width: 3.2;
719
+ stroke-linecap: round;
720
+ }
721
+ .aparte-wx .aparte-wx-fog { stroke: var(--aparte-weather-fog); }
722
+ .aparte-wx .aparte-wx-fog-g { animation: aparte-weather-drift 6s ease-in-out infinite alternate; }
723
+ .aparte-wx .aparte-wx-wind { stroke: var(--aparte-weather-wind); stroke-width: 3.6; animation: aparte-weather-gust 3.2s ease-in-out infinite alternate; }
724
+ .aparte-wx .aparte-wx-wind:nth-child(2) { animation-delay: -1.1s; }
725
+ .aparte-wx .aparte-wx-wind:nth-child(3) { animation-delay: -2.2s; }
726
+
727
+ @keyframes aparte-weather-twinkle { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
728
+ @keyframes aparte-weather-drift { from { transform: translateX(-1.5px); } to { transform: translateX(1.5px); } }
729
+ @keyframes aparte-weather-fall {
730
+ 0% { transform: translateY(-3px); opacity: 0; }
731
+ 25% { opacity: 1; }
732
+ 100% { transform: translateY(6px); opacity: 0; }
733
+ }
734
+ @keyframes aparte-weather-snowfall {
735
+ 0% { transform: translate(0, -3px); opacity: 0; }
736
+ 20% { opacity: 1; }
737
+ 100% { transform: translate(2px, 6px); opacity: 0; }
738
+ }
739
+ @keyframes aparte-weather-flash {
740
+ 0%, 86%, 100% { opacity: 1; }
741
+ 88% { opacity: 0.25; }
742
+ 90% { opacity: 1; }
743
+ 92% { opacity: 0.4; }
744
+ }
745
+ @keyframes aparte-weather-gust {
746
+ from { transform: translateX(-2px); }
747
+ to { transform: translateX(2.5px); }
748
+ }
749
+
750
+ @container aparte-weather (max-width: 22rem) {
751
+ .aparte-weather__body { padding: var(--aparte-space-6); }
752
+ .aparte-weather-card[data-variant="hero"] .aparte-weather__temp { font-size: calc(3rem * var(--aparte-font-scale)); }
753
+ .aparte-weather__days { padding-inline: var(--aparte-space-5); }
754
+ .aparte-weather__day { grid-template-columns: minmax(2.75rem, auto) 1.5rem 2rem 2rem minmax(2rem, 1fr) 2rem; }
755
+ }
756
+ `;
757
+ const W = {
758
+ cardsWeatherTitle: { en: "Weather", fr: "Météo", de: "Wetter", es: "Tiempo", it: "Meteo", ja: "天気", ko: "날씨", pt: "Clima", ru: "Погода", zh: "天气" },
759
+ cardsWeatherIn: { en: "Weather in {place}", fr: "Météo à {place}", de: "Wetter in {place}", es: "Tiempo en {place}", it: "Meteo a {place}", ja: "{place}の天気", ko: "{place} 날씨", pt: "Clima em {place}", ru: "Погода: {place}", zh: "{place}天气" },
760
+ cardsWeatherFeelsLike: { en: "Feels like {t}", fr: "Ressenti {t}", de: "Gefühlt {t}", es: "Sensación {t}", it: "Percepita {t}", ja: "体感 {t}", ko: "체감 {t}", pt: "Sensação {t}", ru: "Ощущается как {t}", zh: "体感 {t}" },
761
+ cardsWeatherHigh: { en: "High", fr: "Max.", de: "Höchst", es: "Máx.", it: "Max", ja: "最高", ko: "최고", pt: "Máx.", ru: "Макс.", zh: "最高" },
762
+ cardsWeatherLow: { en: "Low", fr: "Min.", de: "Tiefst", es: "Mín.", it: "Min", ja: "最低", ko: "최저", pt: "Mín.", ru: "Мин.", zh: "最低" },
763
+ cardsWeatherWind: { en: "Wind", fr: "Vent", de: "Wind", es: "Viento", it: "Vento", ja: "風", ko: "바람", pt: "Vento", ru: "Ветер", zh: "风" },
764
+ cardsWeatherHumidity: { en: "Humidity", fr: "Humidité", de: "Feuchte", es: "Humedad", it: "Umidità", ja: "湿度", ko: "습도", pt: "Umidade", ru: "Влажность", zh: "湿度" },
765
+ cardsWeatherRain: { en: "Rain", fr: "Pluie", de: "Regen", es: "Lluvia", it: "Pioggia", ja: "降水", ko: "강수", pt: "Chuva", ru: "Осадки", zh: "降水" },
766
+ cardsWeatherNow: { en: "Now", fr: "Maint.", de: "Jetzt", es: "Ahora", it: "Ora", ja: "今", ko: "지금", pt: "Agora", ru: "Сейчас", zh: "现在" },
767
+ cardsWeatherForecast: { en: "Forecast", fr: "Prévisions", de: "Vorhersage", es: "Pronóstico", it: "Previsioni", ja: "予報", ko: "예보", pt: "Previsão", ru: "Прогноз", zh: "预报" }
768
+ };
769
+ const WIND_INTL = { "km/h": "kilometer-per-hour", mph: "mile-per-hour", "m/s": "meter-per-second", kn: null };
770
+ const HOURS_SHOWN = 8;
771
+ const DAYS_SHOWN = 7;
772
+ function readCondition(value) {
773
+ if (typeof value === "number") return conditionFromWmo(value);
774
+ return conditionFromText(value);
775
+ }
776
+ function readUnit(value) {
777
+ return typeof value === "string" && /^\s*°?\s*f\b|fahrenheit|imperial/i.test(value) ? "F" : "C";
778
+ }
779
+ function readWindUnit(value) {
780
+ if (typeof value !== "string") return "km/h";
781
+ const v = value.toLowerCase().replace(/\s/g, "");
782
+ if (v.includes("mph") || v.includes("mp/h")) return "mph";
783
+ if (v === "m/s" || v === "ms") return "m/s";
784
+ if (v.startsWith("kn") || v === "kt") return "kn";
785
+ return "km/h";
786
+ }
787
+ function percent(value, share = false) {
788
+ const n = num(value);
789
+ if (n === void 0) return void 0;
790
+ const p = n > 0 && n <= 1 && (share || !Number.isInteger(n)) ? n * 100 : n;
791
+ return Math.max(0, Math.min(100, Math.round(p)));
792
+ }
793
+ function writesShares(items) {
794
+ return items.some((item) => {
795
+ const n = num(item?.["precipitation"]);
796
+ return n !== void 0 && n > 0 && n < 1;
797
+ });
798
+ }
799
+ function chanceOf(item, shares) {
800
+ return percent(item?.["precipitation"], shares) ?? percent(item?.["pop"], true);
801
+ }
802
+ function readWeather(raw) {
803
+ if (!raw || typeof raw !== "object") return null;
804
+ const r2 = raw;
805
+ const temperature = num(r2["temperature"] ?? r2["temp"]);
806
+ const rawDaily = Array.isArray(r2["daily"]) ? r2["daily"] : [];
807
+ const dailyShares = writesShares(rawDaily);
808
+ const daily = rawDaily.map((d) => {
809
+ const date = toDate(d?.date ?? d?.time);
810
+ const high = num(d?.high ?? d?.max);
811
+ const low = num(d?.low ?? d?.min);
812
+ if (!date || high === void 0 || low === void 0) return null;
813
+ return { date, condition: readCondition(d?.condition) ?? "cloudy", high, low, precipitation: chanceOf(d, dailyShares) };
814
+ }).filter((d) => d !== null).slice(0, DAYS_SHOWN);
815
+ if (temperature === void 0 && daily.length === 0) return null;
816
+ const night = r2["night"] === true || r2["isDay"] === false || r2["is_day"] === 0;
817
+ const rawHourly = Array.isArray(r2["hourly"]) ? r2["hourly"] : [];
818
+ const hourlyShares = writesShares(rawHourly);
819
+ const hourly = rawHourly.map((h) => {
820
+ const time = toDate(h?.time);
821
+ const t = num(h?.temperature ?? h?.temp);
822
+ if (!time || t === void 0) return null;
823
+ return { time, temperature: t, condition: readCondition(h?.condition), precipitation: chanceOf(h, hourlyShares), night: h?.night === true };
824
+ }).filter((h) => h !== null).slice(0, HOURS_SHOWN);
825
+ let wind;
826
+ const w = r2["wind"];
827
+ if (typeof w === "number" || typeof w === "string") {
828
+ const speed = num(w);
829
+ if (speed !== void 0) wind = { speed, unit: readWindUnit(r2["windUnit"]), direction: num(r2["windDirection"]) };
830
+ } else if (w && typeof w === "object") {
831
+ const o = w;
832
+ const speed = num(o["speed"]);
833
+ if (speed !== void 0) wind = { speed, unit: readWindUnit(o["unit"]), direction: num(o["direction"]) };
834
+ } else if (num(r2["windSpeed"]) !== void 0) {
835
+ wind = { speed: num(r2["windSpeed"]), unit: readWindUnit(r2["windUnit"]), direction: num(r2["windDirection"]) };
836
+ }
837
+ const condition = readCondition(r2["condition"]) ?? readCondition(r2["summary"]) ?? daily[0]?.condition ?? "cloudy";
838
+ return {
839
+ location: str(r2["location"] ?? r2["city"] ?? r2["place"]),
840
+ condition,
841
+ summary: str(r2["summary"] ?? r2["description"]),
842
+ temperature,
843
+ unit: readUnit(r2["unit"]),
844
+ feelsLike: num(r2["feelsLike"] ?? r2["feels_like"]),
845
+ high: num(r2["high"]) ?? daily[0]?.high,
846
+ low: num(r2["low"]) ?? daily[0]?.low,
847
+ humidity: percent(r2["humidity"]),
848
+ wind,
849
+ precipitation: chanceOf(r2, false),
850
+ night,
851
+ time: toDate(r2["time"]) ?? void 0,
852
+ hourly,
853
+ daily
854
+ };
855
+ }
856
+ function fromOpenMeteo(response, options = {}) {
857
+ const r2 = response && typeof response === "object" ? response : {};
858
+ const current = r2["current"] ?? r2["current_weather"] ?? {};
859
+ const cu = r2["current_units"] ?? {};
860
+ const cwu = r2["current_weather_units"] ?? {};
861
+ const hu = r2["hourly_units"] ?? {};
862
+ const du = r2["daily_units"] ?? {};
863
+ const unit = readUnit(cu["temperature_2m"] ?? cu["temperature"] ?? cwu["temperature"] ?? du["temperature_2m_max"] ?? du["temperature_2m_min"] ?? hu["temperature_2m"]);
864
+ const windUnit = readWindUnit(cu["wind_speed_10m"] ?? cu["windspeed"] ?? cwu["windspeed"] ?? cwu["wind_speed_10m"] ?? hu["wind_speed_10m"] ?? du["wind_speed_10m_max"]);
865
+ const offset = num(r2["utc_offset_seconds"]);
866
+ const instant = (time) => openMeteoTime(time, offset);
867
+ const nowMs = instant(current["time"])?.getTime() ?? Date.now();
868
+ const hourly = [];
869
+ const h = r2["hourly"];
870
+ if (h && Array.isArray(h["time"])) {
871
+ h["time"].forEach((time, i) => {
872
+ const at = instant(time);
873
+ const t = num(h["temperature_2m"]?.[i]);
874
+ if (!at || t === void 0 || at.getTime() < nowMs - 36e5) return;
875
+ hourly.push({
876
+ time: at,
877
+ temperature: t,
878
+ condition: conditionFromWmo(h["weather_code"]?.[i]),
879
+ precipitation: num(h["precipitation_probability"]?.[i]),
880
+ night: h["is_day"]?.[i] === 0
881
+ });
882
+ });
883
+ }
884
+ const daily = [];
885
+ const d = r2["daily"];
886
+ if (d && Array.isArray(d["time"])) {
887
+ d["time"].forEach((date, i) => {
888
+ const high = num(d["temperature_2m_max"]?.[i]);
889
+ const low = num(d["temperature_2m_min"]?.[i]);
890
+ if (high === void 0 || low === void 0) return;
891
+ daily.push({
892
+ date,
893
+ condition: conditionFromWmo(d["weather_code"]?.[i]),
894
+ high,
895
+ low,
896
+ precipitation: num(d["precipitation_probability_max"]?.[i])
897
+ });
898
+ });
899
+ }
900
+ return {
901
+ location: options.location,
902
+ condition: conditionFromWmo(current["weather_code"] ?? current["weathercode"]),
903
+ temperature: num(current["temperature_2m"] ?? current["temperature"]),
904
+ unit,
905
+ feelsLike: num(current["apparent_temperature"]),
906
+ humidity: num(current["relative_humidity_2m"]),
907
+ wind: num(current["wind_speed_10m"] ?? current["windspeed"]) !== void 0 ? { speed: num(current["wind_speed_10m"] ?? current["windspeed"]), unit: windUnit, direction: num(current["wind_direction_10m"] ?? current["winddirection"]) } : void 0,
908
+ precipitation: num(hourly[0]?.precipitation),
909
+ night: current["is_day"] === 0,
910
+ time: instant(current["time"]) ?? void 0,
911
+ hourly: hourly.slice(0, HOURS_SHOWN),
912
+ daily: daily.slice(0, DAYS_SHOWN)
913
+ };
914
+ }
915
+ function openMeteoTime(value, offset) {
916
+ const m = typeof value === "string" ? /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(value.trim()) : null;
917
+ if (!m || offset === void 0) return toDate(value);
918
+ const utc = Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]), Number(m[4]), Number(m[5]), Number(m[6] ?? 0));
919
+ return new Date(utc - offset * 1e3);
920
+ }
921
+ const deg = (config, t) => `${formatNumber(config, Math.round(t))}°`;
922
+ const degFull = (config, t, unit) => formatUnit(config, Math.round(t), unit === "F" ? "fahrenheit" : "celsius");
923
+ function summaryOf(data, config) {
924
+ return data.summary ?? word(config, `cardsWeather_${data.condition}`, CONDITION_WORDS[data.condition]);
925
+ }
926
+ function windText(config, wind) {
927
+ const intl = WIND_INTL[wind.unit];
928
+ return intl ? formatUnit(config, wind.speed, intl) : `${formatNumber(config, Math.round(wind.speed))} kn`;
929
+ }
930
+ function stat(ctx, key, value, extra) {
931
+ const dt = el("dt", { class: "aparte-weather__stat-label" });
932
+ ctx.word(dt, key, W[key]);
933
+ const dd = el("dd", { class: "aparte-weather__stat-value" });
934
+ const text = el("span");
935
+ ctx.bind(text, value);
936
+ dd.append(...extra ? [extra, text] : [text]);
937
+ return el("div", { class: "aparte-weather__stat", attrs: { "data-stat": key.replace("cardsWeather", "").toLowerCase() } }, dt, dd);
938
+ }
939
+ function rangeText(ctx, data) {
940
+ if (data.high === void 0 && data.low === void 0) return null;
941
+ const range = el("span", { class: "aparte-weather__range" });
942
+ if (data.high !== void 0) {
943
+ const hi = el("span", { class: "aparte-weather__hi" });
944
+ ctx.bind(hi, () => `↑ ${deg(ctx.config, data.high)}`);
945
+ ctx.bind(hi, () => `${word(ctx.config, "cardsWeatherHigh", W.cardsWeatherHigh)} ${degFull(ctx.config, data.high, data.unit)}`, "aria-label");
946
+ range.append(hi);
947
+ }
948
+ if (data.low !== void 0) {
949
+ const lo = el("span", { class: "aparte-weather__lo" });
950
+ ctx.bind(lo, () => `↓ ${deg(ctx.config, data.low)}`);
951
+ ctx.bind(lo, () => `${word(ctx.config, "cardsWeatherLow", W.cardsWeatherLow)} ${degFull(ctx.config, data.low, data.unit)}`, "aria-label");
952
+ range.append(lo);
953
+ }
954
+ return range;
955
+ }
956
+ function placeLine(ctx, data) {
957
+ const place = el("div", { class: "aparte-weather__place" });
958
+ const name = el("span", { class: "aparte-weather__location" });
959
+ ctx.bind(name, () => data.location ?? word(ctx.config, "cardsWeatherTitle", W.cardsWeatherTitle));
960
+ place.append(name);
961
+ if (data.time) {
962
+ const when = el("time", { class: "aparte-weather__when", attrs: { datetime: data.time.toISOString() } });
963
+ ctx.bind(when, () => formatWhen(ctx.config, data.time));
964
+ place.append(when);
965
+ }
966
+ return place;
967
+ }
968
+ function sky(data) {
969
+ return el("div", { class: "aparte-weather__sky", attrs: { "data-condition": data.condition, "data-night": data.night, "aria-hidden": "true" } });
970
+ }
971
+ function hours(ctx, data) {
972
+ if (data.hourly.length < 2) return null;
973
+ const temps = data.hourly.map((h) => h.temperature);
974
+ const list = el("ol", { class: "aparte-weather__hours" });
975
+ data.hourly.forEach((h, i) => {
976
+ const time = el("span", { class: "aparte-weather__hour-time" });
977
+ if (i === 0) ctx.word(time, "cardsWeatherNow", W.cardsWeatherNow);
978
+ else ctx.bind(time, () => formatHour(ctx.config, h.time));
979
+ const temp = el("span", { class: "aparte-weather__hour-temp" });
980
+ ctx.bind(temp, () => deg(ctx.config, h.temperature));
981
+ const cond = h.condition ?? data.condition;
982
+ const sky2 = el("span", { class: "aparte-sr-only" });
983
+ ctx.word(sky2, `cardsWeather_${cond}`, CONDITION_WORDS[cond]);
984
+ let rain = null;
985
+ if (h.precipitation !== void 0 && h.precipitation >= 30) {
986
+ rain = el("span", { class: "aparte-weather__hour-rain" });
987
+ ctx.bind(rain, () => formatPercent(ctx.config, h.precipitation / 100));
988
+ }
989
+ list.append(el("li", { class: "aparte-weather__hour" }, time, sky2, glyph(weatherIcon(cond, h.night), "aparte-rich-card__glyph aparte-weather__mini"), rain, temp));
990
+ });
991
+ const strip = el(
992
+ "div",
993
+ { class: "aparte-weather__hourly" },
994
+ el("div", { class: "aparte-weather__curve" }, sparkline(temps, { area: true, pad: 0.2 })),
995
+ list
996
+ );
997
+ strip.style.setProperty("--aparte-weather-hours", String(data.hourly.length));
998
+ return strip;
999
+ }
1000
+ function renderHero(data, ctx) {
1001
+ const { config } = ctx;
1002
+ const head = el("div", { class: "aparte-weather__head" }, placeLine(ctx, data), glyph(weatherIcon(data.condition, data.night), "aparte-rich-card__glyph aparte-weather__icon"));
1003
+ const now = el("div", { class: "aparte-weather__now" });
1004
+ if (data.temperature !== void 0) {
1005
+ const temp = el("span", { class: "aparte-weather__temp" });
1006
+ ctx.bind(temp, () => deg(config, data.temperature));
1007
+ ctx.bind(temp, () => degFull(config, data.temperature, data.unit), "aria-label");
1008
+ now.append(temp);
1009
+ }
1010
+ const text = el("div", { class: "aparte-weather__now-text" });
1011
+ const summary = el("span", { class: "aparte-weather__summary" });
1012
+ ctx.bind(summary, () => summaryOf(data, config));
1013
+ text.append(summary);
1014
+ const line = el("span", { class: "aparte-weather__line" });
1015
+ const range = rangeText(ctx, data);
1016
+ if (range) line.append(range);
1017
+ if (data.feelsLike !== void 0) {
1018
+ const feels = el("span", { class: "aparte-weather__feels" });
1019
+ ctx.bind(feels, () => word(config, "cardsWeatherFeelsLike", W.cardsWeatherFeelsLike, { t: deg(config, data.feelsLike) }));
1020
+ line.append(feels);
1021
+ }
1022
+ if (line.childNodes.length) text.append(line);
1023
+ now.append(text);
1024
+ const stats = el("dl", { class: "aparte-weather__stats" });
1025
+ if (data.wind) {
1026
+ const arrow = data.wind.direction !== void 0 ? el("span", { class: "aparte-weather__wind-arrow", attrs: { "aria-hidden": "true", style: `--aparte-weather-wind-angle: ${Math.round(data.wind.direction + 180)}deg` }, text: "↑" }) : void 0;
1027
+ stats.append(stat(ctx, "cardsWeatherWind", () => windText(config, data.wind), arrow));
1028
+ }
1029
+ if (data.humidity !== void 0) stats.append(stat(ctx, "cardsWeatherHumidity", () => formatUnit(config, data.humidity, "percent")));
1030
+ if (data.precipitation !== void 0) stats.append(stat(ctx, "cardsWeatherRain", () => formatUnit(config, data.precipitation, "percent")));
1031
+ const body = el("div", { class: "aparte-weather__body" }, head, now);
1032
+ if (stats.childNodes.length) body.append(stats);
1033
+ const hourly = hours(ctx, data);
1034
+ if (hourly) body.append(hourly);
1035
+ return [sky(data), body];
1036
+ }
1037
+ function renderCompact(data, ctx) {
1038
+ const { config } = ctx;
1039
+ const row = el("div", { class: "aparte-weather__compact" });
1040
+ row.append(glyph(weatherIcon(data.condition, data.night), "aparte-rich-card__glyph aparte-weather__icon"));
1041
+ if (data.temperature !== void 0) {
1042
+ const temp = el("span", { class: "aparte-weather__temp" });
1043
+ ctx.bind(temp, () => deg(config, data.temperature));
1044
+ ctx.bind(temp, () => degFull(config, data.temperature, data.unit), "aria-label");
1045
+ row.append(temp);
1046
+ }
1047
+ const text = el("div", { class: "aparte-weather__compact-text" });
1048
+ const name = el("span", { class: "aparte-weather__location" });
1049
+ ctx.bind(name, () => data.location ?? word(config, "cardsWeatherTitle", W.cardsWeatherTitle));
1050
+ const summary = el("span", { class: "aparte-weather__summary" });
1051
+ ctx.bind(summary, () => summaryOf(data, config));
1052
+ text.append(name, summary);
1053
+ row.append(text);
1054
+ const range = rangeText(ctx, data);
1055
+ if (range) row.append(range);
1056
+ return [el("span", { class: "aparte-weather__accent", attrs: { "data-condition": data.condition, "data-night": data.night, "aria-hidden": "true" } }), row];
1057
+ }
1058
+ function heat(celsius) {
1059
+ const stops = [
1060
+ [-10, [129, 140, 248]],
1061
+ [0, [96, 165, 250]],
1062
+ [10, [52, 211, 153]],
1063
+ [18, [250, 204, 21]],
1064
+ [26, [251, 146, 60]],
1065
+ [34, [239, 68, 68]]
1066
+ ];
1067
+ if (celsius <= stops[0][0]) return `rgb(${stops[0][1].join(" ")})`;
1068
+ for (let i = 1; i < stops.length; i++) {
1069
+ const [t1, c1] = stops[i];
1070
+ const [t0, c0] = stops[i - 1];
1071
+ if (celsius <= t1) {
1072
+ const k = (celsius - t0) / (t1 - t0);
1073
+ return `rgb(${c0.map((v, j) => Math.round(v + (c1[j] - v) * k)).join(" ")})`;
1074
+ }
1075
+ }
1076
+ return `rgb(${stops[stops.length - 1][1].join(" ")})`;
1077
+ }
1078
+ function renderForecast(data, ctx) {
1079
+ const { config } = ctx;
1080
+ const header = el("div", { class: "aparte-weather__forecast-head" }, sky(data));
1081
+ header.append(...renderCompact(data, ctx).slice(1));
1082
+ if (data.daily.length === 0) return [header];
1083
+ const toC = (t) => data.unit === "F" ? (t - 32) * 5 / 9 : t;
1084
+ const lo = Math.min(...data.daily.map((d) => d.low));
1085
+ const hi = Math.max(...data.daily.map((d) => d.high));
1086
+ const span = hi - lo || 1;
1087
+ const list = el("ol", { class: "aparte-weather__days" });
1088
+ ctx.bind(list, () => word(config, "cardsWeatherForecast", W.cardsWeatherForecast), "aria-label");
1089
+ data.daily.forEach((d, i) => {
1090
+ const name = el("span", { class: "aparte-weather__day-name" });
1091
+ ctx.bind(name, () => formatDay(config, d.date, "short"));
1092
+ const rain = el("span", { class: "aparte-weather__day-rain" });
1093
+ if (d.precipitation !== void 0 && d.precipitation >= 20) ctx.bind(rain, () => formatPercent(config, d.precipitation / 100));
1094
+ const low = el("span", { class: "aparte-weather__day-low" });
1095
+ ctx.bind(low, () => deg(config, d.low));
1096
+ const high = el("span", { class: "aparte-weather__day-high" });
1097
+ ctx.bind(high, () => deg(config, d.high));
1098
+ const fill = el("span", { class: "aparte-weather__bar-fill" });
1099
+ fill.style.setProperty("--aparte-weather-bar-start", `${(d.low - lo) / span * 100}%`);
1100
+ fill.style.setProperty("--aparte-weather-bar-end", `${(d.high - lo) / span * 100}%`);
1101
+ fill.style.setProperty("--aparte-weather-bar-cold", heat(toC(d.low)));
1102
+ fill.style.setProperty("--aparte-weather-bar-warm", heat(toC(d.high)));
1103
+ const bar = el("span", { class: "aparte-weather__bar", attrs: { "aria-hidden": "true" } }, fill);
1104
+ if (i === 0 && data.temperature !== void 0 && data.temperature >= d.low && data.temperature <= d.high) {
1105
+ const dot = el("span", { class: "aparte-weather__bar-now" });
1106
+ dot.style.setProperty("--aparte-weather-bar-at", `${(data.temperature - lo) / span * 100}%`);
1107
+ bar.append(dot);
1108
+ }
1109
+ const row = el("li", { class: "aparte-weather__day" }, name, glyph(weatherIcon(d.condition), "aparte-rich-card__glyph aparte-weather__mini"), rain, low, bar, high);
1110
+ ctx.bind(row, () => `${formatDay(config, d.date, "long")}: ${word(config, `cardsWeather_${d.condition}`, CONDITION_WORDS[d.condition])}, ${word(config, "cardsWeatherLow", W.cardsWeatherLow)} ${degFull(config, d.low, data.unit)}, ${word(config, "cardsWeatherHigh", W.cardsWeatherHigh)} ${degFull(config, d.high, data.unit)}`, "aria-label");
1111
+ list.append(row);
1112
+ });
1113
+ return [header, list];
1114
+ }
1115
+ function skeleton(partial, ctx) {
1116
+ const block = (cls, kind = "rect") => el("span", { class: `aparte-skeleton aparte-skeleton--${kind} ${cls}`, attrs: { "aria-hidden": "true" } });
1117
+ const place = el("div", { class: "aparte-weather__place" });
1118
+ if (partial?.location) place.append(el("span", { class: "aparte-weather__location", text: partial.location }));
1119
+ else place.append(block("aparte-weather__sk-place", "text"));
1120
+ const head = el("div", { class: "aparte-weather__head" }, place, block("aparte-weather__sk-icon", "circle"));
1121
+ if (ctx.variant === "compact") {
1122
+ return [el("div", { class: "aparte-weather__compact" }, block("aparte-weather__sk-icon", "circle"), block("aparte-weather__sk-temp"), place)];
1123
+ }
1124
+ const stats = el("div", { class: "aparte-weather__sk-stats" }, block("aparte-weather__sk-stat"), block("aparte-weather__sk-stat"), block("aparte-weather__sk-stat"));
1125
+ return [el("div", { class: "aparte-weather__body" }, head, el("div", { class: "aparte-weather__now" }, block("aparte-weather__sk-temp"), block("aparte-weather__sk-summary", "text")), stats)];
1126
+ }
1127
+ const weatherCard = defineCard({
1128
+ name: "weather",
1129
+ variants: ["hero", "compact", "forecast"],
1130
+ styles: weatherStyles,
1131
+ icon: weatherIcon("partly-cloudy"),
1132
+ normalize: readWeather,
1133
+ render: (data, ctx) => ctx.variant === "compact" ? renderCompact(data, ctx) : ctx.variant === "forecast" ? renderForecast(data, ctx) : renderHero(data, ctx),
1134
+ skeleton,
1135
+ label: (data, ctx) => data?.location ? word(ctx.config, "cardsWeatherIn", W.cardsWeatherIn, { place: data.location }) : word(ctx.config, "cardsWeatherTitle", W.cardsWeatherTitle),
1136
+ fallback: (data, ctx) => {
1137
+ const parts = [
1138
+ data.temperature !== void 0 ? degFull(ctx.config, data.temperature, data.unit) : null,
1139
+ summaryOf(data, ctx.config),
1140
+ data.high !== void 0 && data.low !== void 0 ? `${word(ctx.config, "cardsWeatherHigh", W.cardsWeatherHigh)} ${degFull(ctx.config, data.high, data.unit)} / ${word(ctx.config, "cardsWeatherLow", W.cardsWeatherLow)} ${degFull(ctx.config, data.low, data.unit)}` : null
1141
+ ].filter(Boolean);
1142
+ return `${data.location ? `${data.location}: ` : ""}${parts.join(", ")}`;
1143
+ },
1144
+ partial: (input) => {
1145
+ const location = str(input["location"] ?? input["city"] ?? input["place"] ?? input["q"] ?? input["query"]);
1146
+ return location ? { location } : null;
1147
+ }
1148
+ });
1149
+ function setupWeatherCard(options = {}) {
1150
+ return weatherCard.setup(options);
1151
+ }
1152
+ export {
1153
+ WEATHER_CONDITIONS,
1154
+ conditionFromOpenWeather,
1155
+ conditionFromText,
1156
+ conditionFromWmo,
1157
+ fromOpenMeteo,
1158
+ readWeather,
1159
+ setupWeatherCard,
1160
+ weatherCard
1161
+ };
1162
+ //# sourceMappingURL=weather.js.map