@wral/report-it 0.1.1 → 0.1.3

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