@wral/report-it 0.1.2 → 0.1.4

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.
@@ -1,6 +1,6 @@
1
- import { css as p, html as l, nothing as c, LitElement as I } from "lit";
2
- import { getAuthContext as W, createStorage as V, verifyCode as N, extractTokens as S, saveTokens as A, decodeJwtPayload as R, refreshTokenSimple as H, sendCode as Y, createUserPool as K, signUpIfNeeded as Q, createCognitoUser as G, getAuthHeaders as J, STORAGE_KEYS as _, isAuthenticatedSimple as X } from "@wral/sdk-auth-audience";
3
- const Z = p`
1
+ import { css as f, html as a, nothing as c, LitElement as T } from "lit";
2
+ import { getAuthContext as Q, createStorage as G, verifyCode as J, extractTokens as D, saveTokens as z, decodeJwtPayload as B, refreshTokenSimple as X, sendCode as Z, createUserPool as ee, signUpIfNeeded as te, createCognitoUser as re, getAuthHeaders as se, STORAGE_KEYS as I, isAuthenticatedSimple as ie } from "@wral/sdk-auth-audience";
3
+ const ne = f`
4
4
  :host {
5
5
  display: block;
6
6
  box-sizing: border-box;
@@ -24,7 +24,7 @@ const Z = p`
24
24
  position: absolute; width: 1px; height: 1px; overflow: hidden;
25
25
  clip: rect(0 0 0 0); white-space: nowrap;
26
26
  }
27
- `, ee = p`
27
+ `, ae = f`
28
28
  @keyframes pop-in {
29
29
  0% { opacity: 0; transform: translateY(16px) scale(0.95); }
30
30
  100% { opacity: 1; transform: translateY(0) scale(1); }
@@ -55,7 +55,7 @@ const Z = p`
55
55
  animation: none !important;
56
56
  }
57
57
  }
58
- `, te = p`
58
+ `, oe = f`
59
59
  .msg { max-width: 85%; padding: 12px 16px; border-radius: 14px; font-size: 15px; }
