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