@aparte/plugin-cards 0.0.0-stage → 0.29.0

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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -2
  3. package/dist/carousel-CPy-0JGN.js +63 -0
  4. package/dist/carousel-CPy-0JGN.js.map +1 -0
  5. package/dist/controls-BVX2u7sK.js +62 -0
  6. package/dist/controls-BVX2u7sK.js.map +1 -0
  7. package/dist/format-CchcJRum.js +720 -0
  8. package/dist/format-CchcJRum.js.map +1 -0
  9. package/dist/index.d.ts +28 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +35 -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 +194 -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/format.d.ts +49 -0
  28. package/dist/kit/format.d.ts.map +1 -0
  29. package/dist/kit/rating.d.ts +19 -0
  30. package/dist/kit/rating.d.ts.map +1 -0
  31. package/dist/kit/sparkline.d.ts +19 -0
  32. package/dist/kit/sparkline.d.ts.map +1 -0
  33. package/dist/kit/strings.d.ts +139 -0
  34. package/dist/kit/strings.d.ts.map +1 -0
  35. package/dist/link/icons.d.ts +16 -0
  36. package/dist/link/icons.d.ts.map +1 -0
  37. package/dist/link/index.d.ts +98 -0
  38. package/dist/link/index.d.ts.map +1 -0
  39. package/dist/link.js +387 -0
  40. package/dist/link.js.map +1 -0
  41. package/dist/media/icons.d.ts +28 -0
  42. package/dist/media/icons.d.ts.map +1 -0
  43. package/dist/media/index.d.ts +107 -0
  44. package/dist/media/index.d.ts.map +1 -0
  45. package/dist/media.js +610 -0
  46. package/dist/media.js.map +1 -0
  47. package/dist/order/icons.d.ts +49 -0
  48. package/dist/order/icons.d.ts.map +1 -0
  49. package/dist/order/index.d.ts +204 -0
  50. package/dist/order/index.d.ts.map +1 -0
  51. package/dist/order.js +1843 -0
  52. package/dist/order.js.map +1 -0
  53. package/dist/place/icons.d.ts +18 -0
  54. package/dist/place/icons.d.ts.map +1 -0
  55. package/dist/place/index.d.ts +207 -0
  56. package/dist/place/index.d.ts.map +1 -0
  57. package/dist/place.js +1456 -0
  58. package/dist/place.js.map +1 -0
  59. package/dist/plan/icons.d.ts +25 -0
  60. package/dist/plan/icons.d.ts.map +1 -0
  61. package/dist/plan/index.d.ts +153 -0
  62. package/dist/plan/index.d.ts.map +1 -0
  63. package/dist/plan.js +1191 -0
  64. package/dist/plan.js.map +1 -0
  65. package/dist/product/icons.d.ts +16 -0
  66. package/dist/product/icons.d.ts.map +1 -0
  67. package/dist/product/index.d.ts +133 -0
  68. package/dist/product/index.d.ts.map +1 -0
  69. package/dist/product.js +1245 -0
  70. package/dist/product.js.map +1 -0
  71. package/dist/rating-B8Mdx_b_.js +35 -0
  72. package/dist/rating-B8Mdx_b_.js.map +1 -0
  73. package/dist/score/icons.d.ts +35 -0
  74. package/dist/score/icons.d.ts.map +1 -0
  75. package/dist/score/index.d.ts +185 -0
  76. package/dist/score/index.d.ts.map +1 -0
  77. package/dist/score.js +1843 -0
  78. package/dist/score.js.map +1 -0
  79. package/dist/sparkline-C-cA9obz.js +56 -0
  80. package/dist/sparkline-C-cA9obz.js.map +1 -0
  81. package/dist/stats/icons.d.ts +19 -0
  82. package/dist/stats/icons.d.ts.map +1 -0
  83. package/dist/stats/index.d.ts +137 -0
  84. package/dist/stats/index.d.ts.map +1 -0
  85. package/dist/stats.js +1085 -0
  86. package/dist/stats.js.map +1 -0
  87. package/dist/stock/chart.d.ts +135 -0
  88. package/dist/stock/chart.d.ts.map +1 -0
  89. package/dist/stock/icons.d.ts +15 -0
  90. package/dist/stock/icons.d.ts.map +1 -0
  91. package/dist/stock/index.d.ts +195 -0
  92. package/dist/stock/index.d.ts.map +1 -0
  93. package/dist/stock.js +1013 -0
  94. package/dist/stock.js.map +1 -0
  95. package/dist/weather/conditions.d.ts +25 -0
  96. package/dist/weather/conditions.d.ts.map +1 -0
  97. package/dist/weather/icons.d.ts +12 -0
  98. package/dist/weather/icons.d.ts.map +1 -0
  99. package/dist/weather/index.d.ts +146 -0
  100. package/dist/weather/index.d.ts.map +1 -0
  101. package/dist/weather.js +1162 -0
  102. package/dist/weather.js.map +1 -0
  103. package/package.json +137 -3
