@openreceive/browser 0.1.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +63 -0
  2. package/dist/chunk-WLLNZH26.js +3051 -0
  3. package/dist/headless.d.ts +804 -0
  4. package/dist/headless.js +891 -0
  5. package/dist/index.d.ts +32 -4
  6. package/dist/index.js +32 -2
  7. package/dist/status-B1vDOhvh.d.ts +1001 -0
  8. package/dist/styles.css +3 -759
  9. package/package.json +57 -15
  10. package/dist/assets/icons/bank.svg +0 -12
  11. package/dist/assets/icons/bnb.svg +0 -1
  12. package/dist/assets/icons/card.svg +0 -14
  13. package/dist/assets/icons/doge.svg +0 -1
  14. package/dist/assets/pay_tutorials/boltz-1.webp +0 -0
  15. package/dist/assets/pay_tutorials/boltz-2.webp +0 -0
  16. package/dist/assets/pay_tutorials/cashapp-1.webp +0 -0
  17. package/dist/assets/pay_tutorials/cashapp-2.webp +0 -0
  18. package/dist/assets/pay_tutorials/cashapp-3.webp +0 -0
  19. package/dist/assets/pay_tutorials/cashapp-4.webp +0 -0
  20. package/dist/assets/pay_tutorials/cashapp-5.webp +0 -0
  21. package/dist/assets/pay_tutorials/cashapp-6.webp +0 -0
  22. package/dist/assets/pay_tutorials/coinbase-1.webp +0 -0
  23. package/dist/assets/pay_tutorials/coinbase-2.webp +0 -0
  24. package/dist/assets/pay_tutorials/fixedfloat-1.webp +0 -0
  25. package/dist/assets/pay_tutorials/fixedfloat-2.webp +0 -0
  26. package/dist/assets/pay_tutorials/kraken-1.webp +0 -0
  27. package/dist/assets/pay_tutorials/kraken-2.webp +0 -0
  28. package/dist/assets/pay_tutorials/kraken-3.webp +0 -0
  29. package/dist/assets/pay_tutorials/kraken-4.webp +0 -0
  30. package/dist/assets/pay_tutorials/strike-1.webp +0 -0
  31. package/dist/assets/pay_tutorials/strike-2.webp +0 -0
  32. package/dist/assets/pay_tutorials/strike-3.webp +0 -0
  33. package/dist/assets/pay_tutorials/strike-4.webp +0 -0
  34. package/dist/assets/provider-icons/aqua.png +0 -0
  35. package/dist/assets/provider-icons/belo.png +0 -0
  36. package/dist/assets/provider-icons/binance.png +0 -0
  37. package/dist/assets/provider-icons/bipa.png +0 -0
  38. package/dist/assets/provider-icons/bitfinex.png +0 -0
  39. package/dist/assets/provider-icons/bitget.png +0 -0
  40. package/dist/assets/provider-icons/bitnob.png +0 -0
  41. package/dist/assets/provider-icons/bitso.png +0 -0
  42. package/dist/assets/provider-icons/bity.png +0 -0
  43. package/dist/assets/provider-icons/blink.png +0 -0
  44. package/dist/assets/provider-icons/bluewallet.png +0 -0
  45. package/dist/assets/provider-icons/boltz.png +0 -0
  46. package/dist/assets/provider-icons/bringin.png +0 -0
  47. package/dist/assets/provider-icons/bullbitcoin.png +0 -0
  48. package/dist/assets/provider-icons/cakewallet.png +0 -0
  49. package/dist/assets/provider-icons/cashapp.png +0 -0
  50. package/dist/assets/provider-icons/changenow.png +0 -0
  51. package/dist/assets/provider-icons/chivo.png +0 -0
  52. package/dist/assets/provider-icons/coinbase.png +0 -0
  53. package/dist/assets/provider-icons/coincorner.png +0 -0
  54. package/dist/assets/provider-icons/fixedfloat.png +0 -0
  55. package/dist/assets/provider-icons/getalby.png +0 -0
  56. package/dist/assets/provider-icons/kraken.png +0 -0
  57. package/dist/assets/provider-icons/kryptex.png +0 -0
  58. package/dist/assets/provider-icons/kucoin.png +0 -0
  59. package/dist/assets/provider-icons/manifest.json +0 -207
  60. package/dist/assets/provider-icons/mtpelerin.png +0 -0
  61. package/dist/assets/provider-icons/muun.png +0 -0
  62. package/dist/assets/provider-icons/okcoin.png +0 -0
  63. package/dist/assets/provider-icons/okx.png +0 -0
  64. package/dist/assets/provider-icons/phoenix.png +0 -0
  65. package/dist/assets/provider-icons/pouch.png +0 -0
  66. package/dist/assets/provider-icons/ripio.png +0 -0
  67. package/dist/assets/provider-icons/river.png +0 -0
  68. package/dist/assets/provider-icons/rizful.png +0 -0
  69. package/dist/assets/provider-icons/shakepay.png +0 -0
  70. package/dist/assets/provider-icons/sideshift.png +0 -0
  71. package/dist/assets/provider-icons/simpleswap.png +0 -0
  72. package/dist/assets/provider-icons/speed.png +0 -0
  73. package/dist/assets/provider-icons/strike.png +0 -0
  74. package/dist/assets/provider-icons/trocador.png +0 -0
  75. package/dist/assets/provider-icons/walletofsatoshi.png +0 -0
  76. package/dist/assets/provider-icons/zeus.png +0 -0
  77. package/dist/country-map.d.ts +0 -5
  78. package/dist/country-map.js +0 -17
  79. package/dist/internal.d.ts +0 -834
  80. package/dist/internal.js +0 -2615
  81. package/dist/pay-tutorials.d.ts +0 -1
  82. package/dist/pay-tutorials.js +0 -1
  83. package/dist/provider-icons.d.ts +0 -1
  84. package/dist/provider-icons.js +0 -1
  85. package/dist/qrcode.d.ts +0 -11
  86. package/dist/status.d.ts +0 -9
  87. package/dist/status.js +0 -25