60
60
  .msg.bot {
61
61
  background: var(--wral-semantic-surface-default, #FFFFFF);
@@ -77,7 +77,7 @@ const Z = p`
77
77
  .msg .sub { display: block; font-size: 13px; color: var(--wral-semantic-fg-muted, #64748B); margin-top: 4px; }
78
78
  .msg.user .sub { color: rgba(255, 255, 255, 0.75); }
79
79
  .msg.error { border-left: 3px solid var(--wral-base-red-on-light, #D1232A); }
80
- `, re = p`
80
+ `, le = f`
81
81
  .options { display: flex; flex-wrap: wrap; gap: 8px; align-self: flex-start; max-width: 92%; padding: 2px 0 6px; }
82
82
  .chip {
83
83
  font-family: var(--wral-base-font-ui, 'IBM Plex Sans Condensed', sans-serif);
@@ -91,7 +91,7 @@ const Z = p`
91
91
  .chip:hover { background: var(--wral-base-secondary-1, #2594E3); color: #FFFFFF; }
92
92
  .chip:focus-visible { outline: 2px solid var(--wral-base-secondary-1, #2594E3); outline-offset: 2px; }
93
93
  .chip:active { transform: scale(0.97); }
94
- `, se = p`
94
+ `, de = f`
95
95
  .form-card {
96
96
  align-self: stretch;
97
97
  background: var(--wral-semantic-surface-default, #FFFFFF);
@@ -156,7 +156,7 @@ const Z = p`
156
156
  .btn-ghost:hover { border-color: var(--wral-base-secondary-1, #2594E3); }
157
157
  .btn-ghost:active { transform: scale(0.97); }
158
158
  .btn-ghost:focus-visible { outline: 2px solid var(--wral-base-secondary-1, #2594E3); outline-offset: 2px; }
159
- `, ie = p`
159
+ `, ce = f`
160
160
  .login-card { padding: 28px 26px; }
161
161
  .login-card h2 {
162
162
  font-family: var(--wral-base-font-display, 'IBM Plex Sans Condensed', sans-serif);
@@ -202,13 +202,48 @@ const Z = p`
202
202
  .login-why ul { margin: 0; padding-left: 20px; font-size: 14px; color: var(--color-gray-6, #565454); }
203
203
  .login-why li { margin-bottom: 4px; line-height: 1.5; }
204
204
  .login-why a { color: var(--color-secondary, #2594E3); font-weight: 600; text-decoration: underline; }
205
- .login-anon {
206
- border-top: 1px solid var(--color-gray-2, #E7E5E4); margin: 16px 0 0; padding-top: 14px;
207
- font-size: 14px; color: var(--color-gray-6, #565454); line-height: 1.5;
205
+ .login-alt {
206
+ border-top: 1px solid var(--color-gray-2, #E7E5E4); margin-top: 16px; padding-top: 12px;
208
207
  }
209
- .login-anon a { color: var(--color-primary-dark, #00144A); font-weight: 600; text-decoration: none; white-space: nowrap; }
210
- .login-anon a:hover { text-decoration: underline; }
211
- `, ae = p`
208
+ .login-alt > summary {
209
+ display: flex; align-items: center; gap: 7px;
210
+ font-size: 14px; font-weight: 600;
211
+ color: var(--color-gray-5, #6C6C6C);
212
+ padding: 3px 0; cursor: pointer; list-style: none;
213
+ }
214
+ .login-alt > summary::-webkit-details-marker { display: none; }
215
+ .login-alt > summary::before {
216
+ content: ''; flex-shrink: 0; padding: 2.5px;
217
+ border: solid currentColor; border-width: 0 1.5px 1.5px 0;
218
+ transform: rotate(-45deg); transition: transform 150ms;
219
+ }
220
+ .login-alt[open] > summary::before { transform: rotate(45deg); }
221
+ .login-alt > summary:hover { color: var(--color-gray-8, #263238); }
222
+ .login-alt > summary:focus-visible { outline: 2px solid var(--color-secondary, #2594E3); outline-offset: 2px; }
223
+ .login-alt .alt-body {
224
+ font-size: 13.5px; color: var(--color-gray-6, #565454);
225
+ line-height: 1.55; padding: 6px 0 2px;
226
+ }
227
+ .login-alt .alt-row { margin: 0 0 10px; }
228
+ .login-alt .alt-row:last-child { margin-bottom: 0; }
229
+ .login-alt a, .login-alt .alt-link {
230
+ color: var(--color-primary-dark, #00144A); font-weight: 600;
231
+ text-decoration: underline;
232
+ }
233
+ .login-alt a { text-decoration: none; white-space: nowrap; }
234
+ .login-alt a:hover { text-decoration: underline; }
235
+ .login-alt .alt-link {
236
+ background: none; border: none; padding: 0; cursor: pointer;
237
+ font-family: inherit; font-size: inherit;
238
+ }
239
+ .login-alt .alt-link:focus-visible { outline: 2px solid var(--color-secondary, #2594E3); outline-offset: 2px; }
240
+ .anon-costs { margin: 0 0 18px; padding: 0; list-style: none; font-size: 14px; color: var(--color-gray-6, #565454); }
241
+ .anon-costs li { display: flex; gap: 9px; align-items: flex-start; margin-bottom: 9px; line-height: 1.5; }
242
+ .anon-costs li:last-child { margin-bottom: 0; }
243
+ .anon-costs .x { flex-shrink: 0; font-weight: 700; color: var(--wral-base-red-on-light, #D1232A); }
244
+ .anon-actions { display: flex; flex-direction: column; gap: 10px; }
245
+ .anon-actions .btn-ghost { width: 100%; }
246
+ `, ue = f`
212
247
  .review-list { margin: 0; padding: 0; list-style: none; font-size: 14px; }
213
248
  .review-list li {
214
249
  display: grid; grid-template-columns: 130px 1fr; gap: 10px;
@@ -240,7 +275,7 @@ const Z = p`
240
275
  color: var(--wral-base-primary-1, #001D68);
241
276
  }
242
277
  @media (max-width: 540px) { .review-list li { grid-template-columns: 1fr; gap: 2px; } }
243
- `, ne = p`
278
+ `, pe = f`
244
279
  .upload-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; font-size: 13.5px; }
245
280
  .upload-row .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
246
281
  .upload-row .state { font-size: 12px; color: var(--wral-semantic-fg-subtle, #64748B); }
@@ -256,7 +291,7 @@ const Z = p`
256
291
  border-radius: 999px; padding: 3px 12px; cursor: pointer;
257
292
  }
258
293
  .retry-chip:focus-visible { outline: 2px solid var(--wral-base-secondary-1, #2594E3); outline-offset: 2px; }
259
- `, oe = p`
294
+ `, he = f`
260
295
  .confirm-card {
261
296
  align-self: stretch;
262
297
  background: var(--wral-base-primary-1, #001D68);
@@ -306,7 +341,7 @@ const Z = p`
306
341
  .c-again:hover { background: rgba(255, 255, 255, 0.12); }
307
342
  .c-again:focus-visible { outline: 2px solid var(--wral-base-secondary-2, #50A9E8); outline-offset: 2px; }
308
343
  .c-again:active { transform: scale(0.97); }
309
- `, le = p`
344
+ `, fe = f`
310
345
  .journey {
311
346
  align-self: stretch;
312
347
  background: var(--wral-semantic-surface-default, #FFFFFF);
@@ -347,7 +382,7 @@ const Z = p`
347
382
  color: var(--wral-base-primary-1, #001D68); margin-bottom: 2px;
348
383
  }
349
384
  .j-body .j-d { font-size: 13.5px; color: var(--wral-semantic-fg-muted, #475569); line-height: 1.55; }
350
- `, de = p`
385
+ `, ge = f`
351
386
  .bottom-bar {
352
387
  position: sticky; bottom: 0; z-index: 20;
353
388
  background: var(--wral-semantic-surface-default, #FFFFFF);
@@ -360,118 +395,145 @@ const Z = p`
360
395
  }
361
396
  .bottom-bar .note { margin-left: auto; font-size: 12px; color: var(--wral-semantic-fg-subtle, #64748B); }
362
397
  @media (max-width: 540px) { .bottom-bar .note { display: none; } }
363
- `, ce = [Z, ee, te, re, se, ie, ae, ne, oe, le, de];
398
+ `, me = [ne, ae, oe, le, de, ce, ue, pe, he, fe, ge];
364
399
  function h(r, e, { noAnim: t = !1, error: s = !1 } = {}) {
365
- return l`
400
+ return a`
366
401
  <div class="msg bot ${t ? "no-anim" : ""} ${s ? "error" : ""}">
367
402
  <span class="lead">${r}</span>
368
- ${e ? l`<span class="sub">${e}</span>` : c}
403
+ ${e ? a`<span class="sub">${e}</span>` : c}
369
404
  </div>
370
405
  `;
371
406
  }
372
- function v(r, { noAnim: e = !1 } = {}) {
373
- return l`<div class="msg user ${e ? "no-anim" : ""}">${r}</div>`;
407
+ function $(r, { noAnim: e = !1 } = {}) {
408
+ return a`<div class="msg user ${e ? "no-anim" : ""}">${r}</div>`;
374
409
  }
375
- function $() {
376
- return l`<div class="msg bot typing"><span></span><span></span><span></span></div>`;
410
+ function E() {
411
+ return a`<div class="msg bot typing"><span></span><span></span><span></span></div>`;
377
412
  }
378
- function ue(r) {
379
- return r ? l`<span class="flag-pill ${r}">${r === "urgent" ? "Urgent" : "Moderate"}</span>` : c;
413
+ function be(r) {
414
+ return r ? a`<span class="flag-pill ${r}">${r === "urgent" ? "Urgent" : "Moderate"}</span>` : c;
380
415
  }
381
- function pe() {
382
- return l`
416
+ function ye() {
417
+ return a`
383
418
  <svg viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="3"
384
419
  stroke-linecap="round" stroke-linejoin="round" width="20" height="20"
385
420
  aria-hidden="true"><path d="M20 6L9 17l-5-5"/></svg>
386
421
  `;
387
422
  }
388
- class w extends Error {
423
+ const we = 15e3;
424
+ class x extends Error {
389
425
  constructor(e, t) {
390
426
  super(`api-forms request failed with status ${e}`), this.status = e, this.body = t;
391
427
  }
392
428
  }
393
- function he({
429
+ const P = Object.freeze({ enabled: !1, humanCheck: null });
430
+ function xe({
394
431
  baseUrl: r,
395
432
  fetchFn: e = (...i) => fetch(...i),
396
433
  xhrFactory: t = () => new XMLHttpRequest(),
397
434
  getAuthHeaders: s
398
435
  }) {
399
436
  const i = String(r || "").replace(/\/+$/, "");
400
- async function a(n, { method: o = "GET", body: d, auth: f = !1 } = {}) {
401
- const u = { Accept: "application/json" };
402
- f && Object.assign(u, await s()), d !== void 0 && (u["Content-Type"] = "application/json");
403
- let m;
437
+ let n = P, o = null;
438
+ async function l(d, { method: u = "GET", body: g, auth: y = !1, timeoutMs: p } = {}) {
439
+ const k = { Accept: "application/json" };
440
+ y && Object.assign(k, o ? { Authorization: `Bearer ${o}` } : await s()), g !== void 0 && (k["Content-Type"] = "application/json");
441
+ let w;
404
442
  try {
405
- m = await e(`${i}${n}`, {
406
- method: o,
407
- headers: u,
408
- ...d !== void 0 ? { body: JSON.stringify(d) } : {}
443
+ w = await e(`${i}${d}`, {
444
+ method: u,
445
+ headers: k,
446
+ ...p ? { signal: AbortSignal.timeout(p) } : {},
447
+ ...g !== void 0 ? { body: JSON.stringify(g) } : {}
409
448
  });
410
- } catch (y) {
411
- throw Object.assign(new w(0, null), { cause: y });
449
+ } catch (_) {
450
+ throw Object.assign(new x(0, null), { cause: _ });
412
451
  }
413
- let b = null;
452
+ let m = null;
414
453
  try {
415
- b = await m.json();
454
+ m = await w.json();
416
455
  } catch {
417
456
  }
418
- if (!m.ok)
419
- throw new w(m.status, b);
420
- return b;
457
+ if (!w.ok)
458
+ throw new x(w.status, m);
459
+ return m;
421
460
  }
422
461
  return {
423
462
  /** @returns {Promise<Array>} published form documents */
424
463
  listForms: async () => {
425
- const { forms: n } = await a("/v1/forms");
426
- return (n || []).filter((o) => o?.formId && o?.start && Array.isArray(o?.nodes));
464
+ const d = await l("/v1/forms", { timeoutMs: we });
465
+ return n = d?.anonymous?.enabled === !0 ? { enabled: !0, humanCheck: d.anonymous.humanCheck || null } : P, (d?.forms || []).filter((u) => u?.formId && u?.start && Array.isArray(u?.nodes));
466
+ },
467
+ /**
468
+ * What the server advertised on the last listForms.
469
+ * @returns {{enabled: boolean, humanCheck: {provider, siteKey}|null}}
470
+ */
471
+ anonymousCapability: () => n,
472
+ /**
473
+ * Mint a submission-scoped anonymous session; subsequent auth-bearing
474
+ * calls present it until endAnonSession(). Unauthenticated by design.
475
+ * @returns {Promise<{expiresIn: number}>}
476
+ */
477
+ createAnonSession: async ({ formId: d, requestId: u, humanToken: g }) => {
478
+ const y = await l("/v1/anon/sessions", {
479
+ method: "POST",
480
+ body: { formId: d, requestId: u, ...g ? { humanToken: g } : {} }
481
+ });
482
+ if (o = y?.token || null, !o)
483
+ throw new x(502, { message: "The anonymous session had no token" });
484
+ return { expiresIn: y.expiresIn };
485
+ },
486
+ /** Drop the anonymous session so identity headers apply again. */
487
+ endAnonSession: () => {
488
+ o = null;
427
489
  },
428
490
  /** @returns {Promise<Array<{assetId,url,method,expires,assetUrl}>>} */
429
- createUploads: async (n) => {
430
- const { uploads: o } = await a("/v1/uploads", { method: "POST", body: n, auth: !0 });
431
- return o || [];
491
+ createUploads: async (d) => {
492
+ const { uploads: u } = await l("/v1/uploads", { method: "POST", body: d, auth: !0 });
493
+ return u || [];
432
494
  },
433
495
  /**
434
496
  * PUT one file to its presigned URL. XHR (not fetch) so upload
435
497
  * progress is observable. Resolves on 2xx; rejects with
436
498
  * ApiError(status) otherwise. Returns { promise, abort }.
437
499
  */
438
- uploadFile: ({ url: n, file: o, contentType: d, onProgress: f = () => {
500
+ uploadFile: ({ url: d, file: u, contentType: g, onProgress: y = () => {
439
501
  } }) => {
440
- const u = t();
441
- return { promise: new Promise((b, y) => {
442
- u.open("PUT", n), u.setRequestHeader("Content-Type", d || o.type), u.upload && (u.upload.onprogress = (C) => {
443
- f({ loaded: C.loaded, total: C.total || o.size });
444
- }), u.onload = () => {
445
- u.status >= 200 && u.status < 300 ? b({ status: u.status }) : y(new w(u.status, null));
446
- }, u.onerror = () => y(new w(0, null)), u.onabort = () => y(new w(0, { aborted: !0 })), u.send(o);
447
- }), abort: () => u.abort() };
502
+ const p = t();
503
+ return { promise: new Promise((w, m) => {
504
+ p.open("PUT", d), p.setRequestHeader("Content-Type", g || u.type), p.upload && (p.upload.onprogress = (_) => {
505
+ y({ loaded: _.loaded, total: _.total || u.size });
506
+ }), p.onload = () => {
507
+ p.status >= 200 && p.status < 300 ? w({ status: p.status }) : m(new x(p.status, null));
508
+ }, p.onerror = () => m(new x(0, null)), p.onabort = () => m(new x(0, { aborted: !0 })), p.send(u);
509
+ }), abort: () => p.abort() };
448
510
  },
449
511
  /** @returns {Promise<{requestId,reference,confirmation,routing}>} */
450
- putRequest: async (n, o) => await a(`/v1/requests/${n}`, { method: "PUT", body: o, auth: !0 })
512
+ putRequest: async (d, u) => await l(`/v1/requests/${d}`, { method: "PUT", body: u, auth: !0 })
451
513
  };
452
514
  }
453
- function fe() {
454
- const { config: r, storage: e } = W();
515
+ function ve() {
516
+ const { config: r, storage: e } = Q();
455
517
  let t = null;
456
518
  return {
457
- isAuthenticated: () => X(),
458
- signedInEmail: () => e.get(_.userEmail) || null,
459
- getAuthHeaders: () => J(r, e),
519
+ isAuthenticated: () => ie(),
520
+ signedInEmail: () => e.get(I.userEmail) || null,
521
+ getAuthHeaders: () => se(r, e),
460
522
  /**
461
523
  * Email step. Keeps the challenge user in memory for verifyCode.
462
524
  * @returns {{challengeRequired?: boolean, authenticated?: boolean}}
463
525
  */
464
526
  sendCode: async (s) => {
465
- const i = await Y(
527
+ const i = await Z(
466
528
  r,
467
529
  s,
468
530
  e,
469
- K,
470
- Q,
471
- G,
472
- S,
473
- A,
474
- R
531
+ ee,
532
+ te,
533
+ re,
534
+ D,
535
+ z,
536
+ B
475
537
  );
476
538
  return t = i.cognitoUser || null, {
477
539
  challengeRequired: !!i.challengeRequired,
@@ -486,114 +548,114 @@ function fe() {
486
548
  if (!t)
487
549
  throw new Error("Please enter your email again to get a new code.");
488
550
  try {
489
- await N(
551
+ await J(
490
552
  t,
491
553
  s,
492
554
  e,
493
- S,
494
- A,
495
- R
555
+ D,
556
+ z,
557
+ B
496
558
  );
497
559
  } catch {
498
560
  throw new Error("Invalid or expired code. Please request a new one and try again.");
499
561
  }
500
- return await H(), { success: !0 };
562
+ return await X(), { success: !0 };
501
563
  },
502
564
  /** Local sign-out only ("use a different email"). */
503
565
  signOut: () => {
504
- t = null, V().clear();
566
+ t = null, G().clear();
505
567
  },
506
568
  /**
507
569
  * Detect a login completed in ANOTHER tab (the storage event
508
570
  * never fires in the tab that wrote). Returns an unsubscribe.
509
571
  */
510
572
  onCrossTabLogin: (s) => {
511
- const i = (a) => {
512
- (a.key === _.accessToken || a.key === _.idToken) && s();
573
+ const i = (n) => {
574
+ (n.key === I.accessToken || n.key === I.idToken) && s();
513
575
  };
514
576
  return window.addEventListener("storage", i), () => window.removeEventListener("storage", i);
515
577
  }
516
578
  };
517
579
  }
518
- function ge({ baseUrl: r }) {
519
- const e = fe();
520
- return { ...he({ baseUrl: r, getAuthHeaders: e.getAuthHeaders }), ...e };
580
+ function ke({ baseUrl: r }) {
581
+ const e = ve();
582
+ return { ...xe({ baseUrl: r, getAuthHeaders: e.getAuthHeaders }), ...e };
521
583
  }
522
- function g(r, e) {
584
+ function b(r, e) {
523
585
  return (r?.nodes || []).find((t) => t.id === e);
524
586
  }
525
- function U(r, e = []) {
587
+ function V(r, e = []) {
526
588
  const t = [];
527
589
  let s = r?.start;
528
- for (const a of e) {
529
- const n = g(r, s);
530
- if (!n)
531
- return { nodeId: null, node: null, flags: t, error: { step: a, reason: `unknown node: ${s}` } };
532
- if (n.type === "terminal" || n.type === "redirect")
533
- return { nodeId: null, node: null, flags: t, error: { step: a, reason: `steps continue past ${n.type}` } };
534
- if (a.nodeId !== s || a.kind !== n.type)
535
- return { nodeId: null, node: null, flags: t, error: { step: a, reason: `step does not match node ${s}` } };
536
- if (n.type === "choice") {
537
- const o = (n.options || []).find((d) => d.id === a.optionId);
538
- if (!o)
539
- return { nodeId: null, node: null, flags: t, error: { step: a, reason: `unknown option: ${a.optionId}` } };
540
- t.push(...o.flags || []), s = o.next;
590
+ for (const n of e) {
591
+ const o = b(r, s);
592
+ if (!o)
593
+ return { nodeId: null, node: null, flags: t, error: { step: n, reason: `unknown node: ${s}` } };
594
+ if (o.type === "terminal" || o.type === "redirect")
595
+ return { nodeId: null, node: null, flags: t, error: { step: n, reason: `steps continue past ${o.type}` } };
596
+ if (n.nodeId !== s || n.kind !== o.type)
597
+ return { nodeId: null, node: null, flags: t, error: { step: n, reason: `step does not match node ${s}` } };
598
+ if (o.type === "choice") {
599
+ const l = (o.options || []).find((d) => d.id === n.optionId);
600
+ if (!l)
601
+ return { nodeId: null, node: null, flags: t, error: { step: n, reason: `unknown option: ${n.optionId}` } };
602
+ t.push(...l.flags || []), s = l.next;
541
603
  continue;
542
604
  }
543
- s = n.next;
605
+ s = o.next;
544
606
  }
545
- const i = g(r, s);
546
- return i ? { nodeId: s, node: i, flags: L(t), error: null } : { nodeId: null, node: null, flags: t, error: { step: null, reason: `unknown node: ${s}` } };
607
+ const i = b(r, s);
608
+ return i ? { nodeId: s, node: i, flags: H(t), error: null } : { nodeId: null, node: null, flags: t, error: { step: null, reason: `unknown node: ${s}` } };
547
609
  }
548
- function me(r, e = []) {
610
+ function _e(r, e = []) {
549
611
  const t = [];
550
612
  for (const s of e) {
551
613
  if (s.kind !== "collect") continue;
552
- const i = g(r, s.nodeId);
614
+ const i = b(r, s.nodeId);
553
615
  t.push(...i?.fields || []);
554
616
  }
555
617
  return t;
556
618
  }
557
- function be(r = []) {
619
+ function $e(r = []) {
558
620
  const e = {};
559
621
  for (const t of r)
560
622
  t.kind === "collect" && Object.assign(e, t.values || {});
561
623
  return e;
562
624
  }
563
- function ye(r = []) {
625
+ function Fe(r = []) {
564
626
  return r.filter((e) => e.kind === "choice").map((e) => `${e.nodeId}:${e.optionId}`);
565
627
  }
566
- function j(r, e = []) {
628
+ function Y(r, e = []) {
567
629
  const t = [];
568
630
  for (const s of e) {
569
631
  if (s.kind !== "choice") continue;
570
- const a = (g(r, s.nodeId)?.options || []).find((n) => n.id === s.optionId);
571
- t.push(...a?.flags || []);
632
+ const n = (b(r, s.nodeId)?.options || []).find((o) => o.id === s.optionId);
633
+ t.push(...n?.flags || []);
572
634
  }
573
- return L(t);
635
+ return H(t);
574
636
  }
575
- function we(r = []) {
637
+ function Ie(r = []) {
576
638
  return r.includes("urgent") ? "urgent" : r.includes("moderate") ? "moderate" : null;
577
639
  }
578
- function L(r) {
640
+ function H(r) {
579
641
  return [...new Set(r)];
580
642
  }
581
- const xe = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/, D = {
643
+ const Ee = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/, M = {
582
644
  text: 500,
583
645
  textarea: 5e3,
584
646
  url: 2048
585
647
  };
586
- function ve(r, e) {
587
- if (e == null || e === "" || r.kind === "location" && ke(e))
648
+ function Se(r, e) {
649
+ if (e == null || e === "" || r.kind === "location" && Ae(e))
588
650
  return r.required ? `Please fill in: ${r.label.toLowerCase()}.` : null;
589
651
  switch (r.kind) {
590
652
  case "text":
591
653
  case "textarea": {
592
- const s = r.maxLength || D[r.kind];
654
+ const s = r.maxLength || M[r.kind];
593
655
  return typeof e != "string" ? `Please enter text for ${r.label.toLowerCase()}.` : e.length > s ? `Please keep ${r.label.toLowerCase()} under ${s} characters.` : null;
594
656
  }
595
657
  case "url": {
596
- if (typeof e != "string" || e.length > D.url)
658
+ if (typeof e != "string" || e.length > M.url)
597
659
  return "Please enter a valid link.";
598
660
  try {
599
661
  return new URL(e), null;
@@ -602,85 +664,85 @@ function ve(r, e) {
602
664
  }
603
665
  }
604
666
  case "datetime":
605
- return xe.test(String(e)) ? null : "Please pick a date and time.";
667
+ return Ee.test(String(e)) ? null : "Please pick a date and time.";
606
668
  case "select":
607
669
  return (r.options || []).map((i) => i.id).includes(e) ? null : `Please choose one of the options for ${r.label.toLowerCase()}.`;
608
670
  case "consent":
609
671
  return e === !0 ? null : "Please confirm the rights statement so we can use what you send.";
610
672
  case "location":
611
- return _e(r, e);
673
+ return Ce(r, e);
612
674
  case "media":
613
675
  return null;
614
676
  default:
615
677
  return `Unsupported field: ${r.kind}`;
616
678
  }
617
679
  }
618
- function ke(r) {
680
+ function Ae(r) {
619
681
  return r == null ? !0 : typeof r != "object" ? !1 : !r.county && !r.where && !(Array.isArray(r.gps) && r.gps.length);
620
682
  }
621
- function _e(r, e) {
683
+ function Ce(r, e) {
622
684
  return typeof e != "object" || Array.isArray(e) ? "Please tell us where this was." : e.county !== void 0 && (typeof e.county != "string" || e.county.length > 100) ? "Please choose a county." : e.where !== void 0 && (typeof e.where != "string" || e.where.length > 500) ? "Please shorten the location description." : e.gps !== void 0 && !(Array.isArray(e.gps) && e.gps.length === 2 && e.gps.every((s) => typeof s == "number" && Number.isFinite(s))) ? "Location coordinates look wrong; try re-sharing your location." : r.required && !e.county && !e.where ? `Please fill in: ${r.label.toLowerCase()}.` : null;
623
685
  }
624
- function T(r, e = {}) {
686
+ function O(r, e = {}) {
625
687
  const t = {};
626
688
  for (const s of r) {
627
689
  if (s.kind === "media") continue;
628
- const i = ve(s, e[s.key]);
690
+ const i = Se(s, e[s.key]);
629
691
  i && (t[s.key] = i);
630
692
  }
631
693
  return { ok: Object.keys(t).length === 0, errors: t };
632
694
  }
633
- function F(r = [], e = {}, { required: t = !1 } = {}) {
695
+ function C(r = [], e = {}, { required: t = !1 } = {}) {
634
696
  const {
635
697
  maxFiles: s = 5,
636
698
  maxFileBytes: i = 512 * 1024 * 1024,
637
- allowedTypes: a = []
638
- } = e, n = [];
639
- return t && r.length === 0 && n.push({ reason: "required", message: "Please attach at least one photo or video." }), r.length > s && n.push({
699
+ allowedTypes: n = []
700
+ } = e, o = [];
701
+ return t && r.length === 0 && o.push({ reason: "required", message: "Please attach at least one photo or video." }), r.length > s && o.push({
640
702
  reason: "count",
641
703
  message: `This form accepts at most ${s} ${s === 1 ? "file" : "files"}.`
642
- }), r.forEach((o, d) => {
643
- a.length && !a.includes(o.type) && n.push({
704
+ }), r.forEach((l, d) => {
705
+ n.length && !n.includes(l.type) && o.push({
644
706
  index: d,
645
707
  reason: "type",
646
- message: `${o.name || "A file"} is a type this form does not accept.`
647
- }), o.size > i && n.push({
708
+ message: `${l.name || "A file"} is a type this form does not accept.`
709
+ }), l.size > i && o.push({
648
710
  index: d,
649
711
  reason: "size",
650
- message: `${o.name || "A file"} is larger than this form allows.`
712
+ message: `${l.name || "A file"} is larger than this form allows.`
651
713
  });
652
- }), { ok: n.length === 0, errors: n };
714
+ }), { ok: o.length === 0, errors: o };
653
715
  }
654
- function z({ formId: r, requestId: e, files: t }) {
716
+ function U({ formId: r, requestId: e, files: t }) {
655
717
  return {
656
718
  formId: r,
657
719
  requestId: e,
658
720
  files: t.map((s) => ({ contentType: s.type, size: s.size }))
659
721
  };
660
722
  }
661
- function $e({ form: r, steps: e, media: t = [] }) {
662
- const s = me(r, e), i = be(e), a = {};
663
- for (const n of s) {
664
- if (n.kind === "media") continue;
665
- const o = i[n.key];
666
- if (!(o == null || o === "") && !(n.kind === "consent" && o !== !0)) {
667
- if (n.kind === "location") {
723
+ function Te({ form: r, steps: e, media: t = [] }) {
724
+ const s = _e(r, e), i = $e(e), n = {};
725
+ for (const o of s) {
726
+ if (o.kind === "media") continue;
727
+ const l = i[o.key];
728
+ if (!(l == null || l === "") && !(o.kind === "consent" && l !== !0)) {
729
+ if (o.kind === "location") {
668
730
  const d = {};
669
- o.county && (d.county = o.county), o.where && (d.where = o.where), Array.isArray(o.gps) && o.gps.length === 2 && (d.gps = o.gps), Object.keys(d).length && (a[n.key] = d);
731
+ l.county && (d.county = l.county), l.where && (d.where = l.where), Array.isArray(l.gps) && l.gps.length === 2 && (d.gps = l.gps), Object.keys(d).length && (n[o.key] = d);
670
732
  continue;
671
733
  }
672
- a[n.key] = o;
734
+ n[o.key] = l;
673
735
  }
674
736
  }
675
737
  return {
676
738
  formId: r.formId,
677
739
  flowVersion: r.flowVersion,
678
- path: ye(e),
679
- answers: a,
680
- media: t.map(({ assetId: n, type: o }) => ({ assetId: n, type: o }))
740
+ path: Fe(e),
741
+ answers: n,
742
+ media: t.map(({ assetId: o, type: l }) => ({ assetId: o, type: l }))
681
743
  };
682
744
  }
683
- function Fe(r, e) {
745
+ function q(r, e) {
684
746
  if (r === 429)
685
747
  return {
686
748
  kind: "throttled",
@@ -718,15 +780,15 @@ function Fe(r, e) {
718
780
  message: "Something went wrong on our end; please try again."
719
781
  };
720
782
  }
721
- const Ie = 34, Ee = 44;
722
- function P(r, e) {
783
+ const Re = 34, De = 44;
784
+ function L(r, e) {
723
785
  const t = String(r);
724
786
  return t.length > e ? `${t.slice(0, e)}…` : t;
725
787
  }
726
- function Ce(r) {
788
+ function ze(r) {
727
789
  return !r || typeof r != "object" ? "" : [r.county, r.where].filter(Boolean).join(", ");
728
790
  }
729
- function Se(r, e = {}, t = []) {
791
+ function Be(r, e = {}, t = []) {
730
792
  const s = [];
731
793
  for (const i of r) {
732
794
  if (i.kind === "consent") continue;
@@ -734,21 +796,21 @@ function Se(r, e = {}, t = []) {
734
796
  t.length && s.push(`${t.length} ${t.length === 1 ? "file" : "files"}`);
735
797
  continue;
736
798
  }
737
- const a = i.kind === "location" ? Ce(e[i.key]) : e[i.key];
738
- a == null || a === "" || (i.kind === "textarea" ? s.push(`"${P(a, Ee)}"`) : s.push(P(a, Ie)));
799
+ const n = i.kind === "location" ? ze(e[i.key]) : e[i.key];
800
+ n == null || n === "" || (i.kind === "textarea" ? s.push(`"${L(n, De)}"`) : s.push(L(n, Re)));
739
801
  }
740
802
  return s.join(" · ") || "Details provided";
741
803
  }
742
- function Ae(r, e = [], t = null) {
804
+ function Pe(r, e = [], t = null) {
743
805
  const s = [];
744
- for (const a of e) {
745
- const n = g(r, a.nodeId);
746
- a.kind === "choice" && n && s.push({ k: (n.prompt || "").replace(/\?$/, ""), v: a.label || a.optionId }), a.kind === "collect" && s.push({ k: "Details", v: a.summary || "Details provided" }), a.kind === "gate" && (a.email || t) && s.push({ k: "Verified email", v: a.email || t });
806
+ for (const n of e) {
807
+ const o = b(r, n.nodeId);
808
+ n.kind === "choice" && o && s.push({ k: (o.prompt || "").replace(/\?$/, ""), v: n.label || n.optionId }), n.kind === "collect" && s.push({ k: "Details", v: n.summary || "Details provided" }), n.kind === "gate" && (n.anonymous ? s.push({ k: "Contact", v: "Anonymous — we will have no way to reach you" }) : (n.email || t) && s.push({ k: "Verified email", v: n.email || t }));
747
809
  }
748
- const i = we(j(r, e));
810
+ const i = Ie(Y(r, e));
749
811
  return i && s.push({ k: "Priority", v: i === "urgent" ? "Urgent" : "Moderate", pill: i }), s;
750
812
  }
751
- function Re(r, e = []) {
813
+ function Me(r, e = []) {
752
814
  const t = r?.confirmation || {};
753
815
  return {
754
816
  title: t.title || "Report received.",
@@ -756,12 +818,12 @@ function Re(r, e = []) {
756
818
  urgentNote: e.includes("urgent") ? t.urgentNote : void 0
757
819
  };
758
820
  }
759
- function De(r, e) {
821
+ function Oe(r, e) {
760
822
  const t = e === "failed" ? " The notification is queued for a delivery retry." : "";
761
823
  return r?.startsWith("studio+email:") ? `Sent to the Studio review queue; the desk is emailed.${t}` : r?.startsWith("studio:") ? "Sent to the Studio review queue." : r?.startsWith("jsm:") ? `A ticket is opened for tech support with your details as fields, not prose.${t}` : r?.startsWith("email:") ? `Emailed to the owning desk with a link to your report.${t}` : "Routed to the right team.";
762
824
  }
763
- function Te({ routing: r = {}, flags: e = [], reference: t = "" }) {
764
- const s = e.includes("urgent");
825
+ function Ue({ routing: r = {}, flags: e = [], reference: t = "", anonymous: s = !1 }) {
826
+ const i = e.includes("urgent");
765
827
  return [
766
828
  {
767
829
  title: "Received",
@@ -769,12 +831,12 @@ function Te({ routing: r = {}, flags: e = [], reference: t = "" }) {
769
831
  },
770
832
  {
771
833
  title: "Routed",
772
- body: De(r.destination, r.state),
773
- pill: s ? "Urgent · pinned first" : void 0
834
+ body: Oe(r.destination, r.state),
835
+ pill: i ? "Urgent · pinned first" : void 0
774
836
  },
775
837
  {
776
838
  title: "Reviewed",
777
- body: "An editor reviews it in the Report It queue: accept and promote with your credit, reject, or re-route."
839
+ body: s ? "An editor reviews it in the Report It queue: accept and promote it uncredited, reject, or re-route." : "An editor reviews it in the Report It queue: accept and promote with your credit, reject, or re-route."
778
840
  },
779
841
  {
780
842
  title: "Monitored",
@@ -786,30 +848,30 @@ function Te({ routing: r = {}, flags: e = [], reference: t = "" }) {
786
848
  }
787
849
  ];
788
850
  }
789
- const E = "wral-report-it:draft:v1", O = 1;
790
- function ze(r, e) {
851
+ const R = "wral-report-it:draft:v1", K = 1;
852
+ function qe(r, e) {
791
853
  try {
792
- r.setItem(E, JSON.stringify({ ...e, v: O, savedAt: Date.now() }));
854
+ r.setItem(R, JSON.stringify({ ...e, v: K, savedAt: Date.now() }));
793
855
  } catch {
794
856
  }
795
857
  }
796
- function Pe(r) {
858
+ function Le(r) {
797
859
  try {
798
- const e = r.getItem(E);
860
+ const e = r.getItem(R);
799
861
  if (!e) return null;
800
862
  const t = JSON.parse(e);
801
- return t?.v !== O ? null : t;
863
+ return t?.v !== K ? null : t;
802
864
  } catch {
803
865
  return null;
804
866
  }
805
867
  }
806
- function B(r) {
868
+ function j(r) {
807
869
  try {
808
- r.removeItem(E);
870
+ r.removeItem(R);
809
871
  } catch {
810
872
  }
811
873
  }
812
- function Be({ apiOrigin: r, form: e, steps: t, requestId: s = null, mediaMeta: i = {} }) {
874
+ function je({ apiOrigin: r, form: e, steps: t, requestId: s = null, mediaMeta: i = {} }) {
813
875
  return {
814
876
  apiOrigin: r,
815
877
  formId: e.formId,
@@ -819,26 +881,26 @@ function Be({ apiOrigin: r, form: e, steps: t, requestId: s = null, mediaMeta: i
819
881
  media: i
820
882
  };
821
883
  }
822
- function qe(r, e, { apiOrigin: t } = {}) {
884
+ function Ne(r, e, { apiOrigin: t } = {}) {
823
885
  if (!r) return { status: "discarded" };
824
886
  if (t && r.apiOrigin && r.apiOrigin !== t)
825
887
  return { status: "discarded" };
826
- const s = (e || []).find((n) => n.formId === r.formId);
888
+ const s = (e || []).find((o) => o.formId === r.formId);
827
889
  if (!s) return { status: "discarded" };
828
- const { error: i } = U(s, r.steps || []);
890
+ const { error: i } = V(s, r.steps || []);
829
891
  if (i) return { status: "discarded" };
830
- const a = {};
831
- for (const [n, o] of Object.entries(r.media || {}))
832
- o?.length && (a[n] = o.map((d) => ({ ...d, lost: !0 })));
892
+ const n = {};
893
+ for (const [o, l] of Object.entries(r.media || {}))
894
+ l?.length && (n[o] = l.map((d) => ({ ...d, lost: !0 })));
833
895
  return {
834
896
  status: r.flowVersion === s.flowVersion ? "ok" : "review-required",
835
897
  form: s,
836
898
  steps: r.steps || [],
837
899
  requestId: r.requestId || null,
838
- lostMedia: a
900
+ lostMedia: n
839
901
  };
840
902
  }
841
- function k(r = []) {
903
+ function F(r = []) {
842
904
  return {
843
905
  stage: "idle",
844
906
  resumeStage: null,
@@ -858,7 +920,7 @@ function k(r = []) {
858
920
  error: null
859
921
  };
860
922
  }
861
- function Me(r, e) {
923
+ function We(r, e) {
862
924
  switch (e.type) {
863
925
  case "START":
864
926
  return { ...r, stage: r.files.length ? "minting" : "requesting", error: null };
@@ -879,29 +941,29 @@ function Me(r, e) {
879
941
  return { ...r, stage: "uploading", files: t };
880
942
  }
881
943
  case "FILE_PROGRESS":
882
- return x(r, e.i, (t) => ({
944
+ return v(r, e.i, (t) => ({
883
945
  ...t,
884
946
  progress: e.total ? e.loaded / e.total : 0
885
947
  }));
886
948
  case "FILE_DONE": {
887
- const t = x(r, e.i, (s) => ({ ...s, status: "done", progress: 1 }));
888
- return Ue(t);
949
+ const t = v(r, e.i, (s) => ({ ...s, status: "done", progress: 1 }));
950
+ return Ve(t);
889
951
  }
890
952
  case "FILE_FAIL":
891
- return { ...x(r, e.i, (s) => ({
953
+ return { ...v(r, e.i, (s) => ({
892
954
  ...s,
893
955
  status: "failed",
894
956
  error: e.error || "upload failed"
895
957
  })), stage: "uploading-error" };
896
958
  case "RETRY_FILE":
897
- return { ...x(r, e.i, (s) => ({
959
+ return { ...v(r, e.i, (s) => ({
898
960
  ...s,
899
961
  status: "uploading",
900
962
  progress: 0,
901
963
  error: null
902
964
  })), stage: "uploading" };
903
965
  case "REMINT_FILE":
904
- return { ...x(r, e.i, (s) => ({
966
+ return { ...v(r, e.i, (s) => ({
905
967
  ...s,
906
968
  assetId: e.upload.assetId,
907
969
  url: e.upload.url,
@@ -917,23 +979,23 @@ function Me(r, e) {
917
979
  case "REQUEST_FAIL":
918
980
  return { ...r, stage: "requesting-error", error: e.error };
919
981
  case "RESET":
920
- return k([]);
982
+ return F([]);
921
983
  default:
922
984
  return r;
923
985
  }
924
986
  }
925
- function x(r, e, t) {
926
- const s = r.files.map((i, a) => a === e ? t(i) : i);
987
+ function v(r, e, t) {
988
+ const s = r.files.map((i, n) => n === e ? t(i) : i);
927
989
  return { ...r, files: s };
928
990
  }
929
- function Ue(r) {
991
+ function Ve(r) {
930
992
  const e = r.files.every((s) => s.status === "done"), t = r.files.some((s) => s.status === "failed");
931
993
  return e ? { ...r, stage: "requesting" } : t ? { ...r, stage: "uploading-error" } : r;
932
994
  }
933
- function q(r) {
995
+ function N(r) {
934
996
  return r.files.map((e, t) => ({ ...e, i: t })).filter((e) => e.status === "failed");
935
997
  }
936
- const je = [
998
+ const Ye = [
937
999
  "Wake",
938
1000
  "Durham",
939
1001
  "Orange",
@@ -950,14 +1012,18 @@ const je = [
950
1012
  "Moore",
951
1013
  "Sampson",
952
1014
  "Other / outside the area"
953
- ], M = "(919) 821-8600", Le = "https://www.wral.com/my-wral/";
954
- function Oe(r) {
1015
+ ], W = "(919) 821-8600", He = "https://www.wral.com/my-wral/", Ke = Object.freeze([
1016
+ "We cannot come back to you for the detail that often turns a tip into a story.",
1017
+ "We cannot credit you if we use your photos or video.",
1018
+ "If you lose your reference number, we cannot look it up for you."
1019
+ ]);
1020
+ function Qe(r) {
955
1021
  const e = String(r).replace(/\D/g, "");
956
1022
  return `tel:+1${e.length === 11 && e.startsWith("1") ? e.slice(1) : e}`;
957
1023
  }
958
- const We = "https://api.wral.com/forms", Ve = 480, Ne = 2;
959
- class Xe extends I {
960
- static styles = ce;
1024
+ const Ge = "https://api.wral.com/forms", Je = 480, Xe = 2, S = "Welcome to Report It. What would you like to send us?", A = "A few quick questions route your report to the right team.", Ze = 2500;
1025
+ class at extends T {
1026
+ static styles = me;
961
1027
  static properties = {
962
1028
  api: { type: String },
963
1029
  _phase: { state: !0 },
@@ -965,6 +1031,7 @@ class Xe extends I {
965
1031
  _form: { state: !0 },
966
1032
  _steps: { state: !0 },
967
1033
  _typing: { state: !0 },
1034
+ _loadingSlow: { state: !0 },
968
1035
  _cardValues: { state: !0 },
969
1036
  _fieldErrors: { state: !0 },
970
1037
  _gate: { state: !0 },
@@ -973,41 +1040,43 @@ class Xe extends I {
973
1040
  _notice: { state: !0 },
974
1041
  _result: { state: !0 }
975
1042
  };
976
- #o = null;
1043
+ #l = null;
977
1044
  #a = null;
978
1045
  #u = null;
979
1046
  #t = null;
980
1047
  #r = {};
981
1048
  #s = {};
982
1049
  #i = /* @__PURE__ */ new Map();
983
- #g = null;
984
- #m = !1;
985
- #l = null;
1050
+ #y = null;
1051
+ #p = null;
1052
+ #w = !1;
1053
+ #d = null;
1054
+ #I = 0;
986
1055
  constructor() {
987
- super(), this.api = We, this._phase = "loading", this._forms = [], this._form = null, this._steps = [], this._typing = !1, this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, this._submit = k([]), this._banner = null, this._notice = null, this._result = null;
1056
+ super(), this.api = Ge, this._phase = "loading", this._forms = [], this._form = null, this._steps = [], this._typing = !1, this._loadingSlow = !1, this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, this._submit = F([]), this._banner = null, this._notice = null, this._result = null;
988
1057
  }
989
1058
  get client() {
990
- return this.#o ? this.#o : ((!this.#a || this.#u !== this.api) && (this.#a = ge({ baseUrl: this.api }), this.#u = this.api), this.#a);
1059
+ return this.#l ? this.#l : ((!this.#a || this.#u !== this.api) && (this.#a = ke({ baseUrl: this.api }), this.#u = this.api), this.#a);
991
1060
  }
992
1061
  set client(e) {
993
- this.#o = e || null, this.isConnected && this.#b();
1062
+ this.#l = e || null, this.isConnected && this.#x();
994
1063
  }
995
1064
  connectedCallback() {
996
- super.connectedCallback(), this.#b();
1065
+ super.connectedCallback(), this.#x();
997
1066
  }
998
1067
  disconnectedCallback() {
999
- super.disconnectedCallback(), clearTimeout(this.#g), this.#l?.();
1068
+ super.disconnectedCallback(), clearTimeout(this.#y), clearTimeout(this.#p), this.#d?.();
1000
1069
  for (const { abort: e } of this.#i.values()) e?.();
1001
1070
  this.#i.clear();
1002
1071
  }
1003
- get #A() {
1072
+ get #z() {
1004
1073
  try {
1005
1074
  return matchMedia("(prefers-reduced-motion: reduce)").matches;
1006
1075
  } catch {
1007
1076
  return !0;
1008
1077
  }
1009
1078
  }
1010
- get #p() {
1079
+ get #h() {
1011
1080
  try {
1012
1081
  return sessionStorage;
1013
1082
  } catch {
@@ -1016,28 +1085,49 @@ class Xe extends I {
1016
1085
  } };
1017
1086
  }
1018
1087
  }
1088
+ /*
1089
+ * The anonymous route is offered only where it can actually complete.
1090
+ * The server is the authority: GET /v1/forms says whether anonymous
1091
+ * submission is enabled on this deployment, and a form whose desk needs
1092
+ * a way to reach the viewer opts out with allowAnonymous: false.
1093
+ */
1094
+ get #B() {
1095
+ return this.client.anonymousCapability?.().enabled === !0 && this._form?.allowAnonymous !== !1;
1096
+ }
1097
+ /* Derived from the gate step, so a reload restores the choice. */
1098
+ get #f() {
1099
+ return this._steps.some((e) => e.kind === "gate" && e.anonymous === !0);
1100
+ }
1019
1101
  // ── Loading + draft restore ─────────────────────────────────────
1020
- async #b() {
1021
- this._phase = "loading", this._banner = null;
1102
+ async #x() {
1103
+ const e = ++this.#I, t = () => e === this.#I;
1104
+ this._phase = "loading", this._banner = null, this._loadingSlow = !1, clearTimeout(this.#p), this.#p = setTimeout(() => {
1105
+ this._loadingSlow = !0;
1106
+ }, Ze);
1107
+ let s;
1022
1108
  try {
1023
- this._forms = await this.client.listForms();
1109
+ s = await this.client.listForms();
1024
1110
  } catch {
1025
- this._phase = "load-error";
1111
+ t() && (this._phase = "load-error");
1026
1112
  return;
1113
+ } finally {
1114
+ t() && (clearTimeout(this.#p), this._loadingSlow = !1);
1027
1115
  }
1028
- const e = qe(Pe(this.#p), this._forms, { apiOrigin: this.api });
1029
- if (e.status === "ok" || e.status === "review-required") {
1030
- this._form = e.form, this._steps = e.steps, this.#t = e.requestId, this.#s = e.lostMedia || {}, e.status === "review-required" ? this._notice = "This form changed since your last visit — please review your answers." : Object.keys(this.#s).length && (this._notice = "Welcome back — your answers were saved, but attachments need to be re-attached."), this.#n({ animate: !1 });
1116
+ if (!t()) return;
1117
+ this._forms = s;
1118
+ const i = Ne(Le(this.#h), this._forms, { apiOrigin: this.api });
1119
+ if (i.status === "ok" || i.status === "review-required") {
1120
+ this._form = i.form, this._steps = i.steps, this.#t = i.requestId, this.#s = i.lostMedia || {}, i.status === "review-required" ? this._notice = "This form changed since your last visit — please review your answers." : Object.keys(this.#s).length && (this._notice = "Welcome back — your answers were saved, but attachments need to be re-attached."), this.#o({ animate: !1 });
1031
1121
  return;
1032
1122
  }
1033
1123
  this._phase = "pick";
1034
1124
  }
1035
- #d() {
1125
+ #c() {
1036
1126
  if (!this._form) return;
1037
1127
  const e = {};
1038
1128
  for (const [t, s] of Object.entries(this.#r))
1039
- s.length && (e[t] = s.map(({ name: i, type: a, size: n }) => ({ name: i, type: a, size: n })));
1040
- ze(this.#p, Be({
1129
+ s.length && (e[t] = s.map(({ name: i, type: n, size: o }) => ({ name: i, type: n, size: o })));
1130
+ qe(this.#h, je({
1041
1131
  apiOrigin: this.api,
1042
1132
  form: this._form,
1043
1133
  steps: this._steps,
@@ -1046,77 +1136,77 @@ class Xe extends I {
1046
1136
  }));
1047
1137
  }
1048
1138
  // ── Walk mechanics ──────────────────────────────────────────────
1049
- #n({ animate: e = !0 } = {}) {
1050
- this._phase = "walk", this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, e && !this.#A ? (this._typing = !0, clearTimeout(this.#g), this.#g = setTimeout(() => {
1139
+ #o({ animate: e = !0 } = {}) {
1140
+ this._phase = "walk", this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, e && !this.#z ? (this._typing = !0, clearTimeout(this.#y), this.#y = setTimeout(() => {
1051
1141
  this._typing = !1;
1052
- }, Ve)) : this._typing = !1;
1142
+ }, Je)) : this._typing = !1;
1053
1143
  }
1054
- get #_() {
1055
- return this._form ? U(this._form, this._steps) : { node: null };
1144
+ get #v() {
1145
+ return this._form ? V(this._form, this._steps) : { node: null };
1056
1146
  }
1057
- #R(e) {
1058
- this._form = e, this._steps = [], this.#t = null, this.#r = {}, this.#s = {}, this._notice = null, this.#d(), this.#n();
1147
+ #P(e) {
1148
+ this._form = e, this._steps = [], this.#t = null, this.#r = {}, this.#s = {}, this._notice = null, this.#c(), this.#o();
1059
1149
  }
1060
- #y(e) {
1061
- this._steps = [...this._steps, e], this.#d(), this.#n();
1150
+ #g(e) {
1151
+ this._steps = [...this._steps, e], this.#c(), this.#o();
1062
1152
  }
1063
- #D() {
1153
+ #M() {
1064
1154
  if (this._phase === "done" || this._phase === "submitting") return;
1065
1155
  if (this._phase === "review") {
1066
- this.#n({ animate: !1 });
1156
+ this.#o({ animate: !1 });
1067
1157
  return;
1068
1158
  }
1069
1159
  if (!this._steps.length) {
1070
- this.#w();
1160
+ this.#k();
1071
1161
  return;
1072
1162
  }
1073
1163
  const e = this._steps.at(-1);
1074
- this._steps = this._steps.slice(0, -1), e.kind === "collect" && (this._cardValues = { ...e.values }), this.#d(), this.#n({ animate: !1 });
1164
+ this._steps = this._steps.slice(0, -1), e.kind === "collect" && (this._cardValues = { ...e.values }), this.#c(), this.#o({ animate: !1 });
1075
1165
  }
1076
- #w() {
1077
- this._form = null, this._steps = [], this.#t = null, this.#r = {}, this.#s = {}, this._result = null, this._banner = null, this._notice = null, this._submit = k([]), B(this.#p), this._phase = "pick";
1166
+ #k() {
1167
+ this.client.endAnonSession?.(), this._form = null, this._steps = [], this.#t = null, this.#r = {}, this.#s = {}, this._result = null, this._banner = null, this._notice = null, this._submit = F([]), j(this.#h), this._phase = "pick";
1078
1168
  }
1079
1169
  // ── Collect card ────────────────────────────────────────────────
1080
- #x(e, t) {
1170
+ #_(e, t) {
1081
1171
  this._cardValues = { ...this._cardValues, [e]: t };
1082
1172
  }
1083
- #T(e) {
1084
- const t = e.fields || [], { ok: s, errors: i } = T(t, this._cardValues), a = t.find((d) => d.kind === "media");
1085
- let n = !0;
1086
- if (a) {
1087
- const d = this.#r[e.id] || [], f = F(d, this._form.budget, {
1088
- required: !!a.required
1173
+ #O(e) {
1174
+ const t = e.fields || [], { ok: s, errors: i } = O(t, this._cardValues), n = t.find((d) => d.kind === "media");
1175
+ let o = !0;
1176
+ if (n) {
1177
+ const d = this.#r[e.id] || [], u = C(d, this._form.budget, {
1178
+ required: !!n.required
1089
1179
  });
1090
- f.ok ? d.length && (this.#s = { ...this.#s, [e.id]: [] }) : (n = !1, i[a.key] = f.errors[0].message);
1180
+ u.ok ? d.length && (this.#s = { ...this.#s, [e.id]: [] }) : (o = !1, i[n.key] = u.errors[0].message);
1091
1181
  }
1092
- if (!s || !n) {
1182
+ if (!s || !o) {
1093
1183
  this._fieldErrors = i;
1094
1184
  return;
1095
1185
  }
1096
- const o = this.#r[e.id] || [];
1097
- this.#y({
1186
+ const l = this.#r[e.id] || [];
1187
+ this.#g({
1098
1188
  nodeId: e.id,
1099
1189
  kind: "collect",
1100
1190
  values: { ...this._cardValues },
1101
- summary: Se(t, this._cardValues, o)
1191
+ summary: Be(t, this._cardValues, l)
1102
1192
  });
1103
1193
  }
1104
1194
  // ── Gate ────────────────────────────────────────────────────────
1105
- async #$() {
1106
- if (!(this._gate.stage || this.#m)) {
1107
- this.#m = !0;
1195
+ async #E() {
1196
+ if (!(this._gate.stage || this.#w)) {
1197
+ this.#w = !0;
1108
1198
  try {
1109
1199
  const e = await this.client.isAuthenticated();
1110
1200
  this._gate = e ? { stage: "signedin", email: this.client.signedInEmail?.() || "", error: "", loading: !1 } : { stage: "email", email: "", error: "", loading: !1 };
1111
1201
  } finally {
1112
- this.#m = !1;
1202
+ this.#w = !1;
1113
1203
  }
1114
- this._gate.stage === "email" && this.client.onCrossTabLogin && !this.#l && (this.#l = this.client.onCrossTabLogin(() => {
1115
- this.#l?.(), this.#l = null, this._gate = { stage: null, email: "", error: "", loading: !1 }, this.#$();
1204
+ this._gate.stage === "email" && this.client.onCrossTabLogin && !this.#d && (this.#d = this.client.onCrossTabLogin(() => {
1205
+ this.#d?.(), this.#d = null, this._gate = { stage: null, email: "", error: "", loading: !1 }, this.#E();
1116
1206
  }));
1117
1207
  }
1118
1208
  }
1119
- async #v() {
1209
+ async #$() {
1120
1210
  const e = this._gate.email.trim();
1121
1211
  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)) {
1122
1212
  this._gate = { ...this._gate, error: "Please enter a valid email address." };
@@ -1134,10 +1224,10 @@ class Xe extends I {
1134
1224
  };
1135
1225
  }
1136
1226
  }
1137
- async #F(e) {
1227
+ async #S(e) {
1138
1228
  this._gate = { ...this._gate, error: "", loading: !0 };
1139
1229
  try {
1140
- await this.client.verifyCode(e), this.#I(this._gate.email);
1230
+ await this.client.verifyCode(e), this.#A(this._gate.email);
1141
1231
  } catch (t) {
1142
1232
  this._gate = {
1143
1233
  ...this._gate,
@@ -1146,19 +1236,53 @@ class Xe extends I {
1146
1236
  };
1147
1237
  }
1148
1238
  }
1149
- #I(e) {
1239
+ #A(e) {
1150
1240
  if (this._gate = { stage: null, email: "", error: "", loading: !1 }, this._submit.stage === "auth") {
1151
- this.#e({ type: "AUTH_OK" }), this._phase = "submitting", this.#c();
1241
+ this.#e({ type: "AUTH_OK" }), this._phase = "submitting", this.#n();
1152
1242
  return;
1153
1243
  }
1154
- const { node: t } = this.#_;
1155
- t?.type === "gate" && this.#y({ nodeId: t.id, kind: "gate", email: e });
1244
+ const { node: t } = this.#v;
1245
+ t?.type === "gate" && this.#g({ nodeId: t.id, kind: "gate", email: e });
1156
1246
  }
1157
- #z() {
1247
+ #U() {
1158
1248
  this.client.signOut?.(), this._gate = { stage: "email", email: "", error: "", loading: !1 };
1159
1249
  }
1250
+ // ── Anonymous route ─────────────────────────────────────────────
1251
+ #q() {
1252
+ this._gate = { ...this._gate, stage: "anon-confirm", error: "" };
1253
+ }
1254
+ #L() {
1255
+ this._gate = { ...this._gate, stage: "email", error: "" };
1256
+ }
1257
+ /*
1258
+ * Records the choice only. The session is minted at submit, against
1259
+ * the requestId, so an abandoned form leaves nothing behind.
1260
+ */
1261
+ #j() {
1262
+ const { node: e } = this.#v;
1263
+ e?.type === "gate" && (this._gate = { stage: null, email: "", error: "", loading: !1 }, this.#g({ nodeId: e.id, kind: "gate", anonymous: !0 }));
1264
+ }
1265
+ async #C() {
1266
+ try {
1267
+ return await this.client.createAnonSession({
1268
+ formId: this._form.formId,
1269
+ requestId: this.#t
1270
+ }), !0;
1271
+ } catch (e) {
1272
+ return this._banner = q(e?.status ?? 0, e?.body ?? null), !1;
1273
+ }
1274
+ }
1275
+ /* An anonymous session outliving the upload run re-mints in place; there
1276
+ * is no identity to send back to the sign-in card. */
1277
+ async #N() {
1278
+ if (await this.#C()) {
1279
+ this.#e({ type: "AUTH_OK" }), this._phase = "submitting", this.#n();
1280
+ return;
1281
+ }
1282
+ this.#e({ type: "REQUEST_FAIL", error: this._banner });
1283
+ }
1160
1284
  // ── Submit pipeline ─────────────────────────────────────────────
1161
- get #h() {
1285
+ get #m() {
1162
1286
  const e = [];
1163
1287
  for (const t of this._steps)
1164
1288
  if (t.kind === "collect")
@@ -1167,117 +1291,129 @@ class Xe extends I {
1167
1291
  return e;
1168
1292
  }
1169
1293
  #e(e) {
1170
- this._submit = Me(this._submit, e);
1294
+ this._submit = We(this._submit, e);
1171
1295
  }
1172
- async #P() {
1296
+ async #W() {
1173
1297
  this._banner = null;
1174
1298
  for (let e = 0; e < this._steps.length; e++) {
1175
1299
  const t = this._steps[e];
1176
1300
  if (t.kind !== "collect") continue;
1177
- const s = g(this._form, t.nodeId), { ok: i, errors: a } = T(s?.fields || [], t.values), n = (s?.fields || []).find((d) => d.kind === "media");
1178
- let o = !0;
1179
- if (n) {
1180
- const d = this.#r[t.nodeId] || [], f = F(d, this._form.budget, {
1181
- required: !!n.required
1301
+ const s = b(this._form, t.nodeId), { ok: i, errors: n } = O(s?.fields || [], t.values), o = (s?.fields || []).find((d) => d.kind === "media");
1302
+ let l = !0;
1303
+ if (o) {
1304
+ const d = this.#r[t.nodeId] || [], u = C(d, this._form.budget, {
1305
+ required: !!o.required
1182
1306
  });
1183
- f.ok || (o = !1, a[n.key] = f.errors[0].message);
1307
+ u.ok || (l = !1, n[o.key] = u.errors[0].message);
1184
1308
  }
1185
- if (!i || !o) {
1186
- this._steps = this._steps.slice(0, e), this._cardValues = { ...t.values }, this._fieldErrors = a, this.#d(), this.#n({ animate: !1 });
1309
+ if (!i || !l) {
1310
+ this._steps = this._steps.slice(0, e), this._cardValues = { ...t.values }, this._fieldErrors = n, this.#c(), this.#o({ animate: !1 });
1187
1311
  return;
1188
1312
  }
1189
1313
  }
1190
- if (this.#t = this.#t || crypto.randomUUID(), this.#d(), this._submit = k(this.#h), this._phase = "submitting", !await this.client.isAuthenticated()) {
1314
+ if (this.#t = this.#t || crypto.randomUUID(), this.#c(), this.#f) {
1315
+ if (!await this.#C()) return;
1316
+ } else
1317
+ this.client.endAnonSession?.();
1318
+ if (this._submit = F(this.#m), this._phase = "submitting", this.#f) {
1319
+ this.#e({ type: "START" }), this.#n();
1320
+ return;
1321
+ }
1322
+ if (!await this.client.isAuthenticated()) {
1191
1323
  this.#e({ type: "START" }), this.#e({ type: "AUTH_REQUIRED" }), this._gate = { stage: "email", email: "", error: "", loading: !1 };
1192
1324
  return;
1193
1325
  }
1194
- this.#e({ type: "START" }), this.#c();
1326
+ this.#e({ type: "START" }), this.#n();
1195
1327
  }
1196
- async #c() {
1328
+ async #n() {
1197
1329
  const e = this._submit.stage;
1198
- if (e === "minting") return this.#B();
1199
- if (e === "uploading") return this.#E();
1200
- if (e === "requesting") return this.#U();
1330
+ if (e === "minting") return this.#V();
1331
+ if (e === "uploading") return this.#T();
1332
+ if (e === "requesting") return this.#K();
1201
1333
  }
1202
- async #B() {
1334
+ async #V() {
1203
1335
  try {
1204
- const e = await this.client.createUploads(z({
1336
+ const e = await this.client.createUploads(U({
1205
1337
  formId: this._form.formId,
1206
1338
  requestId: this.#t,
1207
- files: this.#h
1339
+ files: this.#m
1208
1340
  }));
1209
- this.#e({ type: "MINTED", uploads: e }), this.#c();
1341
+ this.#e({ type: "MINTED", uploads: e }), this.#n();
1210
1342
  } catch (e) {
1211
- this.#k(e);
1343
+ this.#F(e);
1212
1344
  }
1213
1345
  }
1214
- #E() {
1346
+ #T() {
1215
1347
  const e = this._submit.files, t = this.#i.size;
1216
1348
  let s = 0;
1217
- for (let i = 0; i < e.length && t + s < Ne; i++)
1218
- e[i].status !== "uploading" || this.#i.has(i) || (s += 1, this.#q(i));
1349
+ for (let i = 0; i < e.length && t + s < Xe; i++)
1350
+ e[i].status !== "uploading" || this.#i.has(i) || (s += 1, this.#Y(i));
1219
1351
  }
1220
- #q(e) {
1221
- const t = this._submit.files[e], s = this.#h[e], { promise: i, abort: a } = this.client.uploadFile({
1352
+ #Y(e) {
1353
+ const t = this._submit.files[e], s = this.#m[e], { promise: i, abort: n } = this.client.uploadFile({
1222
1354
  url: t.url,
1223
1355
  file: s,
1224
1356
  contentType: t.type,
1225
- onProgress: ({ loaded: n, total: o }) => {
1226
- this.#e({ type: "FILE_PROGRESS", i: e, loaded: n, total: o });
1357
+ onProgress: ({ loaded: o, total: l }) => {
1358
+ this.#e({ type: "FILE_PROGRESS", i: e, loaded: o, total: l });
1227
1359
  }
1228
1360
  });
1229
- this.#i.set(e, { abort: a }), i.then(() => {
1230
- this.#i.delete(e), this.#e({ type: "FILE_DONE", i: e }), this.#c();
1231
- }).catch((n) => {
1361
+ this.#i.set(e, { abort: n }), i.then(() => {
1362
+ this.#i.delete(e), this.#e({ type: "FILE_DONE", i: e }), this.#n();
1363
+ }).catch((o) => {
1232
1364
  this.#i.delete(e), this.#e({
1233
1365
  type: "FILE_FAIL",
1234
1366
  i: e,
1235
- error: n?.status === 403 ? "expired" : "failed"
1367
+ error: o?.status === 403 ? "expired" : "failed"
1236
1368
  });
1237
1369
  });
1238
1370
  }
1239
- async #M(e) {
1371
+ async #H(e) {
1240
1372
  if (this._submit.files[e].error === "expired")
1241
1373
  try {
1242
- const [s] = await this.client.createUploads(z({
1374
+ const [s] = await this.client.createUploads(U({
1243
1375
  formId: this._form.formId,
1244
1376
  requestId: this.#t,
1245
- files: [this.#h[e]]
1377
+ files: [this.#m[e]]
1246
1378
  }));
1247
1379
  this.#e({ type: "REMINT_FILE", i: e, upload: s });
1248
1380
  } catch (s) {
1249
- this.#k(s);
1381
+ this.#F(s);
1250
1382
  return;
1251
1383
  }
1252
1384
  else
1253
1385
  this.#e({ type: "RETRY_FILE", i: e });
1254
- this.#E();
1386
+ this.#T();
1255
1387
  }
1256
- async #U() {
1388
+ async #K() {
1257
1389
  try {
1258
- const e = this._submit.files.map(({ assetId: s, type: i }) => ({ assetId: s, type: i })), t = await this.client.putRequest(this.#t, $e({
1390
+ const e = this._submit.files.map(({ assetId: s, type: i }) => ({ assetId: s, type: i })), t = await this.client.putRequest(this.#t, Te({
1259
1391
  form: this._form,
1260
1392
  steps: this._steps,
1261
1393
  media: e
1262
1394
  }));
1263
- this.#e({ type: "REQUEST_OK", result: t }), this._result = t, B(this.#p), this._phase = "done";
1395
+ this.#e({ type: "REQUEST_OK", result: t }), this._result = t, j(this.#h), this.client.endAnonSession?.(), this._phase = "done";
1264
1396
  } catch (e) {
1265
- this.#k(e);
1397
+ this.#F(e);
1266
1398
  }
1267
1399
  }
1268
- #k(e) {
1269
- const t = Fe(e?.status ?? 0, e?.body ?? null);
1400
+ #F(e) {
1401
+ const t = q(e?.status ?? 0, e?.body ?? null);
1270
1402
  if (t.kind === "auth") {
1271
- this.#e({ type: "AUTH_REQUIRED" }), this._gate = { stage: "email", email: "", error: "", loading: !1 };
1403
+ if (this.#e({ type: "AUTH_REQUIRED" }), this.#f) {
1404
+ this.#N();
1405
+ return;
1406
+ }
1407
+ this._gate = { stage: "email", email: "", error: "", loading: !1 };
1272
1408
  return;
1273
1409
  }
1274
1410
  if (t.kind === "stale") {
1275
- this._banner = t, this.#e({ type: "REQUEST_FAIL", error: t }), this.#j();
1411
+ this._banner = t, this.#e({ type: "REQUEST_FAIL", error: t }), this.#Q();
1276
1412
  return;
1277
1413
  }
1278
1414
  this._banner = t, this.#e({ type: "REQUEST_FAIL", error: t });
1279
1415
  }
1280
- async #j() {
1416
+ async #Q() {
1281
1417
  try {
1282
1418
  this._forms = await this.client.listForms();
1283
1419
  const e = this._forms.find((t) => t.formId === this._form.formId);
@@ -1285,86 +1421,84 @@ class Xe extends I {
1285
1421
  } catch {
1286
1422
  }
1287
1423
  }
1288
- #L() {
1289
- this._banner = null, this.#e({ type: "REQUEST_START" }), this.#c();
1424
+ #G() {
1425
+ this._banner = null, this.#e({ type: "REQUEST_START" }), this.#n();
1290
1426
  }
1291
1427
  // ── Render ──────────────────────────────────────────────────────
1292
1428
  render() {
1293
- return l`
1429
+ return a`
1294
1430
  <div class="chat" aria-live="polite">
1295
- ${this.#O()}
1431
+ ${this.#J()}
1296
1432
  </div>
1297
- ${this.#Z()}
1433
+ ${this.#ce()}
1298
1434
  `;
1299
1435
  }
1300
- #O() {
1436
+ #J() {
1301
1437
  switch (this._phase) {
1302
1438
  case "loading":
1303
- return $();
1439
+ return a`${h(S, this._loadingSlow ? "Loading the form list…" : A)}
1440
+ ${E()}`;
1304
1441
  case "load-error":
1305
- return l`
1442
+ return a`
1306
1443
  ${h("We could not load the forms.", "Check your connection and try again.", { error: !0 })}
1307
1444
  <div class="options">
1308
- <button type="button" class="chip" @click=${() => this.#b()}>Try again</button>
1445
+ <button type="button" class="chip" @click=${() => this.#x()}>Try again</button>
1309
1446
  </div>
1310
1447
  `;
1311
1448
  case "pick":
1312
- return this.#W();
1449
+ return this.#X();
1313
1450
  case "walk":
1314
- return l`${this.#f()}${this._typing ? $() : this.#V()}`;
1451
+ return a`${this.#b()}${this._typing ? E() : this.#Z()}`;
1315
1452
  case "review":
1316
- return l`${this.#f()}${this.#S()}`;
1453
+ return a`${this.#b()}${this.#D()}`;
1317
1454
  case "submitting":
1318
- return l`${this.#f()}${this.#J()}`;
1455
+ return a`${this.#b()}${this.#le()}`;
1319
1456
  case "done":
1320
- return l`${this.#f()}${this.#X()}`;
1457
+ return a`${this.#b()}${this.#de()}`;
1321
1458
  default:
1322
1459
  return c;
1323
1460
  }
1324
1461
  }
1325
- #W() {
1462
+ #X() {
1326
1463
  const e = this._forms;
1327
- return l`
1328
- ${h(
1329
- "Welcome to Report It. What would you like to send us?",
1330
- "A few quick questions route your report to the right team."
1331
- )}
1464
+ return a`
1465
+ ${h(S, A, { noAnim: !0 })}
1332
1466
  <div class="options" role="group" aria-label="What would you like to send us?">
1333
- ${e.map((t, s) => l`
1467
+ ${e.map((t, s) => a`
1334
1468
  <button type="button" class="chip" style="animation-delay: ${60 + s * 50}ms"
1335
- @click=${() => this.#R(t)}>${t.title}</button>
1469
+ @click=${() => this.#P(t)}>${t.title}</button>
1336
1470
  `)}
1337
1471
  </div>
1338
1472
  `;
1339
1473
  }
1340
- #f() {
1474
+ #b() {
1341
1475
  const e = [];
1342
- this._form && (e.push(h(
1343
- "Welcome to Report It. What would you like to send us?",
1344
- "A few quick questions route your report to the right team.",
1345
- { noAnim: !0 }
1346
- )), e.push(v(this._form.title, { noAnim: !0 }))), this._notice && e.push(h(this._notice, "", { noAnim: !0 }));
1476
+ this._form && (e.push(h(S, A, { noAnim: !0 })), e.push($(this._form.title, { noAnim: !0 }))), this._notice && e.push(h(this._notice, "", { noAnim: !0 }));
1347
1477
  for (const t of this._steps) {
1348
- const s = g(this._form, t.nodeId);
1349
- s?.prompt && e.push(h(s.prompt, s.help, { noAnim: !0 })), s?.type === "gate" && e.push(h(
1478
+ const s = b(this._form, t.nodeId);
1479
+ s?.prompt && e.push(h(s.prompt, s.help, { noAnim: !0 })), s?.type === "gate" && e.push(t.anonymous ? h(
1480
+ "Last step: how can we reach you?",
1481
+ "You chose to send this anonymously.",
1482
+ { noAnim: !0 }
1483
+ ) : h(
1350
1484
  "Last step: verify your email so we can follow up.",
1351
1485
  "One address, one code. No password needed.",
1352
1486
  { noAnim: !0 }
1353
- )), t.kind === "choice" && e.push(v(t.label || t.optionId, { noAnim: !0 })), t.kind === "collect" && e.push(v(t.summary || "Details provided", { noAnim: !0 })), t.kind === "gate" && e.push(v(t.email, { noAnim: !0 }));
1487
+ )), t.kind === "choice" && e.push($(t.label || t.optionId, { noAnim: !0 })), t.kind === "collect" && e.push($(t.summary || "Details provided", { noAnim: !0 })), t.kind === "gate" && e.push($(t.anonymous ? "Send anonymously" : t.email, { noAnim: !0 }));
1354
1488
  }
1355
1489
  return e;
1356
1490
  }
1357
- #V() {
1358
- const { node: e, error: t } = this.#_;
1359
- return t || !e ? h("Something went sideways with this form.", "Please start over.", { error: !0 }) : e.type === "choice" ? this.#N(e) : e.type === "collect" ? this.#H(e) : e.type === "gate" ? this.#C(e) : e.type === "redirect" ? this.#G(e) : e.type === "terminal" ? this.#S() : c;
1491
+ #Z() {
1492
+ const { node: e, error: t } = this.#v;
1493
+ return t || !e ? h("Something went sideways with this form.", "Please start over.", { error: !0 }) : e.type === "choice" ? this.#ee(e) : e.type === "collect" ? this.#te(e) : e.type === "gate" ? this.#R(e) : e.type === "redirect" ? this.#oe(e) : e.type === "terminal" ? this.#D() : c;
1360
1494
  }
1361
- #N(e) {
1362
- return l`
1495
+ #ee(e) {
1496
+ return a`
1363
1497
  ${h(e.prompt, e.help)}
1364
1498
  <div class="options" role="group" aria-label=${e.prompt || "Choose one"}>
1365
- ${(e.options || []).map((t, s) => l`
1499
+ ${(e.options || []).map((t, s) => a`
1366
1500
  <button type="button" class="chip" style="animation-delay: ${60 + s * 50}ms"
1367
- @click=${() => this.#y({
1501
+ @click=${() => this.#g({
1368
1502
  nodeId: e.id,
1369
1503
  kind: "choice",
1370
1504
  optionId: t.id,
@@ -1374,61 +1508,61 @@ class Xe extends I {
1374
1508
  </div>
1375
1509
  `;
1376
1510
  }
1377
- #H(e) {
1511
+ #te(e) {
1378
1512
  const t = e.fields || [];
1379
- return l`
1513
+ return a`
1380
1514
  ${h(e.prompt, e.help)}
1381
1515
  <div class="form-card">
1382
- ${t.map((s) => this.#Y(e, s))}
1383
- <button type="button" class="btn-primary" @click=${() => this.#T(e)}>
1516
+ ${t.map((s) => this.#re(e, s))}
1517
+ <button type="button" class="btn-primary" @click=${() => this.#O(e)}>
1384
1518
  Continue
1385
1519
  </button>
1386
1520
  </div>
1387
1521
  `;
1388
1522
  }
1389
- #Y(e, t) {
1390
- const s = this._cardValues[t.key], i = this._fieldErrors[t.key], a = !t.required && t.kind !== "consent" ? l` <span class="opt">optional</span>` : c, n = t.kind === "consent" ? c : l`
1391
- <label for="f-${t.key}">${t.label}${a}</label>
1523
+ #re(e, t) {
1524
+ const s = this._cardValues[t.key], i = this._fieldErrors[t.key], n = !t.required && t.kind !== "consent" ? a` <span class="opt">optional</span>` : c, o = t.kind === "consent" ? c : a`
1525
+ <label for="f-${t.key}">${t.label}${n}</label>
1392
1526
  `;
1393
- return l`
1527
+ return a`
1394
1528
  <div class="field">
1395
- ${n}
1396
- ${this.#K(e, t, s)}
1397
- ${i ? l`<div class="err" role="alert">${i}</div>` : c}
1529
+ ${o}
1530
+ ${this.#se(e, t, s)}
1531
+ ${i ? a`<div class="err" role="alert">${i}</div>` : c}
1398
1532
  </div>
1399
1533
  `;
1400
1534
  }
1401
- #K(e, t, s) {
1402
- const i = (a) => (n) => this.#x(a, n.target.value);
1535
+ #se(e, t, s) {
1536
+ const i = (n) => (o) => this.#_(n, o.target.value);
1403
1537
  switch (t.kind) {
1404
1538
  case "text":
1405
- return l`<input type="text" id="f-${t.key}" .value=${s || ""}
1539
+ return a`<input type="text" id="f-${t.key}" .value=${s || ""}
1406
1540
  placeholder=${t.placeholder || ""} @input=${i(t.key)}>`;
1407
1541
  case "url":
1408
- return l`<input type="url" id="f-${t.key}" .value=${s || ""}
1542
+ return a`<input type="url" id="f-${t.key}" .value=${s || ""}
1409
1543
  placeholder=${t.placeholder || ""} @input=${i(t.key)}>`;
1410
1544
  case "textarea":
1411
- return l`<textarea id="f-${t.key}" .value=${s || ""}
1545
+ return a`<textarea id="f-${t.key}" .value=${s || ""}
1412
1546
  placeholder=${t.placeholder || ""} @input=${i(t.key)}></textarea>`;
1413
1547
  case "datetime":
1414
- return l`<input type="datetime-local" id="f-${t.key}" .value=${s || ""}
1548
+ return a`<input type="datetime-local" id="f-${t.key}" .value=${s || ""}
1415
1549
  @input=${i(t.key)}>`;
1416
1550
  case "select":
1417
- return l`
1551
+ return a`
1418
1552
  <select id="f-${t.key}" @change=${i(t.key)}>
1419
1553
  <option value="">Choose one</option>
1420
- ${(t.options || []).map((a) => l`
1421
- <option value=${a.id} ?selected=${s === a.id}>${a.label}</option>
1554
+ ${(t.options || []).map((n) => a`
1555
+ <option value=${n.id} ?selected=${s === n.id}>${n.label}</option>
1422
1556
  `)}
1423
1557
  </select>
1424
1558
  `;
1425
1559
  case "location":
1426
- return this.#Q(t, s || {});
1560
+ return this.#ie(t, s || {});
1427
1561
  case "consent":
1428
- return l`
1562
+ return a`
1429
1563
  <div class="consent-row">
1430
1564
  <input type="checkbox" id="f-${t.key}" .checked=${s === !0}
1431
- @change=${(a) => this.#x(t.key, a.target.checked)}>
1565
+ @change=${(n) => this.#_(t.key, n.target.checked)}>
1432
1566
  <label for="f-${t.key}" style="all: unset; cursor: pointer;">
1433
1567
  I took or own this material and give WRAL permission to use it
1434
1568
  on air and online with credit to me.
@@ -1436,56 +1570,56 @@ class Xe extends I {
1436
1570
  </div>
1437
1571
  `;
1438
1572
  case "media":
1439
- return l`
1573
+ return a`
1440
1574
  <wral-report-media
1441
1575
  .files=${this.#r[e.id] || []}
1442
1576
  .lostMeta=${this.#s[e.id] || []}
1443
1577
  .budget=${this._form.budget || {}}
1444
1578
  ?required=${!!t.required}
1445
1579
  label=${t.label}
1446
- @files-changed=${(a) => {
1447
- this.#r = { ...this.#r, [e.id]: a.detail.files }, this.requestUpdate();
1580
+ @files-changed=${(n) => {
1581
+ this.#r = { ...this.#r, [e.id]: n.detail.files }, this.requestUpdate();
1448
1582
  }}></wral-report-media>
1449
1583
  `;
1450
1584
  default:
1451
1585
  return c;
1452
1586
  }
1453
1587
  }
1454
- #Q(e, t) {
1455
- const s = e.counties || je, i = (a) => this.#x(e.key, { ...t, ...a });
1456
- return l`
1588
+ #ie(e, t) {
1589
+ const s = e.counties || Ye, i = (n) => this.#_(e.key, { ...t, ...n });
1590
+ return a`
1457
1591
  <select id="f-${e.key}" aria-label="County"
1458
- @change=${(a) => i({ county: a.target.value || void 0 })}>
1592
+ @change=${(n) => i({ county: n.target.value || void 0 })}>
1459
1593
  <option value="">Choose a county</option>
1460
- ${s.map((a) => l`
1461
- <option value=${a} ?selected=${t.county === a}>${a}</option>
1594
+ ${s.map((n) => a`
1595
+ <option value=${n} ?selected=${t.county === n}>${n}</option>
1462
1596
  `)}
1463
1597
  </select>
1464
1598
  <input type="text" style="margin-top: 8px;"
1465
1599
  aria-label="Nearest town or crossroads"
1466
1600
  placeholder="Nearest town or crossroads"
1467
1601
  .value=${t.where || ""}
1468
- @input=${(a) => i({ where: a.target.value || void 0 })}>
1602
+ @input=${(n) => i({ where: n.target.value || void 0 })}>
1469
1603
  `;
1470
1604
  }
1471
- #C(e) {
1472
- this.#$();
1605
+ #R(e) {
1606
+ this.#E();
1473
1607
  const t = this._gate, s = h(
1474
1608
  "Last step: verify your email so we can follow up.",
1475
1609
  "One address, one code. No password needed."
1476
1610
  );
1477
- return t.stage ? t.stage === "signedin" ? l`
1611
+ return t.stage ? t.stage === "signedin" ? a`
1478
1612
  ${s}
1479
1613
  <div class="form-card">
1480
1614
  <p style="margin: 0 0 12px; font-size: 14.5px;">
1481
1615
  You are signed in as <strong>${t.email || "your My WRAL account"}</strong> on this device.
1482
1616
  </p>
1483
1617
  <button type="button" class="btn-primary"
1484
- @click=${() => this.#I(t.email)}>Continue</button>
1618
+ @click=${() => this.#A(t.email)}>Continue</button>
1485
1619
  <button type="button" class="btn-ghost"
1486
- @click=${() => this.#z()}>Use a different email</button>
1620
+ @click=${() => this.#U()}>Use a different email</button>
1487
1621
  </div>
1488
- ` : t.stage === "email" ? l`
1622
+ ` : t.stage === "email" ? a`
1489
1623
  ${s}
1490
1624
  <div class="form-card login-card">
1491
1625
  <h2>Sign in or create account</h2>
@@ -1500,12 +1634,12 @@ class Xe extends I {
1500
1634
  this._gate = { ...t, email: i.target.value };
1501
1635
  }}
1502
1636
  @keydown=${(i) => {
1503
- i.key === "Enter" && this.#v();
1637
+ i.key === "Enter" && this.#$();
1504
1638
  }}>
1505
1639
  </div>
1506
- ${t.error ? l`<div class="err" role="alert">${t.error}</div>` : c}
1640
+ ${t.error ? a`<div class="err" role="alert">${t.error}</div>` : c}
1507
1641
  <button type="button" class="login-btn" ?disabled=${t.loading}
1508
- @click=${() => this.#v()}>
1642
+ @click=${() => this.#$()}>
1509
1643
  ${t.loading ? "Sending…" : "Continue with email"}
1510
1644
  </button>
1511
1645
  <div class="login-why">
@@ -1514,15 +1648,12 @@ class Xe extends I {
1514
1648
  <li>We can follow up on your report</li>
1515
1649
  <li>Your contact information fills in automatically next time</li>
1516
1650
  <li>You are credited by name when we use your photos or video</li>
1517
- <li><a href=${Le} target="_blank" rel="noopener">All other My WRAL account benefits</a></li>
1651
+ <li><a href=${He} target="_blank" rel="noopener">All other My WRAL account benefits</a></li>
1518
1652
  </ul>
1519
1653
  </div>
1520
- <p class="login-anon">
1521
- Want to remain anonymous? Call us at
1522
- <a href=${Oe(M)}>${M}</a>.
1523
- </p>
1654
+ ${this._submit.stage === "auth" ? c : this.#ne()}
1524
1655
  </div>
1525
- ` : l`
1656
+ ` : t.stage === "anon-confirm" ? this.#ae(s) : a`
1526
1657
  ${s}
1527
1658
  <div class="form-card login-card">
1528
1659
  <h2>Enter verification code</h2>
@@ -1536,27 +1667,71 @@ class Xe extends I {
1536
1667
  <div class="field">
1537
1668
  <label>Verification code</label>
1538
1669
  <wral-code-input
1539
- @code-complete=${(i) => this.#F(i.detail?.code ?? i.detail?.value ?? i.target.value)}>
1670
+ @code-complete=${(i) => this.#S(i.detail?.code ?? i.detail?.value ?? i.target.value)}>
1540
1671
  </wral-code-input>
1541
1672
  </div>
1542
- ${t.error ? l`<div class="err" role="alert">${t.error}</div>` : c}
1673
+ ${t.error ? a`<div class="err" role="alert">${t.error}</div>` : c}
1543
1674
  <button type="button" class="login-btn" ?disabled=${t.loading}
1544
1675
  @click=${() => {
1545
1676
  const i = this.renderRoot.querySelector("wral-code-input");
1546
- this.#F(i?.value || "");
1677
+ this.#S(i?.value || "");
1547
1678
  }}>
1548
1679
  ${t.loading ? "Checking…" : "Sign in"}
1549
1680
  </button>
1550
1681
  <p class="login-help">
1551
1682
  Didn’t receive a code? Check your spam folder or
1552
- <button type="button" @click=${() => this.#v()}>resend a new code</button>.
1683
+ <button type="button" @click=${() => this.#$()}>resend a new code</button>.
1684
+ </p>
1685
+ </div>
1686
+ ` : a`${s}${E()}`;
1687
+ }
1688
+ /* Collapsed by default: findable for whoever needs it, never the
1689
+ * first thing a viewer reaches for. */
1690
+ #ne() {
1691
+ return a`
1692
+ <details class="login-alt">
1693
+ <summary>Other ways to send this</summary>
1694
+ <div class="alt-body">
1695
+ <p class="alt-row">
1696
+ Call the newsroom desk at
1697
+ <a href=${Qe(W)}>${W}</a>.
1698
+ </p>
1699
+ ${this.#B ? a`
1700
+ <p class="alt-row">
1701
+ <button type="button" class="alt-link"
1702
+ @click=${() => this.#q()}>Send this anonymously</button>
1703
+ — no follow-up, and no credit if we use your photos or video.
1704
+ </p>
1705
+ ` : c}
1706
+ </div>
1707
+ </details>
1708
+ `;
1709
+ }
1710
+ #ae(e) {
1711
+ return a`
1712
+ ${e}
1713
+ <div class="form-card login-card">
1714
+ <h2>Before you send anonymously</h2>
1715
+ <p class="login-sub">
1716
+ You can send this report without an account. Here is what it costs you.
1553
1717
  </p>
1718
+ <ul class="anon-costs">
1719
+ ${Ke.map((t) => a`
1720
+ <li><span class="x" aria-hidden="true">✕</span><span>${t}</span></li>
1721
+ `)}
1722
+ </ul>
1723
+ <div class="anon-actions">
1724
+ <button type="button" class="login-btn"
1725
+ @click=${() => this.#L()}>Sign in instead</button>
1726
+ <button type="button" class="btn-ghost"
1727
+ @click=${() => this.#j()}>Continue anonymously</button>
1728
+ </div>
1554
1729
  </div>
1555
- ` : l`${s}${$()}`;
1730
+ `;
1556
1731
  }
1557
- #G(e) {
1732
+ #oe(e) {
1558
1733
  const t = e.redirect || {};
1559
- return l`
1734
+ return a`
1560
1735
  <div class="form-card">
1561
1736
  <p style="margin: 0 0 6px; font-weight: 600; font-size: 16px;
1562
1737
  color: var(--wral-base-primary-1, #001D68);
@@ -1573,30 +1748,33 @@ class Xe extends I {
1573
1748
  </div>
1574
1749
  `;
1575
1750
  }
1576
- #S() {
1577
- const e = Ae(this._form, this._steps);
1578
- return l`
1751
+ #D() {
1752
+ const e = Pe(this._form, this._steps);
1753
+ return a`
1579
1754
  ${h("Here is what you are sending.", "Check it over, then submit.")}
1580
1755
  <div class="form-card">
1581
1756
  <ul class="review-list">
1582
- ${e.map((t) => l`
1757
+ ${e.map((t) => a`
1583
1758
  <li>
1584
1759
  <span class="k">${t.k}</span>
1585
- <span>${t.pill ? ue(t.pill) : t.v}</span>
1760
+ <span>${t.pill ? be(t.pill) : t.v}</span>
1586
1761
  </li>
1587
1762
  `)}
1588
1763
  </ul>
1764
+ ${this._banner ? a`
1765
+ <div class="err" role="alert" style="margin-top: 12px;">${this._banner.message}</div>
1766
+ ` : c}
1589
1767
  <div style="margin-top: 16px;">
1590
- <button type="button" class="btn-primary" @click=${() => this.#P()}>
1768
+ <button type="button" class="btn-primary" @click=${() => this.#W()}>
1591
1769
  Submit report
1592
1770
  </button>
1593
1771
  </div>
1594
1772
  </div>
1595
1773
  `;
1596
1774
  }
1597
- #J() {
1775
+ #le() {
1598
1776
  const e = this._submit;
1599
- if (e.stage === "auth") return this.#C({ id: null, type: "gate" });
1777
+ if (e.stage === "auth") return this.#R({ id: null, type: "gate" });
1600
1778
  const t = {
1601
1779
  minting: "Preparing your uploads…",
1602
1780
  uploading: "Uploading your files…",
@@ -1604,10 +1782,10 @@ class Xe extends I {
1604
1782
  requesting: "Sending your report…",
1605
1783
  "requesting-error": this._banner?.message || "We could not send your report."
1606
1784
  }[e.stage] || "Working…";
1607
- return l`
1785
+ return a`
1608
1786
  ${h("Submitting your report.", t)}
1609
1787
  <div class="form-card">
1610
- ${e.files.map((s, i) => l`
1788
+ ${e.files.map((s, i) => a`
1611
1789
  <div class="upload-row">
1612
1790
  <span class="name">${s.name}</span>
1613
1791
  <div class="upload-bar" role="progressbar"
@@ -1618,62 +1796,63 @@ class Xe extends I {
1618
1796
  <span class="state ${s.status === "failed" ? "failed" : ""}">
1619
1797
  ${s.status === "done" ? "Done" : s.status === "failed" ? "Failed" : "Uploading"}
1620
1798
  </span>
1621
- ${s.status === "failed" ? l`
1622
- <button type="button" class="retry-chip" @click=${() => this.#M(i)}>
1799
+ ${s.status === "failed" ? a`
1800
+ <button type="button" class="retry-chip" @click=${() => this.#H(i)}>
1623
1801
  Retry
1624
1802
  </button>
1625
1803
  ` : c}
1626
1804
  </div>
1627
1805
  `)}
1628
- ${e.stage === "requesting-error" ? l`
1806
+ ${e.stage === "requesting-error" ? a`
1629
1807
  <div class="err" role="alert">${this._banner?.message || ""}</div>
1630
- ${this._banner?.retryAfter ? l`
1808
+ ${this._banner?.retryAfter ? a`
1631
1809
  <div class="file-note">You can try again in about
1632
1810
  ${Math.ceil(this._banner.retryAfter / 60)} minutes.</div>
1633
1811
  ` : c}
1634
1812
  <button type="button" class="btn-primary" style="margin-top: 8px;"
1635
- @click=${() => this.#L()}>Try again</button>
1813
+ @click=${() => this.#G()}>Try again</button>
1636
1814
  ` : c}
1637
- ${q(e).length && e.stage === "uploading-error" ? l`
1815
+ ${N(e).length && e.stage === "uploading-error" ? a`
1638
1816
  <div class="err" role="alert">Retry the failed
1639
- ${q(e).length === 1 ? "file" : "files"} to continue.</div>
1817
+ ${N(e).length === 1 ? "file" : "files"} to continue.</div>
1640
1818
  ` : c}
1641
1819
  </div>
1642
1820
  `;
1643
1821
  }
1644
- #X() {
1645
- const e = j(this._form, this._steps), t = Re(this._result, e), s = Te({
1822
+ #de() {
1823
+ const e = Y(this._form, this._steps), t = Me(this._result, e), s = Ue({
1646
1824
  routing: this._result?.routing || {},
1647
1825
  flags: e,
1648
- reference: this._result?.reference || ""
1826
+ reference: this._result?.reference || "",
1827
+ anonymous: this.#f
1649
1828
  });
1650
- return l`
1829
+ return a`
1651
1830
  <div class="confirm-card">
1652
1831
  <div class="c-head">
1653
- <div class="c-check">${pe()}</div>
1832
+ <div class="c-check">${ye()}</div>
1654
1833
  <div>
1655
1834
  <div class="eyebrow">Report received</div>
1656
1835
  <h2>${t.title}</h2>
1657
1836
  </div>
1658
1837
  </div>
1659
1838
  <p>${t.body}</p>
1660
- ${t.urgentNote ? l`<p>${t.urgentNote}</p>` : c}
1839
+ ${t.urgentNote ? a`<p>${t.urgentNote}</p>` : c}
1661
1840
  <div class="refs">
1662
1841
  <span class="ref"><span class="rk">Reference</span>${this._result?.reference || ""}</span>
1663
1842
  </div>
1664
- <button type="button" class="c-again" @click=${() => this.#w()}>
1843
+ <button type="button" class="c-again" @click=${() => this.#k()}>
1665
1844
  Start a new report
1666
1845
  </button>
1667
1846
  </div>
1668
1847
  <div class="journey">
1669
1848
  <div class="j-eyebrow">Behind the scenes</div>
1670
1849
  <div class="j-title">What happens to your report now</div>
1671
- ${s.map((i, a) => l`
1850
+ ${s.map((i, n) => a`
1672
1851
  <div class="j-step">
1673
- <div class="j-dot">${a + 1}</div>
1852
+ <div class="j-dot">${n + 1}</div>
1674
1853
  <div class="j-body">
1675
1854
  <div class="j-t">${i.title}
1676
- ${i.pill ? l` <span class="flag-pill urgent">${i.pill}</span>` : c}
1855
+ ${i.pill ? a` <span class="flag-pill urgent">${i.pill}</span>` : c}
1677
1856
  </div>
1678
1857
  <div class="j-d">${i.body}</div>
1679
1858
  </div>
@@ -1682,15 +1861,15 @@ class Xe extends I {
1682
1861
  </div>
1683
1862
  `;
1684
1863
  }
1685
- #Z() {
1864
+ #ce() {
1686
1865
  const e = this._phase === "submitting" || this._phase === "done" || this._phase === "loading" || this._phase === "load-error";
1687
- return l`
1866
+ return a`
1688
1867
  <div class="bottom-bar">
1689
1868
  <div class="inner">
1690
1869
  <button type="button" class="btn-ghost" ?disabled=${e || this._phase === "pick"}
1691
- @click=${() => this.#D()}>← Back</button>
1870
+ @click=${() => this.#M()}>← Back</button>
1692
1871
  <button type="button" class="btn-ghost" ?disabled=${this._phase === "submitting"}
1693
- @click=${() => this.#w()}>Start over</button>
1872
+ @click=${() => this.#k()}>Start over</button>
1694
1873
  <span class="note">Your report goes to a person on the right desk.</span>
1695
1874
  </div>
1696
1875
  </div>
@@ -1700,7 +1879,7 @@ class Xe extends I {
1700
1879
  this.renderRoot?.querySelector(".chat")?.lastElementChild?.scrollIntoView?.({ block: "nearest" });
1701
1880
  }
1702
1881
  }
1703
- class Ze extends I {
1882
+ class ot extends T {
1704
1883
  static properties = {
1705
1884
  files: { attribute: !1 },
1706
1885
  lostMeta: { attribute: !1 },
@@ -1708,7 +1887,7 @@ class Ze extends I {
1708
1887
  required: { type: Boolean },
1709
1888
  label: { type: String }
1710
1889
  };
1711
- static styles = p`
1890
+ static styles = f`
1712
1891
  :host { display: block; }
1713
1892
  input[type=file] { font-family: inherit; font-size: 14px; }
1714
1893
  .file-list { margin: 8px 0 0; padding: 0; list-style: none; font-size: 13.5px; }
@@ -1730,7 +1909,7 @@ class Ze extends I {
1730
1909
  constructor() {
1731
1910
  super(), this.files = [], this.lostMeta = [], this.budget = {}, this.required = !1, this.label = "Photos or video";
1732
1911
  }
1733
- get #o() {
1912
+ get #l() {
1734
1913
  return (this.budget?.allowedTypes || []).join(",");
1735
1914
  }
1736
1915
  #a(e) {
@@ -1749,18 +1928,18 @@ class Ze extends I {
1749
1928
  t.splice(e, 1), this.#a(t);
1750
1929
  }
1751
1930
  render() {
1752
- const e = this.files || [], { errors: t } = F(e, this.budget, { required: !1 });
1753
- return l`
1931
+ const e = this.files || [], { errors: t } = C(e, this.budget, { required: !1 });
1932
+ return a`
1754
1933
  <input type="file" multiple
1755
- accept=${this.#o || c}
1934
+ accept=${this.#l || c}
1756
1935
  aria-label=${this.label}
1757
1936
  @change=${this.#u}>
1758
- ${e.length ? l`
1937
+ ${e.length ? a`
1759
1938
  <ul class="file-list">
1760
- ${e.map((s, i) => l`
1939
+ ${e.map((s, i) => a`
1761
1940
  <li>
1762
1941
  <span>${s.name}</span>
1763
- <span class="size">${He(s.size)}</span>
1942
+ <span class="size">${et(s.size)}</span>
1764
1943
  <button type="button" class="remove"
1765
1944
  aria-label="Remove ${s.name}"
1766
1945
  @click=${() => this.#t(i)}>✕</button>
@@ -1768,50 +1947,50 @@ class Ze extends I {
1768
1947
  `)}
1769
1948
  </ul>
1770
1949
  ` : c}
1771
- ${(this.lostMeta || []).length ? l`
1950
+ ${(this.lostMeta || []).length ? a`
1772
1951
  <div class="lost">
1773
1952
  Please re-attach your ${this.lostMeta.length === 1 ? "file" : "files"}
1774
1953
  (${this.lostMeta.map((s) => s.name).join(", ")}) —
1775
1954
  attachments can't be saved between visits.
1776
1955
  </div>
1777
1956
  ` : c}
1778
- ${t.map((s) => l`<div class="err">${s.message}</div>`)}
1957
+ ${t.map((s) => a`<div class="err">${s.message}</div>`)}
1779
1958
  `;
1780
1959
  }
1781
1960
  }
1782
- function He(r) {
1961
+ function et(r) {
1783
1962
  return Number.isFinite(r) ? r >= 1024 * 1024 ? `${(r / (1024 * 1024)).toFixed(1)} MB` : r >= 1024 ? `${Math.round(r / 1024)} KB` : `${r} B` : "";
1784
1963
  }
1785
- const Ye = (r, e, t, s) => {
1786
- const i = e.target.value.replace(/\D/g, "").slice(-1), a = [...t];
1787
- a[r] = i;
1788
- const n = a.join(""), o = a.every((d) => d !== "");
1789
- return s("code-change", { value: n, complete: o }), i && o && s("code-complete", { value: n }), a;
1790
- }, Ke = (r, e, t, s) => {
1964
+ const tt = (r, e, t, s) => {
1965
+ const i = e.target.value.replace(/\D/g, "").slice(-1), n = [...t];
1966
+ n[r] = i;
1967
+ const o = n.join(""), l = n.every((d) => d !== "");
1968
+ return s("code-change", { value: o, complete: l }), i && l && s("code-complete", { value: o }), n;
1969
+ }, rt = (r, e, t, s) => {
1791
1970
  if (e.key === "Backspace") {
1792
1971
  const i = [...t];
1793
1972
  !i[r] && r > 0 ? i[r - 1] = "" : i[r] && (i[r] = "");
1794
- const a = i.join("");
1795
- return s("code-change", { value: a, complete: !1 }), i;
1973
+ const n = i.join("");
1974
+ return s("code-change", { value: n, complete: !1 }), i;
1796
1975
  }
1797
1976
  return t;
1798
- }, Qe = (r, e, t) => {
1977
+ }, st = (r, e, t) => {
1799
1978
  r.preventDefault();
1800
1979
  const s = r.clipboardData.getData("text").replace(/\D/g, "").slice(0, 6);
1801
1980
  if (s.length === 0) return e;
1802
1981
  const i = [...e];
1803
- for (let o = 0; o < s.length && o < 6; o++)
1804
- i[o] = s[o];
1805
- const a = i.join(""), n = i.every((o) => o !== "");
1806
- return t("code-change", { value: a, complete: n }), s.length === 6 && t("code-complete", { value: a }), i;
1982
+ for (let l = 0; l < s.length && l < 6; l++)
1983
+ i[l] = s[l];
1984
+ const n = i.join(""), o = i.every((l) => l !== "");
1985
+ return t("code-change", { value: n, complete: o }), s.length === 6 && t("code-complete", { value: n }), i;
1807
1986
  };
1808
- class et extends I {
1987
+ class lt extends T {
1809
1988
  static formAssociated = !0;
1810
1989
  static properties = {
1811
1990
  _values: { type: Array, state: !0 },
1812
1991
  disabled: { type: Boolean, reflect: !0 }
1813
1992
  };
1814
- static styles = p`
1993
+ static styles = f`
1815
1994
  :host {
1816
1995
  display: block;
1817
1996
  width: 100%;
@@ -1910,7 +2089,7 @@ class et extends I {
1910
2089
  this.getInputs()[e]?.focus();
1911
2090
  }
1912
2091
  inputHandler(e, t) {
1913
- this._values = Ye(
2092
+ this._values = tt(
1914
2093
  e,
1915
2094
  t,
1916
2095
  this._values,
@@ -1920,7 +2099,7 @@ class et extends I {
1920
2099
  keydownHandler(e, t) {
1921
2100
  if (t.key === "Backspace") {
1922
2101
  const s = !this._values[e];
1923
- this._values = Ke(
2102
+ this._values = rt(
1924
2103
  e,
1925
2104
  t,
1926
2105
  this._values,
@@ -1929,12 +2108,12 @@ class et extends I {
1929
2108
  }
1930
2109
  }
1931
2110
  pasteHandler(e) {
1932
- this._values = Qe(e, this._values, this.dispatchCustomEvent.bind(this));
2111
+ this._values = st(e, this._values, this.dispatchCustomEvent.bind(this));
1933
2112
  }
1934
2113
  render() {
1935
- return l`
2114
+ return a`
1936
2115
  <div class="code-inputs">
1937
- ${[0, 1, 2, 3, 4, 5].map((e) => l`
2116
+ ${[0, 1, 2, 3, 4, 5].map((e) => a`
1938
2117
  <input
1939
2118
  type = "text"
1940
2119
  inputmode = "numeric"
@@ -1954,10 +2133,10 @@ class et extends I {
1954
2133
  }
1955
2134
  }
1956
2135
  export {
1957
- et as W,
1958
- Ze as a,
1959
- Xe as b,
1960
- fe as c,
1961
- he as d,
1962
- ge as e
2136
+ lt as W,
2137
+ ot as a,
2138
+ at as b,
2139
+ ve as c,
2140
+ xe as d,
2141
+ ke as e
1963
2142
  };