package/dist/order.js ADDED
@@ -0,0 +1,1843 @@
1
+ import { d as defineCard, o as str, l as intlTag, e as el, c as currencyCode, w as webUrl, b as formatNumber, p as word, h as formatPrice, k as glyph, n as num, t as toDate, r as readPriceText } from "./format-CchcJRum.js";
2
+ const svg = (body) => `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg">${body}</svg>`;
3
+ const BAG = svg('<path d="M5.5 8h13l-1 11.2a1.8 1.8 0 0 1-1.8 1.6H8.3a1.8 1.8 0 0 1-1.8-1.6z"/><path d="M9 10.5V6.8a3 3 0 0 1 6 0v3.7"/>');
4
+ const CALENDAR = svg('<rect x="3.5" y="5" width="17" height="15.5" rx="2.2"/><path d="M3.5 9.8h17M8 3v4M16 3v4"/><path d="M7.5 13.6h2M11 13.6h2M14.5 13.6h2M7.5 16.8h2M11 16.8h2"/>');
5
+ const BOX = svg('<path d="M3.8 7.6 12 3.5l8.2 4.1v8.8L12 20.5l-8.2-4.1z"/><path d="M3.8 7.6 12 11.7l8.2-4.1M12 11.7v8.8"/>');
6
+ const TRUCK = svg('<path d="M2.8 6.5h10.4v9.3H2.8z"/><path d="M13.2 9.5h4.1l3 3.2v3.1h-7.1"/><circle cx="7" cy="17.3" r="1.7"/><circle cx="17" cy="17.3" r="1.7"/>');
7
+ const CARD = svg('<rect x="2.8" y="5.5" width="18.4" height="13" rx="2"/><path d="M2.8 9.6h18.4M6.5 15h3.5"/>');
8
+ const PIN = svg('<path d="M12 21s-6.5-5.6-6.5-11a6.5 6.5 0 0 1 13 0c0 5.4-6.5 11-6.5 11z"/><circle cx="12" cy="10" r="2.3"/>');
9
+ const PEOPLE = svg('<circle cx="9" cy="8.5" r="3"/><path d="M3.5 19c.6-3.2 2.8-5 5.5-5s4.9 1.8 5.5 5"/><circle cx="16.8" cy="9.3" r="2.4"/><path d="M15.8 14.2c2.4-.3 4.3 1.3 4.8 4.3"/>');
10
+ const PERSON = svg('<circle cx="12" cy="8.5" r="3.5"/><path d="M5 20c.8-3.7 3.6-5.8 7-5.8s6.2 2.1 7 5.8"/>');
11
+ const HOUSE = svg('<path d="M4 10.5 12 4l8 6.5V20H4z"/><path d="M9.5 20v-5.5h5V20"/>');
12
+ const INFO = svg('<circle cx="12" cy="12" r="8.5"/><path d="M12 11v5"/><circle cx="12" cy="8" r=".6" fill="currentColor"/>');
13
+ const CHEVRON = svg('<path d="M9.5 6l6 6-6 6"/>');
14
+ const ARROW = svg('<path d="M4.5 12h15M14 6.5l5.5 5.5-5.5 5.5"/>');
15
+ const MARKS = {
16
+ success: "M22 32.5l7 7 13.5-14.5",
17
+ info: "M32 22v10.5l7 4.5",
18
+ danger: "M24.5 24.5l15 15M39.5 24.5l-15 15",
19
+ neutral: "M25.5 27.5h9.5a6.5 6.5 0 0 1 0 13h-8M30 22.5l-5 5 5 5"
20
+ };
21
+ function seal(tone) {
22
+ return `<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><circle class="aparte-order__seal-halo" cx="32" cy="32" r="31"/><circle class="aparte-order__seal-disc" cx="32" cy="32" r="22"/><path class="aparte-order__seal-mark" pathLength="1" d="${MARKS[tone]}"/></svg>`;
23
+ }
24
+ const orderStyles = `/* =========================================
25
+ The order card — @aparte/plugin-cards/order
26
+ =========================================
27
+ Three variants of one card, chosen by \`data-variant\` on its root:
28
+ receipt the whole record, in bands: the header (kind, name, date, status),
29
+ the booking's dates, the lines, the totals under a rule, then the
30
+ facts — payment, delivery, address — and the order's page.
31
+ compact one row: the kind, the name over "3 items · €129.90", the pill, a
32
+ chevron when it opens a page. Several in a list stay one line each.
33
+ confirmation the moment it is placed: a seal drawn on, a headline, the number,
34
+ the facts that matter as tiles, what to do next.
35
+ Every colour is a theme token or derived from one, so light and dark follow the chat.
36
+ */
37
+
38
+ .aparte-order-card {
39
+ --aparte-order-kind-size: 2.25rem;
40
+ --aparte-order-thumb-size: 2.75rem;
41
+ --aparte-order-kind-bg: color-mix(in oklab, var(--aparte-primary) 14%, var(--aparte-surface-1));
42
+ --aparte-order-kind-ink: var(--aparte-primary-ink);
43
+ --aparte-order-rule: var(--aparte-border);
44
+ --aparte-order-soft-rule: color-mix(in oklab, var(--aparte-border) 60%, transparent);
45
+ --aparte-order-tile-bg: color-mix(in oklab, var(--aparte-surface-2) 55%, var(--aparte-surface-1));
46
+ /* A product photo is shot on white: the thumbnail's plate is near-white in both
47
+ schemes, and the photo is multiplied into it (the product card's rule). */
48
+ --aparte-order-thumb-bg: color-mix(in oklab, var(--aparte-text) 5%, #fff);
49
+ --aparte-order-placeholder: var(--aparte-surface-2);
50
+ --aparte-order-placeholder-ink: color-mix(in oklab, var(--aparte-text) 32%, transparent);
51
+ --aparte-order-saving: var(--aparte-success-ink);
52
+ --aparte-order-seal-size: 4.5rem;
53
+ }
54
+
55
+ /* ── Widths: each variant asks for its own; the bubble's limit caps them all ── */
56
+
57
+ .aparte-order-card[data-variant="receipt"] { --aparte-rich-card-max-inline-size: 26rem; }
58
+ .aparte-order-card[data-variant="compact"] { --aparte-rich-card-max-inline-size: 26rem; }
59
+ .aparte-order-card[data-variant="confirmation"] { --aparte-rich-card-max-inline-size: 24rem; }
60
+
61
+ /* On the drawn card only: a one-line state shrinks to its words, and a size container
62
+ cannot. */
63
+ .aparte-order-card[data-state="ready"] {
64
+ container: aparte-order / inline-size;
65
+ }
66
+
67
+ /* ── The header ──────────────────────────────────────────────────────── */
68
+
69
+ .aparte-order__head {
70
+ display: flex;
71
+ align-items: center;
72
+ gap: var(--aparte-space-4);
73
+ padding: var(--aparte-space-5) var(--aparte-rich-card-padding);
74
+ }
75
+
76
+ /* The kind's glyph on a tile of the accent: the bag of an order, the calendar of a booking. */
77
+ .aparte-order__kind {
78
+ --aparte-rich-card-glyph-size: var(--aparte-order-kind-size);
79
+ box-sizing: border-box;
80
+ padding: calc(var(--aparte-order-kind-size) * 0.22);
81
+ border-radius: var(--aparte-radius-lg);
82
+ background: var(--aparte-order-kind-bg);
83
+ color: var(--aparte-order-kind-ink);
84
+ }
85
+
86
+ .aparte-order__heading {
87
+ display: flex;
88
+ flex: 1;
89
+ flex-direction: column;
90
+ gap: var(--aparte-space-1);
91
+ min-inline-size: 0;
92
+ }
93
+
94
+ .aparte-order__title {
95
+ color: var(--aparte-text);
96
+ font-size: var(--aparte-font-size-base);
97
+ font-weight: var(--aparte-font-weight-semibold);
98
+ line-height: 1.3;
99
+ overflow-wrap: anywhere;
100
+ }
101
+
102
+ .aparte-order__date {
103
+ color: var(--aparte-text-muted);
104
+ font-size: var(--aparte-font-size-sm);
105
+ }
106
+
107
+ /* The pill: the badge recipe, with a dot in its tone before the word. */
108
+ .aparte-order__status {
109
+ flex: none;
110
+ gap: var(--aparte-space-2);
111
+ margin-inline-start: auto;
112
+ }
113
+
114
+ .aparte-order__status-dot {
115
+ inline-size: 0.375rem;
116
+ block-size: 0.375rem;
117
+ border-radius: var(--aparte-radius-full);
118
+ background: var(--aparte-badge-intent, currentColor);
119
+ }
120
+
121
+ /* ── Bands ───────────────────────────────────────────────────────────── */
122
+
123
+ .aparte-order__section {
124
+ margin: 0;
125
+ padding: var(--aparte-space-5) var(--aparte-rich-card-padding);
126
+ border-block-start: var(--aparte-border-width) solid var(--aparte-order-rule);
127
+ }
128
+
129
+ /* ── The lines ───────────────────────────────────────────────────────── */
130
+
131
+ .aparte-order__items { padding-block: var(--aparte-space-2); }
132
+
133
+ /* One grid for the list, each line a subgrid of it: the quantities line up in one column
134
+ and the totals in another, whatever the names' lengths. A browser without subgrid keeps
135
+ the first declaration and lays each line out alone — the totals still end-aligned. */
136
+ .aparte-order__lines {
137
+ display: grid;
138
+ grid-template-columns: minmax(0, 1fr) auto auto;
139
+ column-gap: var(--aparte-space-4);
140
+ margin: 0;
141
+ padding: 0;
142
+ list-style: none;
143
+ }
144
+
145
+ .aparte-order__lines[data-thumbs] {
146
+ grid-template-columns: var(--aparte-order-thumb-size) minmax(0, 1fr) auto auto;
147
+ }
148
+
149
+ .aparte-order__line {
150
+ display: grid;
151
+ grid-column: 1 / -1;
152
+ grid-template-columns: minmax(0, 1fr) auto auto;
153
+ grid-template-columns: subgrid;
154
+ align-items: center;
155
+ column-gap: var(--aparte-space-4);
156
+ padding-block: var(--aparte-space-3);
157
+ }
158
+
159
+ [data-thumbs] > .aparte-order__line {
160
+ grid-template-columns: var(--aparte-order-thumb-size) minmax(0, 1fr) auto auto;
161
+ grid-template-columns: subgrid;
162
+ }
163
+
164
+ .aparte-order__line + .aparte-order__line {
165
+ border-block-start: var(--aparte-border-width) solid var(--aparte-order-soft-rule);
166
+ }
167
+
168
+ .aparte-order__qty { grid-column: -3 / -2; }
169
+ .aparte-order__line-total { grid-column: -2 / -1; }
170
+
171
+ .aparte-order__thumb {
172
+ position: relative;
173
+ display: grid;
174
+ place-items: center;
175
+ inline-size: var(--aparte-order-thumb-size);
176
+ aspect-ratio: 1;
177
+ overflow: hidden;
178
+ border: var(--aparte-border-width) solid var(--aparte-order-soft-rule);
179
+ border-radius: var(--aparte-radius-md);
180
+ background: var(--aparte-order-thumb-bg);
181
+ isolation: isolate;
182
+ }
183
+
184
+ .aparte-order__thumb[data-empty] { background: var(--aparte-order-placeholder); }
185
+
186
+ .aparte-order__thumb-glyph {
187
+ grid-area: 1 / 1;
188
+ --aparte-rich-card-glyph-size: 45%;
189
+ color: var(--aparte-order-placeholder-ink);
190
+ }
191
+
192
+ .aparte-order__thumb:not([data-empty]) .aparte-order__thumb-glyph { visibility: hidden; }
193
+
194
+ .aparte-order__image {
195
+ grid-area: 1 / 1;
196
+ box-sizing: border-box;
197
+ inline-size: 100%;
198
+ block-size: 100%;
199
+ padding: 6%;
200
+ object-fit: contain;
201
+ mix-blend-mode: multiply;
202
+ }
203
+
204
+ .aparte-order__image[hidden] { display: none; }
205
+
206
+ .aparte-order__line-main {
207
+ display: flex;
208
+ flex-direction: column;
209
+ gap: var(--aparte-space-1);
210
+ min-inline-size: 0;
211
+ }
212
+
213
+ .aparte-order__line-title {
214
+ display: -webkit-box;
215
+ overflow: hidden;
216
+ -webkit-box-orient: vertical;
217
+ -webkit-line-clamp: 2;
218
+ line-clamp: 2;
219
+ color: var(--aparte-text);
220
+ font-size: var(--aparte-font-size-md);
221
+ font-weight: var(--aparte-font-weight-medium);
222
+ line-height: 1.3;
223
+ overflow-wrap: anywhere;
224
+ }
225
+
226
+ .aparte-order__line-meta {
227
+ display: flex;
228
+ flex-wrap: wrap;
229
+ gap: 0 var(--aparte-space-2);
230
+ color: var(--aparte-text-muted);
231
+ font-size: var(--aparte-font-size-xs);
232
+ }
233
+
234
+ .aparte-order__line-meta > * + *::before,
235
+ .aparte-order__row-part + .aparte-order__row-part::before {
236
+ content: "·";
237
+ margin-inline-end: var(--aparte-space-2);
238
+ }
239
+
240
+ .aparte-order__qty {
241
+ color: var(--aparte-text-muted);
242
+ font-size: var(--aparte-font-size-sm);
243
+ white-space: nowrap;
244
+ }
245
+
246
+ .aparte-order__line-total {
247
+ color: var(--aparte-text);
248
+ font-size: var(--aparte-font-size-md);
249
+ font-weight: var(--aparte-font-weight-medium);
250
+ text-align: end;
251
+ white-space: nowrap;
252
+ }
253
+
254
+ /* "and 4 more": a summary that reads as a link, the chevron turning as it opens. */
255
+ .aparte-order__more > .aparte-order__lines {
256
+ border-block-start: var(--aparte-border-width) solid var(--aparte-order-soft-rule);
257
+ }
258
+
259
+ .aparte-order__more-toggle {
260
+ display: inline-flex;
261
+ align-items: center;
262
+ gap: var(--aparte-space-2);
263
+ margin-block: var(--aparte-space-1) var(--aparte-space-2);
264
+ padding: var(--aparte-space-1) var(--aparte-space-2);
265
+ margin-inline-start: calc(var(--aparte-space-2) * -1);
266
+ border-radius: var(--aparte-radius-sm);
267
+ color: var(--aparte-primary-ink);
268
+ font-size: var(--aparte-font-size-sm);
269
+ font-weight: var(--aparte-font-weight-medium);
270
+ list-style: none;
271
+ cursor: pointer;
272
+ transition: background-color var(--aparte-duration-fast) ease;
273
+ --aparte-rich-card-glyph-size: 0.875rem;
274
+ }
275
+
276
+ .aparte-order__more-toggle::-webkit-details-marker { display: none; }
277
+ .aparte-order__more-toggle:hover { background: var(--aparte-surface-2); }
278
+
279
+ .aparte-order__more-toggle:focus-visible {
280
+ outline: var(--aparte-focus-outline-width) solid var(--aparte-border-focus);
281
+ outline-offset: var(--aparte-focus-outline-offset);
282
+ }
283
+
284
+ .aparte-order__more-chevron { transition: rotate var(--aparte-duration-base) ease; }
285
+ .aparte-order__more-chevron:dir(rtl) { transform: scaleX(-1); }
286
+ .aparte-order__more[open] .aparte-order__more-chevron { rotate: 90deg; }
287
+ /* Mirrored first, then turned: a quarter turn the other way also ends pointing down. */
288
+ .aparte-order__more[open] .aparte-order__more-chevron:dir(rtl) { rotate: -90deg; }
289
+
290
+ .aparte-order__dropped {
291
+ padding-block: var(--aparte-space-2) var(--aparte-space-3);
292
+ color: var(--aparte-text-muted);
293
+ font-size: var(--aparte-font-size-xs);
294
+ }
295
+
296
+ /* ── The totals ──────────────────────────────────────────────────────── */
297
+
298
+ .aparte-order__totals {
299
+ display: flex;
300
+ flex-direction: column;
301
+ gap: var(--aparte-space-2);
302
+ background: var(--aparte-order-tile-bg);
303
+ }
304
+
305
+ .aparte-order__sum {
306
+ display: flex;
307
+ align-items: baseline;
308
+ justify-content: space-between;
309
+ gap: var(--aparte-space-4);
310
+ }
311
+
312
+ .aparte-order__sum-label {
313
+ color: var(--aparte-text-muted);
314
+ font-size: var(--aparte-font-size-md);
315
+ }
316
+
317
+ .aparte-order__sum-value {
318
+ margin: 0;
319
+ color: var(--aparte-text);
320
+ font-size: var(--aparte-font-size-md);
321
+ text-align: end;
322
+ white-space: nowrap;
323
+ }
324
+
325
+ .aparte-order__sum--discount .aparte-order__sum-value,
326
+ .aparte-order__sum--free .aparte-order__sum-value {
327
+ color: var(--aparte-order-saving);
328
+ font-weight: var(--aparte-font-weight-medium);
329
+ }
330
+
331
+ .aparte-order__sum--total {
332
+ align-items: center;
333
+ margin-block-start: var(--aparte-space-2);
334
+ padding-block-start: var(--aparte-space-4);
335
+ border-block-start: var(--aparte-border-width) solid var(--aparte-order-rule);
336
+ }
337
+
338
+ .aparte-order__sum--total .aparte-order__sum-label {
339
+ color: var(--aparte-text);
340
+ font-size: var(--aparte-font-size-base);
341
+ font-weight: var(--aparte-font-weight-semibold);
342
+ }
343
+
344
+ .aparte-order__sum--total .aparte-order__sum-value {
345
+ font-size: var(--aparte-font-size-xl);
346
+ font-weight: var(--aparte-font-weight-bold);
347
+ letter-spacing: -0.01em;
348
+ }
349
+
350
+ /* A total alone needs no rule above it. */
351
+ .aparte-order__sum--total:first-child {
352
+ margin-block-start: 0;
353
+ padding-block-start: 0;
354
+ border-block-start: 0;
355
+ }
356
+
357
+ /* ── The facts: payment, delivery, address, the tool's own ───────────── */
358
+
359
+ .aparte-order__infos {
360
+ display: flex;
361
+ flex-direction: column;
362
+ gap: var(--aparte-space-4);
363
+ }
364
+
365
+ .aparte-order__info {
366
+ display: grid;
367
+ grid-template-columns: minmax(6.5rem, 38%) minmax(0, 1fr);
368
+ align-items: start;
369
+ gap: var(--aparte-space-1) var(--aparte-space-4);
370
+ }
371
+
372
+ .aparte-order__info-label {
373
+ display: flex;
374
+ align-items: center;
375
+ gap: var(--aparte-space-2);
376
+ min-inline-size: 0;
377
+ color: var(--aparte-text-muted);
378
+ font-size: var(--aparte-font-size-sm);
379
+ line-height: 1.45;
380
+ --aparte-rich-card-glyph-size: 1rem;
381
+ }
382
+
383
+ .aparte-order__info-glyph { opacity: 0.85; }
384
+
385
+ .aparte-order__info-value {
386
+ display: flex;
387
+ flex-wrap: wrap;
388
+ align-items: center;
389
+ justify-content: space-between;
390
+ gap: var(--aparte-space-2) var(--aparte-space-3);
391
+ min-inline-size: 0;
392
+ margin: 0;
393
+ color: var(--aparte-text);
394
+ font-size: var(--aparte-font-size-md);
395
+ line-height: 1.45;
396
+ overflow-wrap: anywhere;
397
+ }
398
+
399
+ .aparte-order__multiline { white-space: pre-line; }
400
+
401
+ .aparte-order__delivery-text {
402
+ display: flex;
403
+ flex-direction: column;
404
+ min-inline-size: 0;
405
+ }
406
+
407
+ .aparte-order__estimate { font-weight: var(--aparte-font-weight-medium); }
408
+
409
+ .aparte-order__carrier {
410
+ color: var(--aparte-text-muted);
411
+ font-size: var(--aparte-font-size-sm);
412
+ }
413
+
414
+ .aparte-order__track { flex: none; }
415
+
416
+ /* On a narrow card a fact's label goes over its value rather than squeeze it. */
417
+ @container aparte-order (max-width: 22rem) {
418
+ .aparte-order__info { grid-template-columns: minmax(0, 1fr); }
419
+ }
420
+
421
+ .aparte-order__foot {
422
+ display: flex;
423
+ justify-content: flex-end;
424
+ padding: var(--aparte-space-4) var(--aparte-rich-card-padding);
425
+ border-block-start: var(--aparte-border-width) solid var(--aparte-order-rule);
426
+ }
427
+
428
+ /* ── The booking: its dates as calendar leaves, then where and for whom ─ */
429
+
430
+ .aparte-order__leaf {
431
+ display: inline-flex;
432
+ flex: none;
433
+ flex-direction: column;
434
+ align-items: center;
435
+ inline-size: 3.5rem;
436
+ overflow: hidden;
437
+ border: var(--aparte-border-width) solid var(--aparte-order-rule);
438
+ border-radius: var(--aparte-radius-lg);
439
+ background: var(--aparte-surface-1);
440
+ box-shadow: 0 1px 2px color-mix(in oklab, var(--aparte-text) 8%, transparent);
441
+ line-height: 1.1;
442
+ text-align: center;
443
+ }
444
+
445
+ .aparte-order__leaf-month {
446
+ align-self: stretch;
447
+ padding-block: var(--aparte-space-1);
448
+ background: var(--aparte-order-kind-bg);
449
+ color: var(--aparte-order-kind-ink);
450
+ font-size: var(--aparte-font-size-2xs);
451
+ font-weight: var(--aparte-font-weight-bold);
452
+ letter-spacing: 0.06em;
453
+ text-transform: uppercase;
454
+ }
455
+
456
+ .aparte-order__leaf-day {
457
+ padding-block-start: var(--aparte-space-2);
458
+ color: var(--aparte-text);
459
+ font-size: var(--aparte-font-size-xl);
460
+ font-weight: var(--aparte-font-weight-bold);
461
+ }
462
+
463
+ .aparte-order__leaf-weekday {
464
+ padding-block: var(--aparte-space-1) var(--aparte-space-2);
465
+ color: var(--aparte-text-muted);
466
+ font-size: var(--aparte-font-size-2xs);
467
+ }
468
+
469
+ .aparte-order__day {
470
+ display: flex;
471
+ align-items: center;
472
+ gap: var(--aparte-space-5);
473
+ }
474
+
475
+ .aparte-order__day-text {
476
+ display: flex;
477
+ flex-direction: column;
478
+ gap: var(--aparte-space-1);
479
+ min-inline-size: 0;
480
+ }
481
+
482
+ .aparte-order__day-name {
483
+ color: var(--aparte-text);
484
+ font-size: var(--aparte-font-size-base);
485
+ font-weight: var(--aparte-font-weight-semibold);
486
+ }
487
+
488
+ .aparte-order__day-hours {
489
+ color: var(--aparte-text-muted);
490
+ font-size: var(--aparte-font-size-md);
491
+ }
492
+
493
+ .aparte-order__stay {
494
+ display: grid;
495
+ grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
496
+ align-items: center;
497
+ gap: var(--aparte-space-3);
498
+ }
499
+
500
+ .aparte-order__stay-side {
501
+ display: flex;
502
+ flex-direction: column;
503
+ align-items: center;
504
+ gap: var(--aparte-space-2);
505
+ }
506
+
507
+ .aparte-order__stay-time {
508
+ color: var(--aparte-text-muted);
509
+ font-size: var(--aparte-font-size-sm);
510
+ }
511
+
512
+ .aparte-order__stay-span {
513
+ display: flex;
514
+ flex-direction: column;
515
+ align-items: center;
516
+ gap: var(--aparte-space-2);
517
+ color: var(--aparte-text-muted);
518
+ --aparte-rich-card-glyph-size: 1.25rem;
519
+ }
520
+
521
+ .aparte-order__stay-arrow:dir(rtl) { transform: scaleX(-1); }
522
+
523
+ .aparte-order__nights {
524
+ padding: var(--aparte-space-1) var(--aparte-space-3);
525
+ border-radius: var(--aparte-radius-full);
526
+ background: var(--aparte-surface-2);
527
+ color: var(--aparte-text);
528
+ font-size: var(--aparte-font-size-xs);
529
+ font-weight: var(--aparte-font-weight-medium);
530
+ white-space: nowrap;
531
+ }
532
+
533
+ .aparte-order__places {
534
+ display: flex;
535
+ flex-direction: column;
536
+ gap: var(--aparte-space-2);
537
+ margin: 0;
538
+ }
539
+
540
+ .aparte-order__day + .aparte-order__places,
541
+ .aparte-order__stay + .aparte-order__places {
542
+ margin-block-start: var(--aparte-space-5);
543
+ }
544
+
545
+ .aparte-order__place {
546
+ display: flex;
547
+ align-items: flex-start;
548
+ gap: var(--aparte-space-3);
549
+ }
550
+
551
+ .aparte-order__place-label {
552
+ display: inline-flex;
553
+ flex: none;
554
+ color: var(--aparte-text-muted);
555
+ --aparte-rich-card-glyph-size: 1.125rem;
556
+ }
557
+
558
+ .aparte-order__place-value {
559
+ min-inline-size: 0;
560
+ margin: 0;
561
+ color: var(--aparte-text);
562
+ font-size: var(--aparte-font-size-md);
563
+ line-height: 1.4;
564
+ overflow-wrap: anywhere;
565
+ }
566
+
567
+ /* ── compact: one row ────────────────────────────────────────────────── */
568
+
569
+ .aparte-order__row {
570
+ position: relative;
571
+ display: grid;
572
+ grid-template-columns: auto minmax(0, 1fr) auto auto;
573
+ align-items: center;
574
+ column-gap: var(--aparte-space-4);
575
+ padding: var(--aparte-space-4) var(--aparte-space-5);
576
+ transition: background-color var(--aparte-duration-fast) ease;
577
+ --aparte-order-kind-size: 2rem;
578
+ }
579
+
580
+ .aparte-order__row-main {
581
+ display: flex;
582
+ flex-direction: column;
583
+ gap: var(--aparte-space-1);
584
+ min-inline-size: 0;
585
+ }
586
+
587
+ .aparte-order__row .aparte-order__title {
588
+ overflow: hidden;
589
+ font-size: var(--aparte-font-size-md);
590
+ text-overflow: ellipsis;
591
+ white-space: nowrap;
592
+ }
593
+
594
+ .aparte-order__row-meta {
595
+ display: flex;
596
+ flex-wrap: wrap;
597
+ color: var(--aparte-text-muted);
598
+ font-size: var(--aparte-font-size-sm);
599
+ }
600
+
601
+ .aparte-order__row-part { white-space: nowrap; }
602
+ .aparte-order__row-part + .aparte-order__row-part { margin-inline-start: var(--aparte-space-2); }
603
+
604
+ .aparte-order__row .aparte-order__status { margin-inline-start: 0; }
605
+
606
+ .aparte-order__link {
607
+ color: inherit;
608
+ text-decoration: none;
609
+ outline: none;
610
+ }
611
+
612
+ /* The title's link covers the row: one link, read once. */
613
+ .aparte-order__link::after {
614
+ content: "";
615
+ position: absolute;
616
+ inset: 0;
617
+ }
618
+
619
+ .aparte-order__row[data-linked]:hover { background: var(--aparte-surface-2); }
620
+
621
+ .aparte-order__row[data-linked]:hover .aparte-order__link {
622
+ text-decoration: underline;
623
+ text-decoration-thickness: 1px;
624
+ text-underline-offset: 0.18em;
625
+ }
626
+
627
+ /* The row reaches the card's clipped edges: its ring is drawn inside. */
628
+ .aparte-order__row:has(.aparte-order__link:focus-visible) {
629
+ outline: var(--aparte-focus-outline-width) solid var(--aparte-border-focus);
630
+ outline-offset: calc(var(--aparte-focus-outline-width) * -1);
631
+ }
632
+
633
+ .aparte-order__chevron {
634
+ color: var(--aparte-text-muted);
635
+ transition: translate var(--aparte-duration-base) ease;
636
+ --aparte-rich-card-glyph-size: 1rem;
637
+ }
638
+
639
+ .aparte-order__chevron:dir(rtl) { transform: scaleX(-1); }
640
+ .aparte-order__row[data-linked]:hover .aparte-order__chevron { translate: 2px 0; }
641
+ .aparte-order__row[data-linked]:hover .aparte-order__chevron:dir(rtl) { translate: -2px 0; }
642
+
643
+ /* ── confirmation: the seal, the headline, the tiles ─────────────────── */
644
+
645
+ .aparte-order__confirm {
646
+ --aparte-order-tone: var(--aparte-success);
647
+ display: flex;
648
+ flex-direction: column;
649
+ align-items: center;
650
+ gap: var(--aparte-space-2);
651
+ padding: var(--aparte-space-8) var(--aparte-rich-card-padding) var(--aparte-space-6);
652
+ background: radial-gradient(
653
+ 120% 70% at 50% 0%,
654
+ color-mix(in oklab, var(--aparte-order-tone) 13%, transparent) 0%,
655
+ transparent 70%
656
+ );
657
+ text-align: center;
658
+ }
659
+
660
+ .aparte-order__confirm[data-tone="info"] { --aparte-order-tone: var(--aparte-info); }
661
+ .aparte-order__confirm[data-tone="danger"] { --aparte-order-tone: var(--aparte-error); }
662
+ .aparte-order__confirm[data-tone="neutral"] { --aparte-order-tone: var(--aparte-neutral); }
663
+
664
+ .aparte-order__seal {
665
+ display: inline-flex;
666
+ inline-size: var(--aparte-order-seal-size);
667
+ block-size: var(--aparte-order-seal-size);
668
+ margin-block-end: var(--aparte-space-3);
669
+ }
670
+
671
+ .aparte-order__seal > svg {
672
+ inline-size: 100%;
673
+ block-size: 100%;
674
+ overflow: visible;
675
+ }
676
+
677
+ /* Each part rests in its final state; the animations only say where it came from, so
678
+ with motion turned off (the kit stops every animation) the seal is simply there. */
679
+ .aparte-order__seal-halo {
680
+ fill: color-mix(in oklab, var(--aparte-order-tone) 16%, transparent);
681
+ transform-box: fill-box;
682
+ transform-origin: center;
683
+ animation: aparte-order-halo 0.7s cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
684
+ }
685
+
686
+ .aparte-order__seal-disc {
687
+ fill: var(--aparte-order-tone);
688
+ transform-box: fill-box;
689
+ transform-origin: center;
690
+ animation: aparte-order-pop 0.45s cubic-bezier(0.2, 0.9, 0.25, 1.3) backwards;
691
+ }
692
+
693
+ /* The mark in the card's own surface: light on the disc in a light theme, dark in a dark one. */
694
+ .aparte-order__seal-mark {
695
+ fill: none;
696
+ stroke: var(--aparte-surface-1);
697
+ stroke-width: 4.5;
698
+ stroke-linecap: round;
699
+ stroke-linejoin: round;
700
+ stroke-dasharray: 1;
701
+ stroke-dashoffset: 0;
702
+ animation: aparte-order-draw 0.4s 0.25s ease-out backwards;
703
+ }
704
+
705
+ @keyframes aparte-order-pop {
706
+ from { opacity: 0; transform: scale(0.4); }
707
+ }
708
+
709
+ @keyframes aparte-order-halo {
710
+ from { opacity: 0; transform: scale(0.55); }
711
+ }
712
+
713
+ @keyframes aparte-order-draw {
714
+ from { stroke-dashoffset: 1; }
715
+ }
716
+
717
+ .aparte-order__headline {
718
+ color: var(--aparte-text);
719
+ font-size: var(--aparte-font-size-xl);
720
+ font-weight: var(--aparte-font-weight-semibold);
721
+ letter-spacing: -0.01em;
722
+ line-height: 1.25;
723
+ text-wrap: balance;
724
+ }
725
+
726
+ .aparte-order__ref {
727
+ color: var(--aparte-text-muted);
728
+ font-size: var(--aparte-font-size-md);
729
+ overflow-wrap: anywhere;
730
+ }
731
+
732
+ .aparte-order__confirm > .aparte-order__status { margin: var(--aparte-space-1) 0 0; }
733
+
734
+ .aparte-order__keyfacts {
735
+ display: grid;
736
+ grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
737
+ gap: var(--aparte-space-3);
738
+ align-self: stretch;
739
+ margin: var(--aparte-space-5) 0 0;
740
+ text-align: start;
741
+ }
742
+
743
+ .aparte-order__keyfact {
744
+ display: flex;
745
+ flex-direction: column;
746
+ gap: var(--aparte-space-1);
747
+ min-inline-size: 0;
748
+ padding: var(--aparte-space-4);
749
+ border: var(--aparte-border-width) solid var(--aparte-order-soft-rule);
750
+ border-radius: var(--aparte-radius-lg);
751
+ background: var(--aparte-order-tile-bg);
752
+ }
753
+
754
+ .aparte-order__keyfact-label {
755
+ color: var(--aparte-text-muted);
756
+ font-size: var(--aparte-font-size-xs);
757
+ font-weight: var(--aparte-font-weight-medium);
758
+ }
759
+
760
+ .aparte-order__keyfact-value {
761
+ display: flex;
762
+ flex-direction: column;
763
+ gap: var(--aparte-space-1);
764
+ margin: 0;
765
+ }
766
+
767
+ .aparte-order__keyfact-text {
768
+ color: var(--aparte-text);
769
+ font-size: var(--aparte-font-size-md);
770
+ font-weight: var(--aparte-font-weight-semibold);
771
+ line-height: 1.3;
772
+ overflow-wrap: anywhere;
773
+ }
774
+
775
+ .aparte-order__keyfact--total .aparte-order__keyfact-text {
776
+ font-size: var(--aparte-font-size-lg);
777
+ font-weight: var(--aparte-font-weight-bold);
778
+ letter-spacing: -0.01em;
779
+ }
780
+
781
+ .aparte-order__keyfact-note {
782
+ color: var(--aparte-text-muted);
783
+ font-size: var(--aparte-font-size-xs);
784
+ }
785
+
786
+ .aparte-order__confirm-actions {
787
+ display: flex;
788
+ flex-wrap: wrap;
789
+ gap: var(--aparte-space-3);
790
+ align-self: stretch;
791
+ margin-block-start: var(--aparte-space-5);
792
+ }
793
+
794
+ .aparte-order__confirm-actions > .aparte-rich-card__action {
795
+ flex: 1 1 8rem;
796
+ justify-content: center;
797
+ }
798
+
799
+ /* ── Loading ─────────────────────────────────────────────────────────── */
800
+
801
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-title { inline-size: 8rem; block-size: 1rem; }
802
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-date { inline-size: 6rem; }
803
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-meta { inline-size: 9rem; }
804
+
805
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-pill {
806
+ flex: none;
807
+ inline-size: 4.5rem;
808
+ block-size: 1.25rem;
809
+ border-radius: var(--aparte-radius-full);
810
+ }
811
+
812
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-thumb {
813
+ inline-size: var(--aparte-order-thumb-size);
814
+ block-size: var(--aparte-order-thumb-size);
815
+ }
816
+
817
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-line--short { inline-size: 55%; }
818
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-price { inline-size: 3.5rem; margin: 0; }
819
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-label { inline-size: 5rem; }
820
+
821
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-seal {
822
+ inline-size: var(--aparte-order-seal-size);
823
+ block-size: var(--aparte-order-seal-size);
824
+ margin-block-end: var(--aparte-space-3);
825
+ }
826
+
827
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-headline { inline-size: 11rem; block-size: 1.375rem; }
828
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-ref { inline-size: 6rem; margin: 0; }
829
+ .aparte-order-card[data-state="loading"] .aparte-skeleton.aparte-order__sk-fact { block-size: 4rem; border-radius: var(--aparte-radius-lg); }
830
+
831
+ .aparte-order__line > .aparte-order__sk-price { grid-column: -2 / -1; justify-self: end; }
832
+ .aparte-order__line--skeleton + .aparte-order__line--skeleton { border-block-start: 0; }
833
+
834
+ /* ── Small screens, motion ───────────────────────────────────────────── */
835
+
836
+ @media (max-width: 380px) {
837
+ .aparte-order-card {
838
+ --aparte-order-thumb-size: 2.5rem;
839
+ --aparte-order-kind-size: 2rem;
840
+ --aparte-rich-card-padding: var(--aparte-space-5);
841
+ }
842
+
843
+ .aparte-order__row { column-gap: var(--aparte-space-3); padding-inline: var(--aparte-space-4); }
844
+ .aparte-order__keyfacts { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
845
+ .aparte-order__leaf { inline-size: 3.125rem; }
846
+ }
847
+
848
+ /* The kit stops every animation and transition under reduced motion; the chevron's nudge
849
+ on hover is an end state, not a transition, so it is taken out here. */
850
+ @media (prefers-reduced-motion: reduce) {
851
+ .aparte-order__row[data-linked]:hover .aparte-order__chevron,
852
+ .aparte-order__row[data-linked]:hover .aparte-order__chevron:dir(rtl) { translate: none; }
853
+
854
+ .aparte-order__seal-halo,
855
+ .aparte-order__seal-disc,
856
+ .aparte-order__seal-mark { animation: none; }
857
+ }
858
+ `;
859
+ const P = {
860
+ cardsOrderOrder: { en: "Order", fr: "Commande", de: "Bestellung", es: "Pedido", it: "Ordine", ja: "注文", ko: "주문", pt: "Pedido", ru: "Заказ", zh: "订单" },
861
+ cardsOrderBooking: { en: "Booking", fr: "Réservation", de: "Buchung", es: "Reserva", it: "Prenotazione", ja: "予約", ko: "예약", pt: "Reserva", ru: "Бронирование", zh: "预订" },
862
+ cardsOrderNumbered: { en: "Order {reference}", fr: "Commande {reference}", de: "Bestellung {reference}", es: "Pedido {reference}", it: "Ordine {reference}", ja: "注文 {reference}", ko: "주문 {reference}", pt: "Pedido {reference}", ru: "Заказ {reference}", zh: "订单 {reference}" },
863
+ cardsOrderBookingNumbered: { en: "Booking {reference}", fr: "Réservation {reference}", de: "Buchung {reference}", es: "Reserva {reference}", it: "Prenotazione {reference}", ja: "予約 {reference}", ko: "예약 {reference}", pt: "Reserva {reference}", ru: "Бронирование {reference}", zh: "预订 {reference}" },
864
+ cardsOrderStatus_pending: { en: "Pending", fr: "En attente", de: "Ausstehend", es: "Pendiente", it: "In attesa", ja: "保留中", ko: "대기 중", pt: "Pendente", ru: "Ожидает", zh: "待处理" },
865
+ cardsOrderStatus_confirmed: { en: "Confirmed", fr: "Confirmée", de: "Bestätigt", es: "Confirmado", it: "Confermato", ja: "確定済み", ko: "확인됨", pt: "Confirmado", ru: "Подтверждён", zh: "已确认" },
866
+ cardsOrderStatus_processing: { en: "Processing", fr: "En préparation", de: "In Bearbeitung", es: "En preparación", it: "In preparazione", ja: "準備中", ko: "처리 중", pt: "Em preparação", ru: "В обработке", zh: "处理中" },
867
+ cardsOrderStatus_shipped: { en: "Shipped", fr: "Expédiée", de: "Versandt", es: "Enviado", it: "Spedito", ja: "発送済み", ko: "배송 중", pt: "Enviado", ru: "Отправлен", zh: "已发货" },
868
+ cardsOrderStatus_delivered: { en: "Delivered", fr: "Livrée", de: "Zugestellt", es: "Entregado", it: "Consegnato", ja: "配達済み", ko: "배송 완료", pt: "Entregue", ru: "Доставлен", zh: "已送达" },
869
+ cardsOrderStatus_cancelled: { en: "Cancelled", fr: "Annulée", de: "Storniert", es: "Cancelado", it: "Annullato", ja: "キャンセル済み", ko: "취소됨", pt: "Cancelado", ru: "Отменён", zh: "已取消" },
870
+ cardsOrderStatus_refunded: { en: "Refunded", fr: "Remboursée", de: "Erstattet", es: "Reembolsado", it: "Rimborsato", ja: "返金済み", ko: "환불됨", pt: "Reembolsado", ru: "Деньги возвращены", zh: "已退款" },
871
+ cardsOrderStatus_failed: { en: "Failed", fr: "Échouée", de: "Fehlgeschlagen", es: "Fallido", it: "Non riuscito", ja: "失敗", ko: "실패", pt: "Falhou", ru: "Не выполнен", zh: "失败" },
872
+ // A booking is feminine where an order is masculine (es, it, pt) and neuter in Russian:
873
+ // the words that agree with it are its own.
874
+ cardsOrderBookingStatus_pending: { en: "Pending", fr: "En attente", de: "Ausstehend", es: "Pendiente", it: "In attesa", ja: "保留中", ko: "대기 중", pt: "Pendente", ru: "Ожидает", zh: "待确认" },
875
+ cardsOrderBookingStatus_confirmed: { en: "Confirmed", fr: "Confirmée", de: "Bestätigt", es: "Confirmada", it: "Confermata", ja: "確定済み", ko: "확정됨", pt: "Confirmada", ru: "Подтверждено", zh: "已确认" },
876
+ cardsOrderBookingStatus_cancelled: { en: "Cancelled", fr: "Annulée", de: "Storniert", es: "Cancelada", it: "Annullata", ja: "キャンセル済み", ko: "취소됨", pt: "Cancelada", ru: "Отменено", zh: "已取消" },
877
+ cardsOrderBookingStatus_refunded: { en: "Refunded", fr: "Remboursée", de: "Erstattet", es: "Reembolsada", it: "Rimborsata", ja: "返金済み", ko: "환불됨", pt: "Reembolsada", ru: "Деньги возвращены", zh: "已退款" },
878
+ cardsOrderBookingStatus_failed: { en: "Failed", fr: "Échouée", de: "Fehlgeschlagen", es: "Fallida", it: "Non riuscita", ja: "失敗", ko: "실패", pt: "Falhou", ru: "Не выполнено", zh: "失败" },
879
+ cardsOrderHeadline_pending: { en: "Order placed", fr: "Commande passée", de: "Bestellung aufgegeben", es: "Pedido realizado", it: "Ordine effettuato", ja: "ご注文を受け付けました", ko: "주문이 접수되었습니다", pt: "Pedido realizado", ru: "Заказ оформлен", zh: "订单已提交" },
880
+ cardsOrderHeadline_confirmed: { en: "Order confirmed", fr: "Commande confirmée", de: "Bestellung bestätigt", es: "Pedido confirmado", it: "Ordine confermato", ja: "ご注文が確定しました", ko: "주문이 확인되었습니다", pt: "Pedido confirmado", ru: "Заказ подтверждён", zh: "订单已确认" },
881
+ cardsOrderHeadline_processing: { en: "Order being prepared", fr: "Commande en préparation", de: "Bestellung wird bearbeitet", es: "Pedido en preparación", it: "Ordine in preparazione", ja: "ご注文を準備中です", ko: "주문을 준비 중입니다", pt: "Pedido em preparação", ru: "Заказ собирается", zh: "订单处理中" },
882
+ cardsOrderHeadline_shipped: { en: "Order shipped", fr: "Commande expédiée", de: "Bestellung versandt", es: "Pedido enviado", it: "Ordine spedito", ja: "ご注文を発送しました", ko: "주문이 발송되었습니다", pt: "Pedido enviado", ru: "Заказ отправлен", zh: "订单已发货" },
883
+ cardsOrderHeadline_delivered: { en: "Order delivered", fr: "Commande livrée", de: "Bestellung zugestellt", es: "Pedido entregado", it: "Ordine consegnato", ja: "ご注文が配達されました", ko: "주문이 배송 완료되었습니다", pt: "Pedido entregue", ru: "Заказ доставлен", zh: "订单已送达" },
884
+ cardsOrderHeadline_cancelled: { en: "Order cancelled", fr: "Commande annulée", de: "Bestellung storniert", es: "Pedido cancelado", it: "Ordine annullato", ja: "ご注文はキャンセルされました", ko: "주문이 취소되었습니다", pt: "Pedido cancelado", ru: "Заказ отменён", zh: "订单已取消" },
885
+ cardsOrderHeadline_refunded: { en: "Order refunded", fr: "Commande remboursée", de: "Bestellung erstattet", es: "Pedido reembolsado", it: "Ordine rimborsato", ja: "ご注文は返金されました", ko: "주문이 환불되었습니다", pt: "Pedido reembolsado", ru: "Деньги за заказ возвращены", zh: "订单已退款" },
886
+ cardsOrderHeadline_failed: { en: "Order failed", fr: "Échec de la commande", de: "Bestellung fehlgeschlagen", es: "Error en el pedido", it: "Ordine non riuscito", ja: "ご注文を完了できませんでした", ko: "주문에 실패했습니다", pt: "Falha no pedido", ru: "Не удалось оформить заказ", zh: "订单失败" },
887
+ cardsOrderBookingHeadline_pending: { en: "Booking requested", fr: "Réservation demandée", de: "Buchung angefragt", es: "Reserva solicitada", it: "Prenotazione richiesta", ja: "予約をリクエストしました", ko: "예약이 요청되었습니다", pt: "Reserva solicitada", ru: "Запрос на бронирование отправлен", zh: "预订已提交" },
888
+ cardsOrderBookingHeadline_confirmed: { en: "Booking confirmed", fr: "Réservation confirmée", de: "Buchung bestätigt", es: "Reserva confirmada", it: "Prenotazione confermata", ja: "予約が確定しました", ko: "예약이 확정되었습니다", pt: "Reserva confirmada", ru: "Бронирование подтверждено", zh: "预订已确认" },
889
+ cardsOrderBookingHeadline_cancelled: { en: "Booking cancelled", fr: "Réservation annulée", de: "Buchung storniert", es: "Reserva cancelada", it: "Prenotazione annullata", ja: "予約はキャンセルされました", ko: "예약이 취소되었습니다", pt: "Reserva cancelada", ru: "Бронирование отменено", zh: "预订已取消" },
890
+ cardsOrderBookingHeadline_refunded: { en: "Booking refunded", fr: "Réservation remboursée", de: "Buchung erstattet", es: "Reserva reembolsada", it: "Prenotazione rimborsata", ja: "予約は返金されました", ko: "예약이 환불되었습니다", pt: "Reserva reembolsada", ru: "Деньги за бронирование возвращены", zh: "预订已退款" },
891
+ cardsOrderBookingHeadline_failed: { en: "Booking failed", fr: "Échec de la réservation", de: "Buchung fehlgeschlagen", es: "Error en la reserva", it: "Prenotazione non riuscita", ja: "予約を完了できませんでした", ko: "예약에 실패했습니다", pt: "Falha na reserva", ru: "Не удалось забронировать", zh: "预订失败" },
892
+ cardsOrderPlaced: { en: "Placed {date}", fr: "Passée le {date}", de: "Bestellt am {date}", es: "Realizado el {date}", it: "Effettuato il {date}", ja: "注文日 {date}", ko: "주문일 {date}", pt: "Feito em {date}", ru: "Оформлен {date}", zh: "下单于 {date}" },
893
+ cardsOrderBooked: { en: "Booked {date}", fr: "Réservée le {date}", de: "Gebucht am {date}", es: "Reservada el {date}", it: "Prenotata il {date}", ja: "予約日 {date}", ko: "예약일 {date}", pt: "Reservada em {date}", ru: "Забронировано {date}", zh: "预订于 {date}" },
894
+ cardsOrderItem: { en: "{n} item", fr: "{n} article", de: "{n} Artikel", es: "{n} artículo", it: "{n} articolo", ja: "{n}点", ko: "상품 {n}개", pt: "{n} item", ru: "{n} товар", zh: "{n} 件商品" },
895
+ cardsOrderItems: { en: "{n} items", fr: "{n} articles", de: "{n} Artikel", es: "{n} artículos", it: "{n} articoli", ja: "{n}点", ko: "상품 {n}개", pt: "{n} itens", ru: "Товаров: {n}", zh: "{n} 件商品" },
896
+ cardsOrderLines: { en: "Items", fr: "Articles", de: "Artikel", es: "Artículos", it: "Articoli", ja: "商品", ko: "상품", pt: "Itens", ru: "Товары", zh: "商品" },
897
+ cardsOrderMore: { en: "and {n} more", fr: "et {n} de plus", de: "und {n} weitere", es: "y {n} más", it: "e altri {n}", ja: "ほか{n}件", ko: "외 {n}개", pt: "e mais {n}", ru: "и ещё {n}", zh: "还有 {n} 件" },
898
+ cardsOrderEach: { en: "{price} each", fr: "{price} l’unité", de: "je {price}", es: "{price} c/u", it: "{price} cad.", ja: "単価 {price}", ko: "개당 {price}", pt: "{price} cada", ru: "{price} за шт.", zh: "单价 {price}" },
899
+ cardsOrderSubtotal: { en: "Subtotal", fr: "Sous-total", de: "Zwischensumme", es: "Subtotal", it: "Subtotale", ja: "小計", ko: "소계", pt: "Subtotal", ru: "Подытог", zh: "小计" },
900
+ cardsOrderDiscount: { en: "Discount", fr: "Remise", de: "Rabatt", es: "Descuento", it: "Sconto", ja: "割引", ko: "할인", pt: "Desconto", ru: "Скидка", zh: "折扣" },
901
+ cardsOrderShipping: { en: "Shipping", fr: "Livraison", de: "Versand", es: "Envío", it: "Spedizione", ja: "送料", ko: "배송비", pt: "Frete", ru: "Доставка", zh: "运费" },
902
+ cardsOrderFree: { en: "Free", fr: "Gratuite", de: "Kostenlos", es: "Gratis", it: "Gratuita", ja: "無料", ko: "무료", pt: "Grátis", ru: "Бесплатно", zh: "免费" },
903
+ cardsOrderTax: { en: "Tax", fr: "Taxes", de: "Steuern", es: "Impuestos", it: "Imposte", ja: "税", ko: "세금", pt: "Impostos", ru: "Налог", zh: "税费" },
904
+ cardsOrderTotal: { en: "Total", fr: "Total", de: "Gesamt", es: "Total", it: "Totale", ja: "合計", ko: "합계", pt: "Total", ru: "Итого", zh: "合计" },
905
+ cardsOrderFallbackTotal: { en: "total {amount}", fr: "total {amount}", de: "gesamt {amount}", es: "total {amount}", it: "totale {amount}", ja: "合計 {amount}", ko: "합계 {amount}", pt: "total {amount}", ru: "итого {amount}", zh: "合计 {amount}" },
906
+ cardsOrderPayment: { en: "Payment", fr: "Paiement", de: "Zahlung", es: "Pago", it: "Pagamento", ja: "お支払い", ko: "결제", pt: "Pagamento", ru: "Оплата", zh: "付款方式" },
907
+ cardsOrderDelivery: { en: "Estimated delivery", fr: "Livraison prévue", de: "Voraussichtliche Lieferung", es: "Entrega estimada", it: "Consegna prevista", ja: "お届け予定", ko: "도착 예정", pt: "Entrega prevista", ru: "Ожидаемая доставка", zh: "预计送达" },
908
+ cardsOrderTrack: { en: "Track", fr: "Suivre", de: "Verfolgen", es: "Seguir", it: "Traccia", ja: "追跡", ko: "배송 조회", pt: "Rastrear", ru: "Отследить", zh: "查看物流" },
909
+ cardsOrderAddress: { en: "Delivery address", fr: "Adresse de livraison", de: "Lieferadresse", es: "Dirección de entrega", it: "Indirizzo di consegna", ja: "お届け先", ko: "배송지", pt: "Endereço de entrega", ru: "Адрес доставки", zh: "收货地址" },
910
+ cardsOrderCustomer: { en: "Customer", fr: "Client", de: "Kunde", es: "Cliente", it: "Cliente", ja: "お客様", ko: "고객", pt: "Cliente", ru: "Покупатель", zh: "客户" },
911
+ cardsOrderView: { en: "View order", fr: "Voir la commande", de: "Bestellung ansehen", es: "Ver pedido", it: "Vedi ordine", ja: "注文を見る", ko: "주문 보기", pt: "Ver pedido", ru: "Открыть заказ", zh: "查看订单" },
912
+ cardsOrderViewBooking: { en: "View booking", fr: "Voir la réservation", de: "Buchung ansehen", es: "Ver reserva", it: "Vedi prenotazione", ja: "予約を見る", ko: "예약 보기", pt: "Ver reserva", ru: "Открыть бронирование", zh: "查看预订" },
913
+ cardsOrderWhen: { en: "When", fr: "Quand", de: "Wann", es: "Cuándo", it: "Quando", ja: "日時", ko: "일시", pt: "Quando", ru: "Когда", zh: "时间" },
914
+ cardsOrderWhere: { en: "Where", fr: "Où", de: "Wo", es: "Dónde", it: "Dove", ja: "場所", ko: "장소", pt: "Onde", ru: "Где", zh: "地点" },
915
+ cardsOrderGuestsLabel: { en: "Guests", fr: "Personnes", de: "Gäste", es: "Personas", it: "Ospiti", ja: "人数", ko: "인원", pt: "Pessoas", ru: "Гости", zh: "人数" },
916
+ cardsOrderStart: { en: "Start", fr: "Début", de: "Beginn", es: "Inicio", it: "Inizio", ja: "開始", ko: "시작", pt: "Início", ru: "Начало", zh: "开始" },
917
+ cardsOrderEnd: { en: "End", fr: "Fin", de: "Ende", es: "Fin", it: "Fine", ja: "終了", ko: "종료", pt: "Fim", ru: "Конец", zh: "结束" },
918
+ cardsOrderNight: { en: "{n} night", fr: "{n} nuit", de: "{n} Nacht", es: "{n} noche", it: "{n} notte", ja: "{n}泊", ko: "{n}박", pt: "{n} noite", ru: "{n} ночь", zh: "{n} 晚" },
919
+ cardsOrderNights: { en: "{n} nights", fr: "{n} nuits", de: "{n} Nächte", es: "{n} noches", it: "{n} notti", ja: "{n}泊", ko: "{n}박", pt: "{n} noites", ru: "Ночей: {n}", zh: "{n} 晚" },
920
+ cardsOrderGuest: { en: "{n} guest", fr: "{n} personne", de: "{n} Gast", es: "{n} persona", it: "{n} ospite", ja: "{n}名", ko: "{n}명", pt: "{n} pessoa", ru: "{n} гость", zh: "{n} 位" },
921
+ cardsOrderGuests: { en: "{n} guests", fr: "{n} personnes", de: "{n} Gäste", es: "{n} personas", it: "{n} ospiti", ja: "{n}名", ko: "{n}명", pt: "{n} pessoas", ru: "Гостей: {n}", zh: "{n} 位" }
922
+ };
923
+ const INTENT = {
924
+ pending: "warning",
925
+ confirmed: "success",
926
+ processing: "info",
927
+ shipped: "info",
928
+ delivered: "success",
929
+ cancelled: "neutral",
930
+ refunded: "neutral",
931
+ failed: "danger"
932
+ };
933
+ const TONE = {
934
+ pending: "info",
935
+ confirmed: "success",
936
+ processing: "info",
937
+ shipped: "success",
938
+ delivered: "success",
939
+ cancelled: "danger",
940
+ refunded: "neutral",
941
+ failed: "danger"
942
+ };
943
+ const BOOKING_HEADLINE = { processing: "pending", shipped: "confirmed", delivered: "confirmed" };
944
+ const LINES_KEPT = 50;
945
+ const LINES_SHOWN = 6;
946
+ const FACTS_KEPT = 12;
947
+ const FACTS_IN_CONFIRMATION = 2;
948
+ const isObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
949
+ const notNull = (value) => value !== null && value !== void 0 && value !== false;
950
+ function pick(r, keys) {
951
+ if (!isObject(r)) return void 0;
952
+ for (const key of keys) if (r[key] !== void 0 && r[key] !== null && r[key] !== "") return r[key];
953
+ return void 0;
954
+ }
955
+ const squeeze = (value) => typeof value === "string" ? value.toLowerCase().replace(/[^a-z]/g, "") : "";
956
+ const isStripeId = (value) => /^(?:cus|pm|card|src|pi|ch|cs|in)_[A-Za-z0-9]{6,}$/.test(value);
957
+ function moneyOf(value, divisor) {
958
+ if (typeof value === "number") return Number.isFinite(value) ? { amount: value / divisor } : {};
959
+ if (typeof value === "string") {
960
+ const { amount, currency } = readPriceText(value);
961
+ return { ...amount !== void 0 ? { amount: amount / divisor } : {}, ...currency ? { currency } : {} };
962
+ }
963
+ if (isObject(value)) {
964
+ const inner = moneyOf(pick(value, ["amount", "value", "unit_amount", "cents", "shop_money", "shopMoney", "price"]), divisor);
965
+ const currency = currencyCode(pick(value, ["currency", "currency_code", "currencyCode"])) ?? inner.currency;
966
+ return { ...inner.amount !== void 0 ? { amount: inner.amount } : {}, ...currency ? { currency } : {} };
967
+ }
968
+ return {};
969
+ }
970
+ function minorDivisor(currency) {
971
+ if (!currency) return 100;
972
+ try {
973
+ const digits = new Intl.NumberFormat("en", { style: "currency", currency }).resolvedOptions().maximumFractionDigits ?? 2;
974
+ return 10 ** digits;
975
+ } catch {
976
+ return 100;
977
+ }
978
+ }
979
+ const DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
980
+ const DATE_TIME = /^\d{4}-\d{2}-\d{2}[T ]\d{1,2}:\d{2}/;
981
+ function readWhen(value) {
982
+ if (typeof value === "string") {
983
+ const v = value.trim();
984
+ const day = DATE_ONLY.exec(v);
985
+ if (day) {
986
+ const date2 = new Date(Number(day[1]), Number(day[2]) - 1, Number(day[3]));
987
+ return date2.getMonth() === Number(day[2]) - 1 && date2.getDate() === Number(day[3]) ? { date: date2, allDay: true } : void 0;
988
+ }
989
+ if (!DATE_TIME.test(v)) return void 0;
990
+ const date = toDate(v.replace(" ", "T"));
991
+ return date ? { date, allDay: false } : void 0;
992
+ }
993
+ if (typeof value === "number" || value instanceof Date) {
994
+ const date = toDate(value);
995
+ if (!date) return void 0;
996
+ return { date, allDay: date.getHours() === 0 && date.getMinutes() === 0 && date.getSeconds() === 0 };
997
+ }
998
+ return void 0;
999
+ }
1000
+ const MIDNIGHT_UTC = /^(\d{4}-\d{2}-\d{2})T00:00(?::00(?:\.0+)?)?(?:Z|[+-]00:?00)$/i;
1001
+ function readDay(value) {
1002
+ const day = typeof value === "string" ? MIDNIGHT_UTC.exec(value.trim()) : null;
1003
+ return readWhen(day ? day[1] : value);
1004
+ }
1005
+ const TIME_OF_DAY = /^(\d{1,2}):(\d{2})(?::\d{2})?\s*(?:([ap])\.?\s?m\.?)?$/i;
1006
+ function dayAndTime(r) {
1007
+ const day = readDay(r["date"]);
1008
+ const time = typeof r["time"] === "string" ? TIME_OF_DAY.exec(r["time"].trim()) : null;
1009
+ if (!day || !time || !day.allDay) return day;
1010
+ let hours = Number(time[1]);
1011
+ const minutes = Number(time[2]);
1012
+ const half = time[3]?.toLowerCase();
1013
+ if (half) hours = hours % 12 + (half === "p" ? 12 : 0);
1014
+ if (hours > 23 || minutes > 59) return day;
1015
+ const date = new Date(day.date);
1016
+ date.setHours(hours, minutes, 0, 0);
1017
+ return { date, allDay: false };
1018
+ }
1019
+ const STATUS_WORDS = {
1020
+ pending: "pending",
1021
+ onhold: "pending",
1022
+ awaitingpayment: "pending",
1023
+ unpaid: "pending",
1024
+ open: "pending",
1025
+ requested: "pending",
1026
+ tentative: "pending",
1027
+ placed: "pending",
1028
+ orderpaymentdue: "pending",
1029
+ confirmed: "confirmed",
1030
+ paid: "confirmed",
1031
+ booked: "confirmed",
1032
+ reserved: "confirmed",
1033
+ accepted: "confirmed",
1034
+ // WooCommerce's `completed` is "fulfilled and complete": paid and done on the shop's side —
1035
+ // a download, a service, a parcel handed over or not. `delivered` would claim the parcel
1036
+ // arrived and `shipped` that there was one; `confirmed` claims neither, like Stripe's `complete`.
1037
+ complete: "confirmed",
1038
+ completed: "confirmed",
1039
+ succeeded: "confirmed",
1040
+ approved: "confirmed",
1041
+ processing: "processing",
1042
+ preparing: "processing",
1043
+ inprogress: "processing",
1044
+ packed: "processing",
1045
+ orderprocessing: "processing",
1046
+ shipped: "shipped",
1047
+ fulfilled: "shipped",
1048
+ intransit: "shipped",
1049
+ dispatched: "shipped",
1050
+ outfordelivery: "shipped",
1051
+ orderintransit: "shipped",
1052
+ delivered: "delivered",
1053
+ orderdelivered: "delivered",
1054
+ cancelled: "cancelled",
1055
+ canceled: "cancelled",
1056
+ voided: "cancelled",
1057
+ void: "cancelled",
1058
+ expired: "cancelled",
1059
+ ordercancelled: "cancelled",
1060
+ refunded: "refunded",
1061
+ orderreturned: "refunded",
1062
+ failed: "failed",
1063
+ declined: "failed",
1064
+ paymentfailed: "failed",
1065
+ rejected: "failed",
1066
+ orderproblem: "failed"
1067
+ };
1068
+ function readStatus(r) {
1069
+ const own = pick(r, ["status", "state", "order_status", "orderStatus", "booking_status", "bookingStatus"]);
1070
+ if (typeof own === "string" && own.trim()) {
1071
+ const key = squeeze(own.replace(/^https?:\/\/schema\.org\//, ""));
1072
+ const status = STATUS_WORDS[key];
1073
+ return status ? { status } : { text: own.trim() };
1074
+ }
1075
+ if (pick(r, ["cancelled_at", "canceled_at", "cancelledAt", "canceledAt"])) return { status: "cancelled" };
1076
+ const paid = squeeze(pick(r, ["financial_status", "financialStatus", "displayFinancialStatus"]));
1077
+ const sent = squeeze(pick(r, ["fulfillment_status", "fulfillmentStatus", "displayFulfillmentStatus"]));
1078
+ const stripe = squeeze(pick(r, ["payment_status", "paymentStatus"]));
1079
+ if (paid === "refunded") return { status: "refunded" };
1080
+ if (paid === "voided") return { status: "cancelled" };
1081
+ if (sent === "delivered") return { status: "delivered" };
1082
+ if (sent === "fulfilled") return { status: "shipped" };
1083
+ if (paid === "paid" || stripe === "paid") return { status: "confirmed" };
1084
+ if (paid === "pending" || stripe === "unpaid") return { status: "pending" };
1085
+ return void 0;
1086
+ }
1087
+ function listOf(value) {
1088
+ if (Array.isArray(value)) return value;
1089
+ if (!isObject(value)) return void 0;
1090
+ if (Array.isArray(value["data"])) return value["data"];
1091
+ if (Array.isArray(value["nodes"])) return value["nodes"];
1092
+ if (Array.isArray(value["edges"])) return value["edges"].map((e) => isObject(e) ? e["node"] : void 0);
1093
+ return void 0;
1094
+ }
1095
+ function readImage(value) {
1096
+ if (Array.isArray(value)) return value.length ? readImage(value[0]) : void 0;
1097
+ if (isObject(value)) {
1098
+ const src2 = webUrl(pick(value, ["src", "url", "href", "thumbnail"]));
1099
+ const alt = str(pick(value, ["alt", "altText", "alt_text"]));
1100
+ return src2 ? { src: src2, ...alt ? { alt } : {} } : void 0;
1101
+ }
1102
+ const src = webUrl(value);
1103
+ return src ? { src } : void 0;
1104
+ }
1105
+ function readSubtitle(r) {
1106
+ const value = pick(r, ["subtitle", "variant_title", "variantTitle", "variant", "variation", "options"]);
1107
+ if (Array.isArray(value)) {
1108
+ const parts = value.map((v) => isObject(v) ? str(pick(v, ["value", "name", "title"])) : str(v)).filter(notNull);
1109
+ return parts.length ? parts.join(" · ") : void 0;
1110
+ }
1111
+ return isObject(value) ? str(pick(value, ["title", "name"])) : str(value);
1112
+ }
1113
+ function readLine(raw, read) {
1114
+ if (typeof raw === "string") return raw.trim() ? { title: raw.trim(), quantity: 1 } : null;
1115
+ if (!isObject(raw)) return null;
1116
+ const title = str(pick(raw, ["title", "name", "description", "product_name", "productName", "label"]));
1117
+ if (!title) return null;
1118
+ const qty = num(pick(raw, ["quantity", "qty", "count"]));
1119
+ const quantity = qty !== void 0 && qty >= 0 ? qty : 1;
1120
+ const price = read(pick(raw, ["unit_price", "unitPrice", "price", "amount", "unit_amount"]));
1121
+ const given = read(pick(raw, ["subtotal", "amount_subtotal", "line_subtotal"])) ?? read(pick(raw, ["total", "total_price", "totalPrice", "amount_total", "line_total", "lineTotal"]));
1122
+ const total = given ?? (price !== void 0 ? price * quantity : void 0);
1123
+ const subtitle = readSubtitle(raw);
1124
+ const image = readImage(pick(raw, ["image", "image_url", "imageUrl", "thumbnail", "images", "photo", "picture"]));
1125
+ return {
1126
+ title,
1127
+ ...subtitle ? { subtitle } : {},
1128
+ ...image ? { image } : {},
1129
+ quantity,
1130
+ ...price !== void 0 ? { price } : {},
1131
+ ...total !== void 0 ? { total } : {}
1132
+ };
1133
+ }
1134
+ function readPayment(value) {
1135
+ if (Array.isArray(value)) {
1136
+ const parts = value.map(readPayment).filter(notNull);
1137
+ return parts.length ? parts.join(", ") : void 0;
1138
+ }
1139
+ if (isObject(value)) {
1140
+ const card = isObject(value["card"]) ? value["card"] : value;
1141
+ const brand = str(pick(card, ["brand", "network", "type"]));
1142
+ const last4 = str(pick(card, ["last4", "last_4", "lastFour", "last_digits"]));
1143
+ if (last4) return `${brand ? brand.charAt(0).toUpperCase() + brand.slice(1) : ""} •••• ${last4}`.trim();
1144
+ return str(pick(value, ["label", "title", "description", "name"])) ?? brand;
1145
+ }
1146
+ const text = str(value);
1147
+ return text && !isStripeId(text) ? text : void 0;
1148
+ }
1149
+ function nameOf(r) {
1150
+ const name = str(pick(r, ["name", "full_name", "fullName"]));
1151
+ if (name) return name;
1152
+ const parts = [pick(r, ["first_name", "firstName", "given_name"]), pick(r, ["last_name", "lastName", "family_name"])].map(str).filter(notNull);
1153
+ return parts.length ? parts.join(" ") : void 0;
1154
+ }
1155
+ const ADDRESS_KEYS = ["address1", "address_1", "line1", "street", "street1", "city", "postal_code", "postcode", "zip"];
1156
+ const CITY_FIRST = /* @__PURE__ */ new Set(["us", "usa", "unitedstates", "ca", "canada", "au", "australia", "gb", "uk", "unitedkingdom"]);
1157
+ function readAddress(value) {
1158
+ if (typeof value === "string") return value.trim() ? value.trim().replace(/\s*\n\s*/g, "\n") : void 0;
1159
+ if (!isObject(value)) return void 0;
1160
+ const inner = isObject(value["address"]) ? value["address"] : value;
1161
+ const s = (keys) => str(pick(inner, keys));
1162
+ const city = s(["city", "locality", "town"]);
1163
+ const postal = s(["zip", "postal_code", "postalCode", "postcode"]);
1164
+ const region = s(["province_code", "state", "province", "region"]);
1165
+ const country = s(["country", "country_code", "countryCode"]);
1166
+ const cityFirst = CITY_FIRST.has(squeeze(country));
1167
+ const locality = cityFirst ? [[city, region].filter(notNull).join(", "), postal].filter((p) => p).join(" ") : [postal, city].filter(notNull).join(" ");
1168
+ const lines = [
1169
+ nameOf(value) ?? nameOf(inner),
1170
+ s(["company"]),
1171
+ s(["address1", "address_1", "line1", "street", "street1"]),
1172
+ s(["address2", "address_2", "line2", "street2"]),
1173
+ locality || void 0,
1174
+ country
1175
+ ].filter(notNull);
1176
+ return lines.length ? lines.join("\n") : void 0;
1177
+ }
1178
+ function readCustomer(value) {
1179
+ if (typeof value === "string") return value.trim() && !isStripeId(value.trim()) ? value.trim() : void 0;
1180
+ if (!isObject(value)) return void 0;
1181
+ const lines = [nameOf(value), str(pick(value, ["email"])), str(pick(value, ["phone"]))].filter(notNull);
1182
+ return lines.length ? lines.join("\n") : void 0;
1183
+ }
1184
+ function readFacts(value) {
1185
+ const out = [];
1186
+ if (Array.isArray(value)) {
1187
+ for (const item of value) {
1188
+ const label = str(pick(item, ["label", "name", "key", "title"]));
1189
+ const fact = str(pick(item, ["value", "text"]));
1190
+ if (label && fact) out.push({ label, value: fact });
1191
+ }
1192
+ } else if (isObject(value)) {
1193
+ for (const [label, raw] of Object.entries(value)) {
1194
+ const fact = str(raw);
1195
+ if (label.trim() && fact) out.push({ label: label.trim(), value: fact });
1196
+ }
1197
+ }
1198
+ return out.slice(0, FACTS_KEPT);
1199
+ }
1200
+ function readEstimate(value) {
1201
+ if (Array.isArray(value)) value = { from: value[0], to: value[1] };
1202
+ if (isObject(value) && !(value instanceof Date)) {
1203
+ const from = readDay(pick(value, ["from", "start", "earliest", "min"]));
1204
+ const to = readDay(pick(value, ["to", "end", "latest", "max"]));
1205
+ if (from) return to && to.date > from.date ? { from, to } : { from };
1206
+ return to ? { from: to } : void 0;
1207
+ }
1208
+ const when = readDay(value);
1209
+ if (when) return { from: when };
1210
+ const text = str(value);
1211
+ return text ? { text } : void 0;
1212
+ }
1213
+ function readDelivery(r) {
1214
+ const fulfillments = listOf(r["fulfillments"]);
1215
+ const nested = [r["delivery"], r["shipment"], r["fulfillment"], fulfillments?.[0], r["tracking"]].find(isObject);
1216
+ const first = (value) => Array.isArray(value) ? value[0] : value;
1217
+ const estimate = readEstimate(
1218
+ pick(nested, ["estimate", "estimatedDelivery", "estimated_delivery", "eta", "expected", "expectedDate", "expected_date", "date"]) ?? pick(r, ["estimatedDelivery", "estimated_delivery", "deliveryEstimate", "delivery_estimate", "deliveryDate", "delivery_date", "eta"]) ?? (typeof r["delivery"] === "string" ? r["delivery"] : void 0)
1219
+ );
1220
+ const carrier = str(pick(nested, ["carrier", "company", "tracking_company", "trackingCompany", "service"]) ?? pick(r, ["carrier", "tracking_company", "trackingCompany", "shippingCarrier", "shipping_carrier"]));
1221
+ const trackingNumber = str(first(pick(nested, ["trackingNumber", "tracking_number", "tracking_numbers", "number"]) ?? pick(r, ["trackingNumber", "tracking_number"])));
1222
+ const trackingUrl = webUrl(first(pick(nested, ["trackingUrl", "tracking_url", "tracking_urls", "trackingLink", "tracking_link", "url"]) ?? pick(r, ["trackingUrl", "tracking_url", "trackingLink", "tracking_link"])));
1223
+ if (!estimate && !carrier && !trackingNumber && !trackingUrl) return void 0;
1224
+ return {
1225
+ ...estimate ? { estimate } : {},
1226
+ ...carrier ? { carrier } : {},
1227
+ ...trackingNumber ? { trackingNumber } : {},
1228
+ ...trackingUrl ? { trackingUrl } : {}
1229
+ };
1230
+ }
1231
+ const START_KEYS = ["start", "startTime", "start_time", "startDate", "start_date", "checkIn", "check_in", "checkin", "from", "datetime", "dateTime", "time"];
1232
+ const END_KEYS = ["end", "endTime", "end_time", "endDate", "end_date", "checkOut", "check_out", "checkout", "to", "until"];
1233
+ function readBooking(r) {
1234
+ const b = [r["booking"], r["reservation"]].find(isObject) ?? r;
1235
+ const own = readDay(pick(b, START_KEYS));
1236
+ const fromDate = own ? void 0 : dayAndTime(b);
1237
+ const start = own ?? fromDate;
1238
+ const tookDate = fromDate !== void 0 && b === r;
1239
+ const endRead = readDay(pick(b, END_KEYS));
1240
+ const end = endRead && (!start || endRead.date >= start.date) ? endRead : void 0;
1241
+ const place = pick(b, ["location", "venue", "place", "address", "where"]);
1242
+ const location = isObject(place) ? [str(pick(place, ["name", "title"])), str(pick(place, ["address", "formatted_address"]))].filter(notNull).join(", ") || void 0 : str(place);
1243
+ const people = pick(b, ["guests", "partySize", "party_size", "people", "persons", "covers", "attendees"]);
1244
+ const count = Array.isArray(people) ? people.length : num(people);
1245
+ const guests = count !== void 0 && count > 0 ? Math.floor(count) : void 0;
1246
+ if (!start && !location && guests === void 0) return { booking: void 0, tookDate };
1247
+ return {
1248
+ booking: {
1249
+ ...start ? { start } : {},
1250
+ ...end ? { end } : {},
1251
+ ...location ? { location } : {},
1252
+ ...guests !== void 0 ? { guests } : {}
1253
+ },
1254
+ tookDate
1255
+ };
1256
+ }
1257
+ function readKind(r) {
1258
+ const said = squeeze(pick(r, ["kind", "type", "object"]));
1259
+ if (["booking", "reservation", "appointment", "lodgingreservation", "foodestablishmentreservation", "eventreservation"].includes(said)) return "booking";
1260
+ if (["order", "purchase", "checkoutsession"].includes(said)) return "order";
1261
+ if (isObject(r["booking"]) || isObject(r["reservation"])) return "booking";
1262
+ return pick(r, ["checkIn", "check_in", "startTime", "start_time", "startDate", "start_date"]) !== void 0 ? "booking" : "order";
1263
+ }
1264
+ function readOrder(raw) {
1265
+ if (!isObject(raw)) return null;
1266
+ const r = raw;
1267
+ const kind = readKind(r);
1268
+ const minor = r["minorUnits"] === true || r["minor_units"] === true;
1269
+ let currency = currencyCode(pick(r, ["currency", "currency_code", "currencyCode", "presentment_currency"]));
1270
+ const divisor = minor ? minorDivisor(currency) : 1;
1271
+ const read = (value) => {
1272
+ const money2 = moneyOf(value, divisor);
1273
+ currency ??= money2.currency;
1274
+ return money2.amount;
1275
+ };
1276
+ const amount = (from, keys) => {
1277
+ if (!isObject(from)) return void 0;
1278
+ for (const key of keys) {
1279
+ const value = from[key] === void 0 || from[key] === null ? void 0 : read(from[key]);
1280
+ if (value !== void 0) return value;
1281
+ }
1282
+ return void 0;
1283
+ };
1284
+ const all = (["items", "line_items", "lineItems", "products", "lines"].map((key) => listOf(r[key])).find(notNull) ?? []).map((line) => readLine(line, read)).filter(notNull);
1285
+ const items = all.slice(0, LINES_KEPT);
1286
+ const details = isObject(r["total_details"]) ? r["total_details"] : void 0;
1287
+ const shippingLines = listOf(r["shipping_lines"]);
1288
+ let subtotal = amount(r, ["subtotal", "sub_total", "subtotal_price", "subtotalPrice", "amount_subtotal", "items_total", "itemsTotal"]);
1289
+ const discountRaw = amount(r, ["discount", "total_discount", "total_discounts", "totalDiscounts", "discount_total", "discountTotal"]) ?? amount(details, ["amount_discount"]);
1290
+ let shipping = amount(r, ["shipping", "shipping_total", "shippingTotal", "shipping_cost", "shippingCost", "shipping_price", "shippingPrice", "total_shipping", "delivery_fee", "deliveryFee"]) ?? amount(details, ["amount_shipping"]) ?? amount(r["shipping_cost"], ["amount_total"]);
1291
+ if (shipping === void 0 && shippingLines?.length) {
1292
+ const costs = shippingLines.map((l) => amount(l, ["price", "amount"])).filter(notNull);
1293
+ if (costs.length) shipping = costs.reduce((a, b) => a + b, 0);
1294
+ }
1295
+ const tax = amount(r, ["tax", "taxes", "total_tax", "totalTax", "tax_total", "taxTotal", "vat"]) ?? amount(details, ["amount_tax"]);
1296
+ let total = amount(r, ["total", "total_price", "totalPrice", "amount_total", "amountTotal", "grand_total", "grandTotal", "amount"]);
1297
+ const bought = all.filter((l) => l.quantity !== 0);
1298
+ if (subtotal === void 0 && bought.length && bought.every((l) => l.total !== void 0)) {
1299
+ subtotal = bought.reduce((sum, l) => sum + l.total, 0);
1300
+ }
1301
+ const discount = discountRaw !== void 0 ? Math.abs(discountRaw) : void 0;
1302
+ if (total === void 0 && subtotal !== void 0) total = subtotal - (discount ?? 0) + (shipping ?? 0) + (tax ?? 0);
1303
+ const reference = str(pick(r, [
1304
+ "reference",
1305
+ "order_number",
1306
+ "orderNumber",
1307
+ "number",
1308
+ "confirmation_number",
1309
+ "confirmationNumber",
1310
+ "confirmation_code",
1311
+ "confirmationCode",
1312
+ "booking_reference",
1313
+ "bookingReference",
1314
+ "booking_id",
1315
+ "bookingId",
1316
+ "order_id",
1317
+ "orderId",
1318
+ "id"
1319
+ ]))?.replace(/^#\s*/, "") || void 0;
1320
+ const title = str(pick(r, ["title", "heading"]));
1321
+ const ownHeadline = str(r["headline"]);
1322
+ const status = readStatus(r);
1323
+ const { booking, tookDate } = kind === "booking" ? readBooking(r) : { booking: void 0, tookDate: false };
1324
+ const placedKeys = ["date", "created_at", "createdAt", "placed_at", "placedAt", "order_date", "orderDate", "date_created", "dateCreated", "processed_at", "created"];
1325
+ const date = readWhen(pick(r, tookDate ? placedKeys.slice(1) : placedKeys))?.date;
1326
+ const delivery = readDelivery(r);
1327
+ const payment = readPayment(pick(r, ["payment", "paymentMethod", "payment_method", "payment_method_title", "paymentMethodTitle", "payment_method_details", "card", "payment_gateway_names"]));
1328
+ const customer = readCustomer(pick(r, ["customer_details", "customerDetails", "customer", "customer_name", "customerName", "buyer", "contact"]));
1329
+ const shippingAddress = kind === "order" ? readAddress(pick(r, ["shippingAddress", "shipping_address", "shipping_details", "shippingDetails", "deliveryAddress", "delivery_address", "address"]) ?? (isObject(r["shipping"]) && ADDRESS_KEYS.some((k) => k in r["shipping"]) ? r["shipping"] : void 0)) : void 0;
1330
+ const url = webUrl(pick(r, ["url", "orderUrl", "order_url", "order_status_url", "orderStatusUrl", "statusUrl", "status_url", "receipt_url", "receiptUrl", "manageUrl", "manage_url", "link", "href"]));
1331
+ if (!items.length && !reference && total === void 0 && !booking && !title) return null;
1332
+ const whole = all.every((l) => Number.isInteger(l.quantity));
1333
+ return {
1334
+ kind,
1335
+ ...title ? { title } : {},
1336
+ ...ownHeadline ? { headline: ownHeadline } : {},
1337
+ ...reference ? { reference } : {},
1338
+ ...status ? { status } : {},
1339
+ ...date ? { date } : {},
1340
+ items,
1341
+ lineCount: all.length,
1342
+ itemCount: whole ? all.reduce((n, l) => n + l.quantity, 0) : all.length,
1343
+ ...currency ? { currency } : {},
1344
+ ...subtotal !== void 0 ? { subtotal } : {},
1345
+ ...discount !== void 0 ? { discount } : {},
1346
+ ...shipping !== void 0 ? { shipping } : {},
1347
+ ...tax !== void 0 ? { tax } : {},
1348
+ ...total !== void 0 ? { total } : {},
1349
+ ...payment ? { payment } : {},
1350
+ ...customer ? { customer } : {},
1351
+ ...shippingAddress ? { shippingAddress } : {},
1352
+ ...delivery ? { delivery } : {},
1353
+ facts: readFacts(pick(r, ["facts", "details", "extra", "extras", "note_attributes"])),
1354
+ ...booking ? { booking } : {},
1355
+ ...url ? { url } : {}
1356
+ };
1357
+ }
1358
+ const say = (config, key, vars) => word(config, key, P[key], vars);
1359
+ const money = (config, data, amount) => formatPrice(config, amount, data.currency);
1360
+ function counted(config, one, other, n) {
1361
+ const rule = new Intl.PluralRules(intlTag(config)).select(n);
1362
+ return say(config, rule === "one" ? one : other, { n: formatNumber(config, n) });
1363
+ }
1364
+ const shownReference = (reference) => /^\d+$/.test(reference) ? `#${reference}` : reference;
1365
+ function headText(config, data, hash) {
1366
+ if (data?.title) return data.title;
1367
+ const booking = data?.kind === "booking";
1368
+ if (data?.reference) {
1369
+ const reference = hash ? shownReference(data.reference) : data.reference;
1370
+ return say(config, booking ? "cardsOrderBookingNumbered" : "cardsOrderNumbered", { reference });
1371
+ }
1372
+ return say(config, booking ? "cardsOrderBooking" : "cardsOrderOrder");
1373
+ }
1374
+ function statusWord(config, data) {
1375
+ const status = data.status;
1376
+ if (!status) return "";
1377
+ if ("text" in status) return status.text;
1378
+ const own = `cardsOrderBookingStatus_${status.status}`;
1379
+ const key = data.kind === "booking" && own in P ? own : `cardsOrderStatus_${status.status}`;
1380
+ return say(config, key);
1381
+ }
1382
+ function headline(config, data) {
1383
+ if (data.headline) return data.headline;
1384
+ const status = data.status && "status" in data.status ? data.status.status : "confirmed";
1385
+ if (data.kind !== "booking") return say(config, `cardsOrderHeadline_${status}`);
1386
+ const own = BOOKING_HEADLINE[status] ?? status;
1387
+ return say(config, `cardsOrderBookingHeadline_${own}`);
1388
+ }
1389
+ const dateFormat = (config, options) => new Intl.DateTimeFormat(intlTag(config), options);
1390
+ const placedOn = (config, date) => dateFormat(config, { dateStyle: "medium" }).format(date);
1391
+ function dayOptions(date, now = /* @__PURE__ */ new Date()) {
1392
+ return { weekday: "short", day: "numeric", month: "short", ...date.getFullYear() !== now.getFullYear() ? { year: "numeric" } : {} };
1393
+ }
1394
+ const TIME = { hour: "numeric", minute: "2-digit" };
1395
+ function range(format, from, to) {
1396
+ return typeof format.formatRange === "function" ? format.formatRange(from, to) : `${format.format(from)} – ${format.format(to)}`;
1397
+ }
1398
+ function whenText(config, from, to) {
1399
+ const timed = !from.allDay || to !== void 0 && !to.allDay;
1400
+ const format = dateFormat(config, { ...dayOptions(from.date), ...timed ? TIME : {} });
1401
+ return to && to.date.getTime() !== from.date.getTime() ? range(format, from.date, to.date) : format.format(from.date);
1402
+ }
1403
+ const startOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
1404
+ function nightsOf(from, to) {
1405
+ return Math.max(0, Math.round((startOfDay(to) - startOfDay(from)) / 864e5));
1406
+ }
1407
+ const sr = (ctx, key) => {
1408
+ const node = el("span", { class: "aparte-sr-only" });
1409
+ ctx.word(node, key, P[key]);
1410
+ return node;
1411
+ };
1412
+ const bound = (ctx, tag, className, compute) => {
1413
+ const node = el(tag, { class: className });
1414
+ ctx.bind(node, compute);
1415
+ return node;
1416
+ };
1417
+ function kindGlyph(data) {
1418
+ return glyph(data?.kind === "booking" ? CALENDAR : BAG, "aparte-rich-card__glyph aparte-order__kind");
1419
+ }
1420
+ function statusPill(ctx, data) {
1421
+ if (!data.status) return null;
1422
+ const status = "status" in data.status ? data.status.status : void 0;
1423
+ const pill = el("span", {
1424
+ class: `aparte-badge aparte-badge--${status ? INTENT[status] : "neutral"} aparte-badge--sm aparte-order__status`,
1425
+ attrs: { "data-status": status ?? "other" }
1426
+ }, el("span", { class: "aparte-order__status-dot", attrs: { "aria-hidden": "true" } }));
1427
+ pill.append(bound(ctx, "span", "aparte-order__status-text", () => statusWord(ctx.config, data)));
1428
+ return pill;
1429
+ }
1430
+ function viewButton(ctx, data, primary = false) {
1431
+ if (!data.url) return null;
1432
+ const key = data.kind === "booking" ? "cardsOrderViewBooking" : "cardsOrderView";
1433
+ const button = ctx.action({ label: say(ctx.config, key), url: data.url, id: "view", primary }, data, "aparte-order__view");
1434
+ if (button) ctx.word(button, key, P[key]);
1435
+ return button;
1436
+ }
1437
+ function trackButton(ctx, data) {
1438
+ const url = data.delivery?.trackingUrl;
1439
+ if (!url) return null;
1440
+ const button = ctx.action({ label: say(ctx.config, "cardsOrderTrack"), url, id: "track" }, data, "aparte-order__track");
1441
+ if (button) ctx.word(button, "cardsOrderTrack", P.cardsOrderTrack);
1442
+ return button;
1443
+ }
1444
+ function header(ctx, data) {
1445
+ const heading = el(
1446
+ "div",
1447
+ { class: "aparte-order__heading" },
1448
+ bound(ctx, "div", "aparte-order__title", () => headText(ctx.config, data, true))
1449
+ );
1450
+ if (data.date) {
1451
+ const date = data.date;
1452
+ const time = el("time", { class: "aparte-order__date", attrs: { datetime: date.toISOString() } });
1453
+ ctx.bind(time, () => say(ctx.config, data.kind === "booking" ? "cardsOrderBooked" : "cardsOrderPlaced", { date: placedOn(ctx.config, date) }));
1454
+ heading.append(time);
1455
+ }
1456
+ return el("div", { class: "aparte-order__head" }, kindGlyph(data), heading, statusPill(ctx, data));
1457
+ }
1458
+ function thumb(line) {
1459
+ const frame = el("div", { class: "aparte-order__thumb" }, glyph(BOX, "aparte-rich-card__glyph aparte-order__thumb-glyph"));
1460
+ if (!line.image) {
1461
+ frame.setAttribute("data-empty", "");
1462
+ return frame;
1463
+ }
1464
+ const image = el("img", {
1465
+ class: "aparte-order__image",
1466
+ attrs: { src: line.image.src, alt: line.image.alt ?? line.title, loading: "lazy", decoding: "async", referrerpolicy: "no-referrer" }
1467
+ });
1468
+ image.addEventListener("error", () => {
1469
+ image.hidden = true;
1470
+ frame.setAttribute("data-empty", "");
1471
+ }, { once: true });
1472
+ frame.append(image);
1473
+ return frame;
1474
+ }
1475
+ function lineNode(ctx, data, line, thumbs) {
1476
+ const meta = el(
1477
+ "div",
1478
+ { class: "aparte-order__line-meta" },
1479
+ line.subtitle ? el("span", { class: "aparte-order__line-variant", text: line.subtitle }) : null,
1480
+ line.quantity !== 1 && line.price !== void 0 ? bound(ctx, "span", "aparte-order__line-each", () => say(ctx.config, "cardsOrderEach", { price: money(ctx.config, data, line.price) })) : null
1481
+ );
1482
+ return el(
1483
+ "li",
1484
+ { class: "aparte-order__line" },
1485
+ thumbs ? thumb(line) : null,
1486
+ el(
1487
+ "div",
1488
+ { class: "aparte-order__line-main" },
1489
+ el("div", { class: "aparte-order__line-title", text: line.title }),
1490
+ meta.childNodes.length ? meta : null
1491
+ ),
1492
+ line.quantity !== 1 ? bound(ctx, "span", "aparte-order__qty", () => `× ${formatNumber(ctx.config, line.quantity)}`) : null,
1493
+ line.total !== void 0 ? bound(ctx, "span", "aparte-order__line-total", () => money(ctx.config, data, line.total)) : null
1494
+ );
1495
+ }
1496
+ function linesBlock(ctx, data) {
1497
+ if (!data.items.length) return null;
1498
+ const thumbs = data.items.some((l) => l.image);
1499
+ const list = (lines) => {
1500
+ const ul = el(
1501
+ "ul",
1502
+ { class: "aparte-order__lines", attrs: { role: "list", "data-thumbs": thumbs } },
1503
+ ...lines.map((line) => lineNode(ctx, data, line, thumbs))
1504
+ );
1505
+ ctx.bind(ul, () => say(ctx.config, "cardsOrderLines"), "aria-label");
1506
+ return ul;
1507
+ };
1508
+ const block = el("div", { class: "aparte-order__section aparte-order__items" }, list(data.items.slice(0, LINES_SHOWN)));
1509
+ const hidden = data.lineCount - LINES_SHOWN;
1510
+ if (hidden > 0) {
1511
+ const summary = el(
1512
+ "summary",
1513
+ { class: "aparte-order__more-toggle" },
1514
+ glyph(CHEVRON, "aparte-rich-card__glyph aparte-order__more-chevron"),
1515
+ bound(ctx, "span", "aparte-order__more-text", () => say(ctx.config, "cardsOrderMore", { n: formatNumber(ctx.config, hidden) }))
1516
+ );
1517
+ const more = el("details", { class: "aparte-order__more" }, summary, list(data.items.slice(LINES_SHOWN)));
1518
+ const dropped = data.lineCount - data.items.length;
1519
+ if (dropped > 0) more.append(bound(ctx, "div", "aparte-order__dropped", () => say(ctx.config, "cardsOrderMore", { n: formatNumber(ctx.config, dropped) })));
1520
+ block.append(more);
1521
+ }
1522
+ return block;
1523
+ }
1524
+ function sumRow(ctx, key, value, kind) {
1525
+ return el(
1526
+ "div",
1527
+ { class: `aparte-order__sum aparte-order__sum--${kind}` },
1528
+ bound(ctx, "dt", "aparte-order__sum-label", () => say(ctx.config, key)),
1529
+ bound(ctx, "dd", "aparte-order__sum-value", value)
1530
+ );
1531
+ }
1532
+ function totalsBlock(ctx, data) {
1533
+ const { config } = ctx;
1534
+ const between = data.discount !== void 0 || data.shipping !== void 0 || data.tax !== void 0;
1535
+ const rows = [
1536
+ data.subtotal !== void 0 && between ? sumRow(ctx, "cardsOrderSubtotal", () => money(config, data, data.subtotal), "subtotal") : null,
1537
+ data.discount ? sumRow(ctx, "cardsOrderDiscount", () => `−${money(config, data, data.discount)}`, "discount") : null,
1538
+ data.shipping !== void 0 ? sumRow(ctx, "cardsOrderShipping", () => data.shipping === 0 ? say(config, "cardsOrderFree") : money(config, data, data.shipping), data.shipping === 0 ? "free" : "shipping") : null,
1539
+ data.tax !== void 0 ? sumRow(ctx, "cardsOrderTax", () => money(config, data, data.tax), "tax") : null,
1540
+ data.total !== void 0 ? sumRow(ctx, "cardsOrderTotal", () => money(config, data, data.total), "total") : null
1541
+ ].filter(notNull);
1542
+ return rows.length ? el("dl", { class: "aparte-order__section aparte-order__totals" }, ...rows) : null;
1543
+ }
1544
+ function infoRow(ctx, icon, label, ...value) {
1545
+ const dt = el("dt", { class: "aparte-order__info-label" }, glyph(icon, "aparte-rich-card__glyph aparte-order__info-glyph"));
1546
+ dt.append(bound(ctx, "span", "aparte-order__info-label-text", label));
1547
+ return el("div", { class: "aparte-order__info" }, dt, el("dd", { class: "aparte-order__info-value" }, ...value));
1548
+ }
1549
+ function estimateText(config, estimate) {
1550
+ if ("text" in estimate) return estimate.text;
1551
+ const format = dateFormat(config, dayOptions(estimate.from.date));
1552
+ return estimate.to ? range(format, estimate.from.date, estimate.to.date) : format.format(estimate.from.date);
1553
+ }
1554
+ function deliveryRow(ctx, data) {
1555
+ const delivery = data.delivery;
1556
+ if (!delivery) return null;
1557
+ const estimate = delivery.estimate;
1558
+ const carrier = [delivery.carrier, delivery.trackingNumber].filter(notNull).join(" · ");
1559
+ const text = el(
1560
+ "div",
1561
+ { class: "aparte-order__delivery-text" },
1562
+ estimate ? bound(ctx, "div", "aparte-order__estimate", () => estimateText(ctx.config, estimate)) : null,
1563
+ carrier ? el("div", { class: "aparte-order__carrier", text: carrier }) : null
1564
+ );
1565
+ return infoRow(ctx, TRUCK, () => say(ctx.config, "cardsOrderDelivery"), text, trackButton(ctx, data));
1566
+ }
1567
+ function infoBlock(ctx, data) {
1568
+ const text = (value, className = "") => el("span", { class: `aparte-order__info-text${className ? ` ${className}` : ""}`, text: value });
1569
+ const rows = [
1570
+ data.payment ? infoRow(ctx, CARD, () => say(ctx.config, "cardsOrderPayment"), text(data.payment)) : null,
1571
+ deliveryRow(ctx, data),
1572
+ data.shippingAddress ? infoRow(ctx, HOUSE, () => say(ctx.config, "cardsOrderAddress"), text(data.shippingAddress, "aparte-order__multiline")) : null,
1573
+ data.customer ? infoRow(ctx, PERSON, () => say(ctx.config, "cardsOrderCustomer"), text(data.customer, "aparte-order__multiline")) : null,
1574
+ ...data.facts.map((fact) => infoRow(ctx, INFO, () => fact.label, text(fact.value)))
1575
+ ].filter(notNull);
1576
+ return rows.length ? el("dl", { class: "aparte-order__section aparte-order__infos" }, ...rows) : null;
1577
+ }
1578
+ function leaf(ctx, when) {
1579
+ const node = el(
1580
+ "time",
1581
+ { class: "aparte-order__leaf", attrs: { datetime: when.date.toISOString() } },
1582
+ bound(ctx, "span", "aparte-order__leaf-month", () => dateFormat(ctx.config, { month: "short" }).format(when.date)),
1583
+ bound(ctx, "span", "aparte-order__leaf-day", () => dateFormat(ctx.config, { day: "numeric" }).format(when.date)),
1584
+ bound(ctx, "span", "aparte-order__leaf-weekday", () => dateFormat(ctx.config, { weekday: "short" }).format(when.date))
1585
+ );
1586
+ return node;
1587
+ }
1588
+ function bookingBlock(ctx, data) {
1589
+ const booking = data.booking;
1590
+ if (!booking) return null;
1591
+ const { config } = ctx;
1592
+ const out = el("div", { class: "aparte-order__section aparte-order__booking" });
1593
+ const { start, end } = booking;
1594
+ if (start) {
1595
+ const multiDay = end !== void 0 && nightsOf(start.date, end.date) > 0;
1596
+ if (multiDay) {
1597
+ const nights = nightsOf(start.date, end.date);
1598
+ const side = (when, key) => el(
1599
+ "div",
1600
+ { class: "aparte-order__stay-side" },
1601
+ sr(ctx, key),
1602
+ leaf(ctx, when),
1603
+ when.allDay ? null : bound(ctx, "span", "aparte-order__stay-time", () => dateFormat(config, TIME).format(when.date))
1604
+ );
1605
+ out.append(el(
1606
+ "div",
1607
+ { class: "aparte-order__stay" },
1608
+ side(start, "cardsOrderStart"),
1609
+ el(
1610
+ "div",
1611
+ { class: "aparte-order__stay-span" },
1612
+ glyph(ARROW, "aparte-rich-card__glyph aparte-order__stay-arrow"),
1613
+ bound(ctx, "span", "aparte-order__nights", () => counted(config, "cardsOrderNight", "cardsOrderNights", nights))
1614
+ ),
1615
+ side(end, "cardsOrderEnd")
1616
+ ));
1617
+ } else {
1618
+ const hours = start.allDay ? null : bound(ctx, "span", "aparte-order__day-hours", () => end && !end.allDay && end.date > start.date ? range(dateFormat(config, TIME), start.date, end.date) : dateFormat(config, TIME).format(start.date));
1619
+ out.append(el(
1620
+ "div",
1621
+ { class: "aparte-order__day" },
1622
+ leaf(ctx, start),
1623
+ el(
1624
+ "div",
1625
+ { class: "aparte-order__day-text" },
1626
+ bound(ctx, "span", "aparte-order__day-name", () => {
1627
+ const text = dateFormat(config, { weekday: "long", day: "numeric", month: "long", ...start.date.getFullYear() !== (/* @__PURE__ */ new Date()).getFullYear() ? { year: "numeric" } : {} }).format(start.date);
1628
+ return text.charAt(0).toLocaleUpperCase(intlTag(config)) + text.slice(1);
1629
+ }),
1630
+ hours
1631
+ )
1632
+ ));
1633
+ }
1634
+ }
1635
+ const facts = [
1636
+ booking.location ? el(
1637
+ "div",
1638
+ { class: "aparte-order__place" },
1639
+ el("dt", { class: "aparte-order__place-label" }, glyph(PIN, "aparte-rich-card__glyph aparte-order__info-glyph"), sr(ctx, "cardsOrderWhere")),
1640
+ el("dd", { class: "aparte-order__place-value", text: booking.location })
1641
+ ) : null,
1642
+ booking.guests !== void 0 ? el(
1643
+ "div",
1644
+ { class: "aparte-order__place" },
1645
+ el("dt", { class: "aparte-order__place-label" }, glyph(PEOPLE, "aparte-rich-card__glyph aparte-order__info-glyph"), sr(ctx, "cardsOrderGuestsLabel")),
1646
+ bound(ctx, "dd", "aparte-order__place-value", () => counted(config, "cardsOrderGuest", "cardsOrderGuests", booking.guests))
1647
+ ) : null
1648
+ ].filter(notNull);
1649
+ if (facts.length) out.append(el("dl", { class: "aparte-order__places" }, ...facts));
1650
+ return out.childNodes.length ? out : null;
1651
+ }
1652
+ function receipt(ctx, data) {
1653
+ const view = viewButton(ctx, data);
1654
+ return [
1655
+ header(ctx, data),
1656
+ bookingBlock(ctx, data),
1657
+ linesBlock(ctx, data),
1658
+ totalsBlock(ctx, data),
1659
+ infoBlock(ctx, data),
1660
+ view ? el("div", { class: "aparte-order__foot" }, view) : null
1661
+ ].filter(notNull);
1662
+ }
1663
+ function summaryParts(ctx, data) {
1664
+ const { config } = ctx;
1665
+ const part = (compute) => bound(ctx, "span", "aparte-order__row-part", compute);
1666
+ const booking = data.booking;
1667
+ return [
1668
+ booking?.start ? part(() => whenText(config, booking.start, booking.end)) : null,
1669
+ booking?.guests !== void 0 ? part(() => counted(config, "cardsOrderGuest", "cardsOrderGuests", booking.guests)) : null,
1670
+ data.itemCount > 0 ? part(() => counted(config, "cardsOrderItem", "cardsOrderItems", data.itemCount)) : null,
1671
+ data.total !== void 0 ? part(() => money(config, data, data.total)) : null
1672
+ ].filter(notNull);
1673
+ }
1674
+ function compact(ctx, data) {
1675
+ const title = el("div", { class: "aparte-order__title" });
1676
+ if (data.url) {
1677
+ const link = el("a", { class: "aparte-order__link", attrs: { href: data.url, target: "_blank", rel: "noopener noreferrer" } });
1678
+ ctx.bind(link, () => headText(ctx.config, data, true));
1679
+ title.append(link);
1680
+ } else {
1681
+ ctx.bind(title, () => headText(ctx.config, data, true));
1682
+ }
1683
+ const parts = summaryParts(ctx, data);
1684
+ return [el(
1685
+ "div",
1686
+ { class: "aparte-order__row", attrs: { "data-linked": data.url !== void 0 } },
1687
+ kindGlyph(data),
1688
+ el("div", { class: "aparte-order__row-main" }, title, parts.length ? el("div", { class: "aparte-order__row-meta" }, ...parts) : null),
1689
+ statusPill(ctx, data),
1690
+ data.url ? glyph(CHEVRON, "aparte-rich-card__glyph aparte-order__chevron") : null
1691
+ )];
1692
+ }
1693
+ function keyFact(ctx, key, value, kind, note) {
1694
+ const label = typeof key === "function" ? key : () => say(ctx.config, key);
1695
+ return el(
1696
+ "div",
1697
+ { class: `aparte-order__keyfact aparte-order__keyfact--${kind}` },
1698
+ bound(ctx, "dt", "aparte-order__keyfact-label", label),
1699
+ el(
1700
+ "dd",
1701
+ { class: "aparte-order__keyfact-value" },
1702
+ bound(ctx, "span", "aparte-order__keyfact-text", value),
1703
+ note ? bound(ctx, "span", "aparte-order__keyfact-note", note) : null
1704
+ )
1705
+ );
1706
+ }
1707
+ function confirmation(ctx, data) {
1708
+ const { config } = ctx;
1709
+ const status = data.status && "status" in data.status ? data.status.status : void 0;
1710
+ const tone = status ? TONE[status] : "success";
1711
+ const sub = [
1712
+ data.title && data.reference ? data.title : null,
1713
+ data.reference ? shownReference(data.reference) : data.title ?? null
1714
+ ].filter(notNull);
1715
+ const booking = data.booking;
1716
+ const estimate = data.delivery?.estimate;
1717
+ const facts = [
1718
+ data.total !== void 0 ? keyFact(
1719
+ ctx,
1720
+ "cardsOrderTotal",
1721
+ () => money(config, data, data.total),
1722
+ "total",
1723
+ data.itemCount > 0 ? () => counted(config, "cardsOrderItem", "cardsOrderItems", data.itemCount) : void 0
1724
+ ) : null,
1725
+ estimate ? keyFact(ctx, "cardsOrderDelivery", () => estimateText(config, estimate), "delivery", data.delivery?.carrier ? () => data.delivery.carrier : void 0) : null,
1726
+ booking?.start ? keyFact(
1727
+ ctx,
1728
+ "cardsOrderWhen",
1729
+ () => whenText(config, booking.start, booking.end),
1730
+ "when",
1731
+ booking.end && nightsOf(booking.start.date, booking.end.date) > 0 ? () => counted(config, "cardsOrderNight", "cardsOrderNights", nightsOf(booking.start.date, booking.end.date)) : void 0
1732
+ ) : null,
1733
+ booking?.location ? keyFact(ctx, "cardsOrderWhere", () => booking.location, "where") : null,
1734
+ booking?.guests !== void 0 ? keyFact(ctx, "cardsOrderGuestsLabel", () => counted(config, "cardsOrderGuest", "cardsOrderGuests", booking.guests), "guests") : null,
1735
+ ...data.facts.slice(0, FACTS_IN_CONFIRMATION).map((fact) => keyFact(ctx, () => fact.label, () => fact.value, "own"))
1736
+ ].filter(notNull);
1737
+ const buttons = [viewButton(ctx, data, true), trackButton(ctx, data)].filter(notNull);
1738
+ const free = data.status && "text" in data.status ? statusPill(ctx, data) : null;
1739
+ return [el(
1740
+ "div",
1741
+ { class: "aparte-order__confirm", attrs: { "data-tone": tone } },
1742
+ glyph(seal(tone), "aparte-order__seal"),
1743
+ bound(ctx, "div", "aparte-order__headline", () => headline(config, data)),
1744
+ sub.length ? el("div", { class: "aparte-order__ref", text: sub.join(" · ") }) : null,
1745
+ free,
1746
+ facts.length ? el("dl", { class: "aparte-order__keyfacts" }, ...facts) : null,
1747
+ buttons.length ? el("div", { class: "aparte-order__confirm-actions" }, ...buttons) : null
1748
+ )];
1749
+ }
1750
+ function render(data, ctx) {
1751
+ if (ctx.variant === "compact") return compact(ctx, data);
1752
+ if (ctx.variant === "confirmation") return confirmation(ctx, data);
1753
+ return receipt(ctx, data);
1754
+ }
1755
+ function skeleton(partial, ctx) {
1756
+ const block = (cls, kind = "text") => el("span", { class: `aparte-skeleton aparte-skeleton--${kind} ${cls}`, attrs: { "aria-hidden": "true" } });
1757
+ const name = partial?.reference || partial?.title ? bound(ctx, "div", "aparte-order__title", () => headText(ctx.config, partial, true)) : block("aparte-order__sk-title");
1758
+ if (ctx.variant === "compact") {
1759
+ return [el(
1760
+ "div",
1761
+ { class: "aparte-order__row" },
1762
+ kindGlyph(partial),
1763
+ el("div", { class: "aparte-order__row-main" }, name, block("aparte-order__sk-meta")),
1764
+ block("aparte-order__sk-pill", "rect")
1765
+ )];
1766
+ }
1767
+ if (ctx.variant === "confirmation") {
1768
+ return [el(
1769
+ "div",
1770
+ { class: "aparte-order__confirm aparte-order__confirm--skeleton" },
1771
+ block("aparte-order__sk-seal", "circle"),
1772
+ block("aparte-order__sk-headline"),
1773
+ partial?.reference ? el("div", { class: "aparte-order__ref", text: shownReference(partial.reference) }) : block("aparte-order__sk-ref"),
1774
+ el("div", { class: "aparte-order__keyfacts" }, block("aparte-order__sk-fact", "rect"), block("aparte-order__sk-fact", "rect"))
1775
+ )];
1776
+ }
1777
+ const line = () => el(
1778
+ "div",
1779
+ { class: "aparte-order__line aparte-order__line--skeleton" },
1780
+ block("aparte-order__sk-thumb", "rect"),
1781
+ el("div", { class: "aparte-order__line-main" }, block("aparte-order__sk-line"), block("aparte-order__sk-line aparte-order__sk-line--short")),
1782
+ block("aparte-order__sk-price")
1783
+ );
1784
+ return [
1785
+ el(
1786
+ "div",
1787
+ { class: "aparte-order__head" },
1788
+ kindGlyph(partial),
1789
+ el("div", { class: "aparte-order__heading" }, name, block("aparte-order__sk-date")),
1790
+ block("aparte-order__sk-pill", "rect")
1791
+ ),
1792
+ el("div", { class: "aparte-order__section aparte-order__items" }, el("div", { class: "aparte-order__lines", attrs: { "data-thumbs": "" } }, line(), line(), line())),
1793
+ el(
1794
+ "div",
1795
+ { class: "aparte-order__section aparte-order__totals" },
1796
+ el("div", { class: "aparte-order__sum" }, block("aparte-order__sk-label"), block("aparte-order__sk-price")),
1797
+ el("div", { class: "aparte-order__sum aparte-order__sum--total" }, block("aparte-order__sk-label"), block("aparte-order__sk-price"))
1798
+ )
1799
+ ];
1800
+ }
1801
+ function fallback(data, ctx) {
1802
+ const { config } = ctx;
1803
+ const booking = data.booking;
1804
+ const status = data.status ? "status" in data.status ? statusWord(config, data).toLocaleLowerCase(intlTag(config)) : data.status.text : void 0;
1805
+ const parts = [
1806
+ booking?.start ? whenText(config, booking.start, booking.end) : void 0,
1807
+ booking?.location,
1808
+ booking?.guests !== void 0 ? counted(config, "cardsOrderGuest", "cardsOrderGuests", booking.guests) : void 0,
1809
+ data.itemCount > 0 ? counted(config, "cardsOrderItem", "cardsOrderItems", data.itemCount) : void 0,
1810
+ data.total !== void 0 ? say(config, "cardsOrderFallbackTotal", { amount: money(config, data, data.total) }) : void 0,
1811
+ status
1812
+ ].filter(notNull);
1813
+ const head = headText(config, data, false);
1814
+ return parts.length ? `${head} — ${parts.join(", ")}` : head;
1815
+ }
1816
+ const orderCard = defineCard({
1817
+ name: "order",
1818
+ variants: ["receipt", "compact", "confirmation"],
1819
+ styles: orderStyles,
1820
+ icon: BAG,
1821
+ normalize: readOrder,
1822
+ render,
1823
+ skeleton,
1824
+ label: (data, ctx) => headText(ctx.config, data, false),
1825
+ fallback,
1826
+ partial: (input) => {
1827
+ const reference = str(input["reference"] ?? input["orderNumber"] ?? input["order_number"] ?? input["orderId"] ?? input["order_id"] ?? input["bookingId"] ?? input["booking_id"] ?? input["confirmation"] ?? input["number"] ?? input["id"])?.replace(/^#\s*/, "");
1828
+ const booking = ["bookingId", "booking_id", "reservationId", "reservation_id"].some((k) => input[k] !== void 0) || squeeze(input["kind"]) === "booking";
1829
+ if (!reference && !booking) return null;
1830
+ return { kind: booking ? "booking" : "order", ...reference ? { reference } : {} };
1831
+ }
1832
+ });
1833
+ function setupOrderCard(options = {}) {
1834
+ return orderCard.setup(options);
1835
+ }
1836
+ export {
1837
+ nightsOf,
1838
+ orderCard,
1839
+ readOrder,
1840
+ readWhen,
1841
+ setupOrderCard
1842
+ };
1843
+ //# sourceMappingURL=order.js.map