@@ -0,0 +1,3051 @@
1
+ // src/internal/dom-contract.ts
2
+ var OPENRECEIVE_QR_QUIET_ZONE_MODULES = 4;
3
+ var OPENRECEIVE_QR_DARK_COLOR = "#000000";
4
+ var OPENRECEIVE_QR_LIGHT_COLOR = "#FFFFFFFF";
5
+ var OPENRECEIVE_QR_ERROR_CORRECTION = "M";
6
+ var OPENRECEIVE_THEME_STORAGE_KEY = "openreceive.theme";
7
+ var OPENRECEIVE_DEFAULT_POLL_INTERVAL_MS = 3e3;
8
+ var OPENRECEIVE_LIGHTNING_REUSE_BUFFER_SECONDS = 60;
9
+ var OPENRECEIVE_DEFAULT_PREFIX = "/openreceive";
10
+ var OPENRECEIVE_COPY_FEEDBACK_MS = 1800;
11
+ var OPENRECEIVE_CHECKOUT_ELEMENT_TAG_NAME = "openreceive-checkout";
12
+ var OPENRECEIVE_THEME_TOGGLE_ELEMENT_TAG_NAME = "openreceive-theme-toggle";
13
+ var OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS = {
14
+ copy: "openreceive-copy",
15
+ openWallet: "openreceive-open-wallet",
16
+ state: "openreceive-state",
17
+ settled: "openreceive-settled",
18
+ providerCopy: "openreceive-provider-copy",
19
+ startOver: "openreceive-start-over",
20
+ error: "openreceive-error"
21
+ };
22
+ var OPENRECEIVE_THEME_TOGGLE_ELEMENT_EVENTS = {
23
+ change: "openreceive-theme-change"
24
+ };
25
+ var attributeSelectors = (attributes) => Object.fromEntries(
26
+ Object.entries(attributes).map(([key, attribute]) => [key, `[${attribute}]`])
27
+ );
28
+ var partSelectors = (parts) => Object.fromEntries(Object.entries(parts).map(([key, part]) => [key, `[part="${part}"]`]));
29
+ var OPENRECEIVE_PAYMENT_WIZARD_ATTRIBUTES = {
30
+ root: "data-openreceive-wizard",
31
+ breadcrumb: "data-or-breadcrumb",
32
+ method: "data-or-method",
33
+ route: "data-or-route",
34
+ swapStart: "data-or-swap-start",
35
+ swapBack: "data-or-swap-back",
36
+ swapQr: "data-or-swap-qr",
37
+ swapCopy: "data-or-swap-copy",
38
+ swapCopyLabel: "data-or-swap-copy-label",
39
+ swapSelectAll: "data-or-swap-select-all",
40
+ swapNetwork: "data-or-swap-network",
41
+ swapNetworkValue: "data-or-swap-network-value",
42
+ pickerSelect: "data-or-picker-select",
43
+ pickerContinue: "data-or-picker-continue",
44
+ swapRefundForm: "data-or-swap-refund-form",
45
+ swapRefundAddress: "data-or-swap-refund-address",
46
+ swapRefundAllowed: "data-or-swap-refund-allowed",
47
+ swapRefundConfirm: "data-or-swap-refund-confirm",
48
+ swapRefundPayInAsset: "data-or-swap-refund-pay-in-asset",
49
+ swapRefundNetworkLabel: "data-or-swap-refund-network-label",
50
+ swapRefundError: "data-or-swap-refund-error",
51
+ providerCopy: "data-or-provider-copy",
52
+ providerTutorial: "data-or-provider-tutorial",
53
+ providerTutorialIndex: "data-or-provider-tutorial-index"
54
+ };
55
+ var OPENRECEIVE_PAYMENT_WIZARD_SELECTORS = attributeSelectors(
56
+ OPENRECEIVE_PAYMENT_WIZARD_ATTRIBUTES
57
+ );
58
+ var OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES = {
59
+ root: "data-openreceive-checkout",
60
+ qr: "data-openreceive-qr",
61
+ meta: "data-openreceive-meta",
62
+ state: "data-openreceive-state",
63
+ actions: "data-openreceive-actions",
64
+ theme: "data-openreceive-theme",
65
+ themeToggle: "data-openreceive-theme-toggle"
66
+ };
67
+ var OPENRECEIVE_CHECKOUT_DATA_SELECTORS = attributeSelectors(
68
+ OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES
69
+ );
70
+ var OPENRECEIVE_CHECKOUT_ELEMENT_PARTS = {
71
+ copy: "copy",
72
+ startOver: "start-over"
73
+ };
74
+ var OPENRECEIVE_CHECKOUT_ELEMENT_PART_SELECTORS = partSelectors(
75
+ OPENRECEIVE_CHECKOUT_ELEMENT_PARTS
76
+ );
77
+ var OPENRECEIVE_THEME_TOGGLE_ELEMENT_PARTS = {
78
+ button: "button"
79
+ };
80
+ var OPENRECEIVE_THEME_TOGGLE_ELEMENT_PART_SELECTORS = partSelectors(
81
+ OPENRECEIVE_THEME_TOGGLE_ELEMENT_PARTS
82
+ );
83
+ function createCheckoutProviderCopyEvent(providerId) {
84
+ return new CustomEvent(
85
+ OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS.providerCopy,
86
+ {
87
+ detail: {
88
+ providerId
89
+ }
90
+ }
91
+ );
92
+ }
93
+ function createCheckoutActionEvent(eventName) {
94
+ return new CustomEvent(eventName);
95
+ }
96
+ function createCheckoutStateEvent(eventName, state) {
97
+ return new CustomEvent(eventName, {
98
+ detail: {
99
+ state
100
+ }
101
+ });
102
+ }
103
+ function createCheckoutErrorEvent(error) {
104
+ return new CustomEvent(OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS.error, {
105
+ detail: {
106
+ error
107
+ }
108
+ });
109
+ }
110
+ function createThemeChangeEvent(theme) {
111
+ return new CustomEvent(OPENRECEIVE_THEME_TOGGLE_ELEMENT_EVENTS.change, {
112
+ detail: {
113
+ theme: theme.theme,
114
+ resolvedTheme: theme.resolvedTheme
115
+ }
116
+ });
117
+ }
118
+ var OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES = {
119
+ reference: "reference",
120
+ /**
121
+ * Base path the shipped router is mounted at (default `/openreceive`). The
122
+ * element's ONLY URL input: create, prepare, payment-check and the four swap
123
+ * routes are all derived from it. There is deliberately no per-route
124
+ * attribute — see `checkoutRoutes` in ../internal/routes.ts.
125
+ */
126
+ prefix: "prefix",
127
+ /** JSON-encoded create-time metadata forwarded to the create request. */
128
+ metadata: "metadata",
129
+ invoiceId: "invoice-id",
130
+ invoice: "invoice",
131
+ rail: "rail",
132
+ paymentHash: "payment-hash",
133
+ amountMsats: "amount-msats",
134
+ fiatCurrency: "fiat-currency",
135
+ fiatValue: "fiat-value",
136
+ status: "status",
137
+ expiresAt: "expires-at",
138
+ theme: "theme",
139
+ paymentWizard: "payment-wizard",
140
+ /**
141
+ * Opt into History API URL sync to `{resume-path-prefix}/{reference}`.
142
+ * Summary fetch always runs in create mode; this only controls URL mutation.
143
+ */
144
+ syncUrl: "sync-url",
145
+ /** History API path prefix when `sync-url` is set. Default `/checkout`. */
146
+ resumePathPrefix: "resume-path-prefix",
147
+ /**
148
+ * Order id owned by the app router (e.g. Next.js). When set, the element does not
149
+ * push/replace the URL via the History API.
150
+ */
151
+ routeReference: "route-reference",
152
+ /**
153
+ * Base URL of an external bolt11 decoder. When set, the checkout shows a
154
+ * "Decode" link to `{decode-link-url}?invoice={bolt11}`. Omitted (the
155
+ * default), no decode link is rendered and the invoice never leaves the page.
156
+ */
157
+ decodeLinkUrl: "decode-link-url",
158
+ /** `polling="false"` renders the snapshot without status polling (no POST /payments/check). */
159
+ polling: "polling",
160
+ /** Status poll cadence in milliseconds; defaults to OPENRECEIVE_DEFAULT_POLL_INTERVAL_MS. */
161
+ pollIntervalMs: "poll-interval-ms"
162
+ };
163
+ var OPENRECEIVE_THEME_TOGGLE_ELEMENT_ATTRIBUTES = {
164
+ rootSelector: "root-selector",
165
+ checkoutSelector: "checkout-selector",
166
+ defaultTheme: "default-theme",
167
+ storageKey: "storage-key"
168
+ };
169
+
170
+ // src/internal/icons.ts
171
+ var OPENRECEIVE_PAYMENT_ICON_IDS = [
172
+ "btc",
173
+ "crypto",
174
+ "eth",
175
+ "lightning",
176
+ "ltc",
177
+ "sol",
178
+ "trx",
179
+ "usdc",
180
+ "usdt",
181
+ "xmr",
182
+ "xrp"
183
+ ];
184
+ var moduleUrl = typeof import.meta.url === "string" && import.meta.url.length > 0 ? import.meta.url : fileUrlFromPath(__filename);
185
+ function fileUrlFromPath(path) {
186
+ const normalized = path.replace(/\\/g, "/");
187
+ const absolute = normalized.startsWith("/") ? normalized : `/${normalized}`;
188
+ return `file://${encodeURI(absolute).replace(/#/g, "%23").replace(/\?/g, "%3F")}`;
189
+ }
190
+ function paymentIconRoot() {
191
+ if (moduleUrl.includes("/src/internal/")) return "../assets/icons/";
192
+ try {
193
+ const { pathname } = new URL(moduleUrl);
194
+ if (/\/assets\/[^/]+\.js$/i.test(pathname)) return "./icons/";
195
+ } catch {
196
+ }
197
+ return "./assets/icons/";
198
+ }
199
+ function paymentIconUrl(file) {
200
+ return new URL(`${paymentIconRoot()}${file}`, moduleUrl).href;
201
+ }
202
+ var paymentIconUrls = Object.fromEntries(
203
+ OPENRECEIVE_PAYMENT_ICON_IDS.map((id) => [id, paymentIconUrl(`${id}.svg`)])
204
+ );
205
+ var paymentMethodIconIds = {
206
+ bitcoin: "btc"
207
+ };
208
+ var assetIconIds = {
209
+ btc: "btc",
210
+ eth: "eth",
211
+ ltc: "ltc",
212
+ sol: "sol",
213
+ trx: "trx",
214
+ usdc: "usdc",
215
+ usdt: "usdt",
216
+ xmr: "xmr",
217
+ xrp: "xrp"
218
+ };
219
+
220
+ // src/ui-classes.ts
221
+ var orClasses = {
222
+ root: "grid gap-3 min-w-0",
223
+ paymentLayout: "grid gap-3 grid-cols-[auto_minmax(0,1fr)] gap-x-3 md:gap-x-5 items-start min-w-0",
224
+ paymentLayoutExpired: "grid gap-3 grid-cols-1 items-start min-w-0",
225
+ lightningPane: "grid gap-2 items-start justify-items-start min-w-0",
226
+ qr: "justify-self-start w-[min(148px,38vw)] md:w-[min(200px,36vw)] [&_svg]:block [&_svg]:w-full [&_svg]:h-auto",
227
+ satsDetail: "text-base-content/60 text-sm leading-snug justify-self-start max-w-[min(148px,38vw)] md:max-w-[min(200px,36vw)]",
228
+ invoiceTitle: "m-0 text-sm font-semibold leading-tight",
229
+ paymentInfo: "grid gap-1.5 min-w-0 content-start",
230
+ meta: "flex flex-wrap gap-1.5 items-center",
231
+ metaItem: "badge badge-ghost badge-sm min-h-6",
232
+ stateSettled: "badge badge-success badge-sm",
233
+ statePending: "badge badge-ghost badge-sm",
234
+ actions: "flex flex-wrap gap-2 justify-start",
235
+ btn: "btn btn-outline",
236
+ btnGhost: "btn btn-ghost",
237
+ copyIcon: "shrink-0 size-4",
238
+ themeToggle: "btn btn-outline btn-sm gap-2 justify-self-end",
239
+ paymentStatus: "flex items-center gap-2.5 min-w-0",
240
+ paymentStatusBody: "grid gap-0.5 min-w-0 flex-1",
241
+ paymentStatusTitle: "text-base font-semibold leading-tight min-w-0",
242
+ paymentStatusDetail: "text-base-content/60 text-sm leading-snug",
243
+ spinner: "loading loading-spinner loading-md text-warning",
244
+ /** Spinner on a primary button — inherit the button foreground, not the warning color. */
245
+ continueSpinner: "loading loading-spinner loading-md shrink-0",
246
+ settledIcon: "size-8 shrink-0 text-success",
247
+ paymentData: "collapse collapse-arrow border border-base-300 bg-base-100",
248
+ paymentDataTitle: "collapse-title font-semibold",
249
+ paymentDataBody: "collapse-content grid gap-2",
250
+ paymentDataRow: "grid gap-0.5",
251
+ paymentDataKey: "text-xs uppercase tracking-wide text-base-content/60",
252
+ paymentDataValue: "font-mono text-sm break-all m-0",
253
+ countdown: "text-base-content/60 text-sm",
254
+ countdownStrong: "text-base-content font-semibold",
255
+ creating: "grid gap-2 place-items-center p-4",
256
+ wizard: "overflow-hidden rounded-box border border-base-content/20 bg-base-200 grid gap-0",
257
+ wizardHeader: "grid gap-0.5 px-4 py-4 sm:px-5",
258
+ wizardHeaderTitle: "text-lg font-bold m-0 sm:text-xl",
259
+ wizardHeaderSubtitle: "text-base-content/65 text-sm m-0 mt-0.5",
260
+ wizardBody: "border-t border-base-content/15 grid gap-3 p-4 sm:p-5",
261
+ methodGrid: "grid grid-cols-1 items-start gap-2 sm:grid-cols-2 sm:gap-3 lg:grid-cols-5",
262
+ methodCardUnavailable: "flex min-h-14 w-full items-center justify-start gap-3 rounded-field border border-base-content/20 bg-base-100 px-3 py-2 text-left text-base-content opacity-50 cursor-not-allowed shadow-sm sm:px-4",
263
+ methodCurrenciesLoading: "flex min-h-14 w-full items-center justify-start gap-3 rounded-field border border-dashed border-base-content/25 bg-base-100 px-3 py-2 text-left text-base-content/70 shadow-sm sm:px-4 sm:col-span-2 lg:col-span-4",
264
+ methodCardReady: "flex min-h-14 w-full items-center justify-start gap-3 rounded-field border border-base-content/25 bg-base-100 px-3 py-2 text-left text-base-content shadow-sm transition-colors hover:border-base-content/45 hover:bg-base-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary sm:px-4 cursor-pointer",
265
+ methodCardActiveBitcoin: "border-warning bg-warning/10 ring-1 ring-warning/50",
266
+ methodCardActiveUsdt: "border-success bg-success/10 ring-1 ring-success/50",
267
+ methodCardActiveUsdc: "border-info bg-info/10 ring-1 ring-info/50",
268
+ methodCardActiveSol: "border-primary bg-primary/10 ring-1 ring-primary/50",
269
+ methodCardActiveEth: "border-secondary bg-secondary/10 ring-1 ring-secondary/50",
270
+ methodCardActiveDefault: "border-primary bg-primary/10 ring-1 ring-primary/50",
271
+ methodIconWrap: "grid size-8 shrink-0 place-items-center overflow-hidden rounded-full sm:size-9",
272
+ methodIcon: "size-8 aspect-square sm:size-9",
273
+ methodTitle: "block truncate font-semibold text-sm sm:text-base",
274
+ methodTitleWrap: "min-w-0 flex-1 text-left",
275
+ methodDetail: "text-base-content/60 text-xs leading-snug",
276
+ methodDetailMobile: "block truncate text-xs text-base-content/55 sm:hidden",
277
+ /** Limit / unavailable hint under a payment tile — visible at all breakpoints. */
278
+ methodLimitHint: "block px-1 text-xs leading-snug text-base-content/55",
279
+ methodNetworkReveal: "rounded-box border border-base-content/20 bg-base-100 p-3",
280
+ methodNetworkRevealDesktop: "mt-3 hidden sm:block",
281
+ methodNetworkRevealMobile: "ml-4 border-l border-base-content/30 pl-3 sm:hidden",
282
+ methodNetworkRevealMobileUsdt: "ml-4 border-l border-success/40 pl-3 sm:hidden",
283
+ methodNetworkRevealMobileUsdc: "ml-4 border-l border-info/40 pl-3 sm:hidden",
284
+ methodNetworkRevealAnim: "grid overflow-hidden transition-[grid-template-rows,opacity,margin] duration-200 ease-out motion-reduce:transition-none sm:hidden",
285
+ methodNetworkRevealAnimOpen: "mt-2 grid-rows-[1fr] opacity-100",
286
+ methodNetworkRevealAnimClosed: "grid-rows-[0fr] opacity-0",
287
+ methodNetworkRevealInner: "min-h-0 overflow-hidden",
288
+ methodNetworkLayout: "grid gap-3 lg:grid-cols-[9rem_minmax(0,1fr)_minmax(8rem,auto)] lg:items-start",
289
+ methodNetworkHeading: "text-sm font-semibold text-base-content m-0",
290
+ methodNetworkHint: "mt-0.5 text-xs text-base-content/55 m-0",
291
+ methodNetworkGrid: "grid grid-cols-1 gap-2 min-[390px]:grid-cols-3 items-start",
292
+ methodNetworkButton: "btn h-11 min-h-11 w-full justify-start gap-2 rounded-field border border-base-content/25 bg-base-100 px-3 text-sm text-base-content shadow-sm hover:border-base-content/45 hover:bg-base-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary",
293
+ methodNetworkButtonUnavailable: "btn h-11 min-h-11 w-full justify-start gap-2 rounded-field border border-base-content/20 bg-base-100 px-3 text-sm text-base-content opacity-50 cursor-not-allowed shadow-sm pointer-events-none",
294
+ methodNetworkButtonActiveUsdt: "border-success bg-success/10 ring-1 ring-success/50",
295
+ methodNetworkButtonActiveUsdc: "border-info bg-info/10 ring-1 ring-info/50",
296
+ methodNetworkButtonActiveDefault: "border-primary bg-primary/10 ring-1 ring-primary/50",
297
+ methodNetworkIcon: "size-6 shrink-0 aspect-square",
298
+ methodNetworkCheck: "ml-auto grid size-5 place-items-center rounded-full bg-success text-[0.65rem] text-success-content",
299
+ methodNetworkCheckUsdc: "ml-auto grid size-5 place-items-center rounded-full bg-info text-[0.65rem] text-info-content",
300
+ methodNetworkSummary: "mt-2 flex items-center gap-1.5 text-xs text-base-content/65 m-0",
301
+ methodNetworkSummaryIcon: "grid size-4 place-items-center rounded-full bg-success text-[0.65rem] text-success-content",
302
+ methodNetworkSummaryIconUsdc: "grid size-4 place-items-center rounded-full bg-info text-[0.65rem] text-info-content",
303
+ methodConfirmDesktop: "btn btn-primary w-full gap-2",
304
+ methodTile: "grid min-w-0 content-start gap-0.5",
305
+ breadcrumbs: "breadcrumbs text-sm",
306
+ breadcrumbCurrent: "font-bold",
307
+ routePicker: "grid grid-cols-2 md:grid-cols-4 gap-2",
308
+ routeButton: "card card-border bg-base-100 grid gap-1.5 content-start min-h-[120px] p-2.5 text-left cursor-pointer hover:border-primary",
309
+ routeButtonSelected: "card card-border bg-base-100 grid gap-1.5 content-start min-h-[120px] p-2.5 text-left border-primary ring-2 ring-primary/30",
310
+ wizardResults: "grid gap-2.5",
311
+ wizardEmpty: "alert",
312
+ wizardRoute: "grid gap-3",
313
+ wizardRouteHeading: "flex flex-wrap items-center gap-2",
314
+ providerGrid: "grid grid-cols-1 md:grid-cols-2 gap-2",
315
+ providerCard: "card card-border bg-base-100 p-3 grid gap-2 items-center grid-cols-[minmax(0,1fr)_auto] md:grid-cols-[minmax(0,1fr)_auto_auto] md:gap-x-2 md:gap-y-1",
316
+ providerHeading: "flex gap-2 items-center min-w-0",
317
+ providerIcon: "rounded size-7 shrink-0",
318
+ providerName: "font-semibold truncate m-0 min-w-0",
319
+ providerKind: "text-base-content/60 text-sm m-0 justify-self-end text-right",
320
+ providerActions: "col-span-2 flex w-full md:col-span-1 md:w-auto md:justify-self-end",
321
+ providerOpen: "btn btn-outline btn-sm w-full md:w-auto",
322
+ swapActions: "grid gap-2.5 grid-cols-1 md:grid-cols-3",
323
+ swapAction: "grid gap-2",
324
+ swapEstimate: "text-base-content/60 m-0 text-sm",
325
+ swapWarning: "alert alert-warning text-sm",
326
+ swapNetworkWarning: "alert alert-error alert-soft text-sm items-start gap-3",
327
+ swapNetworkWarningIcon: "size-6 shrink-0 stroke-current",
328
+ swapNetworkWarningContent: "grid gap-1 min-w-0",
329
+ swapNetworkWarningTitle: "font-bold m-0",
330
+ swapNetworkWarningBody: "m-0",
331
+ swapNetworkWarningEmphasis: "font-bold underline",
332
+ swapProgress: "text-base-content/60 m-0",
333
+ swapInstruction: "m-0 text-base-content text-base font-bold text-center md:text-left",
334
+ swapStart: "btn btn-outline",
335
+ swapPanel: "grid gap-3",
336
+ swapDepositLayout: "grid gap-3 md:grid-cols-[auto_minmax(0,1fr)] md:gap-x-5 md:items-start min-w-0",
337
+ swapDepositSide: "grid gap-3 min-w-0 content-start",
338
+ swapHeading: "flex flex-wrap gap-2 items-center justify-between",
339
+ swapHeadingTitle: "text-lg font-semibold",
340
+ swapHeadingDetail: "text-base-content/60",
341
+ swapQr: "justify-self-center w-[min(200px,100%)] block h-auto md:justify-self-start md:w-[min(180px,100%)]",
342
+ swapDetails: "grid gap-2 m-0",
343
+ swapDetailsDt: "text-base-content/60 text-xs font-bold uppercase",
344
+ swapDetailsDd: "grid gap-2 grid-cols-[minmax(0,1fr)_auto] items-center m-0",
345
+ swapDetailsCode: "min-w-0 break-all font-mono text-sm",
346
+ // Readonly select-all fields: keep the quiet resting border, suppress daisyUI's
347
+ // focus outline+offset which otherwise reads as a double ring around selected text.
348
+ swapDetailsInput: "input input-sm w-full min-w-0 font-mono text-sm outline-none! focus:outline-none! focus:outline-offset-0!",
349
+ swapDetailsActions: "flex flex-wrap gap-2 justify-end",
350
+ detailCopy: "btn btn-sm btn-square btn-ghost",
351
+ swapDetailsLink: "btn btn-sm btn-outline",
352
+ swapBreakdown: "grid gap-2 py-2 border-t border-base-content/15",
353
+ swapBreakdownTitle: "m-0 text-base-content/60 text-xs font-bold uppercase",
354
+ swapBreakdownRows: "grid grid-cols-[1fr_auto] gap-x-3 gap-y-1.5 items-baseline m-0",
355
+ swapWaitingTitle: "flex items-baseline justify-between gap-3 min-w-0",
356
+ swapCountdown: "shrink-0 text-base-content font-semibold tabular-nums",
357
+ swapBack: "btn btn-sm btn-outline justify-self-start",
358
+ swapSupport: "collapse collapse-arrow bg-base-200",
359
+ swapSupportTitle: "collapse-title font-bold min-h-0 py-2",
360
+ swapSupportContent: "collapse-content",
361
+ transactionDetails: "collapse collapse-arrow bg-base-200",
362
+ transactionDetailsTitle: "collapse-title font-bold min-h-0 py-2",
363
+ transactionDetailsContent: "collapse-content",
364
+ swapRefund: "grid gap-2",
365
+ swapRefundInput: "input input-bordered w-full",
366
+ swapRefundInputInvalid: "input input-bordered input-error w-full",
367
+ swapRefundError: "m-0 text-error text-sm",
368
+ swapRefundHint: "m-0 text-warning text-sm",
369
+ tutorialModal: "modal modal-open",
370
+ tutorialBox: "modal-box grid gap-3 max-w-[min(440px,100%)]",
371
+ tutorialHeader: "flex gap-2 items-center justify-between",
372
+ tutorialTitle: "flex items-center gap-2.5 min-w-0",
373
+ tutorialHeaderLogo: "size-9 rounded shrink-0",
374
+ tutorialClose: "btn btn-sm btn-square btn-ghost",
375
+ tutorialFrame: "flex items-center justify-center min-h-0 overflow-hidden rounded-box border border-base-content/20 bg-base-200",
376
+ tutorialImage: "block w-auto max-w-full h-auto max-h-[min(66vh,720px)] object-contain",
377
+ tutorialCaption: "m-0 text-base font-bold text-center",
378
+ tutorialIntro: "grid gap-3 p-4 text-center",
379
+ tutorialProviderLogo: "justify-self-center size-[52px] rounded",
380
+ tutorialCopy: "btn btn-outline justify-self-center min-w-[min(240px,100%)]",
381
+ tutorialCopyMessage: "text-success font-bold",
382
+ tutorialProgress: "m-0 text-base-content/60 text-xs text-center",
383
+ tutorialSteps: "flex gap-1.5 justify-center",
384
+ tutorialStep: "badge badge-xs badge-ghost size-2 p-0",
385
+ tutorialStepActive: "badge badge-xs badge-neutral size-2 p-0",
386
+ tutorialControls: "grid grid-cols-2 gap-2"
387
+ };
388
+
389
+ // src/generated/compiled-styles.ts
390
+ var compiledStyles = `/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */
391
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-black:#000;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--leading-tight:1.25;--leading-snug:1.375;--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light],:root:has(input.theme-controller[value=light]:checked),[data-theme=light]{color-scheme:light;--color-base-100:oklch(100% 0 0);--color-base-200:oklch(98% 0 0);--color-base-300:oklch(95% 0 0);--color-base-content:oklch(21% .006 285.885);--color-primary:oklch(45% .24 277.023);--color-primary-content:oklch(93% .034 272.788);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}:root:has(input.theme-controller[value=dark]:checked),[data-theme=dark]{color-scheme:dark;--color-base-100:oklch(25.33% .016 252.42);--color-base-200:oklch(23.26% .014 253.1);--color-base-300:oklch(21.15% .012 254.09);--color-base-content:oklch(97.807% .029 256.847);--color-primary:oklch(58% .233 277.117);--color-primary-content:oklch(96% .018 272.314);--color-secondary:oklch(65% .241 354.308);--color-secondary-content:oklch(94% .028 342.258);--color-accent:oklch(77% .152 181.912);--color-accent-content:oklch(38% .063 188.416);--color-neutral:oklch(14% .005 285.823);--color-neutral-content:oklch(92% .004 286.32);--color-info:oklch(74% .16 232.661);--color-info-content:oklch(29% .066 243.157);--color-success:oklch(76% .177 163.223);--color-success-content:oklch(37% .077 168.94);--color-warning:oklch(82% .189 84.429);--color-warning-content:oklch(41% .112 45.904);--color-error:oklch(71% .194 13.428);--color-error-content:oklch(27% .105 12.094);--radius-selector:.5rem;--radius-field:.25rem;--radius-box:.5rem;--size-selector:.25rem;--size-field:.25rem;--border:1px;--depth:1;--noise:0}@property --radialprogress{syntax:"<percentage>";inherits:true;initial-value:0%}@property --aura-angle{syntax:"<angle>";inherits:false;initial-value:0deg}:root{scrollbar-color:currentColor #0000}@supports (color:color-mix(in lab, red, red)){:root{scrollbar-color:color-mix(in oklch, currentColor 35%, #0000) #0000}}:root{--fx-noise:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");--page-scroll-lock:initial;--page-overflow:var(--page-scroll-lock) hidden}:root:not(span){overflow:var(--page-overflow)}:root{--page-has-backdrop:var(--page-scroll-lock) 1;--page-scroll-bg:var(--page-scroll-lock) var(--root-bg,#0000)}@supports (color:color-mix(in lab, red, red)){:root{--page-scroll-bg:var(--page-scroll-lock) color-mix(in srgb, var(--root-bg,#0000), oklch(0% 0 0) calc(var(--page-has-backdrop,0) * 40%))}}:root{background-image:var(--page-scroll-lock) linear-gradient(var(--root-bg,#0000), var(--root-bg,#0000));transition:var(--page-scroll-lock) background-color .3s ease-out;animation:var(--page-scroll-lock) set-page-has-scroll forwards;animation-timeline:var(--page-scroll-lock) scroll();--page-has-scroll:initial;scrollbar-gutter:var(--page-has-scroll) var(--page-scroll-lock) stable}@keyframes set-page-has-scroll{0%,to{--page-has-scroll: }}:root,[data-theme]{background-color:var(--root-bg);color:var(--color-base-content)}:root{background-color:var(--page-scroll-bg,var(--root-bg))}:where(:root,[data-theme]){--root-bg:var(--color-base-100)}}@layer components;@layer utilities{@layer daisyui.l1.l2.l3{.modal{pointer-events:none;visibility:hidden;width:100%;max-width:none;height:100%;max-height:none;color:inherit;transition:overlay .3s allow-discrete, visibility .3s allow-discrete, background-color .3s ease-out, opacity .1s ease-out;overscroll-behavior:contain;z-index:999;scrollbar-gutter:auto;background-color:#0000;place-items:center;margin:0;padding:0;display:grid;position:fixed;inset:0;overflow:clip}.modal::backdrop{display:none}.modal[popover]{color:inherit;background:0 0;border:0;max-width:none;max-height:none;margin:0;padding:0;inset:0}.modal[popover]::backdrop{background-color:oklch(0% 0 0/.4);transition:background-color .3s ease-out}.tab:is(.tabs>.tab){cursor:pointer;appearance:none;text-align:center;webkit-user-select:none;-webkit-user-select:none;user-select:none;flex-wrap:wrap;justify-content:center;align-items:center;display:inline-flex;position:relative}@media (hover:hover){.tab:is(.tabs>.tab):hover{color:var(--color-base-content)}}.tab:is(.tabs>.tab){--tab-p:.75rem;--tab-bg:var(--color-base-100);--tab-border-color:var(--color-base-300);--tab-radius-ss:0;--tab-radius-se:0;--tab-radius-es:0;--tab-radius-ee:0;--tab-order:0;--tab-radius-min:calc(.75rem - var(--border));--tab-radius-limit:min(var(--radius-field), var(--tab-radius-min));--tab-radius-grad:#0000 calc(69% - var(--border)), var(--tab-border-color) calc(69% - var(--border) + .25px), var(--tab-border-color) 69%, var(--tab-bg) calc(69% + .25px);order:var(--tab-order);height:var(--tab-height);padding-inline:var(--tab-p);border-color:#0000;font-size:.875rem}.tab:is(.tabs>.tab):is(input[type=radio]){min-width:fit-content}.tab:is(.tabs>.tab):is(input[type=radio]):after{--tw-content:attr(aria-label);content:var(--tw-content)}.tab:is(.tabs>.tab):is(label){position:relative}.tab:is(.tabs>.tab):is(label) input{cursor:pointer;appearance:none;opacity:0;position:absolute;inset:0}:is(.tab:is(.tabs>.tab):checked,.tab:is(.tabs>.tab):is(label:has(:checked)),.tab:is(.tabs>.tab):is(.tab-active,[aria-selected=true],[aria-current=true],[aria-current=page]))+.tab-content{display:block}.tab:is(.tabs>.tab):not(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true],[aria-current=true],[aria-current=page]){color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.tab:is(.tabs>.tab):not(:checked,label:has(:checked),:hover,.tab-active,[aria-selected=true],[aria-current=true],[aria-current=page]){color:color-mix(in oklab, var(--color-base-content) 50%, transparent)}}.tab:is(.tabs>.tab):not(input):empty{cursor:default;flex-grow:1}.tab:is(.tabs>.tab):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.tab:is(.tabs>.tab):focus{outline-offset:2px;outline:2px solid #0000}}.tab:is(.tabs>.tab):focus-visible,.tab:is(.tabs>.tab):is(label:has(:checked:focus-visible)){outline-offset:-5px;outline:2px solid}.tab:is(.tabs>.tab)[disabled]{pointer-events:none;opacity:.4}.menu{--menu-active-fg:var(--color-neutral-content);--menu-active-bg:var(--color-neutral);flex-flow:column wrap;width:fit-content;padding:.5rem;font-size:.875rem;display:flex}.menu :where(li ul,li menu){white-space:nowrap;margin-inline-start:1rem;padding-inline-start:.5rem;position:relative}.menu :where(li ul,li menu):before{background-color:var(--color-base-content);opacity:.1;width:var(--border);content:"";inset-inline-start:0;position:absolute;top:.75rem;bottom:.75rem}.menu :where(li>.menu-dropdown:not(.menu-dropdown-show)){display:none}.menu :where(li:not(.menu-title)>:not(ul,menu,details,.menu-title,.btn)),.menu :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);text-align:start;-webkit-user-select:none;user-select:none;grid-auto-columns:minmax(auto,max-content) auto max-content;grid-auto-flow:column;align-content:flex-start;align-items:center;gap:.5rem;padding-block:.375rem;padding-inline:.75rem;transition-property:color,background-color,box-shadow;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:grid}.menu :where(li>details>summary){--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.menu :where(li>details>summary){outline-offset:2px;outline:2px solid #0000}}.menu :where(li>details>summary)::-webkit-details-marker{display:none}:is(.menu :where(li>details>summary),.menu :where(li>.menu-dropdown-toggle)):after{content:"";transform-origin:50%;pointer-events:none;justify-self:flex-end;width:.375rem;height:.375rem;transition-property:rotate,translate;transition-duration:.2s;display:block;translate:0 -1px;rotate:-135deg;box-shadow:inset 2px 2px}.menu details{interpolate-size:allow-keywords;overflow:hidden}.menu details::details-content{block-size:0}@media (prefers-reduced-motion:no-preference){.menu details::details-content{transition-behavior:allow-discrete;transition-property:block-size,content-visibility;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1)}}.menu details[open]::details-content{block-size:auto}.menu :where(li>details[open]>summary):after,.menu :where(li>.menu-dropdown-toggle.menu-dropdown-show):after{translate:0 1px;rotate:45deg}.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title),li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.menu-active,:active,.btn).menu-focus,.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title),li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.menu-active,:active,.btn):focus-visible{cursor:pointer;background-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title),li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.menu-active,:active,.btn).menu-focus,.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title),li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.menu-active,:active,.btn):focus-visible{background-color:color-mix(in oklab, var(--color-base-content) 10%, transparent)}}.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title),li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.menu-active,:active,.btn).menu-focus,.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title),li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.menu-active,:active,.btn):focus-visible{color:var(--color-base-content);--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title),li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.menu-active,:active,.btn).menu-focus,.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title),li:not(.menu-title,.disabled)>details>summary:not(.menu-title)):not(.menu-active,:active,.btn):focus-visible{outline-offset:2px;outline:2px solid #0000}}.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title):not(.menu-active,:active,.btn):hover,li:not(.menu-title,.disabled)>details>summary:not(.menu-title):not(.menu-active,:active,.btn):hover){cursor:pointer;background-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title):not(.menu-active,:active,.btn):hover,li:not(.menu-title,.disabled)>details>summary:not(.menu-title):not(.menu-active,:active,.btn):hover){background-color:color-mix(in oklab, var(--color-base-content) 10%, transparent)}}.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title):not(.menu-active,:active,.btn):hover,li:not(.menu-title,.disabled)>details>summary:not(.menu-title):not(.menu-active,:active,.btn):hover){--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title):not(.menu-active,:active,.btn):hover,li:not(.menu-title,.disabled)>details>summary:not(.menu-title):not(.menu-active,:active,.btn):hover){outline-offset:2px;outline:2px solid #0000}}.menu :where(li:not(.menu-title,.disabled)>:not(ul,menu,details,.menu-title):not(.menu-active,:active,.btn):hover,li:not(.menu-title,.disabled)>details>summary:not(.menu-title):not(.menu-active,:active,.btn):hover){box-shadow:inset 0 1px oklch(0% 0 0/.01),inset 0 -1px oklch(100% 0 0/.01)}.menu :where(li:empty){background-color:var(--color-base-content);opacity:.1;height:1px;margin:.5rem 1rem}.menu :where(li){flex-flow:column wrap;flex-shrink:0;align-items:stretch;display:flex;position:relative}.menu :where(li) .badge{justify-self:flex-end}.menu :where(li)>:not(ul,menu,.menu-title,details,.btn):active,.menu :where(li)>:not(ul,menu,.menu-title,details,.btn).menu-active,.menu :where(li)>details>summary:active{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.menu :where(li)>:not(ul,menu,.menu-title,details,.btn):active,.menu :where(li)>:not(ul,menu,.menu-title,details,.btn).menu-active,.menu :where(li)>details>summary:active{outline-offset:2px;outline:2px solid #0000}}.menu :where(li)>:not(ul,menu,.menu-title,details,.btn):active,.menu :where(li)>:not(ul,menu,.menu-title,details,.btn).menu-active,.menu :where(li)>details>summary:active{color:var(--menu-active-fg);background-color:var(--menu-active-bg);background-size:auto, calc(var(--noise) * 100%);background-image:none, var(--fx-noise)}:is(.menu :where(li)>:not(ul,menu,.menu-title,details,.btn):active,.menu :where(li)>:not(ul,menu,.menu-title,details,.btn).menu-active,.menu :where(li)>details>summary:active):not(:is(.menu :where(li)>:not(ul,menu,.menu-title,details,.btn):active,.menu :where(li)>:not(ul,menu,.menu-title,details,.btn).menu-active,.menu :where(li)>details>summary:active):active){box-shadow:0 2px calc(var(--depth) * 3px) -2px var(--menu-active-bg)}.menu :where(li).menu-disabled,.menu :where(li) [disabled]{pointer-events:none;color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.menu :where(li).menu-disabled,.menu :where(li) [disabled]{color:color-mix(in oklab, var(--color-base-content) 20%, transparent)}}.menu .dropdown:focus-within .menu-dropdown-toggle:after{translate:0 1px;rotate:45deg}.menu .dropdown-content{margin-top:.5rem;padding:.5rem}.menu .dropdown-content:before{display:none}.dropdown{position-area:var(--anchor-v,bottom) var(--anchor-h,span-right);display:inline-block;position:relative}.dropdown>:not(:has(~[class*=dropdown-content])):focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.dropdown>:not(:has(~[class*=dropdown-content])):focus{outline-offset:2px;outline:2px solid #0000}}.dropdown .dropdown-content{position:absolute}.dropdown.dropdown-close .dropdown-content,.dropdown:not(details,.dropdown-open,.dropdown-hover:hover,:focus-within) .dropdown-content,.dropdown.dropdown-hover:not(:hover) [tabindex]:first-child:focus:not(:focus-visible)~.dropdown-content{transform-origin:top;opacity:0;display:none;scale:.95}.dropdown[popover],.dropdown .dropdown-content{z-index:999}@media (prefers-reduced-motion:no-preference){.dropdown[popover],.dropdown .dropdown-content{transition-behavior:allow-discrete;transition-property:opacity,scale,display,overlay;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1);animation:.2s dropdown}}@starting-style{.dropdown[popover],.dropdown .dropdown-content{opacity:0;scale:.95}}:is(.dropdown:not(.dropdown-close).dropdown-open,.dropdown:not(.dropdown-close):not(.dropdown-hover):focus,.dropdown:not(.dropdown-close):focus-within)>[tabindex]:first-child{pointer-events:none}:is(.dropdown:not(.dropdown-close).dropdown-open,.dropdown:not(.dropdown-close):not(.dropdown-hover):focus,.dropdown:not(.dropdown-close):focus-within) .dropdown-content,.dropdown:not(.dropdown-close).dropdown-hover:hover .dropdown-content{opacity:1;scale:1}.dropdown:is(details){overflow:revert-layer}.dropdown:is(details) summary::-webkit-details-marker{display:none}.dropdown:where([popover]){background:0 0}.dropdown[popover]{color:inherit;position:fixed}@supports not (position-area:bottom){.dropdown[popover]{margin:auto}.dropdown[popover].dropdown-close{transform-origin:top;opacity:0;display:none;scale:.95}.dropdown[popover].dropdown-open:not(:popover-open){transform-origin:top;opacity:0;display:none;scale:.95}.dropdown[popover]::backdrop{background-color:oklab(0% none none/.3)}}:is(.dropdown[popover].dropdown-close,.dropdown[popover]:not(.dropdown-open,:popover-open)){transform-origin:top;opacity:0;display:none;scale:.95}:where(.btn){width:unset}.btn{--size:calc(var(--size-field,.25rem) * 10);--btn-p:1rem;--btn-fg:var(--color-base-content);cursor:pointer;text-align:center;vertical-align:middle;outline-offset:2px;webkit-user-select:none;-webkit-user-select:none;user-select:none;border-width:var(--border);touch-action:manipulation;--btn-bg:var(--btn-color,var(--color-base-200));--btn-border:var(--btn-color,var(--color-base-200));border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));flex-wrap:nowrap;flex-shrink:0;justify-content:center;align-items:center;gap:.375rem;font-weight:600;transition-property:color,background-color,border-color,box-shadow,transform;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1);display:inline-flex}@supports (color:color-mix(in lab, red, red)){.btn{--btn-border:color-mix(in oklab, var(--btn-color,var(--color-base-200)), #000 calc(var(--depth) * 5%))}}.btn{--btn-soft-bg:initial;--btn-shadow:0 3px 2px -2px var(--btn-bg), 0 4px 3px -2px var(--btn-bg)}@supports (color:color-mix(in lab, red, red)){.btn{--btn-shadow:0 3px 2px -2px color-mix(in oklab, var(--btn-bg) calc(var(--depth) * 30%), #0000), 0 4px 3px -2px color-mix(in oklab, var(--btn-bg) calc(var(--depth) * 30%), #0000)}}.btn{--btn-inset:0 .5px 0 .5px oklch(100% 0 0 / calc(var(--depth) * 6%));height:var(--size);padding-inline:var(--btn-p);font-size:var(--fontsize,.875rem);background-color:var(--btn-bg);color:var(--btn-fg);border-color:var(--btn-border);border-style:var(--btn-border-style,solid);outline-color:var(--btn-color,var(--color-base-content));--tw-prose-links:var(--btn-fg);background-image:none, var(--fx-noise);background-size:auto, calc(var(--noise,0) * 100%);text-shadow:0 .5px oklch(100% 0 0 / calc(var(--depth) * .15));box-shadow:var(--btn-inset) inset, var(--btn-shadow)}.btn:is([type=checkbox],[type=radio]){appearance:none}.btn:is([type=checkbox],[type=radio])[aria-label]:after{--tw-content:attr(aria-label);content:var(--tw-content)}.loading{pointer-events:none;aspect-ratio:1;vertical-align:middle;width:calc(var(--size-selector,.25rem) * 6);background-color:currentColor;display:inline-block;-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='8s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='6s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='6s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='8s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='6s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='6s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");-webkit-mask-position:50%;mask-position:50%;-webkit-mask-size:100%;mask-size:100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}@media (prefers-reduced-motion:no-preference){.loading{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E")}}.countdown{display:inline-flex}.countdown>*{visibility:hidden;--value-v:calc(mod(max(0, var(--value)), 1000));--value-hundreds:calc(round(to-zero, var(--value-v) / 100, 1));--value-tens:calc(round(to-zero, mod(var(--value-v), 100) / 10, 1));--value-ones:calc(mod(var(--value-v), 100));--show-hundreds:clamp(clamp(0, var(--digits,1) - 2, 1), var(--value-hundreds), 1);--show-tens:clamp(clamp(0, var(--digits,1) - 1, 1), var(--value-tens) + var(--show-hundreds), 1);--first-digits:calc(round(to-zero, var(--value-v) / 10, 1));height:1em;width:calc(1ch + var(--show-tens) * 1ch + var(--show-hundreds) * 1ch);direction:ltr;transition:width .4s ease-out .2s;display:inline-block;position:relative;overflow-y:clip}.countdown>:before,.countdown>:after{visibility:visible;--tw-content:"00\\a 01\\a 02\\a 03\\a 04\\a 05\\a 06\\a 07\\a 08\\a 09\\a 10\\a 11\\a 12\\a 13\\a 14\\a 15\\a 16\\a 17\\a 18\\a 19\\a 20\\a 21\\a 22\\a 23\\a 24\\a 25\\a 26\\a 27\\a 28\\a 29\\a 30\\a 31\\a 32\\a 33\\a 34\\a 35\\a 36\\a 37\\a 38\\a 39\\a 40\\a 41\\a 42\\a 43\\a 44\\a 45\\a 46\\a 47\\a 48\\a 49\\a 50\\a 51\\a 52\\a 53\\a 54\\a 55\\a 56\\a 57\\a 58\\a 59\\a 60\\a 61\\a 62\\a 63\\a 64\\a 65\\a 66\\a 67\\a 68\\a 69\\a 70\\a 71\\a 72\\a 73\\a 74\\a 75\\a 76\\a 77\\a 78\\a 79\\a 80\\a 81\\a 82\\a 83\\a 84\\a 85\\a 86\\a 87\\a 88\\a 89\\a 90\\a 91\\a 92\\a 93\\a 94\\a 95\\a 96\\a 97\\a 98\\a 99\\a ";content:var(--tw-content);font-variant-numeric:tabular-nums;white-space:pre;text-align:end;direction:rtl;transition:all 1s cubic-bezier(1,0,0,1),width .2s ease-out .2s,opacity .2s ease-out .2s;position:absolute;overflow-x:clip}.countdown>:before{width:calc(1ch + var(--show-hundreds) * 1ch);top:calc(var(--first-digits) * -1em);opacity:var(--show-tens);inset-inline-end:0}.countdown>:after{width:1ch;top:calc(var(--value-ones) * -1em);inset-inline-start:0}.collapse{border-radius:var(--radius-box,1rem);isolation:isolate;grid-template-rows:max-content 0fr;grid-template-columns:minmax(0,1fr);width:100%;display:grid;position:relative}@media (prefers-reduced-motion:no-preference){.collapse{transition:grid-template-rows .2s}}.collapse>input:is([type=checkbox],[type=radio]){appearance:none;opacity:0;z-index:1;grid-row-start:1;grid-column-start:1;width:100%;min-height:1lh;padding:1rem;padding-inline-end:3rem;transition:background-color .2s ease-out}.collapse:is([open],[tabindex]:focus:not(.collapse-close),[tabindex]:focus-within:not(.collapse-close)),.collapse:not(.collapse-close):has(>input:is([type=checkbox],[type=radio]):checked){grid-template-rows:max-content 1fr}.collapse:is([open],[tabindex]:focus:not(.collapse-close),[tabindex]:focus-within:not(.collapse-close))>.collapse-content,.collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){--overflow-delay:.2s;overflow:revert-layer;content-visibility:visible;min-height:fit-content}@supports not (content-visibility:visible){.collapse:is([open],[tabindex]:focus:not(.collapse-close),[tabindex]:focus-within:not(.collapse-close))>.collapse-content,.collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){visibility:visible}}.collapse:focus-visible,.collapse:has(>input:is([type=checkbox],[type=radio]):focus-visible),.collapse:has(summary:focus-visible){outline-color:var(--color-base-content);outline-offset:2px;outline-width:2px;outline-style:solid}.collapse:not(.collapse-close)>input[type=checkbox],.collapse:not(.collapse-close)>input[type=radio]:not(:checked),.collapse:not(.collapse-close)>.collapse-title{cursor:pointer}:is(.collapse[tabindex]:focus:not(.collapse-close,.collapse[open]),.collapse[tabindex]:focus-within:not(.collapse-close,.collapse[open]))>.collapse-title{cursor:unset}.collapse:is([open],[tabindex]:focus:not(.collapse-close),[tabindex]:focus-within:not(.collapse-close))>:where(.collapse-content),.collapse:not(.collapse-close)>:where(input:is([type=checkbox],[type=radio]):checked~.collapse-content){padding-bottom:1rem}.collapse:is(details){width:100%}.collapse:is(details)::details-content{--overflow-delay:0s;height:0;overflow:clip}.collapse:is(details):where([open])::details-content{overflow:revert-layer;height:auto}@media (prefers-reduced-motion:no-preference){.collapse:is(details)::details-content{transition:overflow .2s allow-discrete var(--overflow-delay), content-visibility .2s allow-discrete, visibility .2s allow-discrete, min-height .2s ease-out allow-discrete, padding .1s ease-out 20ms, background-color .2s ease-out, height .2s;interpolate-size:allow-keywords}.collapse:is(details):where([open])::details-content{--overflow-delay:.2s}}.collapse:is(details)>summary{outline:none;display:block;position:relative}.collapse:is(details)>summary::-webkit-details-marker{display:none}.collapse-content{--overflow-delay:0s;content-visibility:hidden;min-height:0;cursor:unset;grid-row-start:2;grid-column-start:1;padding-left:1rem;padding-right:1rem;overflow:clip}@supports not (content-visibility:hidden){.collapse-content{visibility:hidden}}@media (prefers-reduced-motion:no-preference){.collapse-content{transition:overflow .2s allow-discrete var(--overflow-delay), content-visibility .2s allow-discrete, visibility .2s allow-discrete, min-height .2s ease-out allow-discrete, padding .1s ease-out 20ms, background-color .2s ease-out}}details>.collapse-content{content-visibility:visible}.filter{flex-wrap:wrap;display:flex}.filter [type=radio]{width:auto}.filter input{opacity:1;transition:visibility .1s allow-discrete, margin .1s, opacity .3s, padding .3s, border-width .1s;overflow:hidden;scale:1}.filter input.filter-reset{aspect-ratio:1}.filter input.filter-reset:after{--tw-content:"\xD7";content:var(--tw-content)}.filter>input:not(:last-child),.filter>:not(:last-child) input{margin-inline-end:.25rem}.list{flex-direction:column;font-size:.875rem;display:flex}.list .list-row{--list-grid-cols:minmax(0, auto) 1fr;border-radius:var(--radius-box);word-break:break-word;grid-auto-flow:column;grid-template-columns:var(--list-grid-cols);gap:1rem;padding:1rem;display:grid;position:relative}:is(.list>:not(:last-child).list-row,.list>:not(:last-child) .list-row):after{content:"";border-bottom:var(--border) solid;inset-inline:var(--radius-box);border-color:var(--color-base-content);position:absolute;bottom:0}@supports (color:color-mix(in lab, red, red)){:is(.list>:not(:last-child).list-row,.list>:not(:last-child) .list-row):after{border-color:color-mix(in oklab, var(--color-base-content) 5%, transparent)}}.toast{translate:var(--toast-x,0) var(--toast-y,0);inset-inline:auto 1rem;background-color:#0000;flex-direction:column;gap:.5rem;width:max-content;max-width:calc(100vw - 2rem);display:flex;position:fixed;top:auto;bottom:1rem}@media (prefers-reduced-motion:no-preference){.toast>*{animation:.25s ease-out toast}}.toggle{border:var(--border) solid currentColor;color:var(--input-color);cursor:pointer;appearance:none;vertical-align:middle;webkit-user-select:none;-webkit-user-select:none;user-select:none;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--toggle-p), var(--radius-selector-max)) + min(var(--border), var(--radius-selector-max)));padding:var(--toggle-p);flex-shrink:0;grid-template-columns:0fr 1fr 1fr;place-content:center;display:inline-grid;position:relative;box-shadow:inset 0 1px}@supports (color:color-mix(in lab, red, red)){.toggle{box-shadow:0 1px color-mix(in oklab, currentColor calc(var(--depth) * 10%), #0000) inset}}.toggle{--input-color:var(--color-base-content);transition:color .3s,grid-template-columns .2s}@supports (color:color-mix(in lab, red, red)){.toggle{--input-color:color-mix(in oklab, var(--color-base-content) 50%, #0000)}}.toggle{--toggle-p:calc(var(--size) * .125);--size:calc(var(--size-selector,.25rem) * 6);width:calc((var(--size) * 2) - (var(--border) + var(--toggle-p)) * 2);height:var(--size)}.toggle>*{z-index:1;cursor:pointer;appearance:none;background-color:#0000;border:none;grid-column:2/span 1;grid-row-start:1;height:100%;padding:.125rem;transition:opacity .2s,rotate .4s}.toggle>:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.toggle>:focus{outline-offset:2px;outline:2px solid #0000}}.toggle>:nth-child(2){color:var(--color-base-100);rotate:0deg}.toggle>:nth-child(3){color:var(--color-base-100);opacity:0;rotate:-15deg}.toggle:has(:checked)>:nth-child(2){opacity:0;rotate:15deg}.toggle:has(:checked)>:nth-child(3){opacity:1;rotate:0deg}.toggle:before{aspect-ratio:1;border-radius:var(--radius-selector);--tw-content:"";content:var(--tw-content);width:100%;height:100%;box-shadow:0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px currentColor;background-color:currentColor;grid-row-start:1;grid-column-start:2;transition:background-color .1s,translate .2s,inset-inline-start .2s;position:relative;inset-inline-start:0;translate:0}@supports (color:color-mix(in lab, red, red)){.toggle:before{box-shadow:0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px color-mix(in oklab, currentColor calc(var(--depth) * 10%), #0000)}}.toggle:before{background-size:auto, calc(var(--noise) * 100%);background-image:none, var(--fx-noise)}@media (forced-colors:active){.toggle:before{outline-style:var(--tw-outline-style);outline-offset:calc(1px * -1);outline-width:1px}}@media print{.toggle:before{outline-offset:-1rem;outline:.25rem solid}}.toggle:focus-visible,.toggle:has(:focus-visible){outline-offset:2px;outline:2px solid}.toggle:checked,.toggle[aria-checked=true],.toggle:has(>input:checked){background-color:var(--color-base-100);--input-color:var(--color-base-content);grid-template-columns:1fr 1fr 0fr}:is(.toggle:checked,.toggle[aria-checked=true],.toggle:has(>input:checked)):before{background-color:currentColor}@starting-style{:is(.toggle:checked,.toggle[aria-checked=true],.toggle:has(>input:checked)):before{opacity:0}}.toggle:indeterminate{grid-template-columns:.5fr 1fr .5fr}.toggle:disabled{cursor:not-allowed;opacity:.3}.toggle:disabled:before{border:var(--border) solid currentColor;background-color:#0000}.input{appearance:none;background-color:var(--color-base-100);vertical-align:middle;white-space:nowrap;--size:calc(var(--size-field,.25rem) * var(--in-size-mul));--input-color:var(--color-base-content);flex-shrink:1;align-items:center;gap:.5rem;padding-inline:.75rem;display:inline-flex;position:relative}@supports (color:color-mix(in lab, red, red)){.input{--input-color:color-mix(in oklab, var(--color-base-content) 20%, #0000)}}.input{cursor:text;width:clamp(3rem,20rem,100%);height:var(--size);font-size:max(var(--font-size,0rem), var(--font-size-min));touch-action:manipulation;border:var(--border) solid var(--input-color,#0000);box-shadow:0 1px var(--input-color) inset, 0 -1px oklch(100% 0 0 / calc(var(--depth) * .1)) inset;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field))}@supports (color:color-mix(in lab, red, red)){.input{box-shadow:0 1px color-mix(in oklab, var(--input-color) calc(var(--depth) * 10%), #0000) inset, 0 -1px oklch(100% 0 0 / calc(var(--depth) * .1)) inset}}.input input{appearance:none;background-color:#0000;border:none;width:100%;height:100%}.input input::placeholder{color:var(--color-base-content);opacity:.5}.input input:focus,.input input:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.input input:focus,.input input:focus-within{outline-offset:2px;outline:2px solid #0000}}.input input::-webkit-calendar-picker-indicator{inset-inline-end:-.15em}.input::-webkit-inner-spin-button{margin-inline-end:-10px}.input::-webkit-calendar-picker-indicator{inset-inline-end:.75em}input.input,.input input{display:inline-flex;position:relative}:is(input.input,.input input)[type=url],:is(input.input,.input input)[type=email]{text-align:left}:is(input.input,.input input)::-webkit-datetime-edit{min-height:100%;text-align:inherit;align-items:center;display:grid}:is(input.input,.input input)::-webkit-date-and-time-value{min-height:100%;text-align:inherit;align-items:center;display:grid}:is(input.input,.input input)::-webkit-inner-spin-button{margin-block:calc(.25rem * var(--spin-my))}:is(input.input,.input input)::-webkit-calendar-picker-indicator{cursor:pointer;width:1em;height:1em;position:absolute}:is(input.input,.input input)::-webkit-color-swatch-wrapper{padding-block:.25rem}.input:focus,.input:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab, red, red)){.input:focus,.input:focus-within{box-shadow:0 1px color-mix(in oklab, var(--input-color) calc(var(--depth) * 10%), #0000)}}.input:focus,.input:focus-within{outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}@media (pointer:coarse){@supports (-webkit-touch-callout:none){.input:focus,.input:focus-within{--font-size:1rem}}}.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200)}:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input):is(input),:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input) :is(input){color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input):is(input),:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input) :is(input){color:color-mix(in oklab, var(--color-base-content) 40%, transparent)}}.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input{box-shadow:none}:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input)::placeholder,:is(.input:has(>input[disabled]),.input:is(:disabled,[disabled]),fieldset:disabled .input) ::placeholder{color:var(--color-base-content);opacity:.2}.input:has(>input[disabled])>input[disabled]{cursor:not-allowed}.range{appearance:none;webkit-appearance:none;--range-thumb:var(--color-base-100);--range-thumb-size:calc(var(--size-selector,.25rem) * 6);--range-progress:currentColor;--range-fill:1;--range-p:.25rem;--range-bg:currentColor}@supports (color:color-mix(in lab, red, red)){.range{--range-bg:color-mix(in oklab, currentColor 10%, #0000)}}.range{--range-fill-x:calc((var(--range-dir,1) * -100cqw) - (var(--range-dir,1) * var(--range-thumb-size) / 2));--range-fill-y:0;--range-fill-spread:calc(100cqw * var(--range-fill));cursor:pointer;vertical-align:middle;--radius-selector-max:calc(var(--radius-selector) + var(--radius-selector) + var(--radius-selector));border-radius:calc(var(--radius-selector) + min(var(--range-p), var(--radius-selector-max)));width:clamp(3rem,20rem,100%);height:var(--range-thumb-size);background-color:#0000;border:none;overflow:hidden}[dir=rtl] .range{--range-dir:-1}.range:focus{outline:none}.range:focus-visible{outline-offset:2px;outline:2px solid}.range::-webkit-slider-runnable-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size) * .5)}@media (forced-colors:active){.range::-webkit-slider-runnable-track{border:1px solid}.range::-moz-range-track{border:1px solid}}.range::-webkit-slider-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p), var(--radius-selector-max)));background-color:var(--range-thumb);height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p) solid;appearance:none;webkit-appearance:none;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px currentColor, 0 0 0 2rem var(--range-thumb) inset, var(--range-fill-x) var(--range-fill-y) 0 var(--range-fill-spread);position:relative;inset-block-start:50%;transform:translateY(-50%)}@supports (color:color-mix(in lab, red, red)){.range::-webkit-slider-thumb{box-shadow:0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px color-mix(in oklab, currentColor calc(var(--depth) * 10%), #0000), 0 0 0 2rem var(--range-thumb) inset, var(--range-fill-x) var(--range-fill-y) 0 var(--range-fill-spread)}}.range::-moz-range-track{background-color:var(--range-bg);border-radius:var(--radius-selector);width:100%;height:calc(var(--range-thumb-size) * .5)}.range::-moz-range-thumb{box-sizing:border-box;border-radius:calc(var(--radius-selector) + min(var(--range-p), var(--radius-selector-max)));height:var(--range-thumb-size);width:var(--range-thumb-size);border:var(--range-p) solid;color:var(--range-progress);box-shadow:0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px currentColor, 0 0 0 2rem var(--range-thumb) inset, var(--range-fill-x) var(--range-fill-y) 0 var(--range-fill-spread);background-color:currentColor;position:relative}@supports (color:color-mix(in lab, red, red)){.range::-moz-range-thumb{box-shadow:0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px color-mix(in oklab, currentColor calc(var(--depth) * 10%), #0000), 0 0 0 2rem var(--range-thumb) inset, var(--range-fill-x) var(--range-fill-y) 0 var(--range-fill-spread)}}.range:disabled{cursor:not-allowed;opacity:.3}.table{border-collapse:separate;--tw-border-spacing-x:0;--tw-border-spacing-y:0;width:100%;border-spacing:var(--tw-border-spacing-x) var(--tw-border-spacing-y);border-radius:var(--radius-box);text-align:left;font-size:.875rem;position:relative}.table:where(:dir(rtl),[dir=rtl],[dir=rtl] *){text-align:right}@media (hover:hover){:is(.table tr.row-hover,.table tr.row-hover:nth-child(2n)):hover{background-color:var(--color-base-200)}}.table :where(th,td){vertical-align:middle;padding-block:.75rem;padding-inline:1rem}.table :where(thead,tfoot){white-space:nowrap;color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.table :where(thead,tfoot){color:color-mix(in oklab, var(--color-base-content) 60%, transparent)}}.table :where(thead,tfoot){font-size:.875rem;font-weight:600}.table :where(tfoot tr:first-child :is(td,th)){border-top:var(--border) solid var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.table :where(tfoot tr:first-child :is(td,th)){border-top:var(--border) solid color-mix(in oklch, var(--color-base-content) 5%, #0000)}}.table :where(.table-pin-rows thead tr){z-index:1;background-color:var(--color-base-100);position:sticky;top:0}.table :where(.table-pin-rows tfoot tr){z-index:1;background-color:var(--color-base-100);position:sticky;bottom:0}.table :where(.table-pin-cols tr th){background-color:var(--color-base-100);position:sticky;left:0;right:0}.table :where(thead tr :is(td,th),tbody tr:not(:last-child) :is(td,th)){border-bottom:var(--border) solid var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.table :where(thead tr :is(td,th),tbody tr:not(:last-child) :is(td,th)){border-bottom:var(--border) solid color-mix(in oklch, var(--color-base-content) 5%, #0000)}}.aura{--aura-padding:.125rem;padding:var(--aura-padding);border-radius:calc(var(--aura-padding) + var(--aura-radius,var(--radius-box)));animation:aura var(--tw-duration,6s) linear infinite;background-image:conic-gradient(from var(--aura-angle), transparent 225deg, currentColor);display:inline-block;position:relative}.aura:has(>.card,>.alert){--aura-radius:var(--radius-box)}.aura:has(>.btn,>.input,>.select){--aura-radius:var(--radius-field)}.aura:has(>.checkbox,>.toggle,>.badge){--aura-radius:var(--radius-selector)}.aura:before,.aura:after{animation:inherit;background-color:inherit;background-image:inherit;border-radius:inherit;z-index:0;opacity:.7;filter:blur(.25rem);content:"";width:100%;height:100%;display:block;position:absolute;top:50%;left:50%;translate:-50% -50%}.aura:after{opacity:.3;filter:blur(1rem)}.aura>*{z-index:1;position:relative}.steps{counter-reset:step;grid-auto-columns:1fr;grid-auto-flow:column;display:inline-grid;overflow:auto hidden}.steps .step{text-align:center;--step-bg:var(--color-base-300);--step-fg:var(--color-base-content);grid-template-rows:40px 1fr;grid-template-columns:auto;place-items:center;min-width:4rem;display:grid}.steps .step:before{width:100%;height:.5rem;color:var(--step-bg);background-color:var(--step-bg);content:"";border:1px solid;grid-row-start:1;grid-column-start:1;margin-inline-start:-100%;top:0}.steps .step>.step-icon,.steps .step:not(:has(.step-icon)):after{--tw-content:counter(step);content:var(--tw-content);counter-increment:step;z-index:1;color:var(--step-fg);background-color:var(--step-bg);border:1px solid var(--step-bg);border-radius:3.40282e38px;grid-row-start:1;grid-column-start:1;place-self:center;place-items:center;width:2rem;height:2rem;display:grid;position:relative}.steps .step:first-child:before{--tw-content:none;content:var(--tw-content)}.steps .step[data-content]:after{--tw-content:attr(data-content);content:var(--tw-content)}.select{appearance:none;background-color:var(--color-base-100);vertical-align:middle;--size:calc(var(--size-field,.25rem) * var(--sl-size-mul));--input-color:var(--color-base-content);flex-shrink:1;align-items:center;gap:.375rem;padding-inline:.75rem 1.75rem;display:inline-flex;position:relative}@supports (color:color-mix(in lab, red, red)){.select{--input-color:color-mix(in oklab, var(--color-base-content) 20%, #0000)}}.select{width:clamp(3rem,20rem,100%);height:var(--size);font-size:max(var(--font-size,0rem), var(--font-size-min));touch-action:manipulation;white-space:nowrap;text-overflow:ellipsis;border:var(--border) solid var(--input-color,#0000);box-shadow:0 1px var(--input-color) inset, 0 -1px oklch(100% 0 0 / calc(var(--depth) * .1)) inset;background-image:linear-gradient(45deg,#0000 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,#0000 50%);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16.1px) calc(1px + 50%);background-repeat:no-repeat;background-size:4px 4px,4px 4px;border-start-start-radius:var(--join-ss,var(--radius-field));border-start-end-radius:var(--join-se,var(--radius-field));border-end-end-radius:var(--join-ee,var(--radius-field));border-end-start-radius:var(--join-es,var(--radius-field));overflow:hidden}@supports (color:color-mix(in lab, red, red)){.select{box-shadow:0 1px color-mix(in oklab, var(--input-color) calc(var(--depth) * 10%), #0000) inset, 0 -1px oklch(100% 0 0 / calc(var(--depth) * .1)) inset}}[dir=rtl] .select{background-position:12px calc(1px + 50%),16px calc(1px + 50%)}[dir=rtl] .select::picker(select){translate:.5rem}[dir=rtl] .select select::picker(select){translate:.5rem}.select[multiple]{background-image:none;height:auto;padding-block:.75rem;padding-inline-end:.75rem;overflow:auto}.select select{appearance:none;width:calc(100% + 2.75rem);height:calc(100% - calc(var(--border) * 2));background:inherit;border-radius:inherit;border-style:none;align-items:center;margin-inline:-.75rem -1.75rem;padding-inline:.75rem 1.75rem}.select select::placeholder{color:var(--color-base-content);opacity:.5}.select select:focus,.select select:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.select select:focus,.select select:focus-within{outline-offset:2px;outline:2px solid #0000}}.select select:not(:last-child){background-image:none;margin-inline-end:-1.375rem}:is(.select:focus,.select:focus-within,.select:open){--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab, red, red)){:is(.select:focus,.select:focus-within,.select:open){box-shadow:0 1px color-mix(in oklab, var(--input-color) calc(var(--depth) * 10%), #0000)}}:is(.select:focus,.select:focus-within,.select:open){outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate;background-image:linear-gradient(135deg,#0000 50%,currentColor 50%),linear-gradient(45deg,currentColor 50%,#0000 50%)}.select:has(>select[disabled]),.select:is(:disabled,[disabled]),fieldset:disabled .select{cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200)}:is(.select:has(>select[disabled]),.select:is(:disabled,[disabled]),fieldset:disabled .select):is(select),:is(.select:has(>select[disabled]),.select:is(:disabled,[disabled]),fieldset:disabled .select) :is(select){color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:is(.select:has(>select[disabled]),.select:is(:disabled,[disabled]),fieldset:disabled .select):is(select),:is(.select:has(>select[disabled]),.select:is(:disabled,[disabled]),fieldset:disabled .select) :is(select){color:color-mix(in oklab, var(--color-base-content) 40%, transparent)}}.select:has(>select[disabled]),.select:is(:disabled,[disabled]),fieldset:disabled .select{box-shadow:none}:is(.select:has(>select[disabled]),.select:is(:disabled,[disabled]),fieldset:disabled .select)::placeholder,:is(.select:has(>select[disabled]),.select:is(:disabled,[disabled]),fieldset:disabled .select) ::placeholder{color:var(--color-base-content);opacity:.2}.select:has(>select[disabled])>select[disabled]{cursor:not-allowed}@supports (appearance:base-select){:is(.select,.select select){appearance:base-select}:is(.select,.select select)::picker(select){appearance:base-select}}:is(.select,.select select)::picker(select){color:inherit;border:var(--border) solid var(--color-base-200);border-radius:var(--radius-box);background-color:inherit;max-height:min(24rem,70dvh);box-shadow:0 2px calc(var(--depth) * 3px) -2px oklch(0% 0 0/.2);box-shadow:0 20px 25px -5px rgb(0 0 0/calc(var(--depth) * .1)), 0 8px 10px -6px rgb(0 0 0/calc(var(--depth) * .1));margin-block:.5rem;margin-inline:.5rem;padding:.5rem;translate:-.5rem}:is(.select,.select select)::picker-icon{display:none}:is(.select,.select select) selectedcontent{text-overflow:ellipsis;white-space:nowrap;width:100%;overflow:hidden}:is(.select,.select select) optgroup{padding-top:.5em}:is(.select,.select select) optgroup option:first-child{margin-top:.5em}:is(.select,.select select) option{border-radius:var(--radius-field);padding-block:.375rem;padding-inline:calc(.25rem * var(--option-px));white-space:normal;transition-property:color,background-color;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1)}:is(.select,.select select) option:not(:disabled):hover,:is(.select,.select select) option:not(:disabled):focus-visible{cursor:pointer;background-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:is(.select,.select select) option:not(:disabled):hover,:is(.select,.select select) option:not(:disabled):focus-visible{background-color:color-mix(in oklab, var(--color-base-content) 10%, transparent)}}:is(.select,.select select) option:not(:disabled):hover,:is(.select,.select select) option:not(:disabled):focus-visible{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){:is(.select,.select select) option:not(:disabled):hover,:is(.select,.select select) option:not(:disabled):focus-visible{outline-offset:2px;outline:2px solid #0000}}:is(.select,.select select) option:not(:disabled):active{background-color:var(--color-neutral);color:var(--color-neutral-content);box-shadow:0 2px calc(var(--depth) * 3px) -2px var(--color-neutral)}.collapse-title{grid-row-start:1;grid-column-start:1;width:100%;min-height:1lh;padding:1rem;padding-inline-end:3rem;transition:background-color .2s ease-out;position:relative}.radio{cursor:pointer;appearance:none;vertical-align:middle;border:var(--border) solid var(--input-color,currentColor);border-radius:3.40282e38px;flex-shrink:0;padding:.25rem;display:inline-block;position:relative}@supports (color:color-mix(in lab, red, red)){.radio{border:var(--border) solid var(--input-color,color-mix(in srgb, currentColor 20%, #0000))}}.radio{box-shadow:0 1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset;--size:calc(var(--size-selector,.25rem) * 6);width:var(--size);height:var(--size);color:var(--input-color,currentColor)}.radio:before{--tw-content:"";content:var(--tw-content);background-size:auto, calc(var(--noise) * 100%);background-image:none, var(--fx-noise);border-radius:3.40282e38px;width:100%;height:100%;display:block}.radio:focus-visible{outline:2px solid}.radio:checked,.radio[aria-checked=true]{background-color:var(--color-base-100);border-color:currentColor}@media (prefers-reduced-motion:no-preference){.radio:checked,.radio[aria-checked=true]{animation:.2s ease-out radio}}:is(.radio:checked,.radio[aria-checked=true]):before{box-shadow:0 -1px oklch(0% 0 0 / calc(var(--depth) * .1)) inset, 0 8px 0 -4px oklch(100% 0 0 / calc(var(--depth) * .1)) inset, 0 1px oklch(0% 0 0 / calc(var(--depth) * .1));background-color:currentColor}@media (forced-colors:active){:is(.radio:checked,.radio[aria-checked=true]):before{outline-style:var(--tw-outline-style);outline-offset:calc(1px * -1);outline-width:1px}}@media print{:is(.radio:checked,.radio[aria-checked=true]):before{outline-offset:-1rem;outline:.25rem solid}}.rating{vertical-align:middle;--size:var(--size-selector,.25rem) * 6;display:inline-flex;position:relative}.rating input{cursor:pointer;appearance:none}.rating *{background-color:var(--color-base-content);opacity:.2;width:calc(var(--size) * 1);height:calc(var(--size));border-radius:0}@media (prefers-reduced-motion:no-preference){.rating *{animation:.25s ease-out rating}}.rating .rating-hidden{background-color:#0000;width:.5rem}.rating :checked,.rating [aria-checked=true],.rating [aria-current=true],.rating :has(~:checked,~[aria-checked=true],~[aria-current=true]){opacity:1}.rating :focus-visible{scale:1.1}@media (prefers-reduced-motion:no-preference){.rating :focus-visible{transition:scale .2s ease-out}}.rating :active:focus{animation:none;scale:1.1}.card{border-radius:var(--radius-box);outline-offset:2px;outline:2px solid #0000;flex-direction:column;transition:outline .2s ease-in-out;display:flex;position:relative}.card:focus-visible,.card[aria-checked=true],.card:has(>:checked,>:is([type=checkbox],[type=radio]):focus-visible){outline-color:currentColor}.card:has(>:checked:focus-visible),.card[aria-checked=true]:focus-visible,.card[aria-checked=true]:has(>:is([type=checkbox],[type=radio]):focus-visible){outline-width:4px}.card:has(>:is([type=checkbox],[type=radio])){cursor:pointer;-webkit-user-select:none;user-select:none}.card>:is([type=checkbox],[type=radio]){appearance:none}.progress{appearance:none;border-radius:var(--radius-box);background-color:currentColor;width:100%;height:.5rem;position:relative;overflow:hidden}@supports (color:color-mix(in lab, red, red)){.progress{background-color:color-mix(in oklab, currentcolor 20%, transparent)}}.progress{color:var(--color-base-content)}.progress:indeterminate{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,#0000 10% 90%);background-position-x:15%;background-size:200%}@media (prefers-reduced-motion:no-preference){.progress:indeterminate{animation:5s ease-in-out infinite progress}}@supports ((-moz-appearance:none)){.progress:indeterminate::-moz-progress-bar{background-color:#0000}@media (prefers-reduced-motion:no-preference){.progress:indeterminate::-moz-progress-bar{background-image:repeating-linear-gradient(90deg,currentColor -1% 10%,#0000 10% 90%);background-position-x:15%;background-size:200%;animation:5s ease-in-out infinite progress}}.progress::-moz-progress-bar{border-radius:var(--radius-box);background-color:currentColor}}@supports ((-webkit-appearance:none)){.progress::-webkit-progress-bar{border-radius:var(--radius-box);background-color:#0000}.progress::-webkit-progress-value{border-radius:var(--radius-box);background-color:currentColor}}.textarea{appearance:none;border-radius:var(--radius-field);background-color:var(--color-base-100);vertical-align:middle;--input-color:var(--color-base-content);flex-shrink:1;min-height:5rem;padding-block:.5rem;padding-inline:.75rem}@supports (color:color-mix(in lab, red, red)){.textarea{--input-color:color-mix(in oklab, var(--color-base-content) 20%, #0000)}}.textarea{width:clamp(3rem,20rem,100%);font-size:max(var(--font-size,0rem), var(--font-size-min));touch-action:manipulation;border:var(--border) solid var(--input-color,#0000);box-shadow:0 1px var(--input-color) inset, 0 -1px oklch(100% 0 0 / calc(var(--depth) * .1)) inset}@supports (color:color-mix(in lab, red, red)){.textarea{box-shadow:0 1px color-mix(in oklab, var(--input-color) calc(var(--depth) * 10%), #0000) inset, 0 -1px oklch(100% 0 0 / calc(var(--depth) * .1)) inset}}.textarea textarea{appearance:none;background-color:#0000;border:none}.textarea textarea::placeholder{color:var(--color-base-content);opacity:.5}.textarea textarea:focus,.textarea textarea:focus-within{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.textarea textarea:focus,.textarea textarea:focus-within{outline-offset:2px;outline:2px solid #0000}}.textarea:focus,.textarea:focus-within{--input-color:var(--color-base-content);box-shadow:0 1px var(--input-color)}@supports (color:color-mix(in lab, red, red)){.textarea:focus,.textarea:focus-within{box-shadow:0 1px color-mix(in oklab, var(--input-color) calc(var(--depth) * 10%), #0000)}}.textarea:focus,.textarea:focus-within{outline:2px solid var(--input-color);outline-offset:2px;isolation:isolate}@media (pointer:coarse){@supports (-webkit-touch-callout:none){.textarea:focus,.textarea:focus-within{--font-size:1rem}}}.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]){cursor:not-allowed;border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]){color:color-mix(in oklab, var(--color-base-content) 40%, transparent)}}.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]){box-shadow:none}:is(.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled]))::placeholder,:is(.textarea:has(>textarea[disabled]),.textarea:is(:disabled,[disabled])) ::placeholder{color:var(--color-base-content);opacity:.2}.textarea:has(>textarea[disabled])>textarea[disabled]{cursor:not-allowed}.stack{grid-template-rows:3px 4px 1fr 4px 3px;grid-template-columns:3px 4px 1fr 4px 3px;display:inline-grid}.stack>*{width:100%;height:100%}.stack>:nth-child(n+2){opacity:.7;width:100%}.stack>:nth-child(2){z-index:2;opacity:.9}.stack>:first-child{z-index:3;width:100%}.tab-content{order:var(--tabcontent-order);--tabcontent-radius-ss:var(--radius-box);--tabcontent-radius-se:var(--radius-box);--tabcontent-radius-es:var(--radius-box);--tabcontent-radius-ee:var(--radius-box);--tabcontent-order:1;width:100%;height:calc(100% - var(--tab-height) + var(--border));margin:var(--tabcontent-margin);border-color:#0000;border-width:var(--border);border-start-start-radius:var(--tabcontent-radius-ss);border-start-end-radius:var(--tabcontent-radius-se);border-end-end-radius:var(--tabcontent-radius-ee);border-end-start-radius:var(--tabcontent-radius-es);display:none}.modal-box{background-color:var(--color-base-100);border-top-left-radius:var(--modal-tl,var(--radius-box));border-top-right-radius:var(--modal-tr,var(--radius-box));border-bottom-left-radius:var(--modal-bl,var(--radius-box));border-bottom-right-radius:var(--modal-br,var(--radius-box));opacity:0;overscroll-behavior:contain;grid-row-start:1;grid-column-start:1;width:91.6667%;max-width:32rem;max-height:100vh;padding:1.5rem;transition:translate .3s ease-out,scale .3s ease-out,opacity .2s ease-out 50ms,box-shadow .3s ease-out;overflow-y:auto;scale:.95;box-shadow:0 25px 50px -12px oklch(0% 0 0/.25)}.breadcrumbs{max-width:100%;padding-block:.5rem;overflow-x:auto}.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol{white-space:nowrap;align-items:center;min-height:min-content;display:flex}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li{align-items:center;display:flex}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>*{cursor:pointer;align-items:center;gap:.5rem;display:flex}@media (hover:hover){:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:hover{text-decoration-line:underline}}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:focus{outline-offset:2px;outline:2px solid #0000}}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li>:focus-visible{outline-offset:2px;outline:2px solid}:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li+:before{content:"";opacity:.4;background-color:#0000;border-top:1px solid;border-right:1px solid;width:.375rem;height:.375rem;margin-inline:.5rem .75rem;display:block;rotate:45deg}[dir=rtl] :is(:is(.breadcrumbs>menu,.breadcrumbs>ul,.breadcrumbs>ol)>li)+:before{rotate:-135deg}.label{white-space:nowrap;color:currentColor;align-items:center;gap:.375rem;display:inline-flex}@supports (color:color-mix(in lab, red, red)){.label{color:color-mix(in oklab, currentcolor 60%, transparent)}}.label:has(input){cursor:pointer}.label:is(.input>*,.select>*){white-space:nowrap;height:calc(100% - .5rem);font-size:inherit;align-items:center;padding-inline:.75rem;display:flex}.label:is(.input>*,.select>*):first-child{border-inline-end:var(--border) solid currentColor;margin-inline:-.75rem .75rem}@supports (color:color-mix(in lab, red, red)){.label:is(.input>*,.select>*):first-child{border-inline-end:var(--border) solid color-mix(in oklab, currentColor 10%, #0000)}}.label:is(.input>*,.select>*):last-child{border-inline-start:var(--border) solid currentColor;margin-inline:.75rem -.75rem}@supports (color:color-mix(in lab, red, red)){.label:is(.input>*,.select>*):last-child{border-inline-start:var(--border) solid color-mix(in oklab, currentColor 10%, #0000)}}.status{aspect-ratio:1;border-radius:var(--radius-selector);background-color:var(--color-base-content);width:.5rem;height:.5rem;display:inline-block}@supports (color:color-mix(in lab, red, red)){.status{background-color:color-mix(in oklab, var(--color-base-content) 20%, transparent)}}.status{vertical-align:middle;color:#0000004d;background-position:50%;background-repeat:no-repeat}@supports (color:color-mix(in lab, red, red)){.status{color:color-mix(in oklab, var(--color-black) 30%, transparent)}}.status{background-image:radial-gradient(circle at 35% 30%, oklch(1 0 0 / calc(var(--depth) * .5)), #0000);box-shadow:0 2px 3px -1px}@supports (color:color-mix(in lab, red, red)){.status{box-shadow:0 2px 3px -1px color-mix(in oklab, currentColor calc(var(--depth) * 100%), #0000)}}.badge{border-radius:var(--radius-selector);vertical-align:middle;color:var(--badge-fg);border:var(--border) solid var(--badge-color,var(--color-base-200));background-size:auto, calc(var(--noise) * 100%);background-image:none, var(--fx-noise);background-color:var(--badge-bg);--badge-bg:var(--badge-color,var(--color-base-100));--badge-fg:var(--color-base-content);--size:calc(var(--size-selector,.25rem) * 6);width:fit-content;height:var(--size);padding-inline:calc(var(--size) / 2 - var(--border));justify-content:center;align-items:center;gap:.5rem;font-size:.875rem;display:inline-flex}.alert{--alert-border-color:var(--color-base-200);border-radius:var(--radius-box);color:var(--color-base-content);background-color:var(--alert-color,var(--color-base-200));text-align:start;background-size:auto, calc(var(--noise) * 33%);background-image:none, var(--fx-noise);box-shadow:0 3px 0 -2px oklch(100% 0 0 / calc(var(--depth) * .08)) inset, 0 1px #000, 0 4px 3px -2px oklch(0% 0 0 / calc(var(--depth) * .08));border-style:solid;grid-template-columns:auto;grid-auto-flow:column;justify-content:start;place-items:center start;gap:1rem;padding-block:.75rem;padding-inline:1rem;font-size:.875rem;line-height:1.25rem;display:grid}@supports (color:color-mix(in lab, red, red)){.alert{box-shadow:0 3px 0 -2px oklch(100% 0 0 / calc(var(--depth) * .08)) inset, 0 1px color-mix(in oklab, color-mix(in oklab, #000 20%, var(--alert-color,var(--color-base-200))) calc(var(--depth) * 20%), #0000), 0 4px 3px -2px oklch(0% 0 0 / calc(var(--depth) * .08))}}.alert:has(:nth-child(2)){grid-template-columns:auto minmax(auto,1fr)}.skeleton{border-radius:var(--radius-box);background-color:var(--color-base-300)}@media (prefers-reduced-motion:reduce){.skeleton{transition-duration:15s}}.skeleton{will-change:background-position;background-image:linear-gradient(105deg, #0000 0% 40%, var(--color-base-100) 50%, #0000 60% 100%);background-position-x:-50%;background-size:200%}@media (prefers-reduced-motion:no-preference){.skeleton{animation:1.8s ease-in-out infinite skeleton}}.link{cursor:pointer;text-decoration-line:underline}.link:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.link:focus{outline-offset:2px;outline:2px solid #0000}}.link:focus-visible{outline-offset:2px;outline:2px solid}.btn-outline{--btn-bg:#0000;color:var(--btn-rest-fg,var(--btn-color,var(--color-base-content)));--btn-border:var(--btn-color,var(--color-base-content));--btn-border-style:solid;--btn-inset:0 0 0 0 oklch(0% 0 0/0);--btn-shadow:0 0 0 0 oklch(0% 0 0/0);background-image:none}.btn-soft{--btn-bg:var(--btn-color,var(--color-base-content))}@supports (color:color-mix(in lab, red, red)){.btn-soft{--btn-bg:color-mix(in oklab, var(--btn-color,var(--color-base-content)) 8%, var(--btn-soft-bg,var(--color-base-100)))}}.btn-soft{color:var(--btn-rest-fg,var(--btn-color,var(--color-base-content)));--btn-border:var(--btn-color,var(--color-base-content))}@supports (color:color-mix(in lab, red, red)){.btn-soft{--btn-border:color-mix(in oklab, var(--btn-color,var(--color-base-content)) 10%, var(--btn-soft-bg,var(--color-base-100)))}}.btn-soft{--btn-border-style:solid;--btn-inset:0 0 0 0 oklch(0% 0 0/0);--btn-shadow:0 0 0 0 oklch(0% 0 0/0);background-image:none}.btn-ghost{--btn-bg:#0000;color:var(--btn-rest-fg,var(--btn-color,var(--color-base-content,currentColor)));--btn-border:#0000;--btn-inset:0 0 0 0 oklch(0% 0 0/0);--btn-shadow:0 0 0 0 oklch(0% 0 0/0);background-image:none}.menu-title{color:var(--color-base-content);padding-block:.5rem;padding-inline:.75rem}@supports (color:color-mix(in lab, red, red)){.menu-title{color:color-mix(in oklab, var(--color-base-content) 40%, transparent)}}.menu-title{font-size:.875rem;font-weight:600}}@layer daisyui.l1.l2{.modal.modal-open,.modal[open],.modal:target,.modal-toggle:checked+.modal{pointer-events:auto;visibility:visible;opacity:1;transition:visibility 0s allow-discrete, background-color .3s ease-out, opacity .1s ease-out;background-color:oklch(0% 0 0/.4)}.modal:popover-open{pointer-events:auto;visibility:visible;opacity:1;transition:visibility 0s allow-discrete, background-color .3s ease-out, opacity .1s ease-out;background-color:oklch(0% 0 0/.4)}.modal:popover-open .modal-box{opacity:1;translate:0;scale:1}:root:has(.modal:popover-open){--page-scroll-lock: }:is(.modal.modal-open,.modal[open],.modal:target,.modal-toggle:checked+.modal) .modal-box{opacity:1;translate:0;scale:1}:root:has(:is(.modal.modal-open,.modal[open],.modal:target,.modal-toggle:checked+.modal)){--page-scroll-lock: }@starting-style{.modal.modal-open,.modal[open],.modal:target,.modal-toggle:checked+.modal{opacity:0}.modal:popover-open{opacity:0}}.collapse-arrow>.collapse-title:after{width:.5rem;height:.5rem;display:block;position:absolute;transform:translateY(-100%)rotate(45deg)}@media (prefers-reduced-motion:no-preference){.collapse-arrow>.collapse-title:after{transition-property:all;transition-duration:.2s;transition-timing-function:cubic-bezier(.4,0,.2,1)}}.collapse-arrow>.collapse-title:after{content:"";transform-origin:75% 75%;pointer-events:none;top:50%;inset-inline-end:1.4rem;box-shadow:2px 2px}@media (prefers-reduced-motion:no-preference){.collapse[open].collapse-arrow>.collapse-title:after,.collapse.collapse-open.collapse-arrow>.collapse-title:after{transform:translateY(-50%)rotate(225deg)}}.collapse.collapse-open.collapse-plus>.collapse-title:after{--tw-content:"\u2212";content:var(--tw-content)}:is(.collapse[tabindex].collapse-arrow:focus:not(.collapse-close),.collapse.collapse-arrow[tabindex]:focus-within:not(.collapse-close))>.collapse-title:after,.collapse.collapse-arrow:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{transform:translateY(-50%)rotate(225deg)}.collapse[open].collapse-plus>.collapse-title:after,.collapse[tabindex].collapse-plus:focus:not(.collapse-close)>.collapse-title:after,.collapse.collapse-plus:not(.collapse-close)>input:is([type=checkbox],[type=radio]):checked~.collapse-title:after{--tw-content:"\u2212";content:var(--tw-content)}.list .list-row:has(.list-col-grow:first-child){--list-grid-cols:1fr}.list .list-row:has(.list-col-grow:nth-child(2)){--list-grid-cols:minmax(0, auto) 1fr}.list .list-row:has(.list-col-grow:nth-child(3)){--list-grid-cols:minmax(0, auto) minmax(0, auto) 1fr}.list .list-row:has(.list-col-grow:nth-child(4)){--list-grid-cols:minmax(0, auto) minmax(0, auto) minmax(0, auto) 1fr}.list .list-row:has(.list-col-grow:nth-child(5)){--list-grid-cols:minmax(0, auto) minmax(0, auto) minmax(0, auto) minmax(0, auto) 1fr}.list .list-row:has(.list-col-grow:nth-child(6)){--list-grid-cols:minmax(0, auto) minmax(0, auto) minmax(0, auto) minmax(0, auto) minmax(0, auto) 1fr}.list .list-row>*{grid-row-start:1}.input{--in-size-mul:10;--font-size-min:.875rem;--spin-my:-3}.floating-label:has(.input){--top-mul:5;--font-size:.875rem}.steps .step-neutral+.step-neutral:before,.steps .step-neutral:after,.steps .step-neutral>.step-icon{--step-bg:var(--color-neutral);--step-fg:var(--color-neutral-content)}.steps .step-primary+.step-primary:before,.steps .step-primary:after,.steps .step-primary>.step-icon{--step-bg:var(--color-primary);--step-fg:var(--color-primary-content)}.steps .step-secondary+.step-secondary:before,.steps .step-secondary:after,.steps .step-secondary>.step-icon{--step-bg:var(--color-secondary);--step-fg:var(--color-secondary-content)}.steps .step-accent+.step-accent:before,.steps .step-accent:after,.steps .step-accent>.step-icon{--step-bg:var(--color-accent);--step-fg:var(--color-accent-content)}.steps .step-info+.step-info:before,.steps .step-info:after,.steps .step-info>.step-icon{--step-bg:var(--color-info);--step-fg:var(--color-info-content)}.steps .step-success+.step-success:before,.steps .step-success:after,.steps .step-success>.step-icon{--step-bg:var(--color-success);--step-fg:var(--color-success-content)}.steps .step-warning+.step-warning:before,.steps .step-warning:after,.steps .step-warning>.step-icon{--step-bg:var(--color-warning);--step-fg:var(--color-warning-content)}.steps .step-error+.step-error:before,.steps .step-error:after,.steps .step-error>.step-icon{--step-bg:var(--color-error);--step-fg:var(--color-error-content)}.select{--sl-size-mul:10;--font-size-min:.875rem;--option-px:3}.floating-label:has(.select){--top-mul:5;--font-size:.875rem}.swap{cursor:pointer;vertical-align:middle;webkit-user-select:none;-webkit-user-select:none;user-select:none;place-content:center;display:inline-grid;position:relative}.swap input{appearance:none;border:none}.swap>*{grid-row-start:1;grid-column-start:1}@media (prefers-reduced-motion:no-preference){.swap>*{transition-property:transform,rotate,opacity;transition-duration:.2s;transition-timing-function:cubic-bezier(0,0,.2,1)}}.swap .swap-on,.swap .swap-indeterminate,.swap input:indeterminate~.swap-on,.swap input:is(:checked,:indeterminate)~.swap-off{opacity:0}.swap input:checked~.swap-on,.swap input:indeterminate~.swap-indeterminate{opacity:1;backface-visibility:visible}.radio:disabled{cursor:not-allowed;opacity:.2}.rating{--size:var(--size-selector,.25rem) * 6}.textarea{--font-size-min:.875rem}.floating-label:has(.textarea){--top-mul:5;--font-size:.875rem}:is(.stack,.stack.stack-bottom)>*{grid-area:3/3/6/4}:is(.stack,.stack.stack-bottom)>:nth-child(2){grid-area:2/2/5/5}:is(.stack,.stack.stack-bottom)>:first-child{grid-area:1/1/4/6}.stack.stack-top>*{grid-area:1/3/4/4}.stack.stack-top>:nth-child(2){grid-area:2/2/5/5}.stack.stack-top>:first-child{grid-area:3/1/6/6}.stack.stack-start>*{grid-area:3/1/4/4}.stack.stack-start>:nth-child(2){grid-area:2/2/5/5}.stack.stack-start>:first-child{grid-area:1/3/6/6}.stack.stack-end>*{grid-area:3/3/4/6}.stack.stack-end>:nth-child(2){grid-area:2/2/5/5}.stack.stack-end>:first-child{grid-area:1/1/6/4}.btn-square{width:var(--size);height:var(--size);padding-inline:0}.btn-block{width:100%}.loading-md{width:calc(var(--size-selector,.25rem) * 6)}.aura-glow{background-image:radial-gradient(closest-corner,currentColor 0%,#0000 90%);animation:none}.aura-glow:before{animation:aura-glow var(--tw-duration,6s) ease-out infinite}.aura-glow:after{animation:aura-glow-after var(--tw-duration,6s) ease-out infinite}.menu-sm :where(li:not(.menu-title)>:not(ul,menu,details,.menu-title)),.menu-sm :where(li:not(.menu-title)>details>summary:not(.menu-title)){border-radius:var(--radius-field);padding-block:.25rem;padding-inline:.625rem;font-size:.75rem}.menu-sm .menu-title{padding-block:.5rem;padding-inline:.75rem}.badge-ghost{border-color:var(--color-base-200);background-color:var(--color-base-200);color:var(--color-base-content);background-image:none}.loading-spinner{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='8s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='6s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='6s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='8s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='6s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='6s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E")}@media (prefers-reduced-motion:no-preference){.loading-spinner{-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='black' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg transform-origin='center'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3' stroke-linecap='round'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dasharray' values='0,150;42,150;42,150' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-16;-59' keyTimes='0;0.475;1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E")}}.badge-sm{--size:calc(var(--size-selector,.25rem) * 5);font-size:.75rem}.badge-xs{--size:calc(var(--size-selector,.25rem) * 4);font-size:.625rem}.alert-error{color:var(--color-error-content);--alert-border-color:var(--color-error);--alert-color:var(--color-error)}.alert-warning{color:var(--color-warning-content);--alert-border-color:var(--color-warning);--alert-color:var(--color-warning)}.input-sm{--in-size-mul:8;--font-size-min:.75rem;--spin-my:-2}.floating-label:has(.input-sm){--top-mul:4;--font-size:.75rem}.select-sm{--sl-size-mul:8;--font-size-min:.75rem;--option-px:2.5}.floating-label:has(.select-sm){--top-mul:4;--font-size:.75rem}.btn-primary{--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content);--btn-soft-bg:initial}.btn-sm{--fontsize:.75rem;--btn-p:.75rem;--size:calc(var(--size-field,.25rem) * 8)}.badge-neutral{--badge-color:var(--color-neutral);--badge-fg:var(--color-neutral-content)}.badge-success{--badge-color:var(--color-success);--badge-fg:var(--color-success-content)}.card-border{border:var(--border) solid var(--color-base-200)}.input-error,.input-error:focus,.input-error:focus-within{--input-color:var(--color-error)}}@layer daisyui.l1{.btn:where(:checked:not(.filter [type=radio].btn)){--btn-color:var(--color-primary);--btn-fg:var(--color-primary-content)}@media (hover:hover){.btn:hover{--btn-bg:var(--btn-color,var(--color-base-200))}@supports (color:color-mix(in lab, red, red)){.btn:hover{--btn-bg:color-mix(in oklab, var(--btn-color,var(--color-base-200)), #000 7%)}}.btn:hover{color:var(--btn-fg);--btn-border:var(--btn-bg)}@supports (color:color-mix(in lab, red, red)){.btn:hover{--btn-border:color-mix(in oklab, var(--btn-bg), #000 calc(var(--depth) * 5%))}}.btn:hover{--btn-border-style:solid;--btn-inset:0 .5px 0 .5px oklch(100% 0 0 / calc(var(--depth) * 6%));--btn-shadow:0 3px 2px -2px var(--btn-bg), 0 4px 3px -2px var(--btn-bg)}@supports (color:color-mix(in lab, red, red)){.btn:hover{--btn-shadow:0 3px 2px -2px color-mix(in oklab, var(--btn-bg) calc(var(--depth) * 30%), #0000), 0 4px 3px -2px color-mix(in oklab, var(--btn-bg) calc(var(--depth) * 30%), #0000)}}}.btn:active:not(.btn-active){--btn-bg:var(--btn-color,var(--color-base-200));translate:0 .5px}@supports (color:color-mix(in lab, red, red)){.btn:active:not(.btn-active){--btn-bg:color-mix(in oklab, var(--btn-color,var(--color-base-200)), #000 5%)}}.btn:active:not(.btn-active){color:var(--btn-fg,var(--color-base-content));--btn-border:var(--btn-color,var(--color-base-200))}@supports (color:color-mix(in lab, red, red)){.btn:active:not(.btn-active){--btn-border:color-mix(in oklab, var(--btn-color,var(--color-base-200)), #000 7%)}}.btn:active:not(.btn-active){--btn-border-style:solid;--btn-inset:0 0 0 0 oklch(0% 0 0/0);--btn-shadow:0 0 0 0 oklch(0% 0 0/0)}.btn:where(:checked:not(.filter [type=radio].btn),:not([type=radio],[type=checkbox]):focus-visible){--btn-bg:var(--btn-color,var(--color-base-200));color:var(--btn-fg,var(--color-base-content));--btn-border:var(--btn-bg)}@supports (color:color-mix(in lab, red, red)){.btn:where(:checked:not(.filter [type=radio].btn),:not([type=radio],[type=checkbox]):focus-visible){--btn-border:color-mix(in oklab, var(--btn-bg), #000 calc(var(--depth) * 5%))}}.btn:where(:checked:not(.filter [type=radio].btn),:not([type=radio],[type=checkbox]):focus-visible){--btn-border-style:solid;--btn-inset:0 .5px 0 .5px oklch(100% 0 0 / calc(var(--depth) * 6%));--btn-shadow:0 3px 2px -2px var(--btn-bg), 0 4px 3px -2px var(--btn-bg)}@supports (color:color-mix(in lab, red, red)){.btn:where(:checked:not(.filter [type=radio].btn),:not([type=radio],[type=checkbox]):focus-visible){--btn-shadow:0 3px 2px -2px color-mix(in oklab, var(--btn-bg) calc(var(--depth) * 30%), #0000), 0 4px 3px -2px color-mix(in oklab, var(--btn-bg) calc(var(--depth) * 30%), #0000)}}.btn:where(:checked:not(.filter [type=radio].btn),:not([type=radio],[type=checkbox]):focus-visible){isolation:isolate}.btn:focus-visible,.btn:has(:focus-visible){isolation:isolate;outline-width:2px;outline-style:solid}.filter:not(:has(:checked:not(.filter-reset))) :is(.filter-reset,[type=reset]):not(:focus-visible){visibility:hidden}.filter:not(:has(:checked:not(.filter-reset))) :is(.filter-reset,[type=reset]):not(:focus-visible),.filter:not(:has(:focus-visible)):has(:checked:not(.filter-reset,[type=checkbox])) :is(input,button):not(:checked,.filter-reset,[type=reset]){opacity:0;border-width:0;width:0;margin-inline:0;padding-inline:0;scale:0}.alert-soft{color:var(--alert-color,var(--color-base-content));background:var(--alert-color,var(--color-base-content))}@supports (color:color-mix(in lab, red, red)){.alert-soft{background:color-mix(in oklab, var(--alert-color,var(--color-base-content)) 8%, var(--color-base-100))}}.alert-soft{--alert-border-color:var(--alert-color,var(--color-base-content))}@supports (color:color-mix(in lab, red, red)){.alert-soft{--alert-border-color:color-mix(in oklab, var(--alert-color,var(--color-base-content)) 10%, var(--color-base-100))}}.alert-soft{box-shadow:none;background-image:none}}@layer daisyui{.btn:is(:disabled,[disabled],[aria-disabled=true]){pointer-events:none;color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.btn:is(:disabled,[disabled],[aria-disabled=true]){color:color-mix(in oklch, var(--color-base-content) 20%, #0000)}}.btn:is(:disabled,[disabled],[aria-disabled=true]){--btn-bg:#0000;--btn-border:#0000;--btn-inset:0 0 0 0 oklch(0% 0 0/0);--btn-shadow:0 0 0 0 oklch(0% 0 0/0);background-image:none}.btn:is(:disabled,[disabled],[aria-disabled=true]):not(.btn-link,.btn-ghost){background-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.btn:is(:disabled,[disabled],[aria-disabled=true]):not(.btn-link,.btn-ghost){background-color:color-mix(in oklab, var(--color-base-content) 10%, transparent)}}}.pointer-events-none{pointer-events:none}.countdown.countdown{line-height:1em}.collapse:not(td,tr,colgroup){visibility:revert-layer}.collapse{visibility:collapse}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}@layer daisyui.l1.l2.l3.l4{.card figure:first-child{border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-end-radius:unset;border-end-start-radius:unset;overflow:hidden}.card figure:last-child{border-start-start-radius:unset;border-start-end-radius:unset;border-end-end-radius:inherit;border-end-start-radius:inherit;overflow:hidden}.card figure{justify-content:center;align-items:center;display:flex}}.absolute{position:absolute}.fixed{position:fixed}.sticky{position:sticky}.z-10{z-index:10}.col-span-2{grid-column:span 2/span 2}.m-0{margin:0}.mt-0{margin-top:0}.mt-0\\.5{margin-top:calc(var(--spacing) * .5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.alert{border-width:var(--border);border-color:var(--alert-border-color,var(--color-base-200))}:root .prose{--tw-prose-body:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-body:color-mix(in oklab, var(--color-base-content) 80%, #0000)}}:root .prose{--tw-prose-headings:var(--color-base-content);--tw-prose-lead:var(--color-base-content);--tw-prose-links:var(--color-base-content);--tw-prose-bold:var(--color-base-content);--tw-prose-counters:var(--color-base-content);--tw-prose-bullets:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-bullets:color-mix(in oklab, var(--color-base-content) 50%, #0000)}}:root .prose{--tw-prose-hr:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-hr:color-mix(in oklab, var(--color-base-content) 20%, #0000)}}:root .prose{--tw-prose-quotes:var(--color-base-content);--tw-prose-quote-borders:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-quote-borders:color-mix(in oklab, var(--color-base-content) 20%, #0000)}}:root .prose{--tw-prose-captions:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-captions:color-mix(in oklab, var(--color-base-content) 50%, #0000)}}:root .prose{--tw-prose-code:var(--color-base-content);--tw-prose-pre-code:var(--color-neutral-content);--tw-prose-pre-bg:var(--color-neutral);--tw-prose-th-borders:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-th-borders:color-mix(in oklab, var(--color-base-content) 50%, #0000)}}:root .prose{--tw-prose-td-borders:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-td-borders:color-mix(in oklab, var(--color-base-content) 20%, #0000)}}:root .prose{--tw-prose-kbd:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){:root .prose{--tw-prose-kbd:color-mix(in oklab, var(--color-base-content) 80%, #0000)}}:root .prose :where(code):not(pre>code){background-color:var(--color-base-200);border-radius:var(--radius-selector);border:var(--border) solid var(--color-base-300);font-weight:inherit;padding-block:.2em;padding-inline:.5em}:root .prose :where(code):not(pre>code):before,:root .prose :where(code):not(pre>code):after{display:none}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.aspect-square{aspect-ratio:1}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-10{width:calc(var(--spacing) * 10);height:calc(var(--spacing) * 10)}.size-12{width:calc(var(--spacing) * 12);height:calc(var(--spacing) * 12)}.size-\\[52px\\]{width:52px;height:52px}.h-11{height:calc(var(--spacing) * 11)}.h-auto{height:auto}.max-h-\\[min\\(66vh\\,720px\\)\\]{max-height:min(66vh,720px)}.min-h-0{min-height:0}.min-h-6{min-height:calc(var(--spacing) * 6)}.min-h-7{min-height:calc(var(--spacing) * 7)}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-14{min-height:calc(var(--spacing) * 14)}.min-h-\\[120px\\]{min-height:120px}.w-\\[min\\(148px\\,38vw\\)\\]{width:min(148px,38vw)}.w-\\[min\\(200px\\,100\\%\\)\\]{width:min(200px,100%)}.w-auto{width:auto}.w-full{width:100%}.max-w-\\[min\\(148px\\,38vw\\)\\]{max-width:min(148px,38vw)}.max-w-\\[min\\(440px\\,100\\%\\)\\]{max-width:min(440px,100%)}.max-w-full{max-width:100%}.min-w-0{min-width:0}.min-w-\\[min\\(240px\\,100\\%\\)\\]{min-width:min(240px,100%)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\\[1fr_auto\\]{grid-template-columns:1fr auto}.grid-cols-\\[auto_minmax\\(0\\,1fr\\)\\]{grid-template-columns:auto minmax(0,1fr)}.grid-cols-\\[minmax\\(0\\,1fr\\)_auto\\]{grid-template-columns:minmax(0,1fr) auto}.grid-rows-\\[0fr\\]{grid-template-rows:0fr}.grid-rows-\\[1fr\\]{grid-template-rows:1fr}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.content-start{align-content:flex-start}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.justify-items-start{justify-items:start}.gap-0{gap:0}.gap-0\\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-y-1{row-gap:var(--spacing)}.gap-y-1\\.5{row-gap:calc(var(--spacing) * 1.5)}.justify-self-center{justify-self:center}.justify-self-end{justify-self:flex-end}.justify-self-start{justify-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-box{border-radius:var(--radius-box);border-radius:var(--radius-box)}.rounded-field{border-radius:var(--radius-field);border-radius:var(--radius-field)}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-base-300{border-color:var(--color-base-300)}.border-base-content,.border-base-content\\/15{border-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.border-base-content\\/15{border-color:color-mix(in oklab, var(--color-base-content) 15%, transparent)}}.border-base-content\\/20{border-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.border-base-content\\/20{border-color:color-mix(in oklab, var(--color-base-content) 20%, transparent)}}.border-base-content\\/25{border-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.border-base-content\\/25{border-color:color-mix(in oklab, var(--color-base-content) 25%, transparent)}}.border-base-content\\/30{border-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.border-base-content\\/30{border-color:color-mix(in oklab, var(--color-base-content) 30%, transparent)}}.border-info,.border-info\\/40{border-color:var(--color-info)}@supports (color:color-mix(in lab, red, red)){.border-info\\/40{border-color:color-mix(in oklab, var(--color-info) 40%, transparent)}}.border-primary{border-color:var(--color-primary)}.border-secondary{border-color:var(--color-secondary)}.border-success,.border-success\\/40{border-color:var(--color-success)}@supports (color:color-mix(in lab, red, red)){.border-success\\/40{border-color:color-mix(in oklab, var(--color-success) 40%, transparent)}}.border-warning{border-color:var(--color-warning)}.bg-base-100{background-color:var(--color-base-100)}.bg-base-200{background-color:var(--color-base-200)}.bg-info,.bg-info\\/10{background-color:var(--color-info)}@supports (color:color-mix(in lab, red, red)){.bg-info\\/10{background-color:color-mix(in oklab, var(--color-info) 10%, transparent)}}.bg-primary,.bg-primary\\/10{background-color:var(--color-primary)}@supports (color:color-mix(in lab, red, red)){.bg-primary\\/10{background-color:color-mix(in oklab, var(--color-primary) 10%, transparent)}}.bg-secondary,.bg-secondary\\/10{background-color:var(--color-secondary)}@supports (color:color-mix(in lab, red, red)){.bg-secondary\\/10{background-color:color-mix(in oklab, var(--color-secondary) 10%, transparent)}}.bg-success,.bg-success\\/10{background-color:var(--color-success)}@supports (color:color-mix(in lab, red, red)){.bg-success\\/10{background-color:color-mix(in oklab, var(--color-success) 10%, transparent)}}.bg-warning,.bg-warning\\/10{background-color:var(--color-warning)}@supports (color:color-mix(in lab, red, red)){.bg-warning\\/10{background-color:color-mix(in oklab, var(--color-warning) 10%, transparent)}}.stroke-current{stroke:currentColor}.object-contain{object-fit:contain}.p-0{padding:0}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:var(--spacing)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-1{padding-block:var(--spacing)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-4{padding-block:calc(var(--spacing) * 4)}.pl-3{padding-left:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[0\\.65rem\\]{font-size:.65rem}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.text-base-content,.text-base-content\\/55{color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.text-base-content\\/55{color:color-mix(in oklab, var(--color-base-content) 55%, transparent)}}.text-base-content\\/60{color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.text-base-content\\/60{color:color-mix(in oklab, var(--color-base-content) 60%, transparent)}}.text-base-content\\/65{color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.text-base-content\\/65{color:color-mix(in oklab, var(--color-base-content) 65%, transparent)}}.text-base-content\\/70{color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.text-base-content\\/70{color:color-mix(in oklab, var(--color-base-content) 70%, transparent)}}.text-error{color:var(--color-error)}.text-info-content{color:var(--color-info-content)}.text-success{color:var(--color-success)}.text-success-content{color:var(--color-success-content)}.text-warning{color:var(--color-warning)}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.prose :where(a.btn:not(.btn-link)):not(:where([class~=not-prose],[class~=not-prose] *)){text-decoration-line:none}.underline{text-decoration-line:underline}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring,.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-info,.ring-info\\/50{--tw-ring-color:var(--color-info)}@supports (color:color-mix(in lab, red, red)){.ring-info\\/50{--tw-ring-color:color-mix(in oklab, var(--color-info) 50%, transparent)}}.ring-primary,.ring-primary\\/30{--tw-ring-color:var(--color-primary)}@supports (color:color-mix(in lab, red, red)){.ring-primary\\/30{--tw-ring-color:color-mix(in oklab, var(--color-primary) 30%, transparent)}}.ring-primary\\/50{--tw-ring-color:var(--color-primary)}@supports (color:color-mix(in lab, red, red)){.ring-primary\\/50{--tw-ring-color:color-mix(in oklab, var(--color-primary) 50%, transparent)}}.ring-secondary,.ring-secondary\\/50{--tw-ring-color:var(--color-secondary)}@supports (color:color-mix(in lab, red, red)){.ring-secondary\\/50{--tw-ring-color:color-mix(in oklab, var(--color-secondary) 50%, transparent)}}.ring-success,.ring-success\\/50{--tw-ring-color:var(--color-success)}@supports (color:color-mix(in lab, red, red)){.ring-success\\/50{--tw-ring-color:color-mix(in oklab, var(--color-success) 50%, transparent)}}.ring-warning,.ring-warning\\/50{--tw-ring-color:var(--color-warning)}@supports (color:color-mix(in lab, red, red)){.ring-warning\\/50{--tw-ring-color:color-mix(in oklab, var(--color-warning) 50%, transparent)}}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[grid-template-rows\\,opacity\\,margin\\]{transition-property:grid-template-rows,opacity,margin;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.outline-none\\!{--tw-outline-style:none!important;outline-style:none!important}.select-all{-webkit-user-select:all;user-select:all}@media (hover:hover){.hover\\:border-base-content\\/45:hover{border-color:var(--color-base-content)}@supports (color:color-mix(in lab, red, red)){.hover\\:border-base-content\\/45:hover{border-color:color-mix(in oklab, var(--color-base-content) 45%, transparent)}}.hover\\:border-primary:hover{border-color:var(--color-primary)}.hover\\:bg-base-100:hover{background-color:var(--color-base-100)}}.focus\\:outline-offset-0\\!:focus{outline-offset:0px!important}.focus\\:outline-none\\!:focus{--tw-outline-style:none!important;outline-style:none!important}.focus-visible\\:outline:focus-visible{outline-style:var(--tw-outline-style);outline-width:1px}.focus-visible\\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\\:outline-primary:focus-visible{outline-color:var(--color-primary)}@media (prefers-reduced-motion:reduce){.motion-reduce\\:transition-none{transition-property:none}}@media (min-width:390px){.min-\\[390px\\]\\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:40rem){.sm\\:col-span-2{grid-column:span 2/span 2}.sm\\:block{display:block}.sm\\:hidden{display:none}.sm\\:size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.sm\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\\:gap-3{gap:calc(var(--spacing) * 3)}.sm\\:p-5{padding:calc(var(--spacing) * 5)}.sm\\:px-4{padding-inline:calc(var(--spacing) * 4)}.sm\\:px-5{padding-inline:calc(var(--spacing) * 5)}.sm\\:text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.sm\\:text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}}@media (min-width:48rem){.md\\:col-span-1{grid-column:span 1/span 1}.md\\:w-\\[min\\(180px\\,100\\%\\)\\]{width:min(180px,100%)}.md\\:w-\\[min\\(200px\\,36vw\\)\\]{width:min(200px,36vw)}.md\\:w-auto{width:auto}.md\\:max-w-\\[min\\(200px\\,36vw\\)\\]{max-width:min(200px,36vw)}.md\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\\:grid-cols-\\[auto_minmax\\(0\\,1fr\\)\\]{grid-template-columns:auto minmax(0,1fr)}.md\\:grid-cols-\\[minmax\\(0\\,1fr\\)_auto_auto\\]{grid-template-columns:minmax(0,1fr) auto auto}.md\\:items-start{align-items:flex-start}.md\\:gap-x-2{column-gap:calc(var(--spacing) * 2)}.md\\:gap-x-5{column-gap:calc(var(--spacing) * 5)}.md\\:gap-y-1{row-gap:var(--spacing)}.md\\:justify-self-end{justify-self:flex-end}.md\\:justify-self-start{justify-self:flex-start}.md\\:text-left{text-align:left}}@media (min-width:64rem){.lg\\:col-span-4{grid-column:span 4/span 4}.lg\\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\\:grid-cols-\\[9rem_minmax\\(0\\,1fr\\)_minmax\\(8rem\\,auto\\)\\]{grid-template-columns:9rem minmax(0,1fr) minmax(8rem,auto)}.lg\\:items-start{align-items:flex-start}}.\\[\\&_svg\\]\\:block svg{display:block}.\\[\\&_svg\\]\\:h-auto svg{height:auto}.\\[\\&_svg\\]\\:w-full svg{width:100%}}:host{display:block}:host([hidden]){display:none}@keyframes dropdown{0%{opacity:0}}@keyframes rotator{89.9999%,to{--first-item-position:0 0%}90%,99.9999%{--first-item-position:0 calc(var(--items) * 100%)}to{translate:0 -100%}}@keyframes radio{0%{padding:5px}50%{padding:3px}}@keyframes toast{0%{opacity:0;scale:.9}to{opacity:1;scale:1}}@keyframes skeleton{0%{background-position:150%}to{background-position:-50%}}@keyframes progress{50%{background-position-x:-115%}}@keyframes rating{0%,40%{filter:brightness(1.05)contrast(1.05);scale:1.1}}@keyframes aura{to{--aura-angle:360deg;transform:translateZ(1px)}}@keyframes aura-glow{20%,80%{opacity:.7;filter:blur(.25rem)}50%{opacity:1;filter:blur(.75rem)}}@keyframes aura-glow-after{20%,80%{opacity:.3;filter:blur(1rem)}50%{opacity:.6;filter:blur(1.5rem)}}@keyframes menu{0%{opacity:0}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}`;
392
+
393
+ // src/internal/labels.ts
394
+ var checkoutLabels = {
395
+ copyInvoice: "Copy invoice",
396
+ copied: "Copied!",
397
+ openWallet: "Open Wallet",
398
+ bitcoinLightningInvoice: "Bitcoin Lightning invoice",
399
+ paymentStatus: {
400
+ waitingTitle: "Waiting for payment",
401
+ waitingDetail: "Keep this page open while we verify settlement.",
402
+ settledTitle: "Payment received",
403
+ settledDetail: "Backend settlement verified.",
404
+ expiredTitle: "Invoice expired",
405
+ expiredDetail: "Create a fresh invoice to keep going."
406
+ },
407
+ countdownPrefix: "Invoice expires in",
408
+ startOver: "Start over",
409
+ wizardTitle: "Pay this invoice",
410
+ wizardSubtitle: "Choose how you want to pay.",
411
+ paymentMethod: "Payment method",
412
+ /** Breadcrumb back-link once a method (or swap) is already selected. */
413
+ switchPaymentMethod: "Switch payment method",
414
+ loadingCurrencies: "Loading currencies...",
415
+ emptyBitcoin: "Choose Bitcoin Lightning.",
416
+ viewPaymentData: "View payment data",
417
+ openProvider: "How To Pay",
418
+ tutorialTitlePrefix: "Pay a Lightning invoice with",
419
+ tutorialIntroPrefix: "It's easy to make this payment using",
420
+ tutorialIntroCopy: "The first step is to copy the invoice to your clipboard.",
421
+ tutorialCopiedContinue: "Copied! Click next below to continue with tutorial.",
422
+ tutorialExit: "Exit",
423
+ lightningNetwork: "Lightning Network",
424
+ chooseNetwork: "Choose network",
425
+ selectNetwork: "Select network",
426
+ continue: "Continue",
427
+ preparingPayment: "Preparing payment",
428
+ networkSummary: "{asset} will be sent on {network}.",
429
+ chooseAssetNetwork: "Choose {asset} network",
430
+ selectNetworkToContinue: "Select a network to continue",
431
+ transactionDetails: "Transaction details",
432
+ viewOnExplorer: "Explorer",
433
+ decodeInvoice: "Decode",
434
+ wrongCurrencyOrNetworkTitle: "Wrong currency or network = lost funds",
435
+ // Payer-facing copy the two renderers (React elements, element HTML) both
436
+ // emit. The dual-renderer architecture is deliberate; duplicated strings are
437
+ // not — the drift it already caused was React's hardcoded "Preparing..." next
438
+ // to the element's `preparingPayment`. tests/wrapper-parity.test.mjs holds the
439
+ // line.
440
+ swapStartFailedTitle: "Could not prepare the payment address",
441
+ tryAgain: "Try again",
442
+ payWithLightningInstead: "Pay with Lightning instead",
443
+ supportReviewNeeded: "This payment needs support review.",
444
+ preparingPaymentAddress: "Preparing payment address",
445
+ preparingPaymentAddressDetail: "Getting your {asset} payment address\u2026",
446
+ createPaymentAddress: "Create {asset} ({network}) payment address",
447
+ paymentBreakdown: "Payment breakdown",
448
+ cartTotal: "Cart total",
449
+ youSend: "You send",
450
+ swapAndNetworkFees: "Swap + network fees",
451
+ refundAddressPlaceholder: "{network} refund address",
452
+ reviewRefundAddress: "Review refund address",
453
+ confirmRefund: "Confirm refund",
454
+ confirmRefundTo: "Confirm refund to {address}.",
455
+ submitting: "Submitting...",
456
+ tutorialBack: "Back",
457
+ tutorialNext: "Next",
458
+ tutorialClose: "Close",
459
+ /** Out-of-range swap asset: both renderers build this panel from one model. */
460
+ swapUnavailableTitle: "{asset} unavailable",
461
+ swapUnavailableFallback: "{asset} is not available for this amount.",
462
+ swapUnavailableMinimumOnly: "Minimum {minimum} {asset}.",
463
+ swapUnavailableRange: "Accepted range: {minimum}\u2013{maximum} {asset}.",
464
+ swapUnavailableHint: "Choose another asset above, or pay the Lightning invoice at the top of this page.",
465
+ /** Shown on the refund screen so the payer can return after closing the tab. */
466
+ refundReturnWarning: "Bookmark this page, or copy its URL. You need it to return to this refund screen."
467
+ };
468
+ var checkoutElementStyles = `:host{display:block}${compiledStyles}`;
469
+ var paymentMethods = [
470
+ {
471
+ id: "bitcoin",
472
+ title: "Bitcoin",
473
+ detail: "Pay from Lightning or send on-chain into a swap."
474
+ }
475
+ ];
476
+ function parseOptionalInteger(value, options = {}) {
477
+ if (value === null || value === void 0 || value === "") return void 0;
478
+ const parsed = Number(value);
479
+ if (!Number.isSafeInteger(parsed) || parsed < 0) {
480
+ throw new RangeError(`${options.label ?? "value"} must be a non-negative safe integer`);
481
+ }
482
+ return parsed;
483
+ }
484
+ function parseBooleanAttribute(value) {
485
+ if (value === null || value === void 0) return void 0;
486
+ return value !== "false";
487
+ }
488
+ function parseResolvedTheme(value) {
489
+ return value === "light" || value === "dark" ? value : void 0;
490
+ }
491
+ function parseThemePreference(value) {
492
+ return value === "light" || value === "dark" || value === "system" ? value : void 0;
493
+ }
494
+ function parsePaymentMethod(value) {
495
+ return value === "bitcoin" ? value : null;
496
+ }
497
+
498
+ // src/internal/checkout-ticker.ts
499
+ import { unixSeconds } from "@openreceive/core";
500
+ function createTransientFeedbackController(options) {
501
+ const delayMs = options.delayMs ?? OPENRECEIVE_COPY_FEEDBACK_MS;
502
+ const setTimeoutFn = options.setTimeout ?? globalThis.setTimeout;
503
+ const clearTimeoutFn = options.clearTimeout ?? globalThis.clearTimeout;
504
+ let timeout;
505
+ const clear = () => {
506
+ if (timeout === void 0) return;
507
+ clearTimeoutFn(timeout);
508
+ timeout = void 0;
509
+ };
510
+ return {
511
+ show(value) {
512
+ clear();
513
+ options.onValue(value);
514
+ timeout = setTimeoutFn(() => {
515
+ timeout = void 0;
516
+ options.onValue(options.resetValue);
517
+ }, delayMs);
518
+ },
519
+ clear
520
+ };
521
+ }
522
+ function createTickingValueController(options) {
523
+ const intervalMs = options.intervalMs ?? 1e3;
524
+ const now = options.now ?? unixSeconds;
525
+ const setIntervalFn = options.setInterval ?? globalThis.setInterval;
526
+ const clearIntervalFn = options.clearInterval ?? globalThis.clearInterval;
527
+ let timer;
528
+ const refresh = () => {
529
+ options.onValue(now());
530
+ };
531
+ const stop = () => {
532
+ if (timer === void 0) return;
533
+ clearIntervalFn(timer);
534
+ timer = void 0;
535
+ };
536
+ return {
537
+ start() {
538
+ stop();
539
+ if (options.active === false) return;
540
+ refresh();
541
+ timer = setIntervalFn(refresh, intervalMs);
542
+ },
543
+ stop,
544
+ refresh
545
+ };
546
+ }
547
+
548
+ // src/internal/checkout-format.ts
549
+ import { ceilDiv, formatDecimal, isBitcoinAmountCurrency, parseDecimal } from "@openreceive/core";
550
+ function formatCountdown(seconds) {
551
+ const safeSeconds = Math.max(0, Math.trunc(seconds));
552
+ const minutes = Math.floor(safeSeconds / 60);
553
+ const remainderSeconds = safeSeconds % 60;
554
+ return `${minutes}:${remainderSeconds.toString().padStart(2, "0")}`;
555
+ }
556
+ function formatDepositAmount(amount) {
557
+ if (!/^[0-9]+(?:\.[0-9]+)?$/.test(amount) || !amount.includes(".")) return amount;
558
+ return amount.replace(/0+$/, "").replace(/\.$/, "");
559
+ }
560
+ function roundedDiv(numerator, denominator) {
561
+ return (numerator + denominator / 2n) / denominator;
562
+ }
563
+ function rescaleHalfUp(units, scale, digits) {
564
+ return roundedDiv(units * 10n ** BigInt(digits), 10n ** BigInt(scale));
565
+ }
566
+ function escapeHtml(value) {
567
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
568
+ }
569
+ function isDisplayableMsats(amountMsats) {
570
+ return amountMsats !== void 0 && Number.isSafeInteger(amountMsats) && amountMsats >= 0;
571
+ }
572
+ function formatMsats(amountMsats) {
573
+ if (!isDisplayableMsats(amountMsats)) {
574
+ throw new RangeError("amount_msats must be a non-negative safe integer");
575
+ }
576
+ if (amountMsats % 1e3 === 0) {
577
+ const sats = amountMsats / 1e3;
578
+ return `${formatInteger(sats)} ${sats === 1 ? "sat" : "sats"}`;
579
+ }
580
+ return `${formatInteger(amountMsats)} msats`;
581
+ }
582
+ function formatFiatAmount(fiat) {
583
+ if (fiat?.currency === void 0 || fiat.value === void 0) return void 0;
584
+ if (fiat.currency === "BTC") return `${fiat.value} BTC`;
585
+ if (isBitcoinAmountCurrency(fiat.currency)) return `${fiat.value} sats`;
586
+ return fiat.currency === "USD" ? `$${fiat.value}` : `${fiat.value} ${fiat.currency}`;
587
+ }
588
+ function formatAmountCaption(options) {
589
+ const fiat = options.fiatLabel === void 0 ? void 0 : options.fiatCurrency === "USD" && !options.fiatLabel.endsWith(" US") ? `${options.fiatLabel} US` : options.fiatLabel;
590
+ if (options.amountLabel !== void 0 && fiat !== void 0) {
591
+ return `${options.amountLabel} / ${fiat}`;
592
+ }
593
+ return options.amountLabel ?? fiat;
594
+ }
595
+ function formatInteger(value) {
596
+ return value.toLocaleString("en-US");
597
+ }
598
+ function formatSwapLimit(checkout, limitMsats, rounding = "ceil") {
599
+ if (!isDisplayableMsats(limitMsats) || !isDisplayableMsats(checkout.amount_msats) || checkout.amount_msats === 0) {
600
+ return void 0;
601
+ }
602
+ const fiat = checkout.fiat;
603
+ if (fiat !== void 0 && !isBitcoinAmountCurrency(fiat.currency)) {
604
+ const scaled = scaleFiatLimitExact({
605
+ fiatValue: fiat.value,
606
+ amountMsats: checkout.amount_msats,
607
+ limitMsats,
608
+ rounding
609
+ });
610
+ if (scaled !== void 0) {
611
+ const formatted = formatFiatAmount({
612
+ currency: fiat.currency,
613
+ value: scaled
614
+ });
615
+ if (formatted !== void 0) return formatted;
616
+ }
617
+ }
618
+ const sats = rounding === "floor" ? Math.floor(limitMsats / 1e3) : Math.ceil(limitMsats / 1e3);
619
+ return `${sats} ${sats === 1 ? "sat" : "sats"}`;
620
+ }
621
+ function scaleFiatLimitExact(input) {
622
+ const fiat = parseDecimal(input.fiatValue);
623
+ if (fiat.units <= 0n) return void 0;
624
+ const outScale = 2;
625
+ const numerator = fiat.units * BigInt(input.limitMsats) * 10n ** BigInt(outScale);
626
+ const denominator = BigInt(input.amountMsats) * 10n ** BigInt(fiat.scale);
627
+ if (denominator <= 0n) return void 0;
628
+ const units = input.rounding === "floor" ? numerator / denominator : ceilDiv(numerator, denominator);
629
+ return formatDecimal(units, outScale);
630
+ }
631
+ function formatPaymentHashLabel(hash) {
632
+ return hash.length <= 16 ? hash : `${hash.slice(0, 8)}...${hash.slice(-8)}`;
633
+ }
634
+ var MAX_DISPLAYABLE_UNIX_SECONDS = 864e13 / 1e3;
635
+ function isDisplayableUnixSeconds(seconds) {
636
+ return seconds !== void 0 && Number.isFinite(seconds) && seconds > 0 && seconds <= MAX_DISPLAYABLE_UNIX_SECONDS;
637
+ }
638
+ function formatUnixTime(seconds) {
639
+ if (!isDisplayableUnixSeconds(seconds)) return String(seconds);
640
+ return new Date(seconds * 1e3).toISOString().replace(/\.\d{3}Z$/, "Z");
641
+ }
642
+ function formatInvoiceLabel(invoice) {
643
+ if (invoice.length <= 48) return invoice;
644
+ return `${invoice.slice(0, 20)}\u2026${invoice.slice(-16)}`;
645
+ }
646
+ function deriveCheckoutStateLabels(source) {
647
+ const fiatLabel = formatFiatAmount(source.fiat_quote?.fiat);
648
+ const amountLabel = source.amount_msats === void 0 ? void 0 : formatMsats(source.amount_msats);
649
+ return {
650
+ ...amountLabel === void 0 ? {} : { amountLabel },
651
+ ...fiatLabel === void 0 ? {} : { fiatLabel },
652
+ ...source.payment_hash === void 0 ? {} : { paymentHashLabel: formatPaymentHashLabel(source.payment_hash) }
653
+ };
654
+ }
655
+
656
+ // src/internal/checkout-invoice.ts
657
+ function assertDisplayInvoice(invoice) {
658
+ assertInvoice(invoice);
659
+ }
660
+ function createLightningUri(invoice) {
661
+ assertInvoice(invoice);
662
+ return `lightning:${invoice}`;
663
+ }
664
+ function assertInvoice(invoice) {
665
+ if (typeof invoice !== "string" || invoice.length === 0) {
666
+ throw new TypeError("invoice must be a non-empty BOLT11 string");
667
+ }
668
+ if (invoice.toLowerCase().startsWith("nostr+walletconnect:")) {
669
+ throw new TypeError("invoice must not be an NWC connection string");
670
+ }
671
+ }
672
+
673
+ // src/internal/checkout-swap-view.ts
674
+ import { formatDecimal as formatDecimal2, parseDecimal as parseDecimal2, payInAssetNetwork } from "@openreceive/core";
675
+
676
+ // src/internal/unix-seconds.ts
677
+ import { unixSeconds as unixSeconds2 } from "@openreceive/core";
678
+ var MILLISECONDS_THRESHOLD = 1e12;
679
+ function resolveNow(now) {
680
+ if (now === void 0) return unixSeconds2();
681
+ if (now > MILLISECONDS_THRESHOLD) {
682
+ throw new RangeError(
683
+ `OpenReceive \`now\` is a unix timestamp in SECONDS; received ${now}, which is milliseconds. Pass Math.floor(Date.now() / 1000).`
684
+ );
685
+ }
686
+ return now;
687
+ }
688
+
689
+ // src/internal/checkout-swap-view.ts
690
+ function createSwapFeeBreakdown(fee) {
691
+ if (fee === void 0) return void 0;
692
+ let payIn;
693
+ let payout;
694
+ try {
695
+ payIn = parseDecimal2(fee.pay_in_fiat);
696
+ payout = parseDecimal2(fee.payout_fiat);
697
+ } catch {
698
+ return void 0;
699
+ }
700
+ if (payout.units <= 0n) return void 0;
701
+ const scale = Math.max(payIn.scale, payout.scale);
702
+ const payInUnits = payIn.units * 10n ** BigInt(scale - payIn.scale);
703
+ const payoutUnits = payout.units * 10n ** BigInt(scale - payout.scale);
704
+ const feeUnits = payInUnits > payoutUnits ? payInUnits - payoutUnits : 0n;
705
+ const format = (units) => {
706
+ const value = formatDecimal2(rescaleHalfUp(units, scale, 2), 2);
707
+ return formatFiatAmount({ currency: fee.currency, value }) ?? `${value} ${fee.currency}`;
708
+ };
709
+ const percentTenths = roundedDiv(feeUnits * 1000n, payoutUnits);
710
+ const feePercent = `${(percentTenths / 10n).toString()}.${(percentTenths % 10n).toString()}%`;
711
+ return {
712
+ cartTotal: format(payoutUnits),
713
+ youSend: format(payInUnits),
714
+ fee: format(feeUnits),
715
+ feePercent
716
+ };
717
+ }
718
+ function createSwapDisplayModel(invoice, options = {}) {
719
+ const swap = invoice.swap;
720
+ if (swap === void 0) return void 0;
721
+ const expiresAt = Math.min(
722
+ swap.provider_expires_at,
723
+ invoice.expires_at ?? swap.provider_expires_at
724
+ );
725
+ const expiresInSeconds = Math.max(0, expiresAt - resolveNow(options.now));
726
+ const asset = getSwapAssetDisplay(swap.pay_in_asset);
727
+ const depositAmount = formatDepositAmount(swap.deposit_amount);
728
+ const networkWarningEmphasis = `${depositAmount} ${asset.assetLabel} on the ${asset.networkLabel} network`;
729
+ const settled = invoice.transaction_state === "settled";
730
+ const feeBreakdown = createSwapFeeBreakdown(swap.fee);
731
+ return {
732
+ provider: swap.provider,
733
+ attemptId: swap.attempt_id ?? invoice.invoice_id,
734
+ payInAsset: swap.pay_in_asset,
735
+ assetLabel: asset.assetLabel,
736
+ networkLabel: asset.networkLabel,
737
+ networkWarningTitle: checkoutLabels.wrongCurrencyOrNetworkTitle,
738
+ networkWarningEmphasis,
739
+ networkWarning: `Be sure you are sending exactly ${networkWarningEmphasis}. If you send the wrong currency or send on the wrong network, your funds will be lost! Pay with one method only \u2014 if you already sent ${asset.assetLabel}, do not also pay the Lightning invoice.`,
740
+ depositAddress: swap.deposit_address,
741
+ ...swap.deposit_memo === void 0 ? {} : { depositMemo: swap.deposit_memo },
742
+ depositAmount,
743
+ providerStateLabel: settled ? "Payment complete" : getSwapProviderStateLabel(swap.provider_state),
744
+ providerStateDetail: settled ? "Your payment is confirmed and your order is complete." : getSwapProviderStateDetail(swap.provider_state, swap.pay_in_asset, {
745
+ refundReason: swap.refund_reason,
746
+ depositAmount: swap.deposit_amount,
747
+ depositReceivedAmount: swap.deposit_received_amount,
748
+ refundAmount: swap.refund_amount
749
+ }),
750
+ state: settled ? "settled" : getSwapPanelState(swap.provider_state),
751
+ expiresInSeconds,
752
+ countdownLabel: formatCountdown(expiresInSeconds),
753
+ qrPayload: createSwapQrPayload(swap),
754
+ ...feeBreakdown === void 0 ? {} : { feeBreakdown },
755
+ ...swap.deposit_tx_id === void 0 ? {} : { depositTxId: swap.deposit_tx_id },
756
+ ...swap.payout_tx_id === void 0 ? {} : { payoutTxId: swap.payout_tx_id },
757
+ ...swap.refund_address === void 0 ? {} : { refundAddress: swap.refund_address },
758
+ refundAllowed: swap.provider_state === "refund_required",
759
+ ...swap.refund_tx_id === void 0 ? {} : { refundTxId: swap.refund_tx_id },
760
+ ...swap.refund_reason === void 0 ? {} : { refundReason: swap.refund_reason },
761
+ ...swap.deposit_received_amount === void 0 ? {} : {
762
+ depositReceivedAmount: formatDepositAmount(swap.deposit_received_amount)
763
+ },
764
+ ...swap.refund_amount === void 0 ? {} : { refundAmount: formatDepositAmount(swap.refund_amount) },
765
+ ...swap.provider_order_id === void 0 ? {} : { providerOrderId: swap.provider_order_id }
766
+ };
767
+ }
768
+ function overlaySwapRefundStaging(invoice, local) {
769
+ const localSwap = local?.swap;
770
+ const invoiceSwap = invoice.swap;
771
+ if (local === void 0 || local === null || localSwap === void 0 || invoiceSwap === void 0) {
772
+ return invoice;
773
+ }
774
+ if (local.invoice_id !== invoice.invoice_id) return invoice;
775
+ const refund_address = invoiceSwap.refund_address ?? localSwap.refund_address;
776
+ if (refund_address === invoiceSwap.refund_address) return invoice;
777
+ return {
778
+ ...invoice,
779
+ swap: {
780
+ ...invoiceSwap,
781
+ ...refund_address === void 0 ? {} : { refund_address }
782
+ }
783
+ };
784
+ }
785
+ function swapAssetMatchesRoute(routeKey, payInAsset) {
786
+ if (payInAsset === void 0) return false;
787
+ const route = routeKey.includes(":") ? routeKey.split(":").at(-1) ?? routeKey : routeKey;
788
+ if (route === "usdt") return payInAsset.startsWith("USDT_");
789
+ if (route === "usdc") return payInAsset.startsWith("USDC_");
790
+ if (route === "eth") return payInAsset === "ETH_ETH";
791
+ if (route === "sol") return payInAsset === "SOL_SOL";
792
+ return false;
793
+ }
794
+ function getSwapProviderStateLabel(state) {
795
+ if (state === "creating_provider_order") return "Preparing payment address";
796
+ if (state === "awaiting_deposit") return "Waiting for your payment";
797
+ if (state === "confirming") return "Confirming payment";
798
+ if (state === "exchanging") return "Converting payment";
799
+ if (state === "paying_invoice" || state === "completed") return "Finalizing checkout";
800
+ if (state === "expired") return "Expired";
801
+ if (state === "refund_required") return "Refund needed";
802
+ if (state === "refund_pending") return "Refund pending";
803
+ if (state === "refunded") return "Refunded";
804
+ if (state === "attention") return "Needs attention";
805
+ if (state === "failed") return "Failed";
806
+ return state;
807
+ }
808
+ function getSwapProviderStateDetail(state, payInAsset, refundContext = {}) {
809
+ const { networkLabel, assetLabel } = getSwapAssetDisplay(payInAsset);
810
+ if (state === "creating_provider_order") return "Creating a payment address.";
811
+ if (state === "awaiting_deposit") return "Send exactly the amount shown below.";
812
+ if (state === "confirming") {
813
+ return `Your payment was detected on ${networkLabel}. ${getSwapConfirmationWaitHint(payInAsset)}`;
814
+ }
815
+ if (state === "exchanging") {
816
+ return "Your payment is confirmed and being converted. This usually finishes within a minute.";
817
+ }
818
+ if (state === "paying_invoice" || state === "completed") {
819
+ return "The provider is sending the Lightning payment. This usually takes a few seconds.";
820
+ }
821
+ if (state === "expired") return "No payment was received before the payment window closed.";
822
+ if (state === "refund_required" || state === "refund_pending" || state === "refunded") {
823
+ return getSwapRefundDetail(state, assetLabel, refundContext);
824
+ }
825
+ if (state === "attention") return "This payment needs support review.";
826
+ if (state === "failed") return "This payment address can no longer be used.";
827
+ return state;
828
+ }
829
+ function getSwapRefundDetail(state, assetLabel, refundContext) {
830
+ const reasonDetail = getSwapRefundReasonDetail(refundContext, assetLabel);
831
+ const refundAmountDetail = refundContext.refundAmount === void 0 ? void 0 : `Estimated refund: ${formatDepositAmount(refundContext.refundAmount)} ${assetLabel} before network fees.`;
832
+ if (state === "refund_required") {
833
+ const action = "Enter an address you control to request a refund.";
834
+ return [reasonDetail, action, refundAmountDetail].filter(Boolean).join(" ");
835
+ }
836
+ if (state === "refund_pending") {
837
+ return [reasonDetail, "Your refund request has been sent.", refundAmountDetail].filter(Boolean).join(" ");
838
+ }
839
+ return [reasonDetail, "The provider reports the refund was sent.", refundAmountDetail].filter(Boolean).join(" ");
840
+ }
841
+ function getSwapRefundReasonDetail(refundContext, assetLabel) {
842
+ const expected = refundContext.depositAmount === void 0 ? void 0 : formatDepositAmount(refundContext.depositAmount);
843
+ const received = refundContext.depositReceivedAmount === void 0 ? void 0 : formatDepositAmount(refundContext.depositReceivedAmount);
844
+ if (refundContext.refundReason === "underpaid") {
845
+ if (expected !== void 0 && received !== void 0) {
846
+ return `You sent ${received} ${assetLabel} but ${expected} ${assetLabel} was required.`;
847
+ }
848
+ return "The amount received was less than required.";
849
+ }
850
+ if (refundContext.refundReason === "late_deposit") {
851
+ return "Your payment arrived after the payment window closed.";
852
+ }
853
+ if (refundContext.refundReason === "underpaid_and_late") {
854
+ if (expected !== void 0 && received !== void 0) {
855
+ return `You sent ${received} ${assetLabel} but ${expected} ${assetLabel} was required, and it arrived after the payment window closed.`;
856
+ }
857
+ return "Your payment was under the required amount and arrived after the window closed.";
858
+ }
859
+ return void 0;
860
+ }
861
+ function getSwapConfirmationWaitHint(payInAsset) {
862
+ const network = payInAssetNetwork(payInAsset);
863
+ if (network === "TRON") return "Confirmation usually takes 1\u20133 minutes.";
864
+ if (network === "SOL") return "Confirmation usually takes under a minute.";
865
+ if (network === "ETH") return "Confirmation often takes 5\u201315 minutes.";
866
+ return "Confirmation usually takes a few minutes.";
867
+ }
868
+ function getSwapPanelState(state) {
869
+ if (state === "creating_provider_order") return "creating";
870
+ if (state === "awaiting_deposit") return "deposit";
871
+ if (state === "confirming" || state === "exchanging" || state === "paying_invoice" || state === "completed") {
872
+ return "progress";
873
+ }
874
+ if (state === "expired") return "expired";
875
+ if (state === "refund_required") return "refund_required";
876
+ if (state === "refund_pending") return "refund_pending";
877
+ if (state === "refunded") return "refunded";
878
+ if (state === "attention") return "attention";
879
+ return "failed";
880
+ }
881
+ function getSwapAssetDisplay(payInAsset) {
882
+ const network = payInAssetNetwork(payInAsset);
883
+ const networkLabel = network === "TRON" ? "Tron" : network === "SOL" ? "Solana" : network === "ETH" ? "Ethereum" : network ?? payInAsset;
884
+ return {
885
+ assetLabel: payInAsset.split("_")[0] ?? payInAsset,
886
+ networkLabel
887
+ };
888
+ }
889
+ function createSwapQrPayload(swap) {
890
+ if (swap.pay_in_asset === "ETH_ETH") {
891
+ const wei = decimalAmountToIntegerString(swap.deposit_amount, 18);
892
+ return `ethereum:${swap.deposit_address}?value=${wei}`;
893
+ }
894
+ if (swap.pay_in_asset === "SOL_SOL") {
895
+ const amount = formatDepositAmount(swap.deposit_amount);
896
+ return `solana:${swap.deposit_address}?amount=${encodeURIComponent(amount)}`;
897
+ }
898
+ return swap.deposit_address;
899
+ }
900
+ function decimalAmountToIntegerString(amount, decimals) {
901
+ const parsed = parseDecimal2(amount);
902
+ if (parsed.scale > decimals) {
903
+ throw new RangeError(`deposit_amount is more precise than ${decimals} decimals: ${amount}`);
904
+ }
905
+ return (parsed.units * 10n ** BigInt(decimals - parsed.scale)).toString();
906
+ }
907
+ function isTerminalSwapProviderState(providerState) {
908
+ return providerState === "expired" || providerState === "refunded" || providerState === "attention" || providerState === "failed";
909
+ }
910
+
911
+ // src/internal/checkout-links.ts
912
+ import { payInAssetNetwork as payInAssetNetwork2 } from "@openreceive/core";
913
+ function getExplorerNetwork(payInAsset) {
914
+ const network = payInAsset === void 0 ? void 0 : payInAssetNetwork2(payInAsset);
915
+ if (network === "ETH" || network === "SOL" || network === "TRON") return network;
916
+ return void 0;
917
+ }
918
+ function createBlockExplorerUrl(options) {
919
+ const value = options.value.trim();
920
+ if (value === "") return void 0;
921
+ const network = options.network === "ETH" || options.network === "SOL" || options.network === "TRON" ? options.network : getExplorerNetwork(
922
+ options.payInAsset ?? (typeof options.network === "string" ? options.network : void 0)
923
+ );
924
+ if (network === void 0) return void 0;
925
+ const encoded = encodeURIComponent(value);
926
+ if (network === "ETH") {
927
+ return options.kind === "tx" ? `https://etherscan.io/tx/${encoded}` : `https://etherscan.io/address/${encoded}`;
928
+ }
929
+ if (network === "SOL") {
930
+ return options.kind === "tx" ? `https://solscan.io/tx/${encoded}` : `https://solscan.io/account/${encoded}`;
931
+ }
932
+ return options.kind === "tx" ? `https://tronscan.org/#/transaction/${encoded}` : `https://tronscan.org/#/address/${encoded}`;
933
+ }
934
+ function createLightningInvoiceDecodeUrl(invoice, decodeLinkUrl) {
935
+ const base = decodeLinkUrl?.trim();
936
+ if (base === void 0 || base === "") return void 0;
937
+ const raw = invoice.trim();
938
+ if (raw === "") return void 0;
939
+ const bolt11 = raw.toLowerCase().startsWith("lightning:") ? raw.slice("lightning:".length) : raw;
940
+ if (bolt11 === "") return void 0;
941
+ const separator = base.includes("?") ? "&" : "?";
942
+ return `${base}${separator}invoice=${encodeURIComponent(bolt11)}`;
943
+ }
944
+ function createDetailExternalLink(options) {
945
+ const value = options.value.trim();
946
+ if (value === "") return void 0;
947
+ if (options.kind === "invoice") {
948
+ const href2 = createLightningInvoiceDecodeUrl(value, options.decodeLinkUrl);
949
+ return href2 === void 0 ? void 0 : { href: href2, hrefLabel: checkoutLabels.decodeInvoice };
950
+ }
951
+ const href = createBlockExplorerUrl({
952
+ payInAsset: options.payInAsset,
953
+ kind: options.kind,
954
+ value
955
+ });
956
+ return href === void 0 ? void 0 : { href, hrefLabel: checkoutLabels.viewOnExplorer };
957
+ }
958
+
959
+ // src/internal/checkout-details.ts
960
+ function createTransactionDetails(input) {
961
+ const rows = [];
962
+ const payInAsset = input.swap?.pay_in_asset;
963
+ const push = (label, value, copyValue, kind) => {
964
+ if (value === void 0 || value === "") return;
965
+ const linkValue = copyValue ?? value;
966
+ const link = kind === void 0 ? void 0 : createDetailExternalLink({
967
+ kind,
968
+ value: linkValue,
969
+ ...payInAsset === void 0 ? {} : { payInAsset },
970
+ ...input.decodeLinkUrl === void 0 ? {} : { decodeLinkUrl: input.decodeLinkUrl }
971
+ });
972
+ rows.push({
973
+ label,
974
+ value,
975
+ ...copyValue === void 0 ? {} : { copyValue },
976
+ ...link === void 0 ? {} : { href: link.href, hrefLabel: link.hrefLabel }
977
+ });
978
+ };
979
+ push("Order ID", input.reference);
980
+ push("Checkout ID", input.checkout_id);
981
+ push("Invoice ID", input.invoice_id);
982
+ push("Rail", input.rail);
983
+ push("Status", input.transaction_state);
984
+ push("Workflow", input.workflow_state);
985
+ if (input.amount_msats !== void 0) {
986
+ push("Amount", formatMsats(input.amount_msats));
987
+ push("Amount (msats)", String(input.amount_msats));
988
+ }
989
+ const fiat = formatFiatAmount(input.fiat_quote?.fiat);
990
+ push("Fiat", fiat);
991
+ if (typeof input.invoice === "string" && input.invoice.length > 0) {
992
+ push("Lightning invoice", formatInvoiceLabel(input.invoice), input.invoice, "invoice");
993
+ }
994
+ if (input.payment_hash !== void 0) {
995
+ push("Payment hash", formatPaymentHashLabel(input.payment_hash), input.payment_hash);
996
+ }
997
+ if (input.settled_at !== void 0) {
998
+ push("Settled at", formatUnixTime(input.settled_at));
999
+ }
1000
+ if (input.expires_at !== void 0) {
1001
+ push("Expires at", formatUnixTime(input.expires_at));
1002
+ }
1003
+ const swap = input.swap;
1004
+ if (swap !== void 0) {
1005
+ const settled = input.transaction_state === "settled";
1006
+ const asset = getSwapAssetDisplay(swap.pay_in_asset);
1007
+ push("Swap provider", swap.provider);
1008
+ push("Provider order", swap.provider_order_id);
1009
+ push("Swap attempt", swap.attempt_id);
1010
+ push("Pay-in asset", swap.pay_in_asset);
1011
+ push("Asset", asset.assetLabel);
1012
+ push("Network", asset.networkLabel);
1013
+ push("Deposit address", swap.deposit_address, void 0, "address");
1014
+ push("Deposit memo", swap.deposit_memo);
1015
+ push("Deposit amount", formatDepositAmount(swap.deposit_amount));
1016
+ if (swap.deposit_received_amount !== void 0) {
1017
+ push("Amount received", formatDepositAmount(swap.deposit_received_amount));
1018
+ }
1019
+ push(settled ? "Last provider state" : "Provider state", swap.provider_state);
1020
+ if (swap.refund_reason !== void 0) {
1021
+ push("Refund reason", swap.refund_reason);
1022
+ }
1023
+ if (swap.refund_amount !== void 0) {
1024
+ push("Estimated refund", formatDepositAmount(swap.refund_amount));
1025
+ }
1026
+ if (swap.provider_expires_at !== void 0) {
1027
+ push("Provider expires at", formatUnixTime(swap.provider_expires_at));
1028
+ }
1029
+ push("Deposit transaction", swap.deposit_tx_id, void 0, "tx");
1030
+ push("Lightning payout", swap.payout_tx_id);
1031
+ push("Refund address", swap.refund_address, void 0, "address");
1032
+ push("Refund transaction", swap.refund_tx_id, void 0, "tx");
1033
+ const feeBreakdown = createSwapFeeBreakdown(swap.fee);
1034
+ if (feeBreakdown !== void 0) {
1035
+ push("Cart total", feeBreakdown.cartTotal);
1036
+ push("You send", feeBreakdown.youSend);
1037
+ push(
1038
+ "Swap + network fees",
1039
+ feeBreakdown.feePercent === void 0 ? feeBreakdown.fee : `${feeBreakdown.fee} (${feeBreakdown.feePercent})`
1040
+ );
1041
+ } else if (swap.fee !== void 0) {
1042
+ push("Fee currency", swap.fee.currency);
1043
+ push("Pay-in fiat", swap.fee.pay_in_fiat);
1044
+ push("Payout fiat", swap.fee.payout_fiat);
1045
+ }
1046
+ }
1047
+ return rows;
1048
+ }
1049
+ function createTransactionDetailsFromState(state) {
1050
+ return createTransactionDetails({
1051
+ reference: state.reference,
1052
+ checkout_id: state.checkout_id,
1053
+ invoice_id: state.invoice_id,
1054
+ invoice: state.invoice,
1055
+ rail: state.rail,
1056
+ ...state.payment_hash === void 0 ? {} : { payment_hash: state.payment_hash },
1057
+ ...state.amount_msats === void 0 ? {} : { amount_msats: state.amount_msats },
1058
+ ...state.fiat_quote === void 0 ? {} : { fiat_quote: state.fiat_quote },
1059
+ transaction_state: state.transaction_state,
1060
+ workflow_state: state.workflow_state,
1061
+ ...state.expires_at === void 0 ? {} : { expires_at: state.expires_at },
1062
+ ...state.settled_at === void 0 ? {} : { settled_at: state.settled_at },
1063
+ ...state.swap === void 0 ? {} : { swap: state.swap }
1064
+ });
1065
+ }
1066
+ function resolveTransactionDetailRows(source) {
1067
+ if (source === null || source === void 0) return [];
1068
+ if (Array.isArray(source)) return [...source];
1069
+ if (isCheckoutStateSource(source)) {
1070
+ return createTransactionDetailsFromState(source);
1071
+ }
1072
+ return createTransactionDetails(source);
1073
+ }
1074
+ function isCheckoutStateSource(value) {
1075
+ return "checkout_id" in value && "reference" in value && "invoice_id" in value && "invoice" in value && "transaction_state" in value && "phase" in value;
1076
+ }
1077
+ function createPaymentDataEntries(source) {
1078
+ const entries = [];
1079
+ const add = (label, value) => {
1080
+ if (value !== void 0 && value !== "") entries.push({ label, value });
1081
+ };
1082
+ add("Order", source.reference);
1083
+ add("Checkout", source.checkout_id);
1084
+ add("Invoice ID", source.invoice_id);
1085
+ add("Payment hash", source.payment_hash);
1086
+ if (source.amount_msats !== void 0) {
1087
+ add("Amount", `${formatMsats(source.amount_msats)} (${source.amount_msats} msats)`);
1088
+ }
1089
+ const fiat = source.fiat_quote?.fiat;
1090
+ if (fiat?.value !== void 0) {
1091
+ add("Fiat amount", fiat.currency === void 0 ? fiat.value : `${fiat.value} ${fiat.currency}`);
1092
+ }
1093
+ add("Rail", source.rail);
1094
+ add("Transaction state", source.transaction_state);
1095
+ add("Workflow state", source.workflow_state);
1096
+ if (source.settled_at !== void 0) add("Settled at", formatUnixTime(source.settled_at));
1097
+ if (source.expires_at !== void 0) {
1098
+ add("Invoice expires at", formatUnixTime(source.expires_at));
1099
+ }
1100
+ if (source.swap !== void 0) {
1101
+ add("Swap provider", source.swap.provider);
1102
+ add("Swap pay-in asset", source.swap.pay_in_asset);
1103
+ add("Swap provider order", source.swap.provider_order_id);
1104
+ add("Swap state", source.swap.provider_state);
1105
+ add("Swap deposit tx", source.swap.deposit_tx_id);
1106
+ add("Swap payout tx", source.swap.payout_tx_id);
1107
+ }
1108
+ add("BOLT11 invoice", source.invoice);
1109
+ return entries;
1110
+ }
1111
+
1112
+ // src/internal/wizard.ts
1113
+ import { getSwapRefundAddressError } from "@openreceive/core/swap-address";
1114
+ import {
1115
+ getPaymentWizardRoutes,
1116
+ listAssets,
1117
+ payTutorialUrls,
1118
+ providerIconUrls
1119
+ } from "@openreceive/provider-data";
1120
+ function getBitcoinAssets() {
1121
+ return listAssets().filter((asset) => asset.symbol === "btc" && asset.route !== void 0);
1122
+ }
1123
+ function getDefaultBitcoinRoute() {
1124
+ const routes = [
1125
+ ...new Set(
1126
+ getBitcoinAssets().flatMap((asset) => asset.route === void 0 ? [] : [asset.route])
1127
+ )
1128
+ ];
1129
+ return routes.length === 1 ? routes[0] ?? null : null;
1130
+ }
1131
+ function getPaymentStatusText(phase) {
1132
+ if (phase === "settled") {
1133
+ return {
1134
+ title: checkoutLabels.paymentStatus.settledTitle,
1135
+ detail: checkoutLabels.paymentStatus.settledDetail
1136
+ };
1137
+ }
1138
+ if (phase === "expired") {
1139
+ return {
1140
+ title: checkoutLabels.paymentStatus.expiredTitle,
1141
+ detail: checkoutLabels.paymentStatus.expiredDetail
1142
+ };
1143
+ }
1144
+ return {
1145
+ title: checkoutLabels.paymentStatus.waitingTitle,
1146
+ detail: checkoutLabels.paymentStatus.waitingDetail
1147
+ };
1148
+ }
1149
+ function getWizardEmptyMessage() {
1150
+ return checkoutLabels.emptyBitcoin;
1151
+ }
1152
+ function getCheckoutProviderOpenLabel() {
1153
+ return checkoutLabels.openProvider;
1154
+ }
1155
+ function getCheckoutProviderIcon(provider) {
1156
+ return providerIconUrls[provider.icon_path] ?? paymentIconUrls.crypto;
1157
+ }
1158
+ function getCheckoutProviderTutorials(provider) {
1159
+ return (provider.tutorials ?? []).map((tutorial) => ({
1160
+ index: tutorial.index,
1161
+ path: tutorial.path,
1162
+ image: payTutorialUrls[tutorial.path] ?? tutorial.path,
1163
+ caption: tutorial.caption
1164
+ }));
1165
+ }
1166
+ function getRouteNetworkLabel(routeId) {
1167
+ return routeId === "lightning" || routeId === "btc-lightning" ? checkoutLabels.lightningNetwork : routeId;
1168
+ }
1169
+ function createWizardRouteAssetDisplays(assets, options = {}) {
1170
+ return assets.map((asset) => {
1171
+ const id = asset.route ?? asset.symbol;
1172
+ return {
1173
+ id,
1174
+ label: asset.label,
1175
+ subtitle: getRouteNetworkLabel(id),
1176
+ icon: getRouteIcon(asset),
1177
+ selected: options.selectedRoute === id
1178
+ };
1179
+ });
1180
+ }
1181
+ function createWizardRouteDisplays(routes, options = {}) {
1182
+ return routes.map((route) => ({
1183
+ key: getWizardRouteDisplayKey(route),
1184
+ title: getWizardRouteDisplayTitle(route),
1185
+ subtitle: getWizardRouteDisplaySubtitle(route),
1186
+ providers: (options.providerPreviewLimit === void 0 ? route.providers : route.providers.slice(0, options.providerPreviewLimit)).map((entry) => createWizardProviderDisplay(entry))
1187
+ }));
1188
+ }
1189
+ function getWizardRouteDisplayKey(route) {
1190
+ return route.route.id;
1191
+ }
1192
+ function getWizardRouteDisplayTitle(route) {
1193
+ return route.route.label;
1194
+ }
1195
+ function getWizardRouteDisplaySubtitle(route) {
1196
+ return route.route.symbol.toUpperCase();
1197
+ }
1198
+ function createWizardProviderDisplay(entry) {
1199
+ return {
1200
+ id: entry.provider.id,
1201
+ name: entry.provider.name,
1202
+ kind: entry.provider.kind,
1203
+ url: entry.provider.lightning_docs_url ?? entry.provider.url,
1204
+ icon: getCheckoutProviderIcon(entry.provider),
1205
+ tutorials: getCheckoutProviderTutorials(entry.provider),
1206
+ copyLabel: checkoutLabels.copyInvoice,
1207
+ copiedLabel: checkoutLabels.copied,
1208
+ openLabel: getCheckoutProviderOpenLabel()
1209
+ };
1210
+ }
1211
+ function getPaymentMethodIcon(method) {
1212
+ return paymentIconUrls[paymentMethodIconIds[method]];
1213
+ }
1214
+ function getAssetIcon(symbol) {
1215
+ return paymentIconUrls[assetIconIds[symbol] ?? "crypto"];
1216
+ }
1217
+ function getNetworkIcon(networkLabel) {
1218
+ const key = networkLabel.trim().toLowerCase();
1219
+ if (key === "tron" || key === "trx") return paymentIconUrls.trx;
1220
+ if (key === "solana" || key === "sol") return paymentIconUrls.sol;
1221
+ if (key === "ethereum" || key === "eth") return paymentIconUrls.eth;
1222
+ return paymentIconUrls.crypto;
1223
+ }
1224
+ function getSwapOptionIcon(option) {
1225
+ return getAssetIcon(option.label.trim().toLowerCase());
1226
+ }
1227
+ function groupSwapOptionsByLabel(options) {
1228
+ const groups = [];
1229
+ const indexByLabel = /* @__PURE__ */ new Map();
1230
+ for (const option of options) {
1231
+ const key = option.label.trim().toUpperCase();
1232
+ const existing = indexByLabel.get(key);
1233
+ if (existing === void 0) {
1234
+ indexByLabel.set(key, groups.length);
1235
+ groups.push({ label: option.label, options: [option] });
1236
+ continue;
1237
+ }
1238
+ const group = groups[existing];
1239
+ if (group === void 0) continue;
1240
+ groups[existing] = { label: group.label, options: [...group.options, option] };
1241
+ }
1242
+ return groups;
1243
+ }
1244
+ var OPENRECEIVE_METHOD_GRID_ORDER = [
1245
+ { kind: "method", id: "bitcoin" },
1246
+ { kind: "swap", label: "USDT" },
1247
+ { kind: "swap", label: "USDC" },
1248
+ { kind: "swap", label: "SOL" },
1249
+ { kind: "swap", label: "ETH" }
1250
+ ];
1251
+ function buildMethodGridEntries(paymentMethods2, swapOptions) {
1252
+ const swapGroups = groupSwapOptionsByLabel(swapOptions);
1253
+ if (swapGroups.length === 0) {
1254
+ return paymentMethods2.map((method) => ({ kind: "method", method }));
1255
+ }
1256
+ const methodsById = new Map(paymentMethods2.map((method) => [method.id, method]));
1257
+ const groupsByLabel = new Map(
1258
+ swapGroups.map((group) => [group.label.trim().toUpperCase(), group])
1259
+ );
1260
+ const usedMethodIds = /* @__PURE__ */ new Set();
1261
+ const usedSwapLabels = /* @__PURE__ */ new Set();
1262
+ const entries = [];
1263
+ for (const slot of OPENRECEIVE_METHOD_GRID_ORDER) {
1264
+ if (slot.kind === "method") {
1265
+ const method = methodsById.get(slot.id);
1266
+ if (method === void 0) continue;
1267
+ usedMethodIds.add(method.id);
1268
+ entries.push({ kind: "method", method });
1269
+ continue;
1270
+ }
1271
+ const group = groupsByLabel.get(slot.label);
1272
+ if (group === void 0) continue;
1273
+ usedSwapLabels.add(slot.label);
1274
+ entries.push({ kind: "swap", group });
1275
+ }
1276
+ for (const method of paymentMethods2) {
1277
+ if (usedMethodIds.has(method.id)) continue;
1278
+ entries.push({ kind: "method", method });
1279
+ }
1280
+ for (const group of swapGroups) {
1281
+ const key = group.label.trim().toUpperCase();
1282
+ if (usedSwapLabels.has(key)) continue;
1283
+ entries.push({ kind: "swap", group });
1284
+ }
1285
+ return entries;
1286
+ }
1287
+ function swapPickerKey(label) {
1288
+ return `swap:${label.trim().toUpperCase()}`;
1289
+ }
1290
+ function parseMethodPickerKey(key) {
1291
+ if (!key.startsWith("method:")) return null;
1292
+ return { kind: "method", methodId: key.slice("method:".length) };
1293
+ }
1294
+ function parseSwapPickerKey(key) {
1295
+ if (!key.startsWith("swap:")) return null;
1296
+ return { kind: "swap", label: key.slice("swap:".length) };
1297
+ }
1298
+ function paymentAccentId(labelOrMethodId) {
1299
+ const key = labelOrMethodId.trim().toLowerCase();
1300
+ if (key === "bitcoin" || key === "btc") return "bitcoin";
1301
+ if (key === "usdt") return "usdt";
1302
+ if (key === "usdc") return "usdc";
1303
+ if (key === "sol" || key === "solana") return "sol";
1304
+ if (key === "eth" || key === "ethereum") return "eth";
1305
+ return "default";
1306
+ }
1307
+ var assetActiveClassByAccent = {
1308
+ bitcoin: orClasses.methodCardActiveBitcoin,
1309
+ usdt: orClasses.methodCardActiveUsdt,
1310
+ usdc: orClasses.methodCardActiveUsdc,
1311
+ sol: orClasses.methodCardActiveSol,
1312
+ eth: orClasses.methodCardActiveEth,
1313
+ default: orClasses.methodCardActiveDefault
1314
+ };
1315
+ var networkActiveClassByAccent = {
1316
+ usdt: orClasses.methodNetworkButtonActiveUsdt,
1317
+ usdc: orClasses.methodNetworkButtonActiveUsdc,
1318
+ default: orClasses.methodNetworkButtonActiveDefault
1319
+ };
1320
+ function assetButtonClasses(options) {
1321
+ const base = options.disabled ? orClasses.methodCardUnavailable : orClasses.methodCardReady;
1322
+ if (!options.selected || options.disabled) return base;
1323
+ return `${base} ${assetActiveClassByAccent[options.accent]}`;
1324
+ }
1325
+ function networkButtonClasses(options) {
1326
+ if (options.disabled) return orClasses.methodNetworkButtonUnavailable;
1327
+ if (!options.selected) return orClasses.methodNetworkButton;
1328
+ const accent = options.accent === "usdt" || options.accent === "usdc" ? options.accent : "default";
1329
+ return `${orClasses.methodNetworkButton} ${networkActiveClassByAccent[accent]}`;
1330
+ }
1331
+ function networkMobileRevealClasses(accent) {
1332
+ if (accent === "usdt") return orClasses.methodNetworkRevealMobileUsdt;
1333
+ if (accent === "usdc") return orClasses.methodNetworkRevealMobileUsdc;
1334
+ return orClasses.methodNetworkRevealMobile;
1335
+ }
1336
+ function networkCheckClasses(accent) {
1337
+ return accent === "usdc" ? orClasses.methodNetworkCheckUsdc : orClasses.methodNetworkCheck;
1338
+ }
1339
+ function networkSummaryIconClasses(accent) {
1340
+ return accent === "usdc" ? orClasses.methodNetworkSummaryIconUsdc : orClasses.methodNetworkSummaryIcon;
1341
+ }
1342
+ function formatNetworkSummary(assetLabel, networkLabel) {
1343
+ return checkoutLabels.networkSummary.replace("{asset}", assetLabel).replace("{network}", networkLabel);
1344
+ }
1345
+ function formatChooseNetworkHeading(assetLabel) {
1346
+ return checkoutLabels.chooseAssetNetwork.replace("{asset}", assetLabel);
1347
+ }
1348
+ function resolvePreservedNetworkSelection(options) {
1349
+ const nextKey = options.nextGroup.label.trim().toUpperCase();
1350
+ const current = options.selectedNetworks[nextKey];
1351
+ if (current !== void 0 && options.nextGroup.options.some(
1352
+ (option) => option.pay_in_asset === current && option.available !== false
1353
+ )) {
1354
+ return current;
1355
+ }
1356
+ const previous = options.previousGroup;
1357
+ if (previous === void 0) return void 0;
1358
+ const previousKey = previous.label.trim().toUpperCase();
1359
+ const previousAsset = options.selectedNetworks[previousKey];
1360
+ if (previousAsset === void 0) return void 0;
1361
+ const previousOption = previous.options.find((option) => option.pay_in_asset === previousAsset);
1362
+ if (previousOption === void 0) return void 0;
1363
+ const match = options.nextGroup.options.find(
1364
+ (option) => option.network_label === previousOption.network_label && option.available !== false
1365
+ );
1366
+ return match?.pay_in_asset;
1367
+ }
1368
+ function findSwapGridGroup(entries, pickerKey) {
1369
+ if (pickerKey === null || pickerKey === void 0) return void 0;
1370
+ const parsed = parseSwapPickerKey(pickerKey);
1371
+ if (parsed === null) return void 0;
1372
+ const entry = entries.find(
1373
+ (entry2) => entry2.kind === "swap" && entry2.group.label.trim().toUpperCase() === parsed.label
1374
+ );
1375
+ return entry?.kind === "swap" ? entry.group : void 0;
1376
+ }
1377
+ function updateSelectedSwapNetworks(options) {
1378
+ const nextGroup = findSwapGridGroup(options.entries, options.nextKey);
1379
+ if (nextGroup === void 0 || nextGroup.options.length <= 1) {
1380
+ return options.selectedNetworks;
1381
+ }
1382
+ const previousGroup = findSwapGridGroup(options.entries, options.previousKey);
1383
+ const preserved = resolvePreservedNetworkSelection({
1384
+ previousGroup,
1385
+ nextGroup,
1386
+ selectedNetworks: options.selectedNetworks
1387
+ });
1388
+ const groupKey = nextGroup.label.trim().toUpperCase();
1389
+ if (preserved === void 0) {
1390
+ const { [groupKey]: _removed, ...rest } = options.selectedNetworks;
1391
+ return rest;
1392
+ }
1393
+ return { ...options.selectedNetworks, [groupKey]: preserved };
1394
+ }
1395
+ function wizardNetworkGroupIds(groupKey) {
1396
+ const slug = groupKey.toLowerCase().replace(/[^a-z0-9_-]/g, "-");
1397
+ return { panelId: `network-panel-${slug}`, headingId: `network-heading-${slug}` };
1398
+ }
1399
+ function createSwapUnavailableModel(option, checkout) {
1400
+ const detail = swapOptionLimitMessage(option, checkout) ?? option.unavailable_message ?? checkoutLabels.swapUnavailableFallback.replace("{asset}", option.label);
1401
+ const range = option.minimum_pay_amount === void 0 ? void 0 : option.maximum_pay_amount === void 0 ? checkoutLabels.swapUnavailableMinimumOnly.replace("{minimum}", option.minimum_pay_amount).replace("{asset}", option.label) : checkoutLabels.swapUnavailableRange.replace("{minimum}", option.minimum_pay_amount).replace("{maximum}", option.maximum_pay_amount).replace("{asset}", option.label);
1402
+ return {
1403
+ title: checkoutLabels.swapUnavailableTitle.replace("{asset}", option.label),
1404
+ detail,
1405
+ ...range === void 0 ? {} : { range },
1406
+ hint: checkoutLabels.swapUnavailableHint
1407
+ };
1408
+ }
1409
+ function swapOptionLimitMessage(option, checkout) {
1410
+ if (option.available !== false) return void 0;
1411
+ if (option.unavailable_reason === "amount_too_small") {
1412
+ const fiat = checkout === void 0 ? void 0 : formatSwapLimit(checkout, option.minimum_invoice_amount_msats, "ceil");
1413
+ if (fiat !== void 0) return `Minimum amount ${fiat}`;
1414
+ if (option.minimum_pay_amount !== void 0) {
1415
+ return `Minimum ${option.minimum_pay_amount} ${option.label}`;
1416
+ }
1417
+ }
1418
+ if (option.unavailable_reason === "amount_too_large") {
1419
+ const fiat = checkout === void 0 ? void 0 : formatSwapLimit(checkout, option.maximum_invoice_amount_msats, "floor");
1420
+ if (fiat !== void 0) return `Maximum amount ${fiat}`;
1421
+ if (option.maximum_pay_amount !== void 0) {
1422
+ return `Maximum ${option.maximum_pay_amount} ${option.label}`;
1423
+ }
1424
+ }
1425
+ return option.unavailable_message;
1426
+ }
1427
+ function swapGroupLimitOption(options) {
1428
+ if (options.length === 0) return void 0;
1429
+ const unavailable = options.filter((option) => option.available === false);
1430
+ const tooSmall = unavailable.filter((option) => option.unavailable_reason === "amount_too_small");
1431
+ const candidates = tooSmall.length > 0 ? tooSmall : unavailable.length > 0 ? unavailable : options;
1432
+ let best = candidates[0];
1433
+ for (const option of candidates) {
1434
+ if (best === void 0) {
1435
+ best = option;
1436
+ continue;
1437
+ }
1438
+ const bestMin = best.minimum_invoice_amount_msats;
1439
+ const optionMin = option.minimum_invoice_amount_msats;
1440
+ if (optionMin === void 0) continue;
1441
+ if (bestMin === void 0 || optionMin < bestMin) best = option;
1442
+ }
1443
+ return best;
1444
+ }
1445
+ function getSwapRefundFormError(payInAsset, address, networkLabel) {
1446
+ if (address.length === 0) return "Enter a refund address.";
1447
+ return getSwapRefundAddressError(payInAsset, address, networkLabel);
1448
+ }
1449
+ function getRouteIcon(asset) {
1450
+ const routeId = asset.route ?? asset.symbol;
1451
+ if (asset.symbol === "btc" && routeId.includes("lightning")) {
1452
+ return paymentIconUrls.lightning;
1453
+ }
1454
+ return getAssetIcon(asset.symbol);
1455
+ }
1456
+ function createPaymentWizardState(request) {
1457
+ const selectedRouteId = request.selectedMethod === "bitcoin" ? request.selectedBitcoinRoute ?? getDefaultBitcoinRoute() : null;
1458
+ const routes = selectedRouteId === null ? [] : getPaymentWizardRoutes({ route: selectedRouteId });
1459
+ return {
1460
+ selectedRouteId,
1461
+ routes
1462
+ };
1463
+ }
1464
+ function createPaymentWizardSelection() {
1465
+ return {
1466
+ selectedMethod: null,
1467
+ selectedBitcoinRoute: null
1468
+ };
1469
+ }
1470
+ function createPaymentWizardModel(selection) {
1471
+ const wizard = createPaymentWizardState({
1472
+ selectedMethod: selection.selectedMethod,
1473
+ selectedBitcoinRoute: selection.selectedBitcoinRoute
1474
+ });
1475
+ const routeAssets = selection.selectedMethod === "bitcoin" ? getBitcoinAssets() : [];
1476
+ const selectedRoute = wizard.selectedRouteId;
1477
+ return {
1478
+ selection,
1479
+ wizard,
1480
+ routeAssets,
1481
+ selectedRoute
1482
+ };
1483
+ }
1484
+ function updatePaymentWizardSelection(selection, action) {
1485
+ switch (action.type) {
1486
+ case "select_method": {
1487
+ return {
1488
+ ...selection,
1489
+ selectedMethod: action.method,
1490
+ selectedBitcoinRoute: action.method === "bitcoin" ? selection.selectedBitcoinRoute ?? getDefaultBitcoinRoute() : selection.selectedBitcoinRoute
1491
+ };
1492
+ }
1493
+ case "change_method": {
1494
+ return {
1495
+ ...selection,
1496
+ selectedMethod: null,
1497
+ selectedBitcoinRoute: null
1498
+ };
1499
+ }
1500
+ case "change_route": {
1501
+ if (selection.selectedMethod === "bitcoin") {
1502
+ return {
1503
+ ...selection,
1504
+ selectedBitcoinRoute: null
1505
+ };
1506
+ }
1507
+ return selection;
1508
+ }
1509
+ case "select_route": {
1510
+ if (selection.selectedMethod === "bitcoin") {
1511
+ return {
1512
+ ...selection,
1513
+ selectedBitcoinRoute: action.route
1514
+ };
1515
+ }
1516
+ return selection;
1517
+ }
1518
+ }
1519
+ }
1520
+ var BrowserPaymentWizardController = class {
1521
+ options;
1522
+ selection;
1523
+ constructor(options = {}) {
1524
+ this.options = options;
1525
+ this.selection = options.selection ?? createPaymentWizardSelection();
1526
+ }
1527
+ getSelection() {
1528
+ return this.selection;
1529
+ }
1530
+ getModel() {
1531
+ return createPaymentWizardModel(this.selection);
1532
+ }
1533
+ update(action) {
1534
+ const next = updatePaymentWizardSelection(this.selection, action);
1535
+ this.selection = next;
1536
+ this.options.onSelection?.(next);
1537
+ return next;
1538
+ }
1539
+ selectMethod(method) {
1540
+ return this.update({
1541
+ type: "select_method",
1542
+ method
1543
+ });
1544
+ }
1545
+ changeMethod() {
1546
+ return this.update({
1547
+ type: "change_method"
1548
+ });
1549
+ }
1550
+ selectRoute(route) {
1551
+ return this.update({
1552
+ type: "select_route",
1553
+ route
1554
+ });
1555
+ }
1556
+ };
1557
+ function createPaymentWizardController(options = {}) {
1558
+ return new BrowserPaymentWizardController(options);
1559
+ }
1560
+
1561
+ // src/internal/log-level.ts
1562
+ var BROWSER_LOG_LEVEL_ORDER = {
1563
+ debug: 10,
1564
+ info: 20,
1565
+ warn: 30,
1566
+ error: 40
1567
+ };
1568
+ var BROWSER_LOG_LEVEL_ALIASES = {
1569
+ debug: "debug",
1570
+ info: "info",
1571
+ warn: "warn",
1572
+ warning: "warn",
1573
+ error: "error"
1574
+ };
1575
+ function browserLogLevelOrder(level) {
1576
+ return BROWSER_LOG_LEVEL_ORDER[level];
1577
+ }
1578
+ function parseBrowserLogLevel(value) {
1579
+ if (value === void 0 || value === null) return void 0;
1580
+ const normalized = value.trim().toLowerCase();
1581
+ if (normalized.length === 0) return void 0;
1582
+ return BROWSER_LOG_LEVEL_ALIASES[normalized];
1583
+ }
1584
+ function resolveBrowserLogLevel(value, fallback = "info") {
1585
+ return parseBrowserLogLevel(value) ?? fallback;
1586
+ }
1587
+ function readBrowserLogLevelFromEnvironment(source) {
1588
+ if (source !== void 0) {
1589
+ return resolveBrowserLogLevel(
1590
+ source.LOG_LEVEL ?? source.VITE_LOG_LEVEL ?? source.NEXT_PUBLIC_LOG_LEVEL
1591
+ );
1592
+ }
1593
+ const fromGlobal = parseBrowserLogLevel(readGlobalLogLevel());
1594
+ if (fromGlobal !== void 0) return fromGlobal;
1595
+ const metaEnv = readImportMetaEnv();
1596
+ const parsedMeta = parseBrowserLogLevel(
1597
+ metaEnv?.LOG_LEVEL ?? metaEnv?.VITE_LOG_LEVEL ?? metaEnv?.NEXT_PUBLIC_LOG_LEVEL
1598
+ );
1599
+ if (parsedMeta !== void 0) return parsedMeta;
1600
+ const processEnv = typeof process !== "undefined" ? process.env : void 0;
1601
+ return resolveBrowserLogLevel(processEnv?.LOG_LEVEL);
1602
+ }
1603
+ function readGlobalLogLevel() {
1604
+ try {
1605
+ const value = globalThis.__OPENRECEIVE_LOG_LEVEL__;
1606
+ return typeof value === "string" ? value : void 0;
1607
+ } catch {
1608
+ return void 0;
1609
+ }
1610
+ }
1611
+ function readImportMetaEnv() {
1612
+ try {
1613
+ return import.meta.env;
1614
+ } catch {
1615
+ return void 0;
1616
+ }
1617
+ }
1618
+
1619
+ // src/internal/console-logger.ts
1620
+ function createConsoleWriter(options) {
1621
+ const target = options.console ?? console;
1622
+ const now = options.now ?? (() => /* @__PURE__ */ new Date());
1623
+ return (level, prefix, event, message, fields) => {
1624
+ const minLevel = options.minLevel === void 0 ? readBrowserLogLevelFromEnvironment() : resolveBrowserLogLevel(options.minLevel);
1625
+ if (browserLogLevelOrder(level) < browserLogLevelOrder(minLevel)) {
1626
+ return;
1627
+ }
1628
+ const method = level === "error" ? "error" : level === "warn" ? "warn" : level === "debug" ? "debug" : "info";
1629
+ const sink = target[method] ?? target.log;
1630
+ const {
1631
+ level: _level,
1632
+ event: _event,
1633
+ message: cleanMessage,
1634
+ ...cleanFields
1635
+ } = sanitizeBrowserLogEntry({ level, event, message, ...fields });
1636
+ sink.call(
1637
+ target,
1638
+ `[${now().toISOString()}] ${level.toUpperCase()} [${prefix}] ${event}: ${cleanMessage}`,
1639
+ cleanFields
1640
+ );
1641
+ };
1642
+ }
1643
+ function sanitizeBrowserLogEntry(entry) {
1644
+ const clean = {};
1645
+ for (const [key, value] of Object.entries(entry)) {
1646
+ if (/secret|token|authorization|cookie|nwc/i.test(key)) {
1647
+ clean[key] = "[REDACTED]";
1648
+ } else {
1649
+ clean[key] = sanitizeBrowserLogValue(value);
1650
+ }
1651
+ }
1652
+ return clean;
1653
+ }
1654
+ function sanitizeBrowserLogValue(value) {
1655
+ if (typeof value === "string") return redactBrowserSecrets(value);
1656
+ if (Array.isArray(value)) return value.map(sanitizeBrowserLogValue);
1657
+ if (typeof value !== "object" || value === null) return value;
1658
+ const clean = {};
1659
+ for (const [key, nested] of Object.entries(value)) {
1660
+ if (/secret|token|authorization|cookie|nwc/i.test(key)) {
1661
+ clean[key] = "[REDACTED]";
1662
+ } else {
1663
+ clean[key] = sanitizeBrowserLogValue(nested);
1664
+ }
1665
+ }
1666
+ return clean;
1667
+ }
1668
+ function redactBrowserSecrets(value) {
1669
+ return value.replace(/nostr\+walletconnect:\/\/[^\s"'`<>]+/g, "[REDACTED_NWC]").replace(/([?&](?:_or_evt|token|secret)=)[^&\s"'`<>]+/gi, "$1[REDACTED]");
1670
+ }
1671
+ function createBrowserConsoleLogger(options = {}) {
1672
+ const prefix = options.prefix ?? "openreceive";
1673
+ const write = createConsoleWriter(options);
1674
+ return (entry) => {
1675
+ const { level, event, message, ...fields } = entry;
1676
+ write(level, prefix, event, message, fields);
1677
+ };
1678
+ }
1679
+ function createAppBrowserConsoleLogger(options) {
1680
+ const write = createConsoleWriter(options);
1681
+ return (event, message, fields = {}, level = "info") => {
1682
+ write(level, options.prefix, event, message, fields);
1683
+ };
1684
+ }
1685
+ var defaultBrowserConsoleLogger;
1686
+ function getDefaultBrowserConsoleLogger() {
1687
+ defaultBrowserConsoleLogger ??= createBrowserConsoleLogger();
1688
+ return defaultBrowserConsoleLogger;
1689
+ }
1690
+ function resolveBrowserLogger(logger) {
1691
+ if (logger === false) return void 0;
1692
+ if (logger !== void 0) return logger;
1693
+ return getDefaultBrowserConsoleLogger();
1694
+ }
1695
+
1696
+ // src/internal/checkout-read.ts
1697
+ import { nonEmptyString } from "@openreceive/core";
1698
+ function optionalRecord(value) {
1699
+ if (value === void 0) return void 0;
1700
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
1701
+ throw new Error("OpenReceive metadata must be an object.");
1702
+ }
1703
+ return value;
1704
+ }
1705
+ function requiredInvoiceRail(value) {
1706
+ if (value === "lightning" || value === "swap" || value === "checkout_lock") return value;
1707
+ throw new TypeError("OpenReceive invoice rail must be lightning, swap, or checkout_lock.");
1708
+ }
1709
+ function requiredString(value, fieldName) {
1710
+ const text = nonEmptyString(value);
1711
+ if (text === void 0) {
1712
+ throw new TypeError(`OpenReceive checkout response requires ${fieldName}.`);
1713
+ }
1714
+ return text;
1715
+ }
1716
+ function optionalSafeInteger(value, fieldName = "integer") {
1717
+ if (value === void 0 || value === null) return void 0;
1718
+ if (typeof value !== "number" || !Number.isSafeInteger(value)) {
1719
+ throw new TypeError(`OpenReceive checkout response ${fieldName} must be a safe integer.`);
1720
+ }
1721
+ return value;
1722
+ }
1723
+ function requiredSafeInteger(value, fieldName) {
1724
+ const integer = optionalSafeInteger(value, fieldName);
1725
+ if (integer === void 0) {
1726
+ throw new TypeError(`OpenReceive checkout response requires ${fieldName}.`);
1727
+ }
1728
+ return integer;
1729
+ }
1730
+
1731
+ // src/internal/checkout-log.ts
1732
+ import { compact } from "@openreceive/core";
1733
+ function checkoutLogFields(state) {
1734
+ return compact({
1735
+ checkout_id: state.checkout_id,
1736
+ reference: state.reference,
1737
+ invoice_id: state.invoice_id,
1738
+ payment_hash: state.payment_hash,
1739
+ amount_msats: state.amount_msats,
1740
+ transaction_state: state.transaction_state,
1741
+ workflow_state: state.workflow_state,
1742
+ phase: state.phase,
1743
+ expires_in_seconds: state.expires_in_seconds,
1744
+ settled: state.settled,
1745
+ paid: state.paid,
1746
+ rail: state.rail,
1747
+ ...swapAuditLogFields(state.swap)
1748
+ });
1749
+ }
1750
+ function swapAuditLogFields(swap) {
1751
+ if (swap === void 0) return {};
1752
+ return compact({
1753
+ attempt_id: swap.attempt_id,
1754
+ provider: swap.provider,
1755
+ provider_order_id: swap.provider_order_id,
1756
+ pay_in_asset: swap.pay_in_asset,
1757
+ provider_state: swap.provider_state,
1758
+ attention: swap.attention,
1759
+ attention_reason: swap.attention_reason,
1760
+ refund_reason: swap.refund_reason,
1761
+ refund_tx_id: swap.refund_tx_id,
1762
+ deposit_tx_id: swap.deposit_tx_id,
1763
+ payout_tx_id: swap.payout_tx_id
1764
+ });
1765
+ }
1766
+ function emitBrowserSwapTransition(logger, previous, next) {
1767
+ const previousSwap = previous?.swap;
1768
+ const nextSwap = next.swap;
1769
+ if (nextSwap === void 0) return;
1770
+ const previousState = previousSwap?.provider_state;
1771
+ const nextState = nextSwap.provider_state;
1772
+ const previousAttention = previousSwap?.attention_reason;
1773
+ const nextAttention = nextSwap.attention_reason;
1774
+ const previousSettled = previous?.settled === true || previous?.paid === true;
1775
+ const nextSettled = next.settled === true || next.paid === true;
1776
+ const stateChanged = previousState !== nextState;
1777
+ const attentionChanged = previousAttention !== nextAttention;
1778
+ const settlementChanged = previousSettled !== nextSettled;
1779
+ if (!stateChanged && !attentionChanged && !settlementChanged) return;
1780
+ const level = nextState === "attention" || nextSwap.attention === true ? "warn" : nextState === "refund_required" || nextState === "refund_pending" || nextState === "refunded" || nextState === "failed" || nextState === "expired" || settlementChanged ? "info" : "debug";
1781
+ emitBrowserLog(
1782
+ logger,
1783
+ level,
1784
+ "swap.state.changed",
1785
+ "Swap attempt state changed in checkout UI.",
1786
+ {
1787
+ ...checkoutLogFields(next),
1788
+ previous_provider_state: previousState,
1789
+ previous_settled: previousSettled,
1790
+ wallet_settled: nextSettled,
1791
+ ui_label: nextSettled ? "Payment complete" : getSwapProviderStateLabel(nextState)
1792
+ }
1793
+ );
1794
+ }
1795
+ function emitBrowserLog(logger, level, event, message, fields = {}) {
1796
+ const sink = resolveBrowserLogger(logger);
1797
+ if (sink === void 0) return;
1798
+ try {
1799
+ sink(
1800
+ sanitizeBrowserLogEntry({
1801
+ level,
1802
+ event,
1803
+ message,
1804
+ ...fields
1805
+ })
1806
+ );
1807
+ } catch {
1808
+ }
1809
+ }
1810
+
1811
+ // src/internal/checkout-state.ts
1812
+ function selectCheckoutDisplayInvoice(snapshot) {
1813
+ if (snapshot.active !== void 0 && snapshot.active.rail !== "checkout_lock") {
1814
+ return snapshot.active;
1815
+ }
1816
+ const nonLock = snapshot.invoices.filter((invoice) => invoice.rail !== "checkout_lock");
1817
+ const withBolt11 = nonLock.filter(
1818
+ (invoice) => typeof invoice.invoice === "string" && invoice.invoice.length > 0
1819
+ );
1820
+ const settledBolt11 = withBolt11.find((invoice) => invoice.transaction_state === "settled");
1821
+ if (settledBolt11 !== void 0) return settledBolt11;
1822
+ if (withBolt11[0] !== void 0) return withBolt11[0];
1823
+ const settledSwap = nonLock.find((invoice) => invoice.transaction_state === "settled");
1824
+ return settledSwap ?? nonLock[0];
1825
+ }
1826
+ function isPaidCheckoutSnapshot(snapshot) {
1827
+ return snapshot.status === "paid";
1828
+ }
1829
+ function isReusableLightningInvoice(expiresAt, now) {
1830
+ return expiresAt - resolveNow(now) > OPENRECEIVE_LIGHTNING_REUSE_BUFFER_SECONDS;
1831
+ }
1832
+ function createCheckoutState(snapshot, options = {}) {
1833
+ const invoiceRecord = selectCheckoutDisplayInvoice(snapshot);
1834
+ if (invoiceRecord === void 0) {
1835
+ return normalizeCheckoutState(
1836
+ {
1837
+ checkout_id: snapshot.checkout_id,
1838
+ reference: snapshot.reference,
1839
+ invoice_id: "",
1840
+ invoice: "",
1841
+ rail: "checkout_lock",
1842
+ lightning_uri: "",
1843
+ ...snapshot.amount_msats === void 0 ? {} : { amount_msats: snapshot.amount_msats },
1844
+ ...snapshot.fiat !== void 0 ? { fiat_quote: { fiat: snapshot.fiat } } : {},
1845
+ transaction_state: "pending",
1846
+ workflow_state: "invoice_created",
1847
+ paid: false
1848
+ },
1849
+ resolveNow(options.now)
1850
+ );
1851
+ }
1852
+ const invoice = invoiceRecord;
1853
+ const bolt11 = typeof invoice.invoice === "string" && invoice.invoice.length > 0 ? invoice.invoice : invoice.rail === "swap" || invoice.rail === "checkout_lock" ? "" : missingDisplayInvoice();
1854
+ const paid = isPaidCheckoutSnapshot(snapshot);
1855
+ const settledAt = snapshot.paid_at ?? invoice.settled_at;
1856
+ const transactionState = paid ? "settled" : invoice.transaction_state ?? "pending";
1857
+ const workflowState = paid ? "paid" : invoice.workflow_state ?? "invoice_created";
1858
+ const fiatQuote = invoice.fiat_quote === null && snapshot.fiat !== void 0 ? { fiat: snapshot.fiat } : invoice.fiat_quote ?? (snapshot.fiat === void 0 ? void 0 : { fiat: snapshot.fiat });
1859
+ const state = normalizeCheckoutState(
1860
+ {
1861
+ checkout_id: snapshot.checkout_id,
1862
+ reference: snapshot.reference,
1863
+ invoice_id: invoice.invoice_id,
1864
+ invoice: bolt11,
1865
+ rail: invoice.rail,
1866
+ // G4 divergence (d): the swap rail gets NO `lightning:` URI even when the
1867
+ // attempt happens to carry a bolt11. A swap is paid at the deposit
1868
+ // address, and a wallet-jump link on that screen sends the payer down the
1869
+ // wrong rail. `invoice` above still holds the bolt11 for anything that
1870
+ // legitimately needs it.
1871
+ lightning_uri: invoice.rail === "checkout_lock" || invoice.rail === "swap" || bolt11 === "" ? "" : createLightningUri(bolt11),
1872
+ ...invoice.payment_hash === void 0 ? {} : { payment_hash: invoice.payment_hash },
1873
+ // G4 divergence (b): the checkout's amount is what is owed, so an attempt
1874
+ // that omits its own amount still shows one rather than no amount at all.
1875
+ amount_msats: invoice.amount_msats ?? snapshot.amount_msats,
1876
+ ...fiatQuote === void 0 ? {} : { fiat_quote: fiatQuote },
1877
+ transaction_state: transactionState,
1878
+ workflow_state: workflowState,
1879
+ ...invoice.expires_at === void 0 ? {} : { expires_at: invoice.expires_at },
1880
+ ...settledAt === void 0 ? {} : { settled_at: settledAt },
1881
+ ...invoice.swap === void 0 ? {} : { swap: invoice.swap },
1882
+ paid
1883
+ },
1884
+ resolveNow(options.now)
1885
+ );
1886
+ const source = options.source ?? "create";
1887
+ if (source === "create") {
1888
+ emitBrowserLog(
1889
+ options.logger,
1890
+ "info",
1891
+ "checkout.state.created",
1892
+ "Created checkout state from order snapshot.",
1893
+ checkoutLogFields(state)
1894
+ );
1895
+ } else if (source === "refresh") {
1896
+ emitBrowserLog(
1897
+ options.logger,
1898
+ "debug",
1899
+ "checkout.state.refreshed",
1900
+ "Refreshed checkout state from order status.",
1901
+ checkoutLogFields(state)
1902
+ );
1903
+ emitBrowserSwapTransition(options.logger, options.previousState, state);
1904
+ }
1905
+ return state;
1906
+ }
1907
+ function createCheckoutSnapshotFromInvoice(attempt, identity = {}) {
1908
+ const rail = requiredInvoiceRail(attempt.rail);
1909
+ const invoiceId = requiredString(attempt.invoice_id, "invoice_id");
1910
+ const invoice = {
1911
+ invoice_id: invoiceId,
1912
+ invoice: attempt.invoice,
1913
+ rail,
1914
+ ...attempt.payment_hash === void 0 ? {} : { payment_hash: attempt.payment_hash },
1915
+ ...attempt.amount_msats === void 0 ? {} : { amount_msats: attempt.amount_msats },
1916
+ ...attempt.fiat_quote === void 0 ? {} : { fiat_quote: attempt.fiat_quote },
1917
+ ...attempt.transaction_state === void 0 ? {} : { transaction_state: attempt.transaction_state },
1918
+ ...attempt.workflow_state === void 0 ? {} : { workflow_state: attempt.workflow_state },
1919
+ ...attempt.expires_at === void 0 ? {} : { expires_at: attempt.expires_at },
1920
+ ...attempt.settled_at === void 0 ? {} : { settled_at: attempt.settled_at },
1921
+ ...attempt.swap === void 0 ? {} : { swap: attempt.swap }
1922
+ };
1923
+ const paid = attempt.transaction_state === "settled";
1924
+ return {
1925
+ checkout_id: identity.checkout_id ?? invoiceId,
1926
+ reference: identity.reference ?? invoiceId,
1927
+ status: paid ? "paid" : "open",
1928
+ ...attempt.settled_at === void 0 ? {} : { paid_at: attempt.settled_at },
1929
+ amount_msats: attempt.amount_msats ?? 0,
1930
+ active: paid ? void 0 : invoice,
1931
+ invoices: [invoice]
1932
+ };
1933
+ }
1934
+ function refreshCheckoutState(state, options = {}) {
1935
+ return createCheckoutState(snapshotFromCheckoutState(state), {
1936
+ ...options,
1937
+ source: options.source ?? "countdown",
1938
+ previousState: options.previousState ?? state
1939
+ });
1940
+ }
1941
+ function shouldCheckoutShowWaiting(state, options = {}) {
1942
+ if (state.terminal || state.settled) return false;
1943
+ if (state.expires_at === void 0) return true;
1944
+ return state.expires_at > resolveNow(options.now);
1945
+ }
1946
+ function createCheckoutStatusModel(source, options = {}) {
1947
+ const isCheckoutState = source !== void 0 && "invoice_id" in source && "invoice" in source;
1948
+ const phase = source?.phase ?? "invoice_created";
1949
+ const expiresInSeconds = source?.expires_in_seconds;
1950
+ const displayPhase = phase !== "settled" && phase !== "failed" && phase !== "cancelled" && expiresInSeconds === 0 ? "expired" : phase;
1951
+ const statusText = getPaymentStatusText(displayPhase);
1952
+ return {
1953
+ phase: displayPhase,
1954
+ waiting: displayPhase === "expired" ? false : source === void 0 ? false : isCheckoutState ? shouldCheckoutShowWaiting(source, options) : source.waiting ?? false,
1955
+ title: statusText.title,
1956
+ detail: statusText.detail,
1957
+ countdownPrefix: checkoutLabels.countdownPrefix,
1958
+ // No countdown once settled — the invoice's remaining lifetime is meaningless
1959
+ // to a payer whose payment already landed.
1960
+ ...expiresInSeconds === void 0 || displayPhase === "expired" || displayPhase === "settled" ? {} : {
1961
+ expires_in_seconds: expiresInSeconds,
1962
+ countdownLabel: formatCountdown(expiresInSeconds)
1963
+ }
1964
+ };
1965
+ }
1966
+ function normalizeCheckoutState(state, now) {
1967
+ const {
1968
+ phase: _phase,
1969
+ settled: _settled,
1970
+ terminal: _terminal,
1971
+ expires_in_seconds: _expiresInSeconds,
1972
+ // Labels are derived, never carried: a caller handing back a previous state
1973
+ // with one field changed must not keep that state's stale labels.
1974
+ amountLabel: _amountLabel,
1975
+ fiatLabel: _fiatLabel,
1976
+ paymentHashLabel: _paymentHashLabel,
1977
+ ...base
1978
+ } = state;
1979
+ const statePhase = getCheckoutPhase(state.transaction_state, state.workflow_state);
1980
+ const expiresInSeconds = base.expires_at === void 0 || now === void 0 ? void 0 : Math.max(0, base.expires_at - now);
1981
+ const phase = statePhase === "invoice_created" || statePhase === "verifying" ? expiresInSeconds === 0 ? "expired" : statePhase : statePhase;
1982
+ const settled = base.paid || base.transaction_state === "settled";
1983
+ return {
1984
+ ...base,
1985
+ ...deriveCheckoutStateLabels(base),
1986
+ phase,
1987
+ settled,
1988
+ // A swap that expired, refunded, failed, or needs support review is over:
1989
+ // the shadow invoice behind it will not be paid, so watchers stop polling
1990
+ // both /payments/check and the provider instead of asking forever.
1991
+ terminal: isTerminalPhase(phase) || !settled && isTerminalSwapProviderState(base.swap?.provider_state),
1992
+ ...expiresInSeconds === void 0 ? {} : { expires_in_seconds: expiresInSeconds }
1993
+ };
1994
+ }
1995
+ function missingDisplayInvoice() {
1996
+ throw new TypeError("OpenReceive checkout requires a display Lightning invoice.");
1997
+ }
1998
+ function getCheckoutPhase(transactionState, workflowState) {
1999
+ if (workflowState === "cancelled") return "cancelled";
2000
+ if (transactionState === "settled") return "settled";
2001
+ if (transactionState === "expired" || workflowState === "expired") {
2002
+ return "expired";
2003
+ }
2004
+ if (transactionState === "failed" || workflowState === "failed") {
2005
+ return "failed";
2006
+ }
2007
+ if (workflowState === "verifying") {
2008
+ return "verifying";
2009
+ }
2010
+ return "invoice_created";
2011
+ }
2012
+ function isTerminalPhase(phase) {
2013
+ return phase === "expired" || phase === "failed" || phase === "cancelled";
2014
+ }
2015
+ function snapshotFromCheckoutState(state) {
2016
+ const invoice = {
2017
+ invoice_id: state.invoice_id,
2018
+ invoice: state.invoice,
2019
+ rail: state.rail,
2020
+ ...state.payment_hash === void 0 ? {} : { payment_hash: state.payment_hash },
2021
+ ...state.amount_msats === void 0 ? {} : { amount_msats: state.amount_msats },
2022
+ ...state.fiat_quote === void 0 ? {} : { fiat_quote: state.fiat_quote },
2023
+ transaction_state: state.transaction_state,
2024
+ workflow_state: state.workflow_state,
2025
+ ...state.expires_at === void 0 ? {} : { expires_at: state.expires_at },
2026
+ ...state.settled_at === void 0 ? {} : { settled_at: state.settled_at },
2027
+ ...state.swap === void 0 ? {} : { swap: state.swap }
2028
+ };
2029
+ return {
2030
+ checkout_id: state.checkout_id,
2031
+ reference: state.reference,
2032
+ status: state.paid ? "paid" : state.terminal ? "expired" : "open",
2033
+ ...state.settled_at === void 0 ? {} : { paid_at: state.settled_at },
2034
+ amount_msats: state.amount_msats ?? 0,
2035
+ active: state.paid ? void 0 : invoice,
2036
+ invoices: [invoice]
2037
+ };
2038
+ }
2039
+
2040
+ // src/internal/checkout-merge.ts
2041
+ function findReusableLightningInvoice(snapshot, now) {
2042
+ return snapshot.invoices.find(
2043
+ (invoice) => invoice.rail === "lightning" && typeof invoice.invoice === "string" && invoice.invoice.length > 0 && invoice.expires_at !== void 0 && isReusableLightningInvoice(invoice.expires_at, now)
2044
+ );
2045
+ }
2046
+ function mergeAttemptIntoSnapshot(invoice, base) {
2047
+ const withoutSame = base.invoices.filter(
2048
+ (entry) => entry.invoice_id !== invoice.invoice_id && entry.rail !== "checkout_lock"
2049
+ );
2050
+ return {
2051
+ ...base,
2052
+ checkout_id: invoice.invoice_id,
2053
+ active: invoice,
2054
+ invoices: [invoice, ...withoutSame],
2055
+ ...invoice.amount_msats === void 0 ? {} : { amount_msats: invoice.amount_msats }
2056
+ };
2057
+ }
2058
+ function mergeAttemptIntoCheckout(invoice, previous, reference) {
2059
+ const base = previous ?? {
2060
+ checkout_id: invoice.invoice_id,
2061
+ reference,
2062
+ status: "open",
2063
+ amount_msats: invoice.amount_msats ?? 0,
2064
+ invoices: []
2065
+ };
2066
+ return mergeAttemptIntoSnapshot(invoice, base);
2067
+ }
2068
+ function mergeMintedCheckout(checkout, previous) {
2069
+ const minted = selectCheckoutDisplayInvoice(checkout) ?? checkout.active;
2070
+ if (minted === void 0) {
2071
+ return {
2072
+ ...checkout,
2073
+ ...previous?.payment_methods === void 0 ? {} : { payment_methods: previous.payment_methods }
2074
+ };
2075
+ }
2076
+ if (previous === void 0) return mergeAttemptIntoSnapshot(minted, checkout);
2077
+ return mergeAttemptIntoSnapshot(minted, {
2078
+ ...previous,
2079
+ ...checkout,
2080
+ invoices: previous.invoices,
2081
+ payment_methods: previous.payment_methods ?? checkout.payment_methods
2082
+ });
2083
+ }
2084
+
2085
+ // src/internal/checkout-transport.ts
2086
+ import { isRecord, nonEmptyString as nonEmptyString2, recordOrEmpty } from "@openreceive/core";
2087
+
2088
+ // src/internal/request-headers.ts
2089
+ function requestHeaders(host) {
2090
+ return {
2091
+ "Content-Type": "application/json",
2092
+ ...csrfTokenHeader(),
2093
+ ...host
2094
+ };
2095
+ }
2096
+ function csrfTokenHeader() {
2097
+ if (typeof document === "undefined") return {};
2098
+ const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute("content");
2099
+ return token ? { "X-CSRF-Token": token } : {};
2100
+ }
2101
+
2102
+ // src/internal/routes.ts
2103
+ function checkoutRoutes(prefix) {
2104
+ if (typeof prefix !== "string") {
2105
+ throw new TypeError(
2106
+ `OpenReceive requires \`prefix\`, the base path the shipped router is mounted at (for example "/openreceive"); every checkout, status and swap route is derived from it. Received ${prefix === null ? "null" : typeof prefix}.`
2107
+ );
2108
+ }
2109
+ const base = prefix.replace(/\/+$/, "");
2110
+ return {
2111
+ checkouts: `${base}/checkouts`,
2112
+ checkoutsPrepare: `${base}/checkouts/prepare`,
2113
+ paymentsCheck: `${base}/payments/check`,
2114
+ swaps: `${base}/swaps`,
2115
+ swapsQuote: `${base}/swaps/quote`,
2116
+ swapsStatus: `${base}/swaps/status`,
2117
+ swapsRefunds: `${base}/swaps/refunds`
2118
+ };
2119
+ }
2120
+
2121
+ // src/internal/checkout-transport.ts
2122
+ var SWAP_STATUS_FAILURE_LIMIT = 3;
2123
+ var BrowserRequestError = class extends Error {
2124
+ status;
2125
+ code;
2126
+ retryable;
2127
+ retryAfterSeconds;
2128
+ constructor(message, options) {
2129
+ super(message);
2130
+ this.name = "BrowserRequestError";
2131
+ this.status = options.status;
2132
+ if (options.code !== void 0) this.code = options.code;
2133
+ if (options.retryable !== void 0) this.retryable = options.retryable;
2134
+ if (options.retryAfterSeconds !== void 0) this.retryAfterSeconds = options.retryAfterSeconds;
2135
+ }
2136
+ };
2137
+ async function readJsonResponse(response, fallbackMessage) {
2138
+ let body;
2139
+ try {
2140
+ body = await response.json();
2141
+ } catch {
2142
+ if (response.ok) {
2143
+ throw new BrowserRequestError(`${fallbackMessage} The server returned a non-JSON body.`, {
2144
+ status: response.status,
2145
+ retryable: false
2146
+ });
2147
+ }
2148
+ body = void 0;
2149
+ }
2150
+ if (!response.ok) {
2151
+ const record = body !== null && typeof body === "object" ? body : void 0;
2152
+ const retryAfterRaw = Number(response.headers?.get?.("retry-after") ?? Number.NaN);
2153
+ throw new BrowserRequestError(
2154
+ typeof record?.message === "string" ? record.message : fallbackMessage,
2155
+ {
2156
+ status: response.status,
2157
+ ...typeof record?.code === "string" ? { code: record.code } : {},
2158
+ ...typeof record?.retryable === "boolean" ? { retryable: record.retryable } : {},
2159
+ ...Number.isFinite(retryAfterRaw) && retryAfterRaw > 0 ? { retryAfterSeconds: retryAfterRaw } : {}
2160
+ }
2161
+ );
2162
+ }
2163
+ return body;
2164
+ }
2165
+ function normalizeRequestCheckoutOptions(options) {
2166
+ const reference = nonEmptyString2(options.reference);
2167
+ const metadata = optionalRecord(options.metadata);
2168
+ return {
2169
+ routes: checkoutRoutes(options.prefix),
2170
+ reference: reference ?? "",
2171
+ fetch: options.fetch,
2172
+ headers: options.headers,
2173
+ ...options.memo === void 0 ? {} : { memo: options.memo },
2174
+ ...metadata === void 0 ? {} : { metadata }
2175
+ };
2176
+ }
2177
+ async function requestCheckout(options) {
2178
+ const request = normalizeRequestCheckoutOptions(options);
2179
+ if (request.reference.length === 0) {
2180
+ throw new Error("OpenReceive checkout creation requires reference.");
2181
+ }
2182
+ const fetcher = request.fetch ?? globalThis.fetch;
2183
+ if (fetcher === void 0) {
2184
+ throw new Error("OpenReceive checkout creation requires fetch.");
2185
+ }
2186
+ if (request.memo !== void 0 && request.memo.length > 500) {
2187
+ throw new Error("OpenReceive memo must be 500 characters or fewer.");
2188
+ }
2189
+ const requestBody = {
2190
+ reference: request.reference,
2191
+ ...request.memo === void 0 ? {} : { memo: request.memo },
2192
+ ...request.metadata === void 0 ? {} : { metadata: structuredClone(request.metadata) }
2193
+ };
2194
+ const headers = request.headers === void 0 ? {} : request.headers;
2195
+ const response = await fetcher(request.routes.checkouts, {
2196
+ method: "POST",
2197
+ headers: requestHeaders(headers),
2198
+ body: JSON.stringify(requestBody)
2199
+ });
2200
+ const body = await readJsonResponse(response, "Could not create checkout.");
2201
+ const snapshot = checkoutSnapshotFromResponseBody(body);
2202
+ const responseInvoice = snapshot.active;
2203
+ if (isRecord(responseInvoice) && typeof responseInvoice.invoice === "string") {
2204
+ assertDisplayInvoice(responseInvoice.invoice);
2205
+ }
2206
+ return options.previous === void 0 ? snapshot : mergeMintedCheckout(snapshot, options.previous);
2207
+ }
2208
+ async function prepareCheckout(options) {
2209
+ const request = normalizeRequestCheckoutOptions(options);
2210
+ if (request.reference.length === 0) {
2211
+ throw new Error("OpenReceive checkout prepare requires reference.");
2212
+ }
2213
+ const fetcher = request.fetch ?? globalThis.fetch;
2214
+ if (fetcher === void 0) {
2215
+ throw new Error("OpenReceive checkout prepare requires fetch.");
2216
+ }
2217
+ const headers = request.headers === void 0 ? {} : request.headers;
2218
+ const response = await fetcher(request.routes.checkoutsPrepare, {
2219
+ method: "POST",
2220
+ headers: requestHeaders(headers),
2221
+ body: JSON.stringify({ reference: request.reference })
2222
+ });
2223
+ const body = await readJsonResponse(response, "Could not prepare checkout.");
2224
+ return checkoutLockSnapshotFromPrepareBody(body, request.reference);
2225
+ }
2226
+ function createStatusFetcher(options) {
2227
+ let snapshot = options.snapshot;
2228
+ let swapStatusFailures = 0;
2229
+ const routes = checkoutRoutes(options.prefix);
2230
+ return async (reference) => {
2231
+ if (reference.length === 0) {
2232
+ throw new Error("OpenReceive status refresh requires reference.");
2233
+ }
2234
+ const fetcher = options.fetch ?? globalThis.fetch;
2235
+ if (fetcher === void 0) {
2236
+ throw new Error("OpenReceive status refresh requires fetch.");
2237
+ }
2238
+ const headers = options.headers === void 0 ? {} : options.headers;
2239
+ const activePaymentHash = nonEmptyString2(snapshot.active?.payment_hash) ?? (snapshot.active?.rail === "checkout_lock" ? void 0 : nonEmptyString2(snapshot.active?.invoice_id));
2240
+ if (activePaymentHash === void 0 || !/^[0-9a-f]{64}$/i.test(activePaymentHash)) {
2241
+ return snapshot;
2242
+ }
2243
+ const response = await fetcher(routes.paymentsCheck, {
2244
+ method: "POST",
2245
+ headers: requestHeaders(headers),
2246
+ body: JSON.stringify({
2247
+ reference,
2248
+ payment_hash: activePaymentHash
2249
+ })
2250
+ });
2251
+ const body = await readJsonResponse(response, "Could not refresh invoice status.");
2252
+ const payment = recordOrEmpty(body);
2253
+ const next = structuredClone(snapshot);
2254
+ if (next.active === void 0) return next;
2255
+ const state = nonEmptyString2(payment.status) ?? "pending";
2256
+ const paidAt = optionalSafeInteger(payment.paid_at, "paid_at");
2257
+ let active = {
2258
+ ...next.active,
2259
+ transaction_state: state === "not_found" ? "pending" : state,
2260
+ ...paidAt === void 0 ? {} : { settled_at: paidAt }
2261
+ };
2262
+ if (active.rail === "swap" && active.swap !== void 0 && state !== "settled" && // A terminal provider state is final; re-reading it only adds provider load.
2263
+ !isTerminalSwapProviderState(nonEmptyString2(active.swap.provider_state))) {
2264
+ try {
2265
+ const swapResponse = await fetcher(routes.swapsStatus, {
2266
+ method: "POST",
2267
+ headers: requestHeaders(headers),
2268
+ body: JSON.stringify({ reference, payment_hash: activePaymentHash })
2269
+ });
2270
+ const swapBody = recordOrEmpty(
2271
+ await readJsonResponse(swapResponse, "Could not refresh swap status.")
2272
+ );
2273
+ active = mergeSwapStatusIntoInvoice(active, swapBody);
2274
+ swapStatusFailures = 0;
2275
+ } catch (error) {
2276
+ swapStatusFailures += 1;
2277
+ const definitive = error instanceof BrowserRequestError && error.retryable === false;
2278
+ const swap = active.swap;
2279
+ if (swap !== void 0 && (definitive || swapStatusFailures >= SWAP_STATUS_FAILURE_LIMIT)) {
2280
+ active = {
2281
+ ...active,
2282
+ swap: { ...swap, attention: true, attention_reason: "swap_status_unavailable" }
2283
+ };
2284
+ }
2285
+ }
2286
+ }
2287
+ const paymentMethods2 = normalizePaymentMethods(payment.payment_methods);
2288
+ const others = next.invoices.filter(
2289
+ (entry) => entry.invoice_id !== active.invoice_id && entry.rail !== "checkout_lock"
2290
+ );
2291
+ snapshot = {
2292
+ ...next,
2293
+ active,
2294
+ invoices: [active, ...others],
2295
+ status: state === "settled" ? "paid" : state === "expired" || state === "failed" ? "expired" : "open",
2296
+ ...paymentMethods2 === void 0 ? {} : { payment_methods: paymentMethods2 }
2297
+ };
2298
+ return snapshot;
2299
+ };
2300
+ }
2301
+ function mergeSwapStatusIntoInvoice(invoice, status) {
2302
+ const swap = invoice.swap;
2303
+ if (swap === void 0) return invoice;
2304
+ const merged = { ...swap };
2305
+ const providerState = nonEmptyString2(status.provider_state);
2306
+ if (providerState !== void 0) merged.provider_state = providerState;
2307
+ const providerExpiresAt = optionalSafeInteger(status.provider_expires_at, "provider_expires_at");
2308
+ if (providerExpiresAt !== void 0) merged.provider_expires_at = providerExpiresAt;
2309
+ for (const key of [
2310
+ "deposit_tx_id",
2311
+ "payout_tx_id",
2312
+ "refund_tx_id",
2313
+ "refund_reason",
2314
+ "refund_amount",
2315
+ "deposit_received_amount",
2316
+ "refund_address",
2317
+ "attention_reason"
2318
+ ]) {
2319
+ if (typeof status[key] === "string") merged[key] = status[key];
2320
+ }
2321
+ if (typeof status.attention === "boolean") merged.attention = status.attention;
2322
+ return {
2323
+ ...invoice,
2324
+ swap: merged,
2325
+ ...providerExpiresAt === void 0 ? {} : { expires_at: providerExpiresAt }
2326
+ };
2327
+ }
2328
+ function checkoutLockSnapshotFromPrepareBody(body, fallbackReference) {
2329
+ const record = recordOrEmpty(body);
2330
+ const reference = requiredString(record.reference ?? fallbackReference, "reference");
2331
+ const amountMsats = requiredSafeInteger(record.amount_msats, "amount_msats");
2332
+ const lockId = `lock:${reference}`;
2333
+ const lockInvoice = {
2334
+ invoice_id: lockId,
2335
+ rail: "checkout_lock",
2336
+ amount_msats: amountMsats,
2337
+ transaction_state: "pending",
2338
+ workflow_state: "invoice_created"
2339
+ };
2340
+ const fiatQuote = record.fiat_quote;
2341
+ const fiatRecord = isRecord(fiatQuote) && isRecord(fiatQuote.fiat) ? fiatQuote.fiat : void 0;
2342
+ const fiatCurrency = nonEmptyString2(fiatRecord?.currency);
2343
+ const fiatValue = nonEmptyString2(fiatRecord?.value);
2344
+ const fiat = fiatCurrency === void 0 || fiatValue === void 0 ? void 0 : { currency: fiatCurrency, value: fiatValue };
2345
+ const paymentMethods2 = normalizePaymentMethods(record.payment_methods);
2346
+ return {
2347
+ checkout_id: lockId,
2348
+ reference,
2349
+ status: "open",
2350
+ amount_msats: amountMsats,
2351
+ ...fiat === void 0 ? {} : { fiat },
2352
+ active: lockInvoice,
2353
+ invoices: [lockInvoice],
2354
+ ...paymentMethods2 === void 0 ? {} : { payment_methods: paymentMethods2 }
2355
+ };
2356
+ }
2357
+ function checkoutSnapshotFromResponseBody(body) {
2358
+ const record = recordOrEmpty(body);
2359
+ const wrapped = recordOrEmpty(record.checkout);
2360
+ return checkoutSnapshot(wrapped);
2361
+ }
2362
+ function checkoutSnapshot(checkout) {
2363
+ const paymentHash = requiredString(checkout.payment_hash, "payment_hash");
2364
+ const reference = requiredString(checkout.reference, "reference");
2365
+ const amountMsats = requiredSafeInteger(checkout.amount_msats, "amount_msats");
2366
+ const invoice = {
2367
+ invoice_id: paymentHash,
2368
+ rail: "lightning",
2369
+ invoice: requiredString(checkout.bolt11, "bolt11"),
2370
+ payment_hash: paymentHash,
2371
+ amount_msats: amountMsats,
2372
+ transaction_state: "pending",
2373
+ workflow_state: "invoice_created",
2374
+ expires_at: requiredSafeInteger(checkout.expires_at, "expires_at"),
2375
+ ...isRecord(checkout.fiat_quote) || checkout.fiat_quote === null ? { fiat_quote: checkout.fiat_quote } : {}
2376
+ };
2377
+ return {
2378
+ checkout_id: paymentHash,
2379
+ reference,
2380
+ status: "open",
2381
+ amount_msats: amountMsats,
2382
+ active: invoice,
2383
+ invoices: [invoice]
2384
+ };
2385
+ }
2386
+ function normalizePaymentMethods(value) {
2387
+ if (!Array.isArray(value)) return void 0;
2388
+ return value.map(normalizePaymentMethod);
2389
+ }
2390
+ function normalizePaymentMethod(input) {
2391
+ const record = recordOrEmpty(input);
2392
+ const provider = record.provider;
2393
+ if (typeof provider !== "string") {
2394
+ throw new TypeError("payment method provider must be a string");
2395
+ }
2396
+ const unavailableReason = nonEmptyString2(record.unavailable_reason);
2397
+ const unavailableMessage = nonEmptyString2(record.unavailable_message);
2398
+ const payAmount = nonEmptyString2(record.pay_amount);
2399
+ const minimumPayAmount = nonEmptyString2(record.minimum_pay_amount);
2400
+ const maximumPayAmount = nonEmptyString2(record.maximum_pay_amount);
2401
+ const minimumInvoiceAmountMsats = optionalSafeInteger(
2402
+ record.minimum_invoice_amount_msats,
2403
+ "minimum_invoice_amount_msats"
2404
+ );
2405
+ const maximumInvoiceAmountMsats = optionalSafeInteger(
2406
+ record.maximum_invoice_amount_msats,
2407
+ "maximum_invoice_amount_msats"
2408
+ );
2409
+ return {
2410
+ pay_in_asset: requiredString(record.pay_in_asset, "pay_in_asset"),
2411
+ label: requiredString(record.label, "label"),
2412
+ network_label: requiredString(record.network_label, "network_label"),
2413
+ provider,
2414
+ available: record.available === true,
2415
+ ...unavailableReason === void 0 ? {} : { unavailable_reason: unavailableReason },
2416
+ ...unavailableMessage === void 0 ? {} : { unavailable_message: unavailableMessage },
2417
+ ...payAmount === void 0 ? {} : { pay_amount: payAmount },
2418
+ ...minimumPayAmount === void 0 ? {} : { minimum_pay_amount: minimumPayAmount },
2419
+ ...maximumPayAmount === void 0 ? {} : { maximum_pay_amount: maximumPayAmount },
2420
+ ...minimumInvoiceAmountMsats === void 0 ? {} : { minimum_invoice_amount_msats: minimumInvoiceAmountMsats },
2421
+ ...maximumInvoiceAmountMsats === void 0 ? {} : { maximum_invoice_amount_msats: maximumInvoiceAmountMsats }
2422
+ };
2423
+ }
2424
+
2425
+ // src/internal/checkout-actions.ts
2426
+ import * as defaultQrEncoder from "qrcode";
2427
+ import { recordOrEmpty as recordOrEmpty2 } from "@openreceive/core";
2428
+ async function createQrSvg(invoice, options = {}) {
2429
+ return await createQrPayloadSvg(createLightningUri(invoice), options);
2430
+ }
2431
+ async function createQrPayloadSvg(payload, options = {}) {
2432
+ const encoder = getQrEncoder(options.encoder);
2433
+ const svg = await encoder.toString(payload, {
2434
+ type: "svg",
2435
+ errorCorrectionLevel: OPENRECEIVE_QR_ERROR_CORRECTION,
2436
+ margin: OPENRECEIVE_QR_QUIET_ZONE_MODULES,
2437
+ width: options.width,
2438
+ color: {
2439
+ dark: OPENRECEIVE_QR_DARK_COLOR,
2440
+ light: OPENRECEIVE_QR_LIGHT_COLOR
2441
+ }
2442
+ });
2443
+ return String(svg);
2444
+ }
2445
+ async function createQrPngDataUrl(invoice, options = {}) {
2446
+ const encoder = getQrEncoder(options.encoder);
2447
+ if (encoder.toDataURL === void 0) {
2448
+ throw new Error("QR encoder does not support PNG data URL output.");
2449
+ }
2450
+ const png = await encoder.toDataURL(createLightningUri(invoice), {
2451
+ type: "image/png",
2452
+ errorCorrectionLevel: OPENRECEIVE_QR_ERROR_CORRECTION,
2453
+ margin: OPENRECEIVE_QR_QUIET_ZONE_MODULES,
2454
+ width: options.width,
2455
+ color: {
2456
+ dark: OPENRECEIVE_QR_DARK_COLOR,
2457
+ light: OPENRECEIVE_QR_LIGHT_COLOR
2458
+ }
2459
+ });
2460
+ return String(png);
2461
+ }
2462
+ async function copyInvoice(options) {
2463
+ assertInvoice(options.invoice);
2464
+ const clipboard = options.clipboard ?? globalThis.navigator?.clipboard;
2465
+ if (clipboard === void 0) {
2466
+ throw new Error("Clipboard API is unavailable.");
2467
+ }
2468
+ await clipboard.writeText(options.invoice);
2469
+ emitBrowserLog(
2470
+ options.logger,
2471
+ "info",
2472
+ "checkout.invoice.copied",
2473
+ "Copied Lightning invoice to clipboard.",
2474
+ options.logContext
2475
+ );
2476
+ }
2477
+ function openWallet(options) {
2478
+ const uri = createLightningUri(options.invoice);
2479
+ if (options.open !== void 0) {
2480
+ options.open(uri);
2481
+ emitBrowserLog(
2482
+ options.logger,
2483
+ "info",
2484
+ "checkout.wallet.opened",
2485
+ "Opened Lightning invoice URI.",
2486
+ options.logContext
2487
+ );
2488
+ return uri;
2489
+ }
2490
+ const location = globalThis.window?.location;
2491
+ if (location === void 0) {
2492
+ throw new Error("window.location is unavailable.");
2493
+ }
2494
+ location.assign(uri);
2495
+ emitBrowserLog(
2496
+ options.logger,
2497
+ "info",
2498
+ "checkout.wallet.opened",
2499
+ "Opened Lightning invoice URI.",
2500
+ options.logContext
2501
+ );
2502
+ return uri;
2503
+ }
2504
+ function getQrEncoder(encoder) {
2505
+ if (encoder !== void 0) return encoder;
2506
+ if (isQrEncoder(defaultQrEncoder)) return defaultQrEncoder;
2507
+ throw new Error("qrcode package did not expose a compatible encoder.");
2508
+ }
2509
+ function isQrEncoder(value) {
2510
+ const record = recordOrEmpty2(value);
2511
+ return typeof record.toString === "function" && record.toString !== Object.prototype.toString && (typeof record.create === "function" || typeof record.toDataURL === "function");
2512
+ }
2513
+
2514
+ // src/internal/checkout-watcher.ts
2515
+ import { unixSeconds as unixSeconds3 } from "@openreceive/core";
2516
+ var CheckoutWatcher = class {
2517
+ options;
2518
+ state;
2519
+ countdownTimer;
2520
+ pollTimer;
2521
+ running = false;
2522
+ pollInFlight = false;
2523
+ pollFailureCount = 0;
2524
+ pollBackoffUntil;
2525
+ constructor(options) {
2526
+ this.options = options;
2527
+ }
2528
+ start() {
2529
+ this.stop();
2530
+ this.running = true;
2531
+ this.options.onSnapshot?.(this.options.snapshot);
2532
+ const state = createCheckoutState(this.options.snapshot, {
2533
+ now: this.now(),
2534
+ logger: this.options.logger
2535
+ });
2536
+ this.applyState(state);
2537
+ return state;
2538
+ }
2539
+ stop() {
2540
+ this.running = false;
2541
+ this.stopCountdown();
2542
+ this.stopPolling();
2543
+ }
2544
+ getState() {
2545
+ return this.state;
2546
+ }
2547
+ /**
2548
+ * Stop and enter the terminal `cancelled` phase. Unlike {@link stop}, the
2549
+ * watcher's own state moves, so later reads report `cancelled` instead of the
2550
+ * last polled state.
2551
+ */
2552
+ cancel() {
2553
+ const current = this.state ?? createCheckoutState(this.options.snapshot, {
2554
+ now: this.now(),
2555
+ logger: this.options.logger
2556
+ });
2557
+ this.stop();
2558
+ if (current.settled) {
2559
+ this.state = current;
2560
+ return current;
2561
+ }
2562
+ const cancelled = normalizeCheckoutState(
2563
+ { ...current, workflow_state: "cancelled" },
2564
+ this.now()
2565
+ );
2566
+ this.state = cancelled;
2567
+ this.options.onState(cancelled);
2568
+ return cancelled;
2569
+ }
2570
+ async reloadState() {
2571
+ const current = this.state ?? createCheckoutState(this.options.snapshot, {
2572
+ now: this.now(),
2573
+ logger: this.options.logger
2574
+ });
2575
+ const refreshStatus = this.options.refreshStatus;
2576
+ if (refreshStatus === void 0 || current.reference.length === 0) {
2577
+ return current;
2578
+ }
2579
+ try {
2580
+ const next = await refreshStatus(current.reference);
2581
+ if (next === null) return current;
2582
+ this.options.onSnapshot?.(next);
2583
+ const nextState = createCheckoutState(next, {
2584
+ now: this.now(),
2585
+ logger: this.options.logger,
2586
+ source: "refresh",
2587
+ previousState: current
2588
+ });
2589
+ if (this.running) {
2590
+ this.applyState(nextState);
2591
+ } else {
2592
+ this.state = nextState;
2593
+ }
2594
+ return nextState;
2595
+ } catch (error) {
2596
+ this.options.onError?.(error);
2597
+ throw error;
2598
+ }
2599
+ }
2600
+ applyState(state) {
2601
+ if (!this.running) return;
2602
+ this.state = state;
2603
+ this.options.onState(state);
2604
+ this.syncWatchers();
2605
+ }
2606
+ syncWatchers() {
2607
+ const state = this.state;
2608
+ if (state === void 0 || !this.running) return;
2609
+ if (state.terminal) {
2610
+ this.stop();
2611
+ return;
2612
+ }
2613
+ if (state.settled || state.expires_at === void 0) {
2614
+ this.stopCountdown();
2615
+ } else if (this.countdownTimer === void 0) {
2616
+ this.countdownTimer = this.setInterval()(() => {
2617
+ const current = this.state;
2618
+ if (current === void 0) return;
2619
+ this.applyState(
2620
+ refreshCheckoutState(current, {
2621
+ now: this.now(),
2622
+ logger: this.options.logger,
2623
+ source: "countdown"
2624
+ })
2625
+ );
2626
+ }, 1e3);
2627
+ }
2628
+ const canPollAttempt = state.rail !== "checkout_lock" && typeof state.payment_hash === "string" && /^[0-9a-f]{64}$/i.test(state.payment_hash);
2629
+ if (state.settled || this.options.refreshStatus === void 0 || state.reference.length === 0 || !canPollAttempt) {
2630
+ this.stopPolling();
2631
+ } else if (this.pollTimer === void 0) {
2632
+ this.pollTimer = this.setInterval()(() => {
2633
+ void this.poll();
2634
+ }, this.options.pollIntervalMs ?? OPENRECEIVE_DEFAULT_POLL_INTERVAL_MS);
2635
+ }
2636
+ }
2637
+ async poll() {
2638
+ const refreshStatus = this.options.refreshStatus;
2639
+ const current = this.state;
2640
+ if (!this.running || refreshStatus === void 0 || current === void 0) return;
2641
+ if (current.terminal || current.settled) {
2642
+ this.stopPolling();
2643
+ return;
2644
+ }
2645
+ if (this.pollInFlight) return;
2646
+ if (this.pollBackoffUntil !== void 0 && this.now() < this.pollBackoffUntil) return;
2647
+ this.pollInFlight = true;
2648
+ try {
2649
+ const next = await refreshStatus(current.reference);
2650
+ this.pollFailureCount = 0;
2651
+ this.pollBackoffUntil = void 0;
2652
+ if (next === null) return;
2653
+ if (!this.running || this.state === void 0) return;
2654
+ if (this.state.settled || this.state.terminal) return;
2655
+ this.options.onSnapshot?.(next);
2656
+ this.applyState(
2657
+ createCheckoutState(next, {
2658
+ now: this.now(),
2659
+ logger: this.options.logger,
2660
+ source: "refresh",
2661
+ previousState: this.state
2662
+ })
2663
+ );
2664
+ } catch (error) {
2665
+ this.pollFailureCount += 1;
2666
+ const retryAfterSeconds = error instanceof BrowserRequestError ? error.retryAfterSeconds : void 0;
2667
+ const backoffSeconds = retryAfterSeconds ?? Math.min(60, 2 ** Math.min(this.pollFailureCount, 6));
2668
+ this.pollBackoffUntil = this.now() + backoffSeconds;
2669
+ this.options.onError?.(error);
2670
+ } finally {
2671
+ this.pollInFlight = false;
2672
+ }
2673
+ }
2674
+ stopCountdown() {
2675
+ if (this.countdownTimer === void 0) return;
2676
+ this.clearInterval()(this.countdownTimer);
2677
+ this.countdownTimer = void 0;
2678
+ }
2679
+ stopPolling() {
2680
+ if (this.pollTimer === void 0) return;
2681
+ this.clearInterval()(this.pollTimer);
2682
+ this.pollTimer = void 0;
2683
+ }
2684
+ now() {
2685
+ return this.options.now?.() ?? unixSeconds3();
2686
+ }
2687
+ setInterval() {
2688
+ return this.options.setInterval ?? globalThis.setInterval;
2689
+ }
2690
+ clearInterval() {
2691
+ return this.options.clearInterval ?? globalThis.clearInterval;
2692
+ }
2693
+ };
2694
+ var BrowserCheckoutController = class {
2695
+ options;
2696
+ watcher;
2697
+ state;
2698
+ constructor(options) {
2699
+ this.options = options;
2700
+ this.watcher = this.createWatcher(options);
2701
+ }
2702
+ start() {
2703
+ this.state = this.watcher.start();
2704
+ return this.state;
2705
+ }
2706
+ stop() {
2707
+ this.watcher.stop();
2708
+ }
2709
+ getState() {
2710
+ return this.watcher.getState() ?? this.state;
2711
+ }
2712
+ async copyInvoice() {
2713
+ const state = this.currentState();
2714
+ await copyInvoice({
2715
+ invoice: state.invoice,
2716
+ clipboard: this.options.clipboard,
2717
+ logger: this.options.logger,
2718
+ logContext: checkoutLogFields(state)
2719
+ });
2720
+ }
2721
+ openWallet() {
2722
+ const state = this.currentState();
2723
+ return openWallet({
2724
+ invoice: state.invoice,
2725
+ open: this.options.open,
2726
+ logger: this.options.logger,
2727
+ logContext: checkoutLogFields(state)
2728
+ });
2729
+ }
2730
+ async reloadState() {
2731
+ return this.watcher.reloadState();
2732
+ }
2733
+ cancel() {
2734
+ this.state = this.watcher.cancel();
2735
+ emitBrowserLog(
2736
+ this.options.logger,
2737
+ "info",
2738
+ "checkout.cancelled",
2739
+ "Cancelled checkout and stopped the watcher.",
2740
+ checkoutLogFields(this.state)
2741
+ );
2742
+ return this.state;
2743
+ }
2744
+ createWatcher(options) {
2745
+ const refreshStatus = options.refreshStatus ?? (options.prefix === void 0 ? void 0 : createStatusFetcher({
2746
+ prefix: options.prefix,
2747
+ snapshot: options.snapshot,
2748
+ fetch: options.fetch,
2749
+ headers: options.statusHeaders
2750
+ }));
2751
+ return new CheckoutWatcher({
2752
+ ...options,
2753
+ ...refreshStatus === void 0 ? {} : { refreshStatus },
2754
+ onState: (state) => {
2755
+ this.state = state;
2756
+ options.onState?.(state);
2757
+ },
2758
+ ...options.onSnapshot === void 0 ? {} : { onSnapshot: options.onSnapshot }
2759
+ });
2760
+ }
2761
+ currentState() {
2762
+ return this.getState() ?? createCheckoutState(this.options.snapshot, {
2763
+ now: this.options.now?.(),
2764
+ logger: this.options.logger
2765
+ });
2766
+ }
2767
+ };
2768
+ function createCheckoutController(options) {
2769
+ return new BrowserCheckoutController(options);
2770
+ }
2771
+
2772
+ // src/status.ts
2773
+ function deriveStatus(invoice, options = {}) {
2774
+ if (invoice.transaction_state === "settled") return "settled";
2775
+ if (invoice.transaction_state === "failed") return "failed";
2776
+ if (invoice.transaction_state === "expired") return "expired";
2777
+ const expiresAt = readUnixSeconds(invoice.expires_at);
2778
+ if (expiresAt !== void 0 && expiresAt <= resolveNow(options.now)) {
2779
+ return "expired";
2780
+ }
2781
+ return "pending";
2782
+ }
2783
+ function readUnixSeconds(value) {
2784
+ if (typeof value === "number" && Number.isFinite(value)) return value;
2785
+ if (typeof value !== "string" || value.trim().length === 0) return void 0;
2786
+ const parsed = Number(value);
2787
+ return Number.isFinite(parsed) ? parsed : void 0;
2788
+ }
2789
+
2790
+ // src/internal/guest-resume.ts
2791
+ function createGuestCheckoutResume(options) {
2792
+ const pathPrefix = normalizePathPrefix(options.pathPrefix ?? "/checkout");
2793
+ const pathSegment = pathPrefix.slice(1);
2794
+ const storageKeyPrefix = options.storageKeyPrefix;
2795
+ if (storageKeyPrefix.length === 0) {
2796
+ throw new Error("createGuestCheckoutResume: storageKeyPrefix must be non-empty");
2797
+ }
2798
+ const homePath = options.homePath ?? "/";
2799
+ function checkoutPath(reference) {
2800
+ return `${pathPrefix}/${encodeURIComponent(reference)}`;
2801
+ }
2802
+ function parseReference(pathname) {
2803
+ const segments = pathname.split("/").filter((segment) => segment.length > 0);
2804
+ if (segments.length !== 2 || segments[0] !== pathSegment) return void 0;
2805
+ const raw = segments[1];
2806
+ if (raw === void 0 || raw.length === 0) return void 0;
2807
+ let reference;
2808
+ try {
2809
+ reference = decodeURIComponent(raw);
2810
+ } catch {
2811
+ return void 0;
2812
+ }
2813
+ if (reference.length === 0 || reference.includes("/") || reference.includes(".."))
2814
+ return void 0;
2815
+ return reference;
2816
+ }
2817
+ function orderStorageKey(reference) {
2818
+ return `${storageKeyPrefix}${reference}`;
2819
+ }
2820
+ function rememberOrder(order) {
2821
+ const reference = options.referenceOf(order);
2822
+ if (reference.length === 0) return;
2823
+ const store = sessionStore();
2824
+ if (store === void 0) return;
2825
+ try {
2826
+ store.setItem(orderStorageKey(reference), JSON.stringify(order));
2827
+ } catch {
2828
+ }
2829
+ }
2830
+ function readRememberedOrder(reference) {
2831
+ const store = sessionStore();
2832
+ if (store === void 0) return void 0;
2833
+ try {
2834
+ const raw = store.getItem(orderStorageKey(reference));
2835
+ if (raw === null || raw.length === 0) return void 0;
2836
+ return options.parseOrder(JSON.parse(raw));
2837
+ } catch {
2838
+ return void 0;
2839
+ }
2840
+ }
2841
+ function forgetOrder(reference) {
2842
+ const store = sessionStore();
2843
+ if (store === void 0) return;
2844
+ try {
2845
+ if (reference !== void 0) {
2846
+ store.removeItem(orderStorageKey(reference));
2847
+ return;
2848
+ }
2849
+ const keys = [];
2850
+ for (let index = 0; index < store.length; index += 1) {
2851
+ const key = store.key(index);
2852
+ if (key?.startsWith(storageKeyPrefix)) keys.push(key);
2853
+ }
2854
+ for (const key of keys) store.removeItem(key);
2855
+ } catch {
2856
+ }
2857
+ }
2858
+ function enterCheckout(reference) {
2859
+ enterCheckoutResumePath(reference, { pathPrefix });
2860
+ }
2861
+ function leaveCheckout() {
2862
+ if (typeof globalThis.location === "undefined") return;
2863
+ if (parseReference(globalThis.location.pathname) === void 0) return;
2864
+ globalThis.history.pushState({}, "", homePath);
2865
+ }
2866
+ async function loadOrderForResume(reference) {
2867
+ const remembered = readRememberedOrder(reference);
2868
+ if (remembered !== void 0) return remembered;
2869
+ if (options.fetchOrder === void 0) return void 0;
2870
+ try {
2871
+ const fetched = await options.fetchOrder(reference);
2872
+ if (fetched === void 0) return void 0;
2873
+ rememberOrder(fetched);
2874
+ return fetched;
2875
+ } catch {
2876
+ return void 0;
2877
+ }
2878
+ }
2879
+ return {
2880
+ pathPrefix,
2881
+ checkoutPath,
2882
+ parseReference,
2883
+ rememberOrder,
2884
+ readRememberedOrder,
2885
+ forgetOrder,
2886
+ enterCheckout,
2887
+ leaveCheckout,
2888
+ loadOrderForResume
2889
+ };
2890
+ }
2891
+ function enterCheckoutResumePath(reference, options = {}) {
2892
+ if (options.routeReference !== void 0) return;
2893
+ if (reference.length === 0) return;
2894
+ const pathPrefix = normalizePathPrefix(options.pathPrefix ?? "/checkout");
2895
+ const path = `${pathPrefix}/${encodeURIComponent(reference)}`;
2896
+ if (typeof globalThis.location === "undefined") return;
2897
+ if (globalThis.location.pathname === path) return;
2898
+ globalThis.history.pushState({ openreceiveCheckout: reference }, "", path);
2899
+ }
2900
+ function createGuestOrderFetcher(options) {
2901
+ const fetchFn = options.fetch ?? globalThis.fetch;
2902
+ const hostOrderUrl = options.hostOrderUrl;
2903
+ return async (reference) => {
2904
+ const response = await fetchFn(hostOrderUrl(reference));
2905
+ if (response.status === 404 || !response.ok) return void 0;
2906
+ const body = await response.json();
2907
+ if (typeof body !== "object" || body === null) return void 0;
2908
+ const record = body;
2909
+ if ("summary" in record) return options.parseOrder(record.summary);
2910
+ if ("order" in record) return options.parseOrder(record.order);
2911
+ return void 0;
2912
+ };
2913
+ }
2914
+ function normalizePathPrefix(prefix) {
2915
+ const trimmed = prefix.trim().replace(/^\/+|\/+$/g, "");
2916
+ if (trimmed.length === 0) {
2917
+ throw new Error("createGuestCheckoutResume: pathPrefix must be non-empty");
2918
+ }
2919
+ if (trimmed.includes("/") || trimmed.includes("..")) {
2920
+ throw new Error("createGuestCheckoutResume: pathPrefix must be a single path segment");
2921
+ }
2922
+ return `/${trimmed}`;
2923
+ }
2924
+ function sessionStore() {
2925
+ try {
2926
+ if (typeof sessionStorage === "undefined") return void 0;
2927
+ return sessionStorage;
2928
+ } catch {
2929
+ return void 0;
2930
+ }
2931
+ }
2932
+
2933
+ export {
2934
+ OPENRECEIVE_THEME_STORAGE_KEY,
2935
+ OPENRECEIVE_DEFAULT_POLL_INTERVAL_MS,
2936
+ OPENRECEIVE_DEFAULT_PREFIX,
2937
+ OPENRECEIVE_COPY_FEEDBACK_MS,
2938
+ OPENRECEIVE_CHECKOUT_ELEMENT_TAG_NAME,
2939
+ OPENRECEIVE_THEME_TOGGLE_ELEMENT_TAG_NAME,
2940
+ OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS,
2941
+ OPENRECEIVE_THEME_TOGGLE_ELEMENT_EVENTS,
2942
+ OPENRECEIVE_PAYMENT_WIZARD_ATTRIBUTES,
2943
+ OPENRECEIVE_PAYMENT_WIZARD_SELECTORS,
2944
+ OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES,
2945
+ OPENRECEIVE_CHECKOUT_DATA_SELECTORS,
2946
+ OPENRECEIVE_CHECKOUT_ELEMENT_PARTS,
2947
+ OPENRECEIVE_CHECKOUT_ELEMENT_PART_SELECTORS,
2948
+ OPENRECEIVE_THEME_TOGGLE_ELEMENT_PARTS,
2949
+ OPENRECEIVE_THEME_TOGGLE_ELEMENT_PART_SELECTORS,
2950
+ createCheckoutProviderCopyEvent,
2951
+ createCheckoutActionEvent,
2952
+ createCheckoutStateEvent,
2953
+ createCheckoutErrorEvent,
2954
+ createThemeChangeEvent,
2955
+ OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES,
2956
+ OPENRECEIVE_THEME_TOGGLE_ELEMENT_ATTRIBUTES,
2957
+ paymentIconUrls,
2958
+ orClasses,
2959
+ checkoutLabels,
2960
+ checkoutElementStyles,
2961
+ paymentMethods,
2962
+ parseOptionalInteger,
2963
+ parseBooleanAttribute,
2964
+ parseResolvedTheme,
2965
+ parseThemePreference,
2966
+ parsePaymentMethod,
2967
+ createTransientFeedbackController,
2968
+ createTickingValueController,
2969
+ formatDepositAmount,
2970
+ escapeHtml,
2971
+ formatMsats,
2972
+ formatFiatAmount,
2973
+ formatAmountCaption,
2974
+ formatSwapLimit,
2975
+ formatUnixTime,
2976
+ deriveCheckoutStateLabels,
2977
+ assertDisplayInvoice,
2978
+ createLightningUri,
2979
+ createSwapDisplayModel,
2980
+ overlaySwapRefundStaging,
2981
+ swapAssetMatchesRoute,
2982
+ getExplorerNetwork,
2983
+ createBlockExplorerUrl,
2984
+ createLightningInvoiceDecodeUrl,
2985
+ createDetailExternalLink,
2986
+ createTransactionDetails,
2987
+ createTransactionDetailsFromState,
2988
+ resolveTransactionDetailRows,
2989
+ createPaymentDataEntries,
2990
+ getWizardEmptyMessage,
2991
+ getRouteNetworkLabel,
2992
+ createWizardRouteAssetDisplays,
2993
+ createWizardRouteDisplays,
2994
+ getPaymentMethodIcon,
2995
+ getNetworkIcon,
2996
+ getSwapOptionIcon,
2997
+ buildMethodGridEntries,
2998
+ swapPickerKey,
2999
+ parseMethodPickerKey,
3000
+ paymentAccentId,
3001
+ assetButtonClasses,
3002
+ networkButtonClasses,
3003
+ networkMobileRevealClasses,
3004
+ networkCheckClasses,
3005
+ networkSummaryIconClasses,
3006
+ formatNetworkSummary,
3007
+ formatChooseNetworkHeading,
3008
+ resolvePreservedNetworkSelection,
3009
+ findSwapGridGroup,
3010
+ updateSelectedSwapNetworks,
3011
+ wizardNetworkGroupIds,
3012
+ createSwapUnavailableModel,
3013
+ swapOptionLimitMessage,
3014
+ swapGroupLimitOption,
3015
+ getSwapRefundFormError,
3016
+ createPaymentWizardSelection,
3017
+ createPaymentWizardModel,
3018
+ updatePaymentWizardSelection,
3019
+ createPaymentWizardController,
3020
+ optionalSafeInteger,
3021
+ sanitizeBrowserLogEntry,
3022
+ createAppBrowserConsoleLogger,
3023
+ resolveBrowserLogger,
3024
+ selectCheckoutDisplayInvoice,
3025
+ isPaidCheckoutSnapshot,
3026
+ isReusableLightningInvoice,
3027
+ createCheckoutState,
3028
+ createCheckoutSnapshotFromInvoice,
3029
+ createCheckoutStatusModel,
3030
+ findReusableLightningInvoice,
3031
+ mergeAttemptIntoSnapshot,
3032
+ mergeAttemptIntoCheckout,
3033
+ mergeMintedCheckout,
3034
+ requestHeaders,
3035
+ checkoutRoutes,
3036
+ BrowserRequestError,
3037
+ readJsonResponse,
3038
+ requestCheckout,
3039
+ prepareCheckout,
3040
+ createStatusFetcher,
3041
+ createQrSvg,
3042
+ createQrPayloadSvg,
3043
+ createQrPngDataUrl,
3044
+ copyInvoice,
3045
+ openWallet,
3046
+ createCheckoutController,
3047
+ deriveStatus,
3048
+ createGuestCheckoutResume,
3049
+ enterCheckoutResumePath,
3050
+ createGuestOrderFetcher
3051
+ };