@wral/report-it 0.1.4 → 0.2.1

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,222 @@
1
- import { css as f, html as a, nothing as c, LitElement as T } from "lit";
2
- import { getAuthContext as Q, createStorage as G, verifyCode as J, extractTokens as D, saveTokens as z, decodeJwtPayload as B, refreshTokenSimple as X, sendCode as Z, createUserPool as ee, signUpIfNeeded as te, createCognitoUser as re, getAuthHeaders as se, STORAGE_KEYS as I, isAuthenticatedSimple as ie } from "@wral/sdk-auth-audience";
3
- const ne = f`
1
+ import { css as b, html as c, nothing as h, LitElement as G } from "lit";
2
+ import { getAuthContext as Re, createStorage as Me, verifyCode as Oe, extractTokens as J, saveTokens as X, decodeJwtPayload as ee, refreshTokenSimple as te, sendCode as De, createUserPool as Pe, createCognitoUser as ze, STORAGE_KEYS as S, isAuthenticatedSimple as Ne, signUpIfNeeded as Be } from "@wral/sdk-auth-audience";
3
+ const K = globalThis, se = (r) => r, z = K.trustedTypes, re = z ? z.createPolicy("lit-html", { createHTML: (r) => r }) : void 0, ve = "$lit$", _ = `lit$${Math.random().toFixed(9).slice(2)}$`, _e = "?" + _, Ue = `<${_e}>`, F = document, N = () => F.createComment(""), R = (r) => r === null || typeof r != "object" && typeof r != "function", Q = Array.isArray, Le = (r) => Q(r) || typeof r?.[Symbol.iterator] == "function", H = `[
4
+ \f\r]`, C = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g, ie = /-->/g, ne = />/g, k = RegExp(`>|${H}(?:([^\\s"'>=/]+)(${H}*=${H}*(?:[^
5
+ \f\r"'\`<>=]|("|')|))|$)`, "g"), oe = /'/g, ae = /"/g, $e = /^(?:script|style|textarea|title)$/i, M = /* @__PURE__ */ Symbol.for("lit-noChange"), m = /* @__PURE__ */ Symbol.for("lit-nothing"), le = /* @__PURE__ */ new WeakMap(), A = F.createTreeWalker(F, 129);
6
+ function ke(r, e) {
7
+ if (!Q(r) || !r.hasOwnProperty("raw")) throw Error("invalid template strings array");
8
+ return re !== void 0 ? re.createHTML(e) : e;
9
+ }
10
+ const qe = (r, e) => {
11
+ const t = r.length - 1, s = [];
12
+ let i, n = e === 2 ? "<svg>" : e === 3 ? "<math>" : "", o = C;
13
+ for (let a = 0; a < t; a++) {
14
+ const l = r[a];
15
+ let d, p, u = -1, f = 0;
16
+ for (; f < l.length && (o.lastIndex = f, p = o.exec(l), p !== null); ) f = o.lastIndex, o === C ? p[1] === "!--" ? o = ie : p[1] !== void 0 ? o = ne : p[2] !== void 0 ? ($e.test(p[2]) && (i = RegExp("</" + p[2], "g")), o = k) : p[3] !== void 0 && (o = k) : o === k ? p[0] === ">" ? (o = i ?? C, u = -1) : p[1] === void 0 ? u = -2 : (u = o.lastIndex - p[2].length, d = p[1], o = p[3] === void 0 ? k : p[3] === '"' ? ae : oe) : o === ae || o === oe ? o = k : o === ie || o === ne ? o = C : (o = k, i = void 0);
17
+ const y = o === k && r[a + 1].startsWith("/>") ? " " : "";
18
+ n += o === C ? l + Ue : u >= 0 ? (s.push(d), l.slice(0, u) + ve + l.slice(u) + _ + y) : l + _ + (u === -2 ? a : y);
19
+ }
20
+ return [ke(r, n + (r[t] || "<?>") + (e === 2 ? "</svg>" : e === 3 ? "</math>" : "")), s];
21
+ };
22
+ class O {
23
+ constructor({ strings: e, _$litType$: t }, s) {
24
+ let i;
25
+ this.parts = [];
26
+ let n = 0, o = 0;
27
+ const a = e.length - 1, l = this.parts, [d, p] = qe(e, t);
28
+ if (this.el = O.createElement(d, s), A.currentNode = this.el.content, t === 2 || t === 3) {
29
+ const u = this.el.content.firstChild;
30
+ u.replaceWith(...u.childNodes);
31
+ }
32
+ for (; (i = A.nextNode()) !== null && l.length < a; ) {
33
+ if (i.nodeType === 1) {
34
+ if (i.hasAttributes()) for (const u of i.getAttributeNames()) if (u.endsWith(ve)) {
35
+ const f = p[o++], y = i.getAttribute(u).split(_), w = /([.?@])?(.*)/.exec(f);
36
+ l.push({ type: 1, index: n, name: w[2], strings: y, ctor: w[1] === "." ? je : w[1] === "?" ? We : w[1] === "@" ? Ve : U }), i.removeAttribute(u);
37
+ } else u.startsWith(_) && (l.push({ type: 6, index: n }), i.removeAttribute(u));
38
+ if ($e.test(i.tagName)) {
39
+ const u = i.textContent.split(_), f = u.length - 1;
40
+ if (f > 0) {
41
+ i.textContent = z ? z.emptyScript : "";
42
+ for (let y = 0; y < f; y++) i.append(u[y], N()), A.nextNode(), l.push({ type: 2, index: ++n });
43
+ i.append(u[f], N());
44
+ }
45
+ }
46
+ } else if (i.nodeType === 8) if (i.data === _e) l.push({ type: 2, index: n });
47
+ else {
48
+ let u = -1;
49
+ for (; (u = i.data.indexOf(_, u + 1)) !== -1; ) l.push({ type: 7, index: n }), u += _.length - 1;
50
+ }
51
+ n++;
52
+ }
53
+ }
54
+ static createElement(e, t) {
55
+ const s = F.createElement("template");
56
+ return s.innerHTML = e, s;
57
+ }
58
+ }
59
+ function E(r, e, t = r, s) {
60
+ if (e === M) return e;
61
+ let i = s !== void 0 ? t._$Co?.[s] : t._$Cl;
62
+ const n = R(e) ? void 0 : e._$litDirective$;
63
+ return i?.constructor !== n && (i?._$AO?.(!1), n === void 0 ? i = void 0 : (i = new n(r), i._$AT(r, t, s)), s !== void 0 ? (t._$Co ??= [])[s] = i : t._$Cl = i), i !== void 0 && (e = E(r, i._$AS(r, e.values), i, s)), e;
64
+ }
65
+ class He {
66
+ constructor(e, t) {
67
+ this._$AV = [], this._$AN = void 0, this._$AD = e, this._$AM = t;
68
+ }
69
+ get parentNode() {
70
+ return this._$AM.parentNode;
71
+ }
72
+ get _$AU() {
73
+ return this._$AM._$AU;
74
+ }
75
+ u(e) {
76
+ const { el: { content: t }, parts: s } = this._$AD, i = (e?.creationScope ?? F).importNode(t, !0);
77
+ A.currentNode = i;
78
+ let n = A.nextNode(), o = 0, a = 0, l = s[0];
79
+ for (; l !== void 0; ) {
80
+ if (o === l.index) {
81
+ let d;
82
+ l.type === 2 ? d = new B(n, n.nextSibling, this, e) : l.type === 1 ? d = new l.ctor(n, l.name, l.strings, this, e) : l.type === 6 && (d = new Ye(n, this, e)), this._$AV.push(d), l = s[++a];
83
+ }
84
+ o !== l?.index && (n = A.nextNode(), o++);
85
+ }
86
+ return A.currentNode = F, i;
87
+ }
88
+ p(e) {
89
+ let t = 0;
90
+ for (const s of this._$AV) s !== void 0 && (s.strings !== void 0 ? (s._$AI(e, s, t), t += s.strings.length - 2) : s._$AI(e[t])), t++;
91
+ }
92
+ }
93
+ class B {
94
+ get _$AU() {
95
+ return this._$AM?._$AU ?? this._$Cv;
96
+ }
97
+ constructor(e, t, s, i) {
98
+ this.type = 2, this._$AH = m, this._$AN = void 0, this._$AA = e, this._$AB = t, this._$AM = s, this.options = i, this._$Cv = i?.isConnected ?? !0;
99
+ }
100
+ get parentNode() {
101
+ let e = this._$AA.parentNode;
102
+ const t = this._$AM;
103
+ return t !== void 0 && e?.nodeType === 11 && (e = t.parentNode), e;
104
+ }
105
+ get startNode() {
106
+ return this._$AA;
107
+ }
108
+ get endNode() {
109
+ return this._$AB;
110
+ }
111
+ _$AI(e, t = this) {
112
+ e = E(this, e, t), R(e) ? e === m || e == null || e === "" ? (this._$AH !== m && this._$AR(), this._$AH = m) : e !== this._$AH && e !== M && this._(e) : e._$litType$ !== void 0 ? this.$(e) : e.nodeType !== void 0 ? this.T(e) : Le(e) ? this.k(e) : this._(e);
113
+ }
114
+ O(e) {
115
+ return this._$AA.parentNode.insertBefore(e, this._$AB);
116
+ }
117
+ T(e) {
118
+ this._$AH !== e && (this._$AR(), this._$AH = this.O(e));
119
+ }
120
+ _(e) {
121
+ this._$AH !== m && R(this._$AH) ? this._$AA.nextSibling.data = e : this.T(F.createTextNode(e)), this._$AH = e;
122
+ }
123
+ $(e) {
124
+ const { values: t, _$litType$: s } = e, i = typeof s == "number" ? this._$AC(e) : (s.el === void 0 && (s.el = O.createElement(ke(s.h, s.h[0]), this.options)), s);
125
+ if (this._$AH?._$AD === i) this._$AH.p(t);
126
+ else {
127
+ const n = new He(i, this), o = n.u(this.options);
128
+ n.p(t), this.T(o), this._$AH = n;
129
+ }
130
+ }
131
+ _$AC(e) {
132
+ let t = le.get(e.strings);
133
+ return t === void 0 && le.set(e.strings, t = new O(e)), t;
134
+ }
135
+ k(e) {
136
+ Q(this._$AH) || (this._$AH = [], this._$AR());
137
+ const t = this._$AH;
138
+ let s, i = 0;
139
+ for (const n of e) i === t.length ? t.push(s = new B(this.O(N()), this.O(N()), this, this.options)) : s = t[i], s._$AI(n), i++;
140
+ i < t.length && (this._$AR(s && s._$AB.nextSibling, i), t.length = i);
141
+ }
142
+ _$AR(e = this._$AA.nextSibling, t) {
143
+ for (this._$AP?.(!1, !0, t); e !== this._$AB; ) {
144
+ const s = se(e).nextSibling;
145
+ se(e).remove(), e = s;
146
+ }
147
+ }
148
+ setConnected(e) {
149
+ this._$AM === void 0 && (this._$Cv = e, this._$AP?.(e));
150
+ }
151
+ }
152
+ class U {
153
+ get tagName() {
154
+ return this.element.tagName;
155
+ }
156
+ get _$AU() {
157
+ return this._$AM._$AU;
158
+ }
159
+ constructor(e, t, s, i, n) {
160
+ this.type = 1, this._$AH = m, this._$AN = void 0, this.element = e, this.name = t, this._$AM = i, this.options = n, s.length > 2 || s[0] !== "" || s[1] !== "" ? (this._$AH = Array(s.length - 1).fill(new String()), this.strings = s) : this._$AH = m;
161
+ }
162
+ _$AI(e, t = this, s, i) {
163
+ const n = this.strings;
164
+ let o = !1;
165
+ if (n === void 0) e = E(this, e, t, 0), o = !R(e) || e !== this._$AH && e !== M, o && (this._$AH = e);
166
+ else {
167
+ const a = e;
168
+ let l, d;
169
+ for (e = n[0], l = 0; l < n.length - 1; l++) d = E(this, a[s + l], t, l), d === M && (d = this._$AH[l]), o ||= !R(d) || d !== this._$AH[l], d === m ? e = m : e !== m && (e += (d ?? "") + n[l + 1]), this._$AH[l] = d;
170
+ }
171
+ o && !i && this.j(e);
172
+ }
173
+ j(e) {
174
+ e === m ? this.element.removeAttribute(this.name) : this.element.setAttribute(this.name, e ?? "");
175
+ }
176
+ }
177
+ class je extends U {
178
+ constructor() {
179
+ super(...arguments), this.type = 3;
180
+ }
181
+ j(e) {
182
+ this.element[this.name] = e === m ? void 0 : e;
183
+ }
184
+ }
185
+ class We extends U {
186
+ constructor() {
187
+ super(...arguments), this.type = 4;
188
+ }
189
+ j(e) {
190
+ this.element.toggleAttribute(this.name, !!e && e !== m);
191
+ }
192
+ }
193
+ class Ve extends U {
194
+ constructor(e, t, s, i, n) {
195
+ super(e, t, s, i, n), this.type = 5;
196
+ }
197
+ _$AI(e, t = this) {
198
+ if ((e = E(this, e, t, 0) ?? m) === M) return;
199
+ const s = this._$AH, i = e === m && s !== m || e.capture !== s.capture || e.once !== s.once || e.passive !== s.passive, n = e !== m && (s === m || i);
200
+ i && this.element.removeEventListener(this.name, this, s), n && this.element.addEventListener(this.name, this, e), this._$AH = e;
201
+ }
202
+ handleEvent(e) {
203
+ typeof this._$AH == "function" ? this._$AH.call(this.options?.host ?? this.element, e) : this._$AH.handleEvent(e);
204
+ }
205
+ }
206
+ class Ye {
207
+ constructor(e, t, s) {
208
+ this.element = e, this.type = 6, this._$AN = void 0, this._$AM = t, this.options = s;
209
+ }
210
+ get _$AU() {
211
+ return this._$AM._$AU;
212
+ }
213
+ _$AI(e) {
214
+ E(this, e);
215
+ }
216
+ }
217
+ const Ge = K.litHtmlPolyfillSupport;
218
+ Ge?.(O, B), (K.litHtmlVersions ??= []).push("3.3.3");
219
+ const ce = (r) => r ?? m, Ke = b`
4
220
  :host {
5
221
  display: block;
6
222
  box-sizing: border-box;
@@ -24,7 +240,7 @@ const ne = f`
24
240
  position: absolute; width: 1px; height: 1px; overflow: hidden;
25
241
  clip: rect(0 0 0 0); white-space: nowrap;
26
242
  }
27
- `, ae = f`
243
+ `, Qe = b`
28
244
  @keyframes pop-in {
29
245
  0% { opacity: 0; transform: translateY(16px) scale(0.95); }
30
246
  100% { opacity: 1; transform: translateY(0) scale(1); }
@@ -55,7 +271,7 @@ const ne = f`
55
271
  animation: none !important;
56
272
  }
57
273
  }
58
- `, oe = f`
274
+ `, Ze = b`
59
275
  .msg { max-width: 85%; padding: 12px 16px; border-radius: 14px; font-size: 15px; }
60
276
  .msg.bot {
61
277
  background: var(--wral-semantic-surface-default, #FFFFFF);
@@ -77,7 +293,7 @@ const ne = f`
77
293
  .msg .sub { display: block; font-size: 13px; color: var(--wral-semantic-fg-muted, #64748B); margin-top: 4px; }
78
294
  .msg.user .sub { color: rgba(255, 255, 255, 0.75); }
79
295
  .msg.error { border-left: 3px solid var(--wral-base-red-on-light, #D1232A); }
80
- `, le = f`
296
+ `, Je = b`
81
297
  .options { display: flex; flex-wrap: wrap; gap: 8px; align-self: flex-start; max-width: 92%; padding: 2px 0 6px; }
82
298
  .chip {
83
299
  font-family: var(--wral-base-font-ui, 'IBM Plex Sans Condensed', sans-serif);
@@ -91,7 +307,7 @@ const ne = f`
91
307
  .chip:hover { background: var(--wral-base-secondary-1, #2594E3); color: #FFFFFF; }
92
308
  .chip:focus-visible { outline: 2px solid var(--wral-base-secondary-1, #2594E3); outline-offset: 2px; }
93
309
  .chip:active { transform: scale(0.97); }
94
- `, de = f`
310
+ `, Xe = b`
95
311
  .form-card {
96
312
  align-self: stretch;
97
313
  background: var(--wral-semantic-surface-default, #FFFFFF);
@@ -156,7 +372,7 @@ const ne = f`
156
372
  .btn-ghost:hover { border-color: var(--wral-base-secondary-1, #2594E3); }
157
373
  .btn-ghost:active { transform: scale(0.97); }
158
374
  .btn-ghost:focus-visible { outline: 2px solid var(--wral-base-secondary-1, #2594E3); outline-offset: 2px; }
159
- `, ce = f`
375
+ `, et = b`
160
376
  .login-card { padding: 28px 26px; }
161
377
  .login-card h2 {
162
378
  font-family: var(--wral-base-font-display, 'IBM Plex Sans Condensed', sans-serif);
@@ -243,7 +459,7 @@ const ne = f`
243
459
  .anon-costs .x { flex-shrink: 0; font-weight: 700; color: var(--wral-base-red-on-light, #D1232A); }
244
460
  .anon-actions { display: flex; flex-direction: column; gap: 10px; }
245
461
  .anon-actions .btn-ghost { width: 100%; }
246
- `, ue = f`
462
+ `, tt = b`
247
463
  .review-list { margin: 0; padding: 0; list-style: none; font-size: 14px; }
248
464
  .review-list li {
249
465
  display: grid; grid-template-columns: 130px 1fr; gap: 10px;
@@ -275,7 +491,7 @@ const ne = f`
275
491
  color: var(--wral-base-primary-1, #001D68);
276
492
  }
277
493
  @media (max-width: 540px) { .review-list li { grid-template-columns: 1fr; gap: 2px; } }
278
- `, pe = f`
494
+ `, st = b`
279
495
  .upload-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; font-size: 13.5px; }
280
496
  .upload-row .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
281
497
  .upload-row .state { font-size: 12px; color: var(--wral-semantic-fg-subtle, #64748B); }
@@ -291,7 +507,7 @@ const ne = f`
291
507
  border-radius: 999px; padding: 3px 12px; cursor: pointer;
292
508
  }
293
509
  .retry-chip:focus-visible { outline: 2px solid var(--wral-base-secondary-1, #2594E3); outline-offset: 2px; }
294
- `, he = f`
510
+ `, rt = b`
295
511
  .confirm-card {
296
512
  align-self: stretch;
297
513
  background: var(--wral-base-primary-1, #001D68);
@@ -341,7 +557,23 @@ const ne = f`
341
557
  .c-again:hover { background: rgba(255, 255, 255, 0.12); }
342
558
  .c-again:focus-visible { outline: 2px solid var(--wral-base-secondary-2, #50A9E8); outline-offset: 2px; }
343
559
  .c-again:active { transform: scale(0.97); }
344
- `, fe = f`
560
+ .facts-offer dl {
561
+ display: grid; grid-template-columns: auto 1fr; gap: 4px 14px;
562
+ margin: 0 0 14px; font-size: 14.5px;
563
+ }
564
+ .facts-offer dt { font-weight: 700; color: var(--wral-semantic-fg-subtle, #64748B); }
565
+ .facts-offer dd { margin: 0; overflow-wrap: anywhere; }
566
+ .facts-offer .facts-note {
567
+ display: flex; gap: 8px; align-items: center;
568
+ margin: 0 0 14px; font-size: 13.5px;
569
+ color: var(--wral-semantic-fg-muted, #475569);
570
+ }
571
+ .facts-offer .my-wral-icon {
572
+ flex-shrink: 0; width: 28px; height: 28px;
573
+ color: var(--wral-base-primary-1, #001D68);
574
+ }
575
+ .facts-offer .actions { display: flex; flex-wrap: wrap; gap: 8px; }
576
+ `, it = b`
345
577
  .journey {
346
578
  align-self: stretch;
347
579
  background: var(--wral-semantic-surface-default, #FFFFFF);
@@ -382,7 +614,7 @@ const ne = f`
382
614
  color: var(--wral-base-primary-1, #001D68); margin-bottom: 2px;
383
615
  }
384
616
  .j-body .j-d { font-size: 13.5px; color: var(--wral-semantic-fg-muted, #475569); line-height: 1.55; }
385
- `, ge = f`
617
+ `, nt = b`
386
618
  .bottom-bar {
387
619
  position: sticky; bottom: 0; z-index: 20;
388
620
  background: var(--wral-semantic-surface-default, #FFFFFF);
@@ -395,74 +627,85 @@ const ne = f`
395
627
  }
396
628
  .bottom-bar .note { margin-left: auto; font-size: 12px; color: var(--wral-semantic-fg-subtle, #64748B); }
397
629
  @media (max-width: 540px) { .bottom-bar .note { display: none; } }
398
- `, me = [ne, ae, oe, le, de, ce, ue, pe, he, fe, ge];
399
- function h(r, e, { noAnim: t = !1, error: s = !1 } = {}) {
400
- return a`
630
+ `, ot = [Ke, Qe, Ze, Je, Xe, et, tt, st, rt, it, nt];
631
+ function g(r, e, { noAnim: t = !1, error: s = !1 } = {}) {
632
+ return c`
401
633
  <div class="msg bot ${t ? "no-anim" : ""} ${s ? "error" : ""}">
402
634
  <span class="lead">${r}</span>
403
- ${e ? a`<span class="sub">${e}</span>` : c}
635
+ ${e ? c`<span class="sub">${e}</span>` : h}
404
636
  </div>
405
637
  `;
406
638
  }
407
- function $(r, { noAnim: e = !1 } = {}) {
408
- return a`<div class="msg user ${e ? "no-anim" : ""}">${r}</div>`;
639
+ function v(r, { noAnim: e = !1 } = {}) {
640
+ return c`<div class="msg user ${e ? "no-anim" : ""}">${r}</div>`;
409
641
  }
410
- function E() {
411
- return a`<div class="msg bot typing"><span></span><span></span><span></span></div>`;
642
+ function j() {
643
+ return c`<div class="msg bot typing"><span></span><span></span><span></span></div>`;
412
644
  }
413
- function be(r) {
414
- return r ? a`<span class="flag-pill ${r}">${r === "urgent" ? "Urgent" : "Moderate"}</span>` : c;
645
+ function at(r) {
646
+ return r ? c`<span class="flag-pill ${r}">${r === "urgent" ? "Urgent" : "Moderate"}</span>` : h;
415
647
  }
416
- function ye() {
417
- return a`
648
+ function lt() {
649
+ return c`
418
650
  <svg viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="3"
419
651
  stroke-linecap="round" stroke-linejoin="round" width="20" height="20"
420
652
  aria-hidden="true"><path d="M20 6L9 17l-5-5"/></svg>
421
653
  `;
422
654
  }
423
- const we = 15e3;
424
- class x extends Error {
655
+ function ct() {
656
+ return c`
657
+ <svg class="my-wral-icon" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 423 423">
658
+ <rect x="7.4" y="7.4" width="408.21" height="408.21" rx="204.1" ry="204.1" transform="translate(-46.49 60.15) rotate(-14.6)" fill="#fff"/>
659
+ <path d="M275.54,335.39c-6.35-4.36-6.31-10.09-2.64-8.95,2.38.89,7.28,2.02,12.45.67,28.16-7.34,33.71-60.25,33.4-90.88-8.42,12.43-14.4,23.62-24.46,26.24-6.04,1.57-15.9.23-23.04-3.63-9.31-5.1-13.58-10.91-16.81-23.31-4.04-15.5,1.11-47.55,3.78-60.89.07-.92.86-1.43,1.72-1.65,9.48-2.47,28.53,7.02,28.44,17.28.01,15.35-6.27,38.36-3.41,49.35.81,3.1,2.97,4.34,4.98,3.82,7.76-2.02,21.85-31.58,26.87-46.44,6.59-19.48,6.85-37.3,10.88-38.35,6.89-1.8,22.4,5.9,24.17,13.87,10.85,52.26.88,151.79-51.71,165.48-7.47,1.95-16.82,2.57-24.62-2.62Z" fill="currentColor"/>
660
+ <path d="M77.88,314.03c-4.19-16.07-3.14-35.61-2.89-44.1,1.84-47.14,4.3-84.81,13.75-133.32,1.05-5.39,4.7-9.05,16.15-7.52,10.8,1.4,14.78,6.08,16.1,11.16.66,2.54.97,6.07,2,11.22,12.38,1.59,15.13,5.09,19.64,14.15,4.58,9.34,6.28,17.03,8.04,23.79,2.72,10.43,4.49,18.4,7.34,26.99,11.89-22.67,15.82-55.9,34.99-75.34,6.66-6.25,10.81-9.14,15.41-10.34,3.74-.97,4.31-1.12,7.98-1.17,11.21-2.92,20.44,1.9,21.91,7.54.44,1.69,1.77,7.97,2,10.01,2.08,12.7-1.86,42.33-.69,73.93.66,15.48.93,25.95,2.42,36.4.75,5.22-.23,10.9-9.71,13.37-3.16.82-7.4,2.23-10.42,2.41-6.33.45-8.81-6.73-9.78-12.8-6.74-36.47,1.6-91.63-1.83-101.27-9.11,19.23-13.35,32.38-18.54,45.47-3.41,9.32-6.93,21.67-10.7,30.78-3.69,10.59-4.88,15.42-13.22,17.59-3.45.9-6.39,1.36-9.27,2.11-7.19,1.87-17.92-1.65-20.41-8.83-6.22-19.15-9-27.46-20.28-66.06-5.84,78.88-6.35,118.15.88,140.04,1.83,5.85-9.96,7.71-12.04,7.96-23,3.58-26.87-6.55-28.85-14.16Z" fill="currentColor"/>
661
+ <rect x="7.4" y="7.4" width="408.21" height="408.21" rx="204.1" ry="204.1" transform="translate(-46.49 60.15) rotate(-14.6)" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"/>
662
+ <rect x="7.4" y="7.4" width="408.21" height="408.21" rx="204.1" ry="204.1" transform="translate(-46.49 60.15) rotate(-14.6)" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="10"/>
663
+ </svg>
664
+ `;
665
+ }
666
+ const dt = 15e3;
667
+ class I extends Error {
425
668
  constructor(e, t) {
426
669
  super(`api-forms request failed with status ${e}`), this.status = e, this.body = t;
427
670
  }
428
671
  }
429
- const P = Object.freeze({ enabled: !1, humanCheck: null });
430
- function xe({
672
+ const de = Object.freeze({ enabled: !1, humanCheck: null });
673
+ function ut({
431
674
  baseUrl: r,
432
675
  fetchFn: e = (...i) => fetch(...i),
433
676
  xhrFactory: t = () => new XMLHttpRequest(),
434
677
  getAuthHeaders: s
435
678
  }) {
436
679
  const i = String(r || "").replace(/\/+$/, "");
437
- let n = P, o = null;
438
- async function l(d, { method: u = "GET", body: g, auth: y = !1, timeoutMs: p } = {}) {
439
- const k = { Accept: "application/json" };
440
- y && Object.assign(k, o ? { Authorization: `Bearer ${o}` } : await s()), g !== void 0 && (k["Content-Type"] = "application/json");
680
+ let n = de, o = null;
681
+ async function a(l, { method: d = "GET", body: p, auth: u = !1, timeoutMs: f } = {}) {
682
+ const y = { Accept: "application/json" };
683
+ u && Object.assign(y, o ? { Authorization: `Bearer ${o}` } : await s()), p !== void 0 && (y["Content-Type"] = "application/json");
441
684
  let w;
442
685
  try {
443
- w = await e(`${i}${d}`, {
444
- method: u,
445
- headers: k,
446
- ...p ? { signal: AbortSignal.timeout(p) } : {},
447
- ...g !== void 0 ? { body: JSON.stringify(g) } : {}
686
+ w = await e(`${i}${l}`, {
687
+ method: d,
688
+ headers: y,
689
+ ...f ? { signal: AbortSignal.timeout(f) } : {},
690
+ ...p !== void 0 ? { body: JSON.stringify(p) } : {}
448
691
  });
449
- } catch (_) {
450
- throw Object.assign(new x(0, null), { cause: _ });
692
+ } catch (D) {
693
+ throw Object.assign(new I(0, null), { cause: D });
451
694
  }
452
- let m = null;
695
+ let $ = null;
453
696
  try {
454
- m = await w.json();
697
+ $ = await w.json();
455
698
  } catch {
456
699
  }
457
700
  if (!w.ok)
458
- throw new x(w.status, m);
459
- return m;
701
+ throw new I(w.status, $);
702
+ return $;
460
703
  }
461
704
  return {
462
705
  /** @returns {Promise<Array>} published form documents */
463
706
  listForms: async () => {
464
- const d = await l("/v1/forms", { timeoutMs: we });
465
- return n = d?.anonymous?.enabled === !0 ? { enabled: !0, humanCheck: d.anonymous.humanCheck || null } : P, (d?.forms || []).filter((u) => u?.formId && u?.start && Array.isArray(u?.nodes));
707
+ const l = await a("/v1/forms", { timeoutMs: dt });
708
+ return n = l?.anonymous?.enabled === !0 ? { enabled: !0, humanCheck: l.anonymous.humanCheck || null } : de, (l?.forms || []).filter((d) => d?.formId && d?.start && Array.isArray(d?.nodes));
466
709
  },
467
710
  /**
468
711
  * What the server advertised on the last listForms.
@@ -474,121 +717,241 @@ function xe({
474
717
  * calls present it until endAnonSession(). Unauthenticated by design.
475
718
  * @returns {Promise<{expiresIn: number}>}
476
719
  */
477
- createAnonSession: async ({ formId: d, requestId: u, humanToken: g }) => {
478
- const y = await l("/v1/anon/sessions", {
720
+ createAnonSession: async ({ formId: l, requestId: d, humanToken: p }) => {
721
+ const u = await a("/v1/anon/sessions", {
479
722
  method: "POST",
480
- body: { formId: d, requestId: u, ...g ? { humanToken: g } : {} }
723
+ body: { formId: l, requestId: d, ...p ? { humanToken: p } : {} }
481
724
  });
482
- if (o = y?.token || null, !o)
483
- throw new x(502, { message: "The anonymous session had no token" });
484
- return { expiresIn: y.expiresIn };
725
+ if (o = u?.token || null, !o)
726
+ throw new I(502, { message: "The anonymous session had no token" });
727
+ return { expiresIn: u.expiresIn };
485
728
  },
486
729
  /** Drop the anonymous session so identity headers apply again. */
487
730
  endAnonSession: () => {
488
731
  o = null;
489
732
  },
490
733
  /** @returns {Promise<Array<{assetId,url,method,expires,assetUrl}>>} */
491
- createUploads: async (d) => {
492
- const { uploads: u } = await l("/v1/uploads", { method: "POST", body: d, auth: !0 });
493
- return u || [];
734
+ createUploads: async (l) => {
735
+ const { uploads: d } = await a("/v1/uploads", { method: "POST", body: l, auth: !0 });
736
+ return d || [];
494
737
  },
495
738
  /**
496
739
  * PUT one file to its presigned URL. XHR (not fetch) so upload
497
740
  * progress is observable. Resolves on 2xx; rejects with
498
741
  * ApiError(status) otherwise. Returns { promise, abort }.
499
742
  */
500
- uploadFile: ({ url: d, file: u, contentType: g, onProgress: y = () => {
743
+ uploadFile: ({ url: l, file: d, contentType: p, onProgress: u = () => {
501
744
  } }) => {
502
- const p = t();
503
- return { promise: new Promise((w, m) => {
504
- p.open("PUT", d), p.setRequestHeader("Content-Type", g || u.type), p.upload && (p.upload.onprogress = (_) => {
505
- y({ loaded: _.loaded, total: _.total || u.size });
506
- }), p.onload = () => {
507
- p.status >= 200 && p.status < 300 ? w({ status: p.status }) : m(new x(p.status, null));
508
- }, p.onerror = () => m(new x(0, null)), p.onabort = () => m(new x(0, { aborted: !0 })), p.send(u);
509
- }), abort: () => p.abort() };
745
+ const f = t();
746
+ return { promise: new Promise((w, $) => {
747
+ f.open("PUT", l), f.setRequestHeader("Content-Type", p || d.type), f.upload && (f.upload.onprogress = (D) => {
748
+ u({ loaded: D.loaded, total: D.total || d.size });
749
+ }), f.onload = () => {
750
+ f.status >= 200 && f.status < 300 ? w({ status: f.status }) : $(new I(f.status, null));
751
+ }, f.onerror = () => $(new I(0, null)), f.onabort = () => $(new I(0, { aborted: !0 })), f.send(d);
752
+ }), abort: () => f.abort() };
510
753
  },
511
754
  /** @returns {Promise<{requestId,reference,confirmation,routing}>} */
512
- putRequest: async (d, u) => await l(`/v1/requests/${d}`, { method: "PUT", body: u, auth: !0 })
755
+ putRequest: async (l, d) => await a(`/v1/requests/${l}`, { method: "PUT", body: d, auth: !0 })
513
756
  };
514
757
  }
515
- function ve() {
516
- const { config: r, storage: e } = Q();
517
- let t = null;
758
+ const ue = 60 * 1e3;
759
+ async function pt({ read: r, refresh: e, now: t = Date.now }) {
760
+ const s = (n) => {
761
+ const { token: o, expiry: a } = r() || {};
762
+ return o && Number(a) - n > t() ? o : null;
763
+ };
764
+ let i = s(ue);
765
+ if (!i) {
766
+ try {
767
+ await e();
768
+ } catch {
769
+ }
770
+ i = s(ue) || s(0);
771
+ }
772
+ if (!i)
773
+ throw Object.assign(new Error("Please sign in again to continue."), { status: 401, body: null });
774
+ return { Authorization: `Bearer ${i}` };
775
+ }
776
+ const pe = (r) => String(r || "").toLowerCase().trim();
777
+ function ht(r) {
778
+ const e = /* @__PURE__ */ new Set();
518
779
  return {
519
- isAuthenticated: () => ie(),
520
- signedInEmail: () => e.get(I.userEmail) || null,
521
- getAuthHeaders: () => se(r, e),
780
+ signUpIfNeeded: async (t, ...s) => {
781
+ const i = await r(t, ...s);
782
+ return i?.exists === !1 && !i.error && e.add(pe(t)), i;
783
+ },
784
+ isNewAccount: (t) => e.has(pe(t))
785
+ };
786
+ }
787
+ const ft = "wral_user_facts", mt = "1", gt = 100;
788
+ function yt(r, e) {
789
+ let t = "";
790
+ for (const s of r) {
791
+ if (t.length + s.length > e) break;
792
+ t += s;
793
+ }
794
+ return t;
795
+ }
796
+ const bt = [
797
+ {
798
+ autocomplete: "name",
799
+ factName: "preferred_name",
800
+ label: "Name",
801
+ shape: (r) => {
802
+ const e = String(r ?? "").replace(/\s+/g, " ").trim();
803
+ return e ? yt(e, gt).trim() : null;
804
+ }
805
+ },
806
+ {
807
+ autocomplete: "postal-code",
808
+ factName: "zipcode",
809
+ label: "Zip code",
810
+ shape: (r) => String(r ?? "").trim().match(/^(\d{5})(-\d{4})?$/)?.[1] ?? null
811
+ }
812
+ ];
813
+ function wt(r = [], e = {}) {
814
+ const t = [];
815
+ for (const s of bt) {
816
+ const i = r.find((n) => n?.kind === "text" && n.autocomplete === s.autocomplete && s.shape(e[n.key]) !== null);
817
+ i && t.push({ factName: s.factName, label: s.label, value: s.shape(e[i.key]) });
818
+ }
819
+ return t;
820
+ }
821
+ async function xt(r, {
822
+ baseUrl: e,
823
+ getAuthHeaders: t,
824
+ fetchFn: s = (...n) => fetch(...n),
825
+ onSaved: i = () => {
826
+ }
827
+ }) {
828
+ const n = String(e).replace(/\/+$/, "");
829
+ let o = !1;
830
+ try {
831
+ for (const { factName: a, value: l } of r) {
832
+ const d = { "Content-Type": "application/json", ...await t() };
833
+ let p;
834
+ try {
835
+ p = await s(
836
+ `${n}/user/${encodeURIComponent(a)}/${mt}`,
837
+ { method: "PUT", headers: d, body: JSON.stringify({ value: l }) }
838
+ );
839
+ } catch (u) {
840
+ throw Object.assign(new Error("user-facts request failed"), { status: 0, cause: u });
841
+ }
842
+ if (!p.ok)
843
+ throw Object.assign(
844
+ new Error(`user-facts request failed with status ${p.status}`),
845
+ { status: p.status }
846
+ );
847
+ o = !0;
848
+ }
849
+ } finally {
850
+ o && i();
851
+ }
852
+ }
853
+ function vt({ factsBaseUrl: r } = {}) {
854
+ const { config: e, storage: t } = Re(), s = ht(Be);
855
+ let i = null;
856
+ const n = () => pt({
857
+ read: () => ({
858
+ token: t.get(S.idToken),
859
+ expiry: t.get(S.idTokenExpiry)
860
+ }),
861
+ refresh: () => te()
862
+ });
863
+ return {
864
+ isAuthenticated: () => Ne(),
865
+ signedInEmail: () => t.get(S.userEmail) || null,
866
+ getAuthHeaders: n,
867
+ /* Save mapped answers (../lib/user-facts.mjs) to the viewer's My WRAL user facts. */
868
+ ...r ? {
869
+ saveUserFacts: (o) => xt(o, {
870
+ baseUrl: r,
871
+ getAuthHeaders: n,
872
+ onSaved: () => {
873
+ try {
874
+ localStorage.removeItem(ft);
875
+ } catch {
876
+ }
877
+ }
878
+ })
879
+ } : {},
522
880
  /**
523
881
  * Email step. Keeps the challenge user in memory for verifyCode.
524
- * @returns {{challengeRequired?: boolean, authenticated?: boolean}}
882
+ * `newAccount` is true when this page load created the account.
883
+ * @returns {{challengeRequired?: boolean, authenticated?: boolean, newAccount: boolean}}
525
884
  */
526
- sendCode: async (s) => {
527
- const i = await Z(
528
- r,
529
- s,
885
+ sendCode: async (o) => {
886
+ const a = await De(
530
887
  e,
531
- ee,
532
- te,
533
- re,
534
- D,
535
- z,
536
- B
888
+ o,
889
+ t,
890
+ Pe,
891
+ s.signUpIfNeeded,
892
+ ze,
893
+ J,
894
+ X,
895
+ ee
537
896
  );
538
- return t = i.cognitoUser || null, {
539
- challengeRequired: !!i.challengeRequired,
540
- authenticated: !!i.authenticated
897
+ return i = a.cognitoUser || null, {
898
+ challengeRequired: !!a.challengeRequired,
899
+ authenticated: !!a.authenticated,
900
+ newAccount: s.isNewAccount(o)
541
901
  };
542
902
  },
543
903
  /**
544
904
  * Code step; refreshes immediately after verify so the session
545
905
  * starts with a full lifetime (house pattern).
546
906
  */
547
- verifyCode: async (s) => {
548
- if (!t)
907
+ verifyCode: async (o) => {
908
+ if (!i)
549
909
  throw new Error("Please enter your email again to get a new code.");
550
910
  try {
551
- await J(
911
+ await Oe(
912
+ i,
913
+ o,
552
914
  t,
553
- s,
554
- e,
555
- D,
556
- z,
557
- B
915
+ J,
916
+ X,
917
+ ee
558
918
  );
559
919
  } catch {
560
920
  throw new Error("Invalid or expired code. Please request a new one and try again.");
561
921
  }
562
- return await X(), { success: !0 };
922
+ return await te(), { success: !0 };
563
923
  },
564
924
  /** Local sign-out only ("use a different email"). */
565
925
  signOut: () => {
566
- t = null, G().clear();
926
+ i = null, Me().clear();
567
927
  },
568
928
  /**
569
929
  * Detect a login completed in ANOTHER tab (the storage event
570
930
  * never fires in the tab that wrote). Returns an unsubscribe.
571
931
  */
572
- onCrossTabLogin: (s) => {
573
- const i = (n) => {
574
- (n.key === I.accessToken || n.key === I.idToken) && s();
932
+ onCrossTabLogin: (o) => {
933
+ const a = (l) => {
934
+ (l.key === S.accessToken || l.key === S.idToken) && o();
575
935
  };
576
- return window.addEventListener("storage", i), () => window.removeEventListener("storage", i);
936
+ return window.addEventListener("storage", a), () => window.removeEventListener("storage", a);
577
937
  }
578
938
  };
579
939
  }
580
- function ke({ baseUrl: r }) {
581
- const e = ve();
582
- return { ...xe({ baseUrl: r, getAuthHeaders: e.getAuthHeaders }), ...e };
940
+ function _t({ baseUrl: r, factsBaseUrl: e }) {
941
+ const t = vt({ factsBaseUrl: e });
942
+ return { ...ut({ baseUrl: r, getAuthHeaders: t.getAuthHeaders }), ...t };
583
943
  }
584
- function b(r, e) {
944
+ function x(r, e) {
585
945
  return (r?.nodes || []).find((t) => t.id === e);
586
946
  }
587
- function V(r, e = []) {
947
+ function L(r) {
948
+ return r?.form ? { formId: r.form, path: [...r.path || []] } : null;
949
+ }
950
+ function q(r, e = []) {
588
951
  const t = [];
589
952
  let s = r?.start;
590
953
  for (const n of e) {
591
- const o = b(r, s);
954
+ const o = x(r, s);
592
955
  if (!o)
593
956
  return { nodeId: null, node: null, flags: t, error: { step: n, reason: `unknown node: ${s}` } };
594
957
  if (o.type === "terminal" || o.type === "redirect")
@@ -596,66 +959,142 @@ function V(r, e = []) {
596
959
  if (n.nodeId !== s || n.kind !== o.type)
597
960
  return { nodeId: null, node: null, flags: t, error: { step: n, reason: `step does not match node ${s}` } };
598
961
  if (o.type === "choice") {
599
- const l = (o.options || []).find((d) => d.id === n.optionId);
600
- if (!l)
962
+ const a = (o.options || []).find((l) => l.id === n.optionId);
963
+ if (!a)
601
964
  return { nodeId: null, node: null, flags: t, error: { step: n, reason: `unknown option: ${n.optionId}` } };
602
- t.push(...l.flags || []), s = l.next;
965
+ if (L(a))
966
+ return { nodeId: null, node: null, flags: t, error: { step: n, reason: `steps continue past a hand-off: ${n.optionId}` } };
967
+ t.push(...a.flags || []), s = a.next;
603
968
  continue;
604
969
  }
605
970
  s = o.next;
606
971
  }
607
- const i = b(r, s);
608
- return i ? { nodeId: s, node: i, flags: H(t), error: null } : { nodeId: null, node: null, flags: t, error: { step: null, reason: `unknown node: ${s}` } };
972
+ const i = x(r, s);
973
+ return i ? { nodeId: s, node: i, flags: Ee(t), error: null } : { nodeId: null, node: null, flags: t, error: { step: null, reason: `unknown node: ${s}` } };
609
974
  }
610
- function _e(r, e = []) {
975
+ function Ae(r, e = []) {
611
976
  const t = [];
612
977
  for (const s of e) {
613
978
  if (s.kind !== "collect") continue;
614
- const i = b(r, s.nodeId);
979
+ const i = x(r, s.nodeId);
615
980
  t.push(...i?.fields || []);
616
981
  }
617
982
  return t;
618
983
  }
619
- function $e(r = []) {
984
+ function Fe(r = []) {
620
985
  const e = {};
621
986
  for (const t of r)
622
987
  t.kind === "collect" && Object.assign(e, t.values || {});
623
988
  return e;
624
989
  }
625
- function Fe(r = []) {
990
+ function $t(r = []) {
626
991
  return r.filter((e) => e.kind === "choice").map((e) => `${e.nodeId}:${e.optionId}`);
627
992
  }
628
- function Y(r, e = []) {
993
+ function Ie(r, e = []) {
629
994
  const t = [];
630
995
  for (const s of e) {
631
996
  if (s.kind !== "choice") continue;
632
- const n = (b(r, s.nodeId)?.options || []).find((o) => o.id === s.optionId);
997
+ const n = (x(r, s.nodeId)?.options || []).find((o) => o.id === s.optionId);
633
998
  t.push(...n?.flags || []);
634
999
  }
635
- return H(t);
1000
+ return Ee(t);
636
1001
  }
637
- function Ie(r = []) {
1002
+ function kt(r = []) {
638
1003
  return r.includes("urgent") ? "urgent" : r.includes("moderate") ? "moderate" : null;
639
1004
  }
640
- function H(r) {
1005
+ function Ee(r) {
641
1006
  return [...new Set(r)];
642
1007
  }
643
- const Ee = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/, M = {
1008
+ function At(r, e = []) {
1009
+ const t = [];
1010
+ for (const i of e) {
1011
+ const [n, o] = String(i).split(":"), a = x(r, n), l = a?.type === "choice" ? (a.options || []).find((d) => d.id === o) : null;
1012
+ if (!l)
1013
+ return { steps: [], error: `unknown preset step: ${i}` };
1014
+ t.push({ nodeId: n, kind: "choice", optionId: o, label: l.label, preset: !0 });
1015
+ }
1016
+ const { error: s } = q(r, t);
1017
+ return s ? { steps: [], error: s.reason } : { steps: t, error: null };
1018
+ }
1019
+ function Ft(r, e) {
1020
+ const t = L(e);
1021
+ if (!t) return { form: null, steps: [], error: "not a hand-off" };
1022
+ const s = (r || []).find((o) => o.formId === t.formId);
1023
+ if (!s) return { form: null, steps: [], error: `unknown form: ${t.formId}` };
1024
+ const { steps: i, error: n } = At(s, t.path);
1025
+ return n ? { form: null, steps: [], error: n } : { form: s, steps: i, error: null };
1026
+ }
1027
+ function It(r, e, t, s) {
1028
+ return {
1029
+ form: r,
1030
+ steps: e,
1031
+ option: { nodeId: t.id, optionId: s.id, label: s.label }
1032
+ };
1033
+ }
1034
+ function Et(r = []) {
1035
+ return r.every((e) => e.preset === !0);
1036
+ }
1037
+ function St(r, e, t) {
1038
+ if (!Array.isArray(r) || !r.length) return [];
1039
+ const s = [];
1040
+ for (let i = 0; i < r.length; i++) {
1041
+ const n = r[i], o = (e || []).find((u) => u.formId === n?.formId);
1042
+ if (!o) return [];
1043
+ const { node: a, error: l } = q(o, n.steps || []);
1044
+ if (l || a?.id !== n.option?.nodeId) return [];
1045
+ const d = (a.options || []).find((u) => u.id === n.option.optionId), p = i + 1 < r.length ? r[i + 1].formId : t;
1046
+ if (L(d)?.formId !== p) return [];
1047
+ s.push({ form: o, steps: n.steps || [], option: n.option });
1048
+ }
1049
+ return s;
1050
+ }
1051
+ function Ct({ attr: r = null, search: e = "" } = {}) {
1052
+ const t = String(r ?? "").trim();
1053
+ if (t) return t;
1054
+ try {
1055
+ return new URLSearchParams(e || "").get("flow")?.trim() || null;
1056
+ } catch {
1057
+ return null;
1058
+ }
1059
+ }
1060
+ function Tt(r, e) {
1061
+ return e && (r || []).find((t) => t.formId === e) || null;
1062
+ }
1063
+ function Rt(r, e) {
1064
+ return !e || r?.form?.formId === e ? !0 : (r?.origins || []).some((t) => t.form?.formId === e);
1065
+ }
1066
+ const Mt = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/, he = {
644
1067
  text: 500,
645
1068
  textarea: 5e3,
646
1069
  url: 2048
647
- };
648
- function Se(r, e) {
649
- if (e == null || e === "" || r.kind === "location" && Ae(e))
650
- return r.required ? `Please fill in: ${r.label.toLowerCase()}.` : null;
1070
+ }, Ot = "Please confirm the rights statement so we can use what you send.";
1071
+ function Se(r, { mediaCount: e = 0 } = {}) {
1072
+ return r.kind === "consent" && r.requiredIf === "media" ? e > 0 : !!r.required;
1073
+ }
1074
+ function Dt(r, e) {
1075
+ try {
1076
+ return new RegExp(r, "u").test(e);
1077
+ } catch {
1078
+ return !0;
1079
+ }
1080
+ }
1081
+ function Pt(r) {
1082
+ return r.key === "zip" ? "Please enter a five-digit zip code." : `Please check the format of ${r.label.toLowerCase()}.`;
1083
+ }
1084
+ function zt(r, e, { mediaCount: t = 0 } = {}) {
1085
+ const s = Se(r, { mediaCount: t });
1086
+ if (r.kind === "consent")
1087
+ return e === !0 || !s ? null : Ot;
1088
+ if (e == null || e === "" || r.kind === "location" && Nt(e))
1089
+ return s ? `Please fill in: ${r.label.toLowerCase()}.` : null;
651
1090
  switch (r.kind) {
652
1091
  case "text":
653
1092
  case "textarea": {
654
- const s = r.maxLength || M[r.kind];
655
- return typeof e != "string" ? `Please enter text for ${r.label.toLowerCase()}.` : e.length > s ? `Please keep ${r.label.toLowerCase()} under ${s} characters.` : null;
1093
+ const n = r.maxLength || he[r.kind];
1094
+ return typeof e != "string" ? `Please enter text for ${r.label.toLowerCase()}.` : e.length > n ? `Please keep ${r.label.toLowerCase()} under ${n} characters.` : r.kind === "text" && r.pattern && !Dt(r.pattern, e) ? Pt(r) : null;
656
1095
  }
657
1096
  case "url": {
658
- if (typeof e != "string" || e.length > M.url)
1097
+ if (typeof e != "string" || e.length > he.url)
659
1098
  return "Please enter a valid link.";
660
1099
  try {
661
1100
  return new URL(e), null;
@@ -664,35 +1103,33 @@ function Se(r, e) {
664
1103
  }
665
1104
  }
666
1105
  case "datetime":
667
- return Ee.test(String(e)) ? null : "Please pick a date and time.";
1106
+ return Mt.test(String(e)) ? null : "Please pick a date and time.";
668
1107
  case "select":
669
- return (r.options || []).map((i) => i.id).includes(e) ? null : `Please choose one of the options for ${r.label.toLowerCase()}.`;
670
- case "consent":
671
- return e === !0 ? null : "Please confirm the rights statement so we can use what you send.";
1108
+ return (r.options || []).map((o) => o.id).includes(e) ? null : `Please choose one of the options for ${r.label.toLowerCase()}.`;
672
1109
  case "location":
673
- return Ce(r, e);
1110
+ return Bt(r, e);
674
1111
  case "media":
675
1112
  return null;
676
1113
  default:
677
1114
  return `Unsupported field: ${r.kind}`;
678
1115
  }
679
1116
  }
680
- function Ae(r) {
1117
+ function Nt(r) {
681
1118
  return r == null ? !0 : typeof r != "object" ? !1 : !r.county && !r.where && !(Array.isArray(r.gps) && r.gps.length);
682
1119
  }
683
- function Ce(r, e) {
1120
+ function Bt(r, e) {
684
1121
  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;
685
1122
  }
686
- function O(r, e = {}) {
687
- const t = {};
688
- for (const s of r) {
689
- if (s.kind === "media") continue;
690
- const i = Se(s, e[s.key]);
691
- i && (t[s.key] = i);
1123
+ function fe(r, e = {}, { mediaCount: t = 0 } = {}) {
1124
+ const s = {};
1125
+ for (const i of r) {
1126
+ if (i.kind === "media") continue;
1127
+ const n = zt(i, e[i.key], { mediaCount: t });
1128
+ n && (s[i.key] = n);
692
1129
  }
693
- return { ok: Object.keys(t).length === 0, errors: t };
1130
+ return { ok: Object.keys(s).length === 0, errors: s };
694
1131
  }
695
- function C(r = [], e = {}, { required: t = !1 } = {}) {
1132
+ function Y(r = [], e = {}, { required: t = !1 } = {}) {
696
1133
  const {
697
1134
  maxFiles: s = 5,
698
1135
  maxFileBytes: i = 512 * 1024 * 1024,
@@ -701,48 +1138,48 @@ function C(r = [], e = {}, { required: t = !1 } = {}) {
701
1138
  return t && r.length === 0 && o.push({ reason: "required", message: "Please attach at least one photo or video." }), r.length > s && o.push({
702
1139
  reason: "count",
703
1140
  message: `This form accepts at most ${s} ${s === 1 ? "file" : "files"}.`
704
- }), r.forEach((l, d) => {
705
- n.length && !n.includes(l.type) && o.push({
706
- index: d,
1141
+ }), r.forEach((a, l) => {
1142
+ n.length && !n.includes(a.type) && o.push({
1143
+ index: l,
707
1144
  reason: "type",
708
- message: `${l.name || "A file"} is a type this form does not accept.`
709
- }), l.size > i && o.push({
710
- index: d,
1145
+ message: `${a.name || "A file"} is a type this form does not accept.`
1146
+ }), a.size > i && o.push({
1147
+ index: l,
711
1148
  reason: "size",
712
- message: `${l.name || "A file"} is larger than this form allows.`
1149
+ message: `${a.name || "A file"} is larger than this form allows.`
713
1150
  });
714
1151
  }), { ok: o.length === 0, errors: o };
715
1152
  }
716
- function U({ formId: r, requestId: e, files: t }) {
1153
+ function me({ formId: r, requestId: e, files: t }) {
717
1154
  return {
718
1155
  formId: r,
719
1156
  requestId: e,
720
1157
  files: t.map((s) => ({ contentType: s.type, size: s.size }))
721
1158
  };
722
1159
  }
723
- function Te({ form: r, steps: e, media: t = [] }) {
724
- const s = _e(r, e), i = $e(e), n = {};
1160
+ function Ut({ form: r, steps: e, media: t = [] }) {
1161
+ const s = Ae(r, e), i = Fe(e), n = {};
725
1162
  for (const o of s) {
726
1163
  if (o.kind === "media") continue;
727
- const l = i[o.key];
728
- if (!(l == null || l === "") && !(o.kind === "consent" && l !== !0)) {
1164
+ const a = i[o.key];
1165
+ if (!(a == null || a === "") && !(o.kind === "consent" && (a !== !0 || o.requiredIf === "media" && !t.length))) {
729
1166
  if (o.kind === "location") {
730
- const d = {};
731
- l.county && (d.county = l.county), l.where && (d.where = l.where), Array.isArray(l.gps) && l.gps.length === 2 && (d.gps = l.gps), Object.keys(d).length && (n[o.key] = d);
1167
+ const l = {};
1168
+ a.county && (l.county = a.county), a.where && (l.where = a.where), Array.isArray(a.gps) && a.gps.length === 2 && (l.gps = a.gps), Object.keys(l).length && (n[o.key] = l);
732
1169
  continue;
733
1170
  }
734
- n[o.key] = l;
1171
+ n[o.key] = a;
735
1172
  }
736
1173
  }
737
1174
  return {
738
1175
  formId: r.formId,
739
1176
  flowVersion: r.flowVersion,
740
- path: Fe(e),
1177
+ path: $t(e),
741
1178
  answers: n,
742
- media: t.map(({ assetId: o, type: l }) => ({ assetId: o, type: l }))
1179
+ media: t.map(({ assetId: o, type: a }) => ({ assetId: o, type: a }))
743
1180
  };
744
1181
  }
745
- function q(r, e) {
1182
+ function ge(r, e) {
746
1183
  if (r === 429)
747
1184
  return {
748
1185
  kind: "throttled",
@@ -780,15 +1217,19 @@ function q(r, e) {
780
1217
  message: "Something went wrong on our end; please try again."
781
1218
  };
782
1219
  }
783
- const Re = 34, De = 44;
784
- function L(r, e) {
1220
+ const Lt = 34, qt = 44;
1221
+ function ye(r, e) {
785
1222
  const t = String(r);
786
1223
  return t.length > e ? `${t.slice(0, e)}…` : t;
787
1224
  }
788
- function ze(r) {
1225
+ function Ht(r, e) {
1226
+ const t = (r.options || []).find((s) => s.id === e);
1227
+ return t ? t.label : e;
1228
+ }
1229
+ function jt(r) {
789
1230
  return !r || typeof r != "object" ? "" : [r.county, r.where].filter(Boolean).join(", ");
790
1231
  }
791
- function Be(r, e = {}, t = []) {
1232
+ function Wt(r, e = {}, t = []) {
792
1233
  const s = [];
793
1234
  for (const i of r) {
794
1235
  if (i.kind === "consent") continue;
@@ -796,21 +1237,21 @@ function Be(r, e = {}, t = []) {
796
1237
  t.length && s.push(`${t.length} ${t.length === 1 ? "file" : "files"}`);
797
1238
  continue;
798
1239
  }
799
- const n = i.kind === "location" ? ze(e[i.key]) : e[i.key];
800
- n == null || n === "" || (i.kind === "textarea" ? s.push(`"${L(n, De)}"`) : s.push(L(n, Re)));
1240
+ const n = i.kind === "location" ? jt(e[i.key]) : i.kind === "select" ? Ht(i, e[i.key]) : e[i.key];
1241
+ n == null || n === "" || (i.kind === "textarea" ? s.push(`"${ye(n, qt)}"`) : s.push(ye(n, Lt)));
801
1242
  }
802
1243
  return s.join(" · ") || "Details provided";
803
1244
  }
804
- function Pe(r, e = [], t = null) {
1245
+ function Vt(r, e = [], t = null) {
805
1246
  const s = [];
806
1247
  for (const n of e) {
807
- const o = b(r, n.nodeId);
1248
+ const o = x(r, n.nodeId);
808
1249
  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 }));
809
1250
  }
810
- const i = Ie(Y(r, e));
1251
+ const i = kt(Ie(r, e));
811
1252
  return i && s.push({ k: "Priority", v: i === "urgent" ? "Urgent" : "Moderate", pill: i }), s;
812
1253
  }
813
- function Me(r, e = []) {
1254
+ function Yt(r, e = []) {
814
1255
  const t = r?.confirmation || {};
815
1256
  return {
816
1257
  title: t.title || "Report received.",
@@ -818,11 +1259,11 @@ function Me(r, e = []) {
818
1259
  urgentNote: e.includes("urgent") ? t.urgentNote : void 0
819
1260
  };
820
1261
  }
821
- function Oe(r, e) {
1262
+ function Gt(r, e) {
822
1263
  const t = e === "failed" ? " The notification is queued for a delivery retry." : "";
823
1264
  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.";
824
1265
  }
825
- function Ue({ routing: r = {}, flags: e = [], reference: t = "", anonymous: s = !1 }) {
1266
+ function Kt({ routing: r = {}, flags: e = [], reference: t = "", anonymous: s = !1 }) {
826
1267
  const i = e.includes("urgent");
827
1268
  return [
828
1269
  {
@@ -831,7 +1272,7 @@ function Ue({ routing: r = {}, flags: e = [], reference: t = "", anonymous: s =
831
1272
  },
832
1273
  {
833
1274
  title: "Routed",
834
- body: Oe(r.destination, r.state),
1275
+ body: Gt(r.destination, r.state),
835
1276
  pill: i ? "Urgent · pinned first" : void 0
836
1277
  },
837
1278
  {
@@ -848,59 +1289,72 @@ function Ue({ routing: r = {}, flags: e = [], reference: t = "", anonymous: s =
848
1289
  }
849
1290
  ];
850
1291
  }
851
- const R = "wral-report-it:draft:v1", K = 1;
852
- function qe(r, e) {
1292
+ const Z = "wral-report-it:draft:v1", Ce = 1;
1293
+ function Qt(r, e) {
853
1294
  try {
854
- r.setItem(R, JSON.stringify({ ...e, v: K, savedAt: Date.now() }));
1295
+ r.setItem(Z, JSON.stringify({ ...e, v: Ce, savedAt: Date.now() }));
855
1296
  } catch {
856
1297
  }
857
1298
  }
858
- function Le(r) {
1299
+ function Zt(r) {
859
1300
  try {
860
- const e = r.getItem(R);
1301
+ const e = r.getItem(Z);
861
1302
  if (!e) return null;
862
1303
  const t = JSON.parse(e);
863
- return t?.v !== K ? null : t;
1304
+ return t?.v !== Ce ? null : t;
864
1305
  } catch {
865
1306
  return null;
866
1307
  }
867
1308
  }
868
- function j(r) {
1309
+ function be(r) {
869
1310
  try {
870
- r.removeItem(R);
1311
+ r.removeItem(Z);
871
1312
  } catch {
872
1313
  }
873
1314
  }
874
- function je({ apiOrigin: r, form: e, steps: t, requestId: s = null, mediaMeta: i = {} }) {
1315
+ function Jt({
1316
+ apiOrigin: r,
1317
+ form: e,
1318
+ steps: t,
1319
+ requestId: s = null,
1320
+ mediaMeta: i = {},
1321
+ origins: n = []
1322
+ }) {
875
1323
  return {
876
1324
  apiOrigin: r,
877
1325
  formId: e.formId,
878
1326
  flowVersion: e.flowVersion,
879
1327
  requestId: s,
880
1328
  steps: t,
881
- media: i
1329
+ media: i,
1330
+ origins: n.map(({ form: o, steps: a, option: l }) => ({
1331
+ formId: o.formId,
1332
+ steps: a,
1333
+ option: l
1334
+ }))
882
1335
  };
883
1336
  }
884
- function Ne(r, e, { apiOrigin: t } = {}) {
1337
+ function Xt(r, e, { apiOrigin: t } = {}) {
885
1338
  if (!r) return { status: "discarded" };
886
1339
  if (t && r.apiOrigin && r.apiOrigin !== t)
887
1340
  return { status: "discarded" };
888
1341
  const s = (e || []).find((o) => o.formId === r.formId);
889
1342
  if (!s) return { status: "discarded" };
890
- const { error: i } = V(s, r.steps || []);
1343
+ const { error: i } = q(s, r.steps || []);
891
1344
  if (i) return { status: "discarded" };
892
1345
  const n = {};
893
- for (const [o, l] of Object.entries(r.media || {}))
894
- l?.length && (n[o] = l.map((d) => ({ ...d, lost: !0 })));
1346
+ for (const [o, a] of Object.entries(r.media || {}))
1347
+ a?.length && (n[o] = a.map((l) => ({ ...l, lost: !0 })));
895
1348
  return {
896
1349
  status: r.flowVersion === s.flowVersion ? "ok" : "review-required",
897
1350
  form: s,
898
1351
  steps: r.steps || [],
899
1352
  requestId: r.requestId || null,
900
- lostMedia: n
1353
+ lostMedia: n,
1354
+ origins: St(r.origins, e, s.formId)
901
1355
  };
902
1356
  }
903
- function F(r = []) {
1357
+ function P(r = []) {
904
1358
  return {
905
1359
  stage: "idle",
906
1360
  resumeStage: null,
@@ -920,7 +1374,7 @@ function F(r = []) {
920
1374
  error: null
921
1375
  };
922
1376
  }
923
- function We(r, e) {
1377
+ function es(r, e) {
924
1378
  switch (e.type) {
925
1379
  case "START":
926
1380
  return { ...r, stage: r.files.length ? "minting" : "requesting", error: null };
@@ -941,29 +1395,29 @@ function We(r, e) {
941
1395
  return { ...r, stage: "uploading", files: t };
942
1396
  }
943
1397
  case "FILE_PROGRESS":
944
- return v(r, e.i, (t) => ({
1398
+ return T(r, e.i, (t) => ({
945
1399
  ...t,
946
1400
  progress: e.total ? e.loaded / e.total : 0
947
1401
  }));
948
1402
  case "FILE_DONE": {
949
- const t = v(r, e.i, (s) => ({ ...s, status: "done", progress: 1 }));
950
- return Ve(t);
1403
+ const t = T(r, e.i, (s) => ({ ...s, status: "done", progress: 1 }));
1404
+ return ts(t);
951
1405
  }
952
1406
  case "FILE_FAIL":
953
- return { ...v(r, e.i, (s) => ({
1407
+ return { ...T(r, e.i, (s) => ({
954
1408
  ...s,
955
1409
  status: "failed",
956
1410
  error: e.error || "upload failed"
957
1411
  })), stage: "uploading-error" };
958
1412
  case "RETRY_FILE":
959
- return { ...v(r, e.i, (s) => ({
1413
+ return { ...T(r, e.i, (s) => ({
960
1414
  ...s,
961
1415
  status: "uploading",
962
1416
  progress: 0,
963
1417
  error: null
964
1418
  })), stage: "uploading" };
965
1419
  case "REMINT_FILE":
966
- return { ...v(r, e.i, (s) => ({
1420
+ return { ...T(r, e.i, (s) => ({
967
1421
  ...s,
968
1422
  assetId: e.upload.assetId,
969
1423
  url: e.upload.url,
@@ -979,23 +1433,23 @@ function We(r, e) {
979
1433
  case "REQUEST_FAIL":
980
1434
  return { ...r, stage: "requesting-error", error: e.error };
981
1435
  case "RESET":
982
- return F([]);
1436
+ return P([]);
983
1437
  default:
984
1438
  return r;
985
1439
  }
986
1440
  }
987
- function v(r, e, t) {
1441
+ function T(r, e, t) {
988
1442
  const s = r.files.map((i, n) => n === e ? t(i) : i);
989
1443
  return { ...r, files: s };
990
1444
  }
991
- function Ve(r) {
1445
+ function ts(r) {
992
1446
  const e = r.files.every((s) => s.status === "done"), t = r.files.some((s) => s.status === "failed");
993
1447
  return e ? { ...r, stage: "requesting" } : t ? { ...r, stage: "uploading-error" } : r;
994
1448
  }
995
- function N(r) {
1449
+ function we(r) {
996
1450
  return r.files.map((e, t) => ({ ...e, i: t })).filter((e) => e.status === "failed");
997
1451
  }
998
- const Ye = [
1452
+ const ss = [
999
1453
  "Wake",
1000
1454
  "Durham",
1001
1455
  "Orange",
@@ -1012,24 +1466,28 @@ const Ye = [
1012
1466
  "Moore",
1013
1467
  "Sampson",
1014
1468
  "Other / outside the area"
1015
- ], W = "(919) 821-8600", He = "https://www.wral.com/my-wral/", Ke = Object.freeze([
1469
+ ], xe = "(919) 821-8600", rs = "https://www.wral.com/my-wral/", is = Object.freeze([
1016
1470
  "We cannot come back to you for the detail that often turns a tip into a story.",
1017
1471
  "We cannot credit you if we use your photos or video.",
1018
1472
  "If you lose your reference number, we cannot look it up for you."
1019
1473
  ]);
1020
- function Qe(r) {
1474
+ function ns(r) {
1021
1475
  const e = String(r).replace(/\D/g, "");
1022
1476
  return `tel:+1${e.length === 11 && e.startsWith("1") ? e.slice(1) : e}`;
1023
1477
  }
1024
- const Ge = "https://api.wral.com/forms", Je = 480, Xe = 2, S = "Welcome to Report It. What would you like to send us?", A = "A few quick questions route your report to the right team.", Ze = 2500;
1025
- class at extends T {
1026
- static styles = me;
1478
+ const os = "https://api.wral.com/forms", as = 480, ls = 2, Te = "What would you like to send to WRAL?", W = `Welcome to Report It. ${Te}`, V = "A few quick questions route your report to the right team.", cs = 2500, ds = "I took or own this material and give WRAL permission to use it on air and online with credit to me.";
1479
+ class ys extends G {
1480
+ static styles = ot;
1027
1481
  static properties = {
1028
1482
  api: { type: String },
1483
+ factsApi: { type: String, attribute: "facts-api" },
1484
+ flow: { type: String },
1029
1485
  _phase: { state: !0 },
1030
1486
  _forms: { state: !0 },
1031
1487
  _form: { state: !0 },
1032
1488
  _steps: { state: !0 },
1489
+ _origins: { state: !0 },
1490
+ _handoffError: { state: !0 },
1033
1491
  _typing: { state: !0 },
1034
1492
  _loadingSlow: { state: !0 },
1035
1493
  _cardValues: { state: !0 },
@@ -1038,45 +1496,51 @@ class at extends T {
1038
1496
  _submit: { state: !0 },
1039
1497
  _banner: { state: !0 },
1040
1498
  _notice: { state: !0 },
1041
- _result: { state: !0 }
1499
+ _result: { state: !0 },
1500
+ _factsOffer: { state: !0 }
1042
1501
  };
1502
+ #c = null;
1043
1503
  #l = null;
1044
- #a = null;
1045
- #u = null;
1504
+ #p = null;
1046
1505
  #t = null;
1047
- #r = {};
1048
1506
  #s = {};
1049
- #i = /* @__PURE__ */ new Map();
1050
- #y = null;
1051
- #p = null;
1052
- #w = !1;
1507
+ #r = {};
1508
+ #n = /* @__PURE__ */ new Map();
1509
+ #w = null;
1510
+ #h = null;
1511
+ #x = !1;
1053
1512
  #d = null;
1054
1513
  #I = 0;
1514
+ /* The gate was passed with an account created on this page load; offered once. */
1515
+ #f = !1;
1055
1516
  constructor() {
1056
- super(), this.api = Ge, this._phase = "loading", this._forms = [], this._form = null, this._steps = [], this._typing = !1, this._loadingSlow = !1, this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, this._submit = F([]), this._banner = null, this._notice = null, this._result = null;
1517
+ super(), this.api = os, this.factsApi = null, this.flow = null, this._phase = "loading", this._forms = [], this._form = null, this._steps = [], this._origins = [], this._handoffError = !1, this._typing = !1, this._loadingSlow = !1, this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, this._submit = P([]), this._banner = null, this._notice = null, this._result = null, this._factsOffer = null;
1057
1518
  }
1058
1519
  get client() {
1059
- return this.#l ? this.#l : ((!this.#a || this.#u !== this.api) && (this.#a = ke({ baseUrl: this.api }), this.#u = this.api), this.#a);
1520
+ if (this.#c) return this.#c;
1521
+ const e = `${this.api}
1522
+ ${this.factsApi || ""}`;
1523
+ return (!this.#l || this.#p !== e) && (this.#l = _t({ baseUrl: this.api, factsBaseUrl: this.factsApi || null }), this.#p = e), this.#l;
1060
1524
  }
1061
1525
  set client(e) {
1062
- this.#l = e || null, this.isConnected && this.#x();
1526
+ this.#c = e || null, this.isConnected && this.#v();
1063
1527
  }
1064
1528
  connectedCallback() {
1065
- super.connectedCallback(), this.#x();
1529
+ super.connectedCallback(), this.#v();
1066
1530
  }
1067
1531
  disconnectedCallback() {
1068
- super.disconnectedCallback(), clearTimeout(this.#y), clearTimeout(this.#p), this.#d?.();
1069
- for (const { abort: e } of this.#i.values()) e?.();
1070
- this.#i.clear();
1532
+ super.disconnectedCallback(), clearTimeout(this.#w), clearTimeout(this.#h), this.#d?.();
1533
+ for (const { abort: e } of this.#n.values()) e?.();
1534
+ this.#n.clear();
1071
1535
  }
1072
- get #z() {
1536
+ get #U() {
1073
1537
  try {
1074
1538
  return matchMedia("(prefers-reduced-motion: reduce)").matches;
1075
1539
  } catch {
1076
1540
  return !0;
1077
1541
  }
1078
1542
  }
1079
- get #h() {
1543
+ get #m() {
1080
1544
  try {
1081
1545
  return sessionStorage;
1082
1546
  } catch {
@@ -1091,19 +1555,19 @@ class at extends T {
1091
1555
  * submission is enabled on this deployment, and a form whose desk needs
1092
1556
  * a way to reach the viewer opts out with allowAnonymous: false.
1093
1557
  */
1094
- get #B() {
1558
+ get #L() {
1095
1559
  return this.client.anonymousCapability?.().enabled === !0 && this._form?.allowAnonymous !== !1;
1096
1560
  }
1097
1561
  /* Derived from the gate step, so a reload restores the choice. */
1098
- get #f() {
1562
+ get #u() {
1099
1563
  return this._steps.some((e) => e.kind === "gate" && e.anonymous === !0);
1100
1564
  }
1101
1565
  // ── Loading + draft restore ─────────────────────────────────────
1102
- async #x() {
1566
+ async #v() {
1103
1567
  const e = ++this.#I, t = () => e === this.#I;
1104
- this._phase = "loading", this._banner = null, this._loadingSlow = !1, clearTimeout(this.#p), this.#p = setTimeout(() => {
1568
+ this._phase = "loading", this._banner = null, this._loadingSlow = !1, clearTimeout(this.#h), this.#h = setTimeout(() => {
1105
1569
  this._loadingSlow = !0;
1106
- }, Ze);
1570
+ }, cs);
1107
1571
  let s;
1108
1572
  try {
1109
1573
  s = await this.client.listForms();
@@ -1111,102 +1575,161 @@ class at extends T {
1111
1575
  t() && (this._phase = "load-error");
1112
1576
  return;
1113
1577
  } finally {
1114
- t() && (clearTimeout(this.#p), this._loadingSlow = !1);
1578
+ t() && (clearTimeout(this.#h), this._loadingSlow = !1);
1115
1579
  }
1116
1580
  if (!t()) return;
1117
1581
  this._forms = s;
1118
- const i = Ne(Le(this.#h), this._forms, { apiOrigin: this.api });
1119
- if (i.status === "ok" || i.status === "review-required") {
1120
- this._form = i.form, this._steps = i.steps, this.#t = i.requestId, this.#s = i.lostMedia || {}, i.status === "review-required" ? this._notice = "This form changed since your last visit — please review your answers." : Object.keys(this.#s).length && (this._notice = "Welcome back — your answers were saved, but attachments need to be re-attached."), this.#o({ animate: !1 });
1582
+ const i = Ct({ attr: this.flow, search: globalThis.location?.search }), n = Xt(Zt(this.#m), this._forms, { apiOrigin: this.api });
1583
+ if ((n.status === "ok" || n.status === "review-required") && Rt(n, i)) {
1584
+ this._form = n.form, this._steps = n.steps, this._origins = n.origins || [], this.#t = n.requestId, this.#r = n.lostMedia || {}, n.status === "review-required" ? this._notice = "This form changed since your last visit — please review your answers." : Object.keys(this.#r).length && (this._notice = "Welcome back — your answers were saved, but attachments need to be re-attached."), this.#i({ animate: !1 });
1585
+ return;
1586
+ }
1587
+ const o = Tt(this._forms, i);
1588
+ if (o) {
1589
+ this.#E(o);
1121
1590
  return;
1122
1591
  }
1123
1592
  this._phase = "pick";
1124
1593
  }
1125
- #c() {
1594
+ #o() {
1126
1595
  if (!this._form) return;
1127
1596
  const e = {};
1128
- for (const [t, s] of Object.entries(this.#r))
1597
+ for (const [t, s] of Object.entries(this.#s))
1129
1598
  s.length && (e[t] = s.map(({ name: i, type: n, size: o }) => ({ name: i, type: n, size: o })));
1130
- qe(this.#h, je({
1599
+ Qt(this.#m, Jt({
1131
1600
  apiOrigin: this.api,
1132
1601
  form: this._form,
1133
1602
  steps: this._steps,
1134
1603
  requestId: this.#t,
1135
- mediaMeta: e
1604
+ mediaMeta: e,
1605
+ origins: this._origins
1136
1606
  }));
1137
1607
  }
1138
1608
  // ── Walk mechanics ──────────────────────────────────────────────
1139
- #o({ animate: e = !0 } = {}) {
1140
- this._phase = "walk", this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, e && !this.#z ? (this._typing = !0, clearTimeout(this.#y), this.#y = setTimeout(() => {
1609
+ #i({ animate: e = !0 } = {}) {
1610
+ this._phase = "walk", this._cardValues = {}, this._fieldErrors = {}, this._gate = { stage: null, email: "", error: "", loading: !1 }, e && !this.#U ? (this._typing = !0, clearTimeout(this.#w), this.#w = setTimeout(() => {
1141
1611
  this._typing = !1;
1142
- }, Je)) : this._typing = !1;
1612
+ }, as)) : this._typing = !1;
1143
1613
  }
1144
- get #v() {
1145
- return this._form ? V(this._form, this._steps) : { node: null };
1614
+ get #_() {
1615
+ return this._form ? q(this._form, this._steps) : { node: null };
1146
1616
  }
1147
- #P(e) {
1148
- this._form = e, this._steps = [], this.#t = null, this.#r = {}, this.#s = {}, this._notice = null, this.#c(), this.#o();
1617
+ #E(e) {
1618
+ this._form = e, this._steps = [], this._origins = [], this._handoffError = !1, this.#t = null, this.#s = {}, this.#r = {}, this._notice = null, this.#o(), this.#i();
1149
1619
  }
1150
1620
  #g(e) {
1151
- this._steps = [...this._steps, e], this.#c(), this.#o();
1621
+ this._steps = [...this._steps, e], this.#o(), this.#i();
1622
+ }
1623
+ #q(e, t) {
1624
+ if (L(t)) {
1625
+ this.#H(e, t);
1626
+ return;
1627
+ }
1628
+ this._handoffError = !1, this.#g({
1629
+ nodeId: e.id,
1630
+ kind: "choice",
1631
+ optionId: t.id,
1632
+ label: t.label
1633
+ });
1634
+ }
1635
+ /*
1636
+ * Switch to the form a hand-off option names, replaying its preset
1637
+ * steps there. The form being left becomes an origin (see
1638
+ * ../lib/handoff.mjs); its attachments are parked with it in memory so
1639
+ * Back can return them. A target that is missing or no longer matches
1640
+ * its preset path is a config mistake: say so and stay put.
1641
+ */
1642
+ #H(e, t) {
1643
+ const { form: s, steps: i, error: n } = Ft(this._forms, t);
1644
+ if (n) {
1645
+ this._handoffError = !0;
1646
+ return;
1647
+ }
1648
+ this._handoffError = !1, this._origins = [...this._origins, {
1649
+ ...It(this._form, this._steps, e, t),
1650
+ media: this.#s,
1651
+ lostMedia: this.#r
1652
+ }], this._form = s, this._steps = i, this.#t = null, this.#s = {}, this.#r = {}, this._notice = null, this.#o(), this.#i();
1653
+ }
1654
+ /* Back past a hand-off: the originating form, on the choice card. */
1655
+ #j() {
1656
+ const e = this._origins.at(-1);
1657
+ this._origins = this._origins.slice(0, -1), this._form = e.form, this._steps = e.steps, this.#t = null, this.#s = e.media || {}, this.#r = e.lostMedia || {}, this._handoffError = !1, this.#o(), this.#i({ animate: !1 });
1152
1658
  }
1153
- #M() {
1659
+ #W() {
1154
1660
  if (this._phase === "done" || this._phase === "submitting") return;
1155
1661
  if (this._phase === "review") {
1156
- this.#o({ animate: !1 });
1662
+ this.#i({ animate: !1 });
1663
+ return;
1664
+ }
1665
+ if (this._origins.length && Et(this._steps)) {
1666
+ this.#j();
1157
1667
  return;
1158
1668
  }
1159
1669
  if (!this._steps.length) {
1160
- this.#k();
1670
+ this.#$();
1161
1671
  return;
1162
1672
  }
1163
1673
  const e = this._steps.at(-1);
1164
- this._steps = this._steps.slice(0, -1), e.kind === "collect" && (this._cardValues = { ...e.values }), this.#c(), this.#o({ animate: !1 });
1674
+ this._steps = this._steps.slice(0, -1), e.kind === "collect" && (this._cardValues = { ...e.values }), this.#o(), this.#i({ animate: !1 });
1165
1675
  }
1166
- #k() {
1167
- this.client.endAnonSession?.(), this._form = null, this._steps = [], this.#t = null, this.#r = {}, this.#s = {}, this._result = null, this._banner = null, this._notice = null, this._submit = F([]), j(this.#h), this._phase = "pick";
1676
+ #$() {
1677
+ this.client.endAnonSession?.(), this._form = null, this._steps = [], this._origins = [], this._handoffError = !1, this.#t = null, this.#s = {}, this.#r = {}, this._result = null, this._banner = null, this._notice = null, this._submit = P([]), this._factsOffer = null, be(this.#m), this._phase = "pick";
1168
1678
  }
1169
1679
  // ── Collect card ────────────────────────────────────────────────
1170
- #_(e, t) {
1680
+ #k(e, t) {
1171
1681
  this._cardValues = { ...this._cardValues, [e]: t };
1172
1682
  }
1173
- #O(e) {
1174
- const t = e.fields || [], { ok: s, errors: i } = O(t, this._cardValues), n = t.find((d) => d.kind === "media");
1683
+ /* Files attached on the given collect cards (a files-only consent counts them). */
1684
+ #S(e) {
1685
+ let t = 0;
1686
+ for (const s of new Set(e)) t += (this.#s[s] || []).length;
1687
+ return t;
1688
+ }
1689
+ /* Files attached so far on this walk, the card being filled in included. */
1690
+ #C(e) {
1691
+ const t = this._steps.filter((s) => s.kind === "collect").map((s) => s.nodeId);
1692
+ return this.#S([...t, e]);
1693
+ }
1694
+ #V(e) {
1695
+ const t = e.fields || [], { ok: s, errors: i } = fe(t, this._cardValues, {
1696
+ mediaCount: this.#C(e.id)
1697
+ }), n = t.find((l) => l.kind === "media");
1175
1698
  let o = !0;
1176
1699
  if (n) {
1177
- const d = this.#r[e.id] || [], u = C(d, this._form.budget, {
1700
+ const l = this.#s[e.id] || [], d = Y(l, this._form.budget, {
1178
1701
  required: !!n.required
1179
1702
  });
1180
- u.ok ? d.length && (this.#s = { ...this.#s, [e.id]: [] }) : (o = !1, i[n.key] = u.errors[0].message);
1703
+ d.ok ? l.length && (this.#r = { ...this.#r, [e.id]: [] }) : (o = !1, i[n.key] = d.errors[0].message);
1181
1704
  }
1182
1705
  if (!s || !o) {
1183
1706
  this._fieldErrors = i;
1184
1707
  return;
1185
1708
  }
1186
- const l = this.#r[e.id] || [];
1709
+ const a = this.#s[e.id] || [];
1187
1710
  this.#g({
1188
1711
  nodeId: e.id,
1189
1712
  kind: "collect",
1190
1713
  values: { ...this._cardValues },
1191
- summary: Be(t, this._cardValues, l)
1714
+ summary: Wt(t, this._cardValues, a)
1192
1715
  });
1193
1716
  }
1194
1717
  // ── Gate ────────────────────────────────────────────────────────
1195
- async #E() {
1196
- if (!(this._gate.stage || this.#w)) {
1197
- this.#w = !0;
1718
+ async #T() {
1719
+ if (!(this._gate.stage || this.#x)) {
1720
+ this.#x = !0;
1198
1721
  try {
1199
1722
  const e = await this.client.isAuthenticated();
1200
1723
  this._gate = e ? { stage: "signedin", email: this.client.signedInEmail?.() || "", error: "", loading: !1 } : { stage: "email", email: "", error: "", loading: !1 };
1201
1724
  } finally {
1202
- this.#w = !1;
1725
+ this.#x = !1;
1203
1726
  }
1204
1727
  this._gate.stage === "email" && this.client.onCrossTabLogin && !this.#d && (this.#d = this.client.onCrossTabLogin(() => {
1205
- this.#d?.(), this.#d = null, this._gate = { stage: null, email: "", error: "", loading: !1 }, this.#E();
1728
+ this.#d?.(), this.#d = null, this._gate = { stage: null, email: "", error: "", loading: !1 }, this.#T();
1206
1729
  }));
1207
1730
  }
1208
1731
  }
1209
- async #$() {
1732
+ async #A() {
1210
1733
  const e = this._gate.email.trim();
1211
1734
  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)) {
1212
1735
  this._gate = { ...this._gate, error: "Please enter a valid email address." };
@@ -1214,8 +1737,8 @@ class at extends T {
1214
1737
  }
1215
1738
  this._gate = { ...this._gate, error: "", loading: !0 };
1216
1739
  try {
1217
- const t = await this.client.sendCode(e);
1218
- this._gate = t.authenticated ? { stage: "signedin", email: e, error: "", loading: !1 } : { ...this._gate, stage: "code", loading: !1 };
1740
+ const t = await this.client.sendCode(e), s = !!t.newAccount;
1741
+ this._gate = t.authenticated ? { stage: "signedin", email: e, error: "", loading: !1, newAccount: s } : { ...this._gate, stage: "code", loading: !1, newAccount: s };
1219
1742
  } catch (t) {
1220
1743
  this._gate = {
1221
1744
  ...this._gate,
@@ -1224,10 +1747,10 @@ class at extends T {
1224
1747
  };
1225
1748
  }
1226
1749
  }
1227
- async #S(e) {
1750
+ async #R(e) {
1228
1751
  this._gate = { ...this._gate, error: "", loading: !0 };
1229
1752
  try {
1230
- await this.client.verifyCode(e), this.#A(this._gate.email);
1753
+ await this.client.verifyCode(e), this.#M(this._gate.email);
1231
1754
  } catch (t) {
1232
1755
  this._gate = {
1233
1756
  ...this._gate,
@@ -1236,145 +1759,147 @@ class at extends T {
1236
1759
  };
1237
1760
  }
1238
1761
  }
1239
- #A(e) {
1240
- if (this._gate = { stage: null, email: "", error: "", loading: !1 }, this._submit.stage === "auth") {
1241
- this.#e({ type: "AUTH_OK" }), this._phase = "submitting", this.#n();
1762
+ #M(e) {
1763
+ if (this.#f = !!this._gate.newAccount, this._gate = { stage: null, email: "", error: "", loading: !1 }, this._submit.stage === "auth") {
1764
+ this.#e({ type: "AUTH_OK" }), this._phase = "submitting", this.#a();
1242
1765
  return;
1243
1766
  }
1244
- const { node: t } = this.#v;
1767
+ const { node: t } = this.#_;
1245
1768
  t?.type === "gate" && this.#g({ nodeId: t.id, kind: "gate", email: e });
1246
1769
  }
1247
- #U() {
1248
- this.client.signOut?.(), this._gate = { stage: "email", email: "", error: "", loading: !1 };
1770
+ #Y() {
1771
+ this.client.signOut?.(), this.#f = !1, this._gate = { stage: "email", email: "", error: "", loading: !1 };
1249
1772
  }
1250
1773
  // ── Anonymous route ─────────────────────────────────────────────
1251
- #q() {
1774
+ #G() {
1252
1775
  this._gate = { ...this._gate, stage: "anon-confirm", error: "" };
1253
1776
  }
1254
- #L() {
1777
+ #K() {
1255
1778
  this._gate = { ...this._gate, stage: "email", error: "" };
1256
1779
  }
1257
1780
  /*
1258
1781
  * Records the choice only. The session is minted at submit, against
1259
1782
  * the requestId, so an abandoned form leaves nothing behind.
1260
1783
  */
1261
- #j() {
1262
- const { node: e } = this.#v;
1784
+ #Q() {
1785
+ const { node: e } = this.#_;
1263
1786
  e?.type === "gate" && (this._gate = { stage: null, email: "", error: "", loading: !1 }, this.#g({ nodeId: e.id, kind: "gate", anonymous: !0 }));
1264
1787
  }
1265
- async #C() {
1788
+ async #O() {
1266
1789
  try {
1267
1790
  return await this.client.createAnonSession({
1268
1791
  formId: this._form.formId,
1269
1792
  requestId: this.#t
1270
1793
  }), !0;
1271
1794
  } catch (e) {
1272
- return this._banner = q(e?.status ?? 0, e?.body ?? null), !1;
1795
+ return this._banner = ge(e?.status ?? 0, e?.body ?? null), !1;
1273
1796
  }
1274
1797
  }
1275
1798
  /* An anonymous session outliving the upload run re-mints in place; there
1276
1799
  * is no identity to send back to the sign-in card. */
1277
- async #N() {
1278
- if (await this.#C()) {
1279
- this.#e({ type: "AUTH_OK" }), this._phase = "submitting", this.#n();
1800
+ async #Z() {
1801
+ if (await this.#O()) {
1802
+ this.#e({ type: "AUTH_OK" }), this._phase = "submitting", this.#a();
1280
1803
  return;
1281
1804
  }
1282
1805
  this.#e({ type: "REQUEST_FAIL", error: this._banner });
1283
1806
  }
1284
1807
  // ── Submit pipeline ─────────────────────────────────────────────
1285
- get #m() {
1808
+ get #y() {
1286
1809
  const e = [];
1287
1810
  for (const t of this._steps)
1288
1811
  if (t.kind === "collect")
1289
- for (const s of this.#r[t.nodeId] || [])
1812
+ for (const s of this.#s[t.nodeId] || [])
1290
1813
  e.push(s);
1291
1814
  return e;
1292
1815
  }
1293
1816
  #e(e) {
1294
- this._submit = We(this._submit, e);
1817
+ this._submit = es(this._submit, e);
1295
1818
  }
1296
- async #W() {
1819
+ async #J() {
1297
1820
  this._banner = null;
1298
1821
  for (let e = 0; e < this._steps.length; e++) {
1299
1822
  const t = this._steps[e];
1300
1823
  if (t.kind !== "collect") continue;
1301
- const s = b(this._form, t.nodeId), { ok: i, errors: n } = O(s?.fields || [], t.values), o = (s?.fields || []).find((d) => d.kind === "media");
1824
+ const s = x(this._form, t.nodeId), i = this._steps.slice(0, e + 1).filter((d) => d.kind === "collect").map((d) => d.nodeId), { ok: n, errors: o } = fe(s?.fields || [], t.values, {
1825
+ mediaCount: this.#S(i)
1826
+ }), a = (s?.fields || []).find((d) => d.kind === "media");
1302
1827
  let l = !0;
1303
- if (o) {
1304
- const d = this.#r[t.nodeId] || [], u = C(d, this._form.budget, {
1305
- required: !!o.required
1828
+ if (a) {
1829
+ const d = this.#s[t.nodeId] || [], p = Y(d, this._form.budget, {
1830
+ required: !!a.required
1306
1831
  });
1307
- u.ok || (l = !1, n[o.key] = u.errors[0].message);
1832
+ p.ok || (l = !1, o[a.key] = p.errors[0].message);
1308
1833
  }
1309
- if (!i || !l) {
1310
- this._steps = this._steps.slice(0, e), this._cardValues = { ...t.values }, this._fieldErrors = n, this.#c(), this.#o({ animate: !1 });
1834
+ if (!n || !l) {
1835
+ this._steps = this._steps.slice(0, e), this._cardValues = { ...t.values }, this._fieldErrors = o, this.#o(), this.#i({ animate: !1 });
1311
1836
  return;
1312
1837
  }
1313
1838
  }
1314
- if (this.#t = this.#t || crypto.randomUUID(), this.#c(), this.#f) {
1315
- if (!await this.#C()) return;
1839
+ if (this.#t = this.#t || crypto.randomUUID(), this.#o(), this.#u) {
1840
+ if (!await this.#O()) return;
1316
1841
  } else
1317
1842
  this.client.endAnonSession?.();
1318
- if (this._submit = F(this.#m), this._phase = "submitting", this.#f) {
1319
- this.#e({ type: "START" }), this.#n();
1843
+ if (this._submit = P(this.#y), this._phase = "submitting", this.#u) {
1844
+ this.#e({ type: "START" }), this.#a();
1320
1845
  return;
1321
1846
  }
1322
1847
  if (!await this.client.isAuthenticated()) {
1323
1848
  this.#e({ type: "START" }), this.#e({ type: "AUTH_REQUIRED" }), this._gate = { stage: "email", email: "", error: "", loading: !1 };
1324
1849
  return;
1325
1850
  }
1326
- this.#e({ type: "START" }), this.#n();
1851
+ this.#e({ type: "START" }), this.#a();
1327
1852
  }
1328
- async #n() {
1853
+ async #a() {
1329
1854
  const e = this._submit.stage;
1330
- if (e === "minting") return this.#V();
1331
- if (e === "uploading") return this.#T();
1332
- if (e === "requesting") return this.#K();
1855
+ if (e === "minting") return this.#X();
1856
+ if (e === "uploading") return this.#D();
1857
+ if (e === "requesting") return this.#se();
1333
1858
  }
1334
- async #V() {
1859
+ async #X() {
1335
1860
  try {
1336
- const e = await this.client.createUploads(U({
1861
+ const e = await this.client.createUploads(me({
1337
1862
  formId: this._form.formId,
1338
1863
  requestId: this.#t,
1339
- files: this.#m
1864
+ files: this.#y
1340
1865
  }));
1341
- this.#e({ type: "MINTED", uploads: e }), this.#n();
1866
+ this.#e({ type: "MINTED", uploads: e }), this.#a();
1342
1867
  } catch (e) {
1343
1868
  this.#F(e);
1344
1869
  }
1345
1870
  }
1346
- #T() {
1347
- const e = this._submit.files, t = this.#i.size;
1871
+ #D() {
1872
+ const e = this._submit.files, t = this.#n.size;
1348
1873
  let s = 0;
1349
- for (let i = 0; i < e.length && t + s < Xe; i++)
1350
- e[i].status !== "uploading" || this.#i.has(i) || (s += 1, this.#Y(i));
1874
+ for (let i = 0; i < e.length && t + s < ls; i++)
1875
+ e[i].status !== "uploading" || this.#n.has(i) || (s += 1, this.#ee(i));
1351
1876
  }
1352
- #Y(e) {
1353
- const t = this._submit.files[e], s = this.#m[e], { promise: i, abort: n } = this.client.uploadFile({
1877
+ #ee(e) {
1878
+ const t = this._submit.files[e], s = this.#y[e], { promise: i, abort: n } = this.client.uploadFile({
1354
1879
  url: t.url,
1355
1880
  file: s,
1356
1881
  contentType: t.type,
1357
- onProgress: ({ loaded: o, total: l }) => {
1358
- this.#e({ type: "FILE_PROGRESS", i: e, loaded: o, total: l });
1882
+ onProgress: ({ loaded: o, total: a }) => {
1883
+ this.#e({ type: "FILE_PROGRESS", i: e, loaded: o, total: a });
1359
1884
  }
1360
1885
  });
1361
- this.#i.set(e, { abort: n }), i.then(() => {
1362
- this.#i.delete(e), this.#e({ type: "FILE_DONE", i: e }), this.#n();
1886
+ this.#n.set(e, { abort: n }), i.then(() => {
1887
+ this.#n.delete(e), this.#e({ type: "FILE_DONE", i: e }), this.#a();
1363
1888
  }).catch((o) => {
1364
- this.#i.delete(e), this.#e({
1889
+ this.#n.delete(e), this.#e({
1365
1890
  type: "FILE_FAIL",
1366
1891
  i: e,
1367
1892
  error: o?.status === 403 ? "expired" : "failed"
1368
1893
  });
1369
1894
  });
1370
1895
  }
1371
- async #H(e) {
1896
+ async #te(e) {
1372
1897
  if (this._submit.files[e].error === "expired")
1373
1898
  try {
1374
- const [s] = await this.client.createUploads(U({
1899
+ const [s] = await this.client.createUploads(me({
1375
1900
  formId: this._form.formId,
1376
1901
  requestId: this.#t,
1377
- files: [this.#m[e]]
1902
+ files: [this.#y[e]]
1378
1903
  }));
1379
1904
  this.#e({ type: "REMINT_FILE", i: e, upload: s });
1380
1905
  } catch (s) {
@@ -1383,37 +1908,55 @@ class at extends T {
1383
1908
  }
1384
1909
  else
1385
1910
  this.#e({ type: "RETRY_FILE", i: e });
1386
- this.#T();
1911
+ this.#D();
1387
1912
  }
1388
- async #K() {
1913
+ async #se() {
1389
1914
  try {
1390
- const e = this._submit.files.map(({ assetId: s, type: i }) => ({ assetId: s, type: i })), t = await this.client.putRequest(this.#t, Te({
1915
+ const e = this._submit.files.map(({ assetId: s, type: i }) => ({ assetId: s, type: i })), t = await this.client.putRequest(this.#t, Ut({
1391
1916
  form: this._form,
1392
1917
  steps: this._steps,
1393
1918
  media: e
1394
1919
  }));
1395
- this.#e({ type: "REQUEST_OK", result: t }), this._result = t, j(this.#h), this.client.endAnonSession?.(), this._phase = "done";
1920
+ this.#e({ type: "REQUEST_OK", result: t }), this._result = t, be(this.#m), this.client.endAnonSession?.(), this.#re(), this._phase = "done";
1396
1921
  } catch (e) {
1397
1922
  this.#F(e);
1398
1923
  }
1399
1924
  }
1925
+ // ── Save to My WRAL (new accounts only) ─────────────────────────
1926
+ #re() {
1927
+ if (!this.#f || this.#u || !this.client.saveUserFacts) return;
1928
+ this.#f = !1;
1929
+ const e = wt(Ae(this._form, this._steps), Fe(this._steps));
1930
+ e.length && (this._factsOffer = { stage: "offer", facts: e });
1931
+ }
1932
+ async #ie() {
1933
+ const e = this._factsOffer;
1934
+ if (!(!e || e.stage === "saving")) {
1935
+ this._factsOffer = { ...e, stage: "saving" };
1936
+ try {
1937
+ await this.client.saveUserFacts(e.facts), this._factsOffer = { ...e, stage: "saved" };
1938
+ } catch {
1939
+ this._factsOffer = { ...e, stage: "error" };
1940
+ }
1941
+ }
1942
+ }
1400
1943
  #F(e) {
1401
- const t = q(e?.status ?? 0, e?.body ?? null);
1944
+ const t = ge(e?.status ?? 0, e?.body ?? null);
1402
1945
  if (t.kind === "auth") {
1403
- if (this.#e({ type: "AUTH_REQUIRED" }), this.#f) {
1404
- this.#N();
1946
+ if (this.#e({ type: "AUTH_REQUIRED" }), this.#u) {
1947
+ this.#Z();
1405
1948
  return;
1406
1949
  }
1407
1950
  this._gate = { stage: "email", email: "", error: "", loading: !1 };
1408
1951
  return;
1409
1952
  }
1410
1953
  if (t.kind === "stale") {
1411
- this._banner = t, this.#e({ type: "REQUEST_FAIL", error: t }), this.#Q();
1954
+ this._banner = t, this.#e({ type: "REQUEST_FAIL", error: t }), this.#ne();
1412
1955
  return;
1413
1956
  }
1414
1957
  this._banner = t, this.#e({ type: "REQUEST_FAIL", error: t });
1415
1958
  }
1416
- async #Q() {
1959
+ async #ne() {
1417
1960
  try {
1418
1961
  this._forms = await this.client.listForms();
1419
1962
  const e = this._forms.find((t) => t.formId === this._form.formId);
@@ -1421,177 +1964,206 @@ class at extends T {
1421
1964
  } catch {
1422
1965
  }
1423
1966
  }
1424
- #G() {
1425
- this._banner = null, this.#e({ type: "REQUEST_START" }), this.#n();
1967
+ #oe() {
1968
+ this._banner = null, this.#e({ type: "REQUEST_START" }), this.#a();
1426
1969
  }
1427
1970
  // ── Render ──────────────────────────────────────────────────────
1428
1971
  render() {
1429
- return a`
1972
+ return c`
1430
1973
  <div class="chat" aria-live="polite">
1431
- ${this.#J()}
1974
+ ${this.#ae()}
1432
1975
  </div>
1433
- ${this.#ce()}
1976
+ ${this.#$e()}
1434
1977
  `;
1435
1978
  }
1436
- #J() {
1979
+ #ae() {
1437
1980
  switch (this._phase) {
1438
1981
  case "loading":
1439
- return a`${h(S, this._loadingSlow ? "Loading the form list…" : A)}
1440
- ${E()}`;
1982
+ return c`${g(W, this._loadingSlow ? "Loading the form list…" : V)}
1983
+ ${j()}`;
1441
1984
  case "load-error":
1442
- return a`
1443
- ${h("We could not load the forms.", "Check your connection and try again.", { error: !0 })}
1985
+ return c`
1986
+ ${g("We could not load the forms.", "Check your connection and try again.", { error: !0 })}
1444
1987
  <div class="options">
1445
- <button type="button" class="chip" @click=${() => this.#x()}>Try again</button>
1988
+ <button type="button" class="chip" @click=${() => this.#v()}>Try again</button>
1446
1989
  </div>
1447
1990
  `;
1448
1991
  case "pick":
1449
- return this.#X();
1992
+ return this.#le();
1450
1993
  case "walk":
1451
- return a`${this.#b()}${this._typing ? E() : this.#Z()}`;
1994
+ return c`${this.#b()}${this._typing ? j() : this.#ce()}`;
1452
1995
  case "review":
1453
- return a`${this.#b()}${this.#D()}`;
1996
+ return c`${this.#b()}${this.#N()}`;
1454
1997
  case "submitting":
1455
- return a`${this.#b()}${this.#le()}`;
1998
+ return c`${this.#b()}${this.#be()}`;
1456
1999
  case "done":
1457
- return a`${this.#b()}${this.#de()}`;
2000
+ return c`${this.#b()}${this.#xe ? this.#_e() : c`${this.#ve()}${this.#we()}`}`;
1458
2001
  default:
1459
- return c;
2002
+ return h;
1460
2003
  }
1461
2004
  }
1462
- #X() {
1463
- const e = this._forms;
1464
- return a`
1465
- ${h(S, A, { noAnim: !0 })}
1466
- <div class="options" role="group" aria-label="What would you like to send us?">
1467
- ${e.map((t, s) => a`
2005
+ #le() {
2006
+ const e = this._forms.filter((t) => t.listed !== !1);
2007
+ return c`
2008
+ ${g(W, V, { noAnim: !0 })}
2009
+ <div class="options" role="group" aria-label=${Te}>
2010
+ ${e.map((t, s) => c`
1468
2011
  <button type="button" class="chip" style="animation-delay: ${60 + s * 50}ms"
1469
- @click=${() => this.#P(t)}>${t.title}</button>
2012
+ @click=${() => this.#E(t)}>${t.title}</button>
1470
2013
  `)}
1471
2014
  </div>
1472
2015
  `;
1473
2016
  }
2017
+ /*
2018
+ * One conversation across hand-offs: the entry choice is the first
2019
+ * form's title, each origin replays its steps and the hand-off option
2020
+ * the viewer picked, and preset steps read as the viewer's own answers
2021
+ * (minus one that merely repeats the hand-off option).
2022
+ */
1474
2023
  #b() {
1475
2024
  const e = [];
1476
- this._form && (e.push(h(S, A, { noAnim: !0 })), e.push($(this._form.title, { noAnim: !0 }))), this._notice && e.push(h(this._notice, "", { noAnim: !0 }));
1477
- for (const t of this._steps) {
1478
- const s = b(this._form, t.nodeId);
1479
- s?.prompt && e.push(h(s.prompt, s.help, { noAnim: !0 })), s?.type === "gate" && e.push(t.anonymous ? h(
2025
+ if (!this._form) return e;
2026
+ const t = this._origins[0]?.form || this._form;
2027
+ e.push(g(W, V, { noAnim: !0 })), e.push(v(t.title, { noAnim: !0 })), this._notice && e.push(g(this._notice, "", { noAnim: !0 }));
2028
+ let s = null;
2029
+ for (const i of this._origins) {
2030
+ e.push(...this.#P(i.form, i.steps, s));
2031
+ const n = x(i.form, i.option.nodeId);
2032
+ n?.prompt && e.push(g(n.prompt, n.help, { noAnim: !0 })), s = i.option.label || i.option.optionId, e.push(v(s, { noAnim: !0 }));
2033
+ }
2034
+ return e.push(...this.#P(this._form, this._steps, s)), e;
2035
+ }
2036
+ #P(e, t, s = null) {
2037
+ const i = [];
2038
+ for (const n of t) {
2039
+ if (n.preset) {
2040
+ const a = n.label || n.optionId;
2041
+ a !== s && i.push(v(a, { noAnim: !0 }));
2042
+ continue;
2043
+ }
2044
+ const o = x(e, n.nodeId);
2045
+ o?.prompt && i.push(g(o.prompt, o.help, { noAnim: !0 })), o?.type === "gate" && i.push(n.anonymous ? g(
1480
2046
  "Last step: how can we reach you?",
1481
2047
  "You chose to send this anonymously.",
1482
2048
  { noAnim: !0 }
1483
- ) : h(
1484
- "Last step: verify your email so we can follow up.",
2049
+ ) : g(
2050
+ "Almost done: verify your email so we can follow up.",
1485
2051
  "One address, one code. No password needed.",
1486
2052
  { noAnim: !0 }
1487
- )), t.kind === "choice" && e.push($(t.label || t.optionId, { noAnim: !0 })), t.kind === "collect" && e.push($(t.summary || "Details provided", { noAnim: !0 })), t.kind === "gate" && e.push($(t.anonymous ? "Send anonymously" : t.email, { noAnim: !0 }));
2053
+ )), n.kind === "choice" && i.push(v(n.label || n.optionId, { noAnim: !0 })), n.kind === "collect" && i.push(v(n.summary || "Details provided", { noAnim: !0 })), n.kind === "gate" && i.push(v(n.anonymous ? "Send anonymously" : n.email, { noAnim: !0 }));
1488
2054
  }
1489
- return e;
2055
+ return i;
1490
2056
  }
1491
- #Z() {
1492
- const { node: e, error: t } = this.#v;
1493
- return t || !e ? h("Something went sideways with this form.", "Please start over.", { error: !0 }) : e.type === "choice" ? this.#ee(e) : e.type === "collect" ? this.#te(e) : e.type === "gate" ? this.#R(e) : e.type === "redirect" ? this.#oe(e) : e.type === "terminal" ? this.#D() : c;
2057
+ #ce() {
2058
+ const { node: e, error: t } = this.#_;
2059
+ return t || !e ? g("Something went sideways with this form.", "Please start over.", { error: !0 }) : e.type === "choice" ? this.#de(e) : e.type === "collect" ? this.#ue(e) : e.type === "gate" ? this.#z(e) : e.type === "redirect" ? this.#ye(e) : e.type === "terminal" ? this.#N() : h;
1494
2060
  }
1495
- #ee(e) {
1496
- return a`
1497
- ${h(e.prompt, e.help)}
2061
+ #de(e) {
2062
+ return c`
2063
+ ${g(e.prompt, e.help)}
2064
+ ${this._handoffError ? g("We could not load the forms.", "Check your connection and try again.", { error: !0 }) : h}
1498
2065
  <div class="options" role="group" aria-label=${e.prompt || "Choose one"}>
1499
- ${(e.options || []).map((t, s) => a`
2066
+ ${(e.options || []).map((t, s) => c`
1500
2067
  <button type="button" class="chip" style="animation-delay: ${60 + s * 50}ms"
1501
- @click=${() => this.#g({
1502
- nodeId: e.id,
1503
- kind: "choice",
1504
- optionId: t.id,
1505
- label: t.label
1506
- })}>${t.label}</button>
2068
+ @click=${() => this.#q(e, t)}>${t.label}</button>
1507
2069
  `)}
1508
2070
  </div>
1509
2071
  `;
1510
2072
  }
1511
- #te(e) {
2073
+ /*
2074
+ * A real <form>, so browsers offer the viewer's saved name, phone and
2075
+ * address for the autocomplete-tagged fields, and Enter continues.
2076
+ * novalidate: the card validates itself (native url checks would
2077
+ * otherwise block the submit silently).
2078
+ */
2079
+ #ue(e) {
1512
2080
  const t = e.fields || [];
1513
- return a`
1514
- ${h(e.prompt, e.help)}
1515
- <div class="form-card">
1516
- ${t.map((s) => this.#re(e, s))}
1517
- <button type="button" class="btn-primary" @click=${() => this.#O(e)}>
1518
- Continue
1519
- </button>
1520
- </div>
2081
+ return c`
2082
+ ${g(e.prompt, e.help)}
2083
+ <form class="form-card" autocomplete="on" novalidate
2084
+ @submit=${(s) => {
2085
+ s.preventDefault(), this.#V(e);
2086
+ }}>
2087
+ ${t.map((s) => this.#pe(e, s))}
2088
+ <button type="submit" class="btn-primary">Continue</button>
2089
+ </form>
1521
2090
  `;
1522
2091
  }
1523
- #re(e, t) {
1524
- const s = this._cardValues[t.key], i = this._fieldErrors[t.key], n = !t.required && t.kind !== "consent" ? a` <span class="opt">optional</span>` : c, o = t.kind === "consent" ? c : a`
1525
- <label for="f-${t.key}">${t.label}${n}</label>
2092
+ #pe(e, t) {
2093
+ const s = this.#C(e.id);
2094
+ if (t.kind === "consent" && t.requiredIf === "media" && s === 0)
2095
+ return h;
2096
+ const i = this._cardValues[t.key], n = this._fieldErrors[t.key], o = !Se(t, { mediaCount: s }) && t.kind !== "consent" ? c` <span class="opt">optional</span>` : h, a = t.kind === "consent" ? h : c`
2097
+ <label for="f-${t.key}">${t.label}${o}</label>
1526
2098
  `;
1527
- return a`
2099
+ return c`
1528
2100
  <div class="field">
1529
- ${o}
1530
- ${this.#se(e, t, s)}
1531
- ${i ? a`<div class="err" role="alert">${i}</div>` : c}
2101
+ ${a}
2102
+ ${this.#he(e, t, i)}
2103
+ ${n ? c`<div class="err" role="alert">${n}</div>` : h}
1532
2104
  </div>
1533
2105
  `;
1534
2106
  }
1535
- #se(e, t, s) {
1536
- const i = (n) => (o) => this.#_(n, o.target.value);
2107
+ #he(e, t, s) {
2108
+ const i = (n) => (o) => this.#k(n, o.target.value);
1537
2109
  switch (t.kind) {
1538
2110
  case "text":
1539
- return a`<input type="text" id="f-${t.key}" .value=${s || ""}
2111
+ return c`<input type="text" id="f-${t.key}" name=${t.key} .value=${s || ""}
2112
+ inputmode=${ce(t.inputMode)} autocomplete=${ce(t.autocomplete)}
1540
2113
  placeholder=${t.placeholder || ""} @input=${i(t.key)}>`;
1541
2114
  case "url":
1542
- return a`<input type="url" id="f-${t.key}" .value=${s || ""}
2115
+ return c`<input type="url" id="f-${t.key}" .value=${s || ""}
1543
2116
  placeholder=${t.placeholder || ""} @input=${i(t.key)}>`;
1544
2117
  case "textarea":
1545
- return a`<textarea id="f-${t.key}" .value=${s || ""}
2118
+ return c`<textarea id="f-${t.key}" .value=${s || ""}
1546
2119
  placeholder=${t.placeholder || ""} @input=${i(t.key)}></textarea>`;
1547
2120
  case "datetime":
1548
- return a`<input type="datetime-local" id="f-${t.key}" .value=${s || ""}
2121
+ return c`<input type="datetime-local" id="f-${t.key}" .value=${s || ""}
1549
2122
  @input=${i(t.key)}>`;
1550
2123
  case "select":
1551
- return a`
2124
+ return c`
1552
2125
  <select id="f-${t.key}" @change=${i(t.key)}>
1553
2126
  <option value="">Choose one</option>
1554
- ${(t.options || []).map((n) => a`
2127
+ ${(t.options || []).map((n) => c`
1555
2128
  <option value=${n.id} ?selected=${s === n.id}>${n.label}</option>
1556
2129
  `)}
1557
2130
  </select>
1558
2131
  `;
1559
2132
  case "location":
1560
- return this.#ie(t, s || {});
2133
+ return this.#fe(t, s || {});
1561
2134
  case "consent":
1562
- return a`
2135
+ return c`
1563
2136
  <div class="consent-row">
1564
2137
  <input type="checkbox" id="f-${t.key}" .checked=${s === !0}
1565
- @change=${(n) => this.#_(t.key, n.target.checked)}>
2138
+ @change=${(n) => this.#k(t.key, n.target.checked)}>
1566
2139
  <label for="f-${t.key}" style="all: unset; cursor: pointer;">
1567
- I took or own this material and give WRAL permission to use it
1568
- on air and online with credit to me.
2140
+ ${t.text || ds}
1569
2141
  </label>
1570
2142
  </div>
1571
2143
  `;
1572
2144
  case "media":
1573
- return a`
2145
+ return c`
1574
2146
  <wral-report-media
1575
- .files=${this.#r[e.id] || []}
1576
- .lostMeta=${this.#s[e.id] || []}
2147
+ .files=${this.#s[e.id] || []}
2148
+ .lostMeta=${this.#r[e.id] || []}
1577
2149
  .budget=${this._form.budget || {}}
1578
2150
  ?required=${!!t.required}
1579
2151
  label=${t.label}
1580
2152
  @files-changed=${(n) => {
1581
- this.#r = { ...this.#r, [e.id]: n.detail.files }, this.requestUpdate();
2153
+ this.#s = { ...this.#s, [e.id]: n.detail.files }, this.requestUpdate();
1582
2154
  }}></wral-report-media>
1583
2155
  `;
1584
2156
  default:
1585
- return c;
2157
+ return h;
1586
2158
  }
1587
2159
  }
1588
- #ie(e, t) {
1589
- const s = e.counties || Ye, i = (n) => this.#_(e.key, { ...t, ...n });
1590
- return a`
2160
+ #fe(e, t) {
2161
+ const s = e.counties || ss, i = (n) => this.#k(e.key, { ...t, ...n });
2162
+ return c`
1591
2163
  <select id="f-${e.key}" aria-label="County"
1592
2164
  @change=${(n) => i({ county: n.target.value || void 0 })}>
1593
2165
  <option value="">Choose a county</option>
1594
- ${s.map((n) => a`
2166
+ ${s.map((n) => c`
1595
2167
  <option value=${n} ?selected=${t.county === n}>${n}</option>
1596
2168
  `)}
1597
2169
  </select>
@@ -1602,24 +2174,24 @@ class at extends T {
1602
2174
  @input=${(n) => i({ where: n.target.value || void 0 })}>
1603
2175
  `;
1604
2176
  }
1605
- #R(e) {
1606
- this.#E();
1607
- const t = this._gate, s = h(
1608
- "Last step: verify your email so we can follow up.",
2177
+ #z(e) {
2178
+ this.#T();
2179
+ const t = this._gate, s = g(
2180
+ "Almost done: verify your email so we can follow up.",
1609
2181
  "One address, one code. No password needed."
1610
2182
  );
1611
- return t.stage ? t.stage === "signedin" ? a`
2183
+ return t.stage ? t.stage === "signedin" ? c`
1612
2184
  ${s}
1613
2185
  <div class="form-card">
1614
2186
  <p style="margin: 0 0 12px; font-size: 14.5px;">
1615
2187
  You are signed in as <strong>${t.email || "your My WRAL account"}</strong> on this device.
1616
2188
  </p>
1617
2189
  <button type="button" class="btn-primary"
1618
- @click=${() => this.#A(t.email)}>Continue</button>
2190
+ @click=${() => this.#M(t.email)}>Continue</button>
1619
2191
  <button type="button" class="btn-ghost"
1620
- @click=${() => this.#U()}>Use a different email</button>
2192
+ @click=${() => this.#Y()}>Use a different email</button>
1621
2193
  </div>
1622
- ` : t.stage === "email" ? a`
2194
+ ` : t.stage === "email" ? c`
1623
2195
  ${s}
1624
2196
  <div class="form-card login-card">
1625
2197
  <h2>Sign in or create account</h2>
@@ -1634,12 +2206,12 @@ class at extends T {
1634
2206
  this._gate = { ...t, email: i.target.value };
1635
2207
  }}
1636
2208
  @keydown=${(i) => {
1637
- i.key === "Enter" && this.#$();
2209
+ i.key === "Enter" && this.#A();
1638
2210
  }}>
1639
2211
  </div>
1640
- ${t.error ? a`<div class="err" role="alert">${t.error}</div>` : c}
2212
+ ${t.error ? c`<div class="err" role="alert">${t.error}</div>` : h}
1641
2213
  <button type="button" class="login-btn" ?disabled=${t.loading}
1642
- @click=${() => this.#$()}>
2214
+ @click=${() => this.#A()}>
1643
2215
  ${t.loading ? "Sending…" : "Continue with email"}
1644
2216
  </button>
1645
2217
  <div class="login-why">
@@ -1648,12 +2220,12 @@ class at extends T {
1648
2220
  <li>We can follow up on your report</li>
1649
2221
  <li>Your contact information fills in automatically next time</li>
1650
2222
  <li>You are credited by name when we use your photos or video</li>
1651
- <li><a href=${He} target="_blank" rel="noopener">All other My WRAL account benefits</a></li>
2223
+ <li><a href=${rs} target="_blank" rel="noopener">All other My WRAL account benefits</a></li>
1652
2224
  </ul>
1653
2225
  </div>
1654
- ${this._submit.stage === "auth" ? c : this.#ne()}
2226
+ ${this._submit.stage === "auth" ? h : this.#me()}
1655
2227
  </div>
1656
- ` : t.stage === "anon-confirm" ? this.#ae(s) : a`
2228
+ ` : t.stage === "anon-confirm" ? this.#ge(s) : c`
1657
2229
  ${s}
1658
2230
  <div class="form-card login-card">
1659
2231
  <h2>Enter verification code</h2>
@@ -1667,48 +2239,48 @@ class at extends T {
1667
2239
  <div class="field">
1668
2240
  <label>Verification code</label>
1669
2241
  <wral-code-input
1670
- @code-complete=${(i) => this.#S(i.detail?.code ?? i.detail?.value ?? i.target.value)}>
2242
+ @code-complete=${(i) => this.#R(i.detail?.code ?? i.detail?.value ?? i.target.value)}>
1671
2243
  </wral-code-input>
1672
2244
  </div>
1673
- ${t.error ? a`<div class="err" role="alert">${t.error}</div>` : c}
2245
+ ${t.error ? c`<div class="err" role="alert">${t.error}</div>` : h}
1674
2246
  <button type="button" class="login-btn" ?disabled=${t.loading}
1675
2247
  @click=${() => {
1676
2248
  const i = this.renderRoot.querySelector("wral-code-input");
1677
- this.#S(i?.value || "");
2249
+ this.#R(i?.value || "");
1678
2250
  }}>
1679
2251
  ${t.loading ? "Checking…" : "Sign in"}
1680
2252
  </button>
1681
2253
  <p class="login-help">
1682
2254
  Didn’t receive a code? Check your spam folder or
1683
- <button type="button" @click=${() => this.#$()}>resend a new code</button>.
2255
+ <button type="button" @click=${() => this.#A()}>resend a new code</button>.
1684
2256
  </p>
1685
2257
  </div>
1686
- ` : a`${s}${E()}`;
2258
+ ` : c`${s}${j()}`;
1687
2259
  }
1688
2260
  /* Collapsed by default: findable for whoever needs it, never the
1689
2261
  * first thing a viewer reaches for. */
1690
- #ne() {
1691
- return a`
2262
+ #me() {
2263
+ return c`
1692
2264
  <details class="login-alt">
1693
2265
  <summary>Other ways to send this</summary>
1694
2266
  <div class="alt-body">
1695
2267
  <p class="alt-row">
1696
2268
  Call the newsroom desk at
1697
- <a href=${Qe(W)}>${W}</a>.
2269
+ <a href=${ns(xe)}>${xe}</a>.
1698
2270
  </p>
1699
- ${this.#B ? a`
2271
+ ${this.#L ? c`
1700
2272
  <p class="alt-row">
1701
2273
  <button type="button" class="alt-link"
1702
- @click=${() => this.#q()}>Send this anonymously</button>
2274
+ @click=${() => this.#G()}>Send this anonymously</button>
1703
2275
  — no follow-up, and no credit if we use your photos or video.
1704
2276
  </p>
1705
- ` : c}
2277
+ ` : h}
1706
2278
  </div>
1707
2279
  </details>
1708
2280
  `;
1709
2281
  }
1710
- #ae(e) {
1711
- return a`
2282
+ #ge(e) {
2283
+ return c`
1712
2284
  ${e}
1713
2285
  <div class="form-card login-card">
1714
2286
  <h2>Before you send anonymously</h2>
@@ -1716,22 +2288,22 @@ class at extends T {
1716
2288
  You can send this report without an account. Here is what it costs you.
1717
2289
  </p>
1718
2290
  <ul class="anon-costs">
1719
- ${Ke.map((t) => a`
2291
+ ${is.map((t) => c`
1720
2292
  <li><span class="x" aria-hidden="true">✕</span><span>${t}</span></li>
1721
2293
  `)}
1722
2294
  </ul>
1723
2295
  <div class="anon-actions">
1724
2296
  <button type="button" class="login-btn"
1725
- @click=${() => this.#L()}>Sign in instead</button>
2297
+ @click=${() => this.#K()}>Sign in instead</button>
1726
2298
  <button type="button" class="btn-ghost"
1727
- @click=${() => this.#j()}>Continue anonymously</button>
2299
+ @click=${() => this.#Q()}>Continue anonymously</button>
1728
2300
  </div>
1729
2301
  </div>
1730
2302
  `;
1731
2303
  }
1732
- #oe(e) {
2304
+ #ye(e) {
1733
2305
  const t = e.redirect || {};
1734
- return a`
2306
+ return c`
1735
2307
  <div class="form-card">
1736
2308
  <p style="margin: 0 0 6px; font-weight: 600; font-size: 16px;
1737
2309
  color: var(--wral-base-primary-1, #001D68);
@@ -1748,33 +2320,33 @@ class at extends T {
1748
2320
  </div>
1749
2321
  `;
1750
2322
  }
1751
- #D() {
1752
- const e = Pe(this._form, this._steps);
1753
- return a`
1754
- ${h("Here is what you are sending.", "Check it over, then submit.")}
2323
+ #N() {
2324
+ const e = Vt(this._form, this._steps);
2325
+ return c`
2326
+ ${g("Here is what you are sending.", "Check it over, then submit.")}
1755
2327
  <div class="form-card">
1756
2328
  <ul class="review-list">
1757
- ${e.map((t) => a`
2329
+ ${e.map((t) => c`
1758
2330
  <li>
1759
2331
  <span class="k">${t.k}</span>
1760
- <span>${t.pill ? be(t.pill) : t.v}</span>
2332
+ <span>${t.pill ? at(t.pill) : t.v}</span>
1761
2333
  </li>
1762
2334
  `)}
1763
2335
  </ul>
1764
- ${this._banner ? a`
2336
+ ${this._banner ? c`
1765
2337
  <div class="err" role="alert" style="margin-top: 12px;">${this._banner.message}</div>
1766
- ` : c}
2338
+ ` : h}
1767
2339
  <div style="margin-top: 16px;">
1768
- <button type="button" class="btn-primary" @click=${() => this.#W()}>
2340
+ <button type="button" class="btn-primary" @click=${() => this.#J()}>
1769
2341
  Submit report
1770
2342
  </button>
1771
2343
  </div>
1772
2344
  </div>
1773
2345
  `;
1774
2346
  }
1775
- #le() {
2347
+ #be() {
1776
2348
  const e = this._submit;
1777
- if (e.stage === "auth") return this.#R({ id: null, type: "gate" });
2349
+ if (e.stage === "auth") return this.#z({ id: null, type: "gate" });
1778
2350
  const t = {
1779
2351
  minting: "Preparing your uploads…",
1780
2352
  uploading: "Uploading your files…",
@@ -1782,10 +2354,10 @@ class at extends T {
1782
2354
  requesting: "Sending your report…",
1783
2355
  "requesting-error": this._banner?.message || "We could not send your report."
1784
2356
  }[e.stage] || "Working…";
1785
- return a`
1786
- ${h("Submitting your report.", t)}
2357
+ return c`
2358
+ ${g("Submitting your report.", t)}
1787
2359
  <div class="form-card">
1788
- ${e.files.map((s, i) => a`
2360
+ ${e.files.map((s, i) => c`
1789
2361
  <div class="upload-row">
1790
2362
  <span class="name">${s.name}</span>
1791
2363
  <div class="upload-bar" role="progressbar"
@@ -1796,63 +2368,67 @@ class at extends T {
1796
2368
  <span class="state ${s.status === "failed" ? "failed" : ""}">
1797
2369
  ${s.status === "done" ? "Done" : s.status === "failed" ? "Failed" : "Uploading"}
1798
2370
  </span>
1799
- ${s.status === "failed" ? a`
1800
- <button type="button" class="retry-chip" @click=${() => this.#H(i)}>
2371
+ ${s.status === "failed" ? c`
2372
+ <button type="button" class="retry-chip" @click=${() => this.#te(i)}>
1801
2373
  Retry
1802
2374
  </button>
1803
- ` : c}
2375
+ ` : h}
1804
2376
  </div>
1805
2377
  `)}
1806
- ${e.stage === "requesting-error" ? a`
2378
+ ${e.stage === "requesting-error" ? c`
1807
2379
  <div class="err" role="alert">${this._banner?.message || ""}</div>
1808
- ${this._banner?.retryAfter ? a`
2380
+ ${this._banner?.retryAfter ? c`
1809
2381
  <div class="file-note">You can try again in about
1810
2382
  ${Math.ceil(this._banner.retryAfter / 60)} minutes.</div>
1811
- ` : c}
2383
+ ` : h}
1812
2384
  <button type="button" class="btn-primary" style="margin-top: 8px;"
1813
- @click=${() => this.#G()}>Try again</button>
1814
- ` : c}
1815
- ${N(e).length && e.stage === "uploading-error" ? a`
2385
+ @click=${() => this.#oe()}>Try again</button>
2386
+ ` : h}
2387
+ ${we(e).length && e.stage === "uploading-error" ? c`
1816
2388
  <div class="err" role="alert">Retry the failed
1817
- ${N(e).length === 1 ? "file" : "files"} to continue.</div>
1818
- ` : c}
2389
+ ${we(e).length === 1 ? "file" : "files"} to continue.</div>
2390
+ ` : h}
1819
2391
  </div>
1820
2392
  `;
1821
2393
  }
1822
- #de() {
1823
- const e = Y(this._form, this._steps), t = Me(this._result, e), s = Ue({
2394
+ #we() {
2395
+ const e = Ie(this._form, this._steps), t = Yt(this._result, e), s = Kt({
1824
2396
  routing: this._result?.routing || {},
1825
2397
  flags: e,
1826
2398
  reference: this._result?.reference || "",
1827
- anonymous: this.#f
2399
+ anonymous: this.#u
1828
2400
  });
1829
- return a`
2401
+ return c`
1830
2402
  <div class="confirm-card">
1831
2403
  <div class="c-head">
1832
- <div class="c-check">${ye()}</div>
2404
+ <div class="c-check">${lt()}</div>
1833
2405
  <div>
1834
2406
  <div class="eyebrow">Report received</div>
1835
2407
  <h2>${t.title}</h2>
1836
2408
  </div>
1837
2409
  </div>
1838
2410
  <p>${t.body}</p>
1839
- ${t.urgentNote ? a`<p>${t.urgentNote}</p>` : c}
2411
+ ${t.urgentNote ? c`<p>${t.urgentNote}</p>` : h}
2412
+ ${this._factsOffer?.stage === "saved" ? c`
2413
+ <p role="status">Your ${this.#B} ${this._factsOffer.facts.length === 1 ? "is" : "are"}
2414
+ saved to your My WRAL account.</p>
2415
+ ` : h}
1840
2416
  <div class="refs">
1841
2417
  <span class="ref"><span class="rk">Reference</span>${this._result?.reference || ""}</span>
1842
2418
  </div>
1843
- <button type="button" class="c-again" @click=${() => this.#k()}>
2419
+ <button type="button" class="c-again" @click=${() => this.#$()}>
1844
2420
  Start a new report
1845
2421
  </button>
1846
2422
  </div>
1847
2423
  <div class="journey">
1848
2424
  <div class="j-eyebrow">Behind the scenes</div>
1849
2425
  <div class="j-title">What happens to your report now</div>
1850
- ${s.map((i, n) => a`
2426
+ ${s.map((i, n) => c`
1851
2427
  <div class="j-step">
1852
2428
  <div class="j-dot">${n + 1}</div>
1853
2429
  <div class="j-body">
1854
2430
  <div class="j-t">${i.title}
1855
- ${i.pill ? a` <span class="flag-pill urgent">${i.pill}</span>` : c}
2431
+ ${i.pill ? c` <span class="flag-pill urgent">${i.pill}</span>` : h}
1856
2432
  </div>
1857
2433
  <div class="j-d">${i.body}</div>
1858
2434
  </div>
@@ -1861,15 +2437,59 @@ class at extends T {
1861
2437
  </div>
1862
2438
  `;
1863
2439
  }
1864
- #ce() {
2440
+ /* The offer is a step of its own: the confirmation waits for Save or No thanks. */
2441
+ get #xe() {
2442
+ return ["offer", "saving", "error"].includes(this._factsOffer?.stage);
2443
+ }
2444
+ get #B() {
2445
+ return (this._factsOffer?.facts || []).map((e) => e.label.toLowerCase()).join(" and ");
2446
+ }
2447
+ #ve() {
2448
+ const e = this._factsOffer?.stage;
2449
+ return e === "saved" ? v("Save to my account", { noAnim: !0 }) : e === "dismissed" ? v("No thanks", { noAnim: !0 }) : h;
2450
+ }
2451
+ #_e() {
2452
+ const e = this._factsOffer, t = e.stage === "saving";
2453
+ return c`
2454
+ ${g(
2455
+ `One more step: save your ${this.#B} to your new My WRAL account?`,
2456
+ "Only what is listed here is saved."
2457
+ )}
2458
+ <div class="form-card facts-offer">
2459
+ <dl>
2460
+ ${e.facts.map((s) => c`<dt>${s.label}</dt><dd>${s.value}</dd>`)}
2461
+ </dl>
2462
+ <p class="facts-note">
2463
+ ${ct()}
2464
+ <span>${e.facts.length === 1 ? "This is saved to your My WRAL dashboard, where you can change it anytime." : "These are saved to your My WRAL dashboard, where you can change them anytime."}</span>
2465
+ </p>
2466
+ ${e.stage === "error" ? c`
2467
+ <div class="err" role="alert">We couldn't save these. Please try again.</div>
2468
+ ` : h}
2469
+ <div class="actions">
2470
+ <button type="button" class="btn-primary" ?disabled=${t}
2471
+ @click=${() => this.#ie()}>
2472
+ ${t ? "Saving…" : e.stage === "error" ? "Try again" : "Save to my account"}
2473
+ </button>
2474
+ <button type="button" class="btn-ghost" ?disabled=${t}
2475
+ @click=${() => {
2476
+ this._factsOffer = { ...e, stage: "dismissed" };
2477
+ }}>
2478
+ No thanks
2479
+ </button>
2480
+ </div>
2481
+ </div>
2482
+ `;
2483
+ }
2484
+ #$e() {
1865
2485
  const e = this._phase === "submitting" || this._phase === "done" || this._phase === "loading" || this._phase === "load-error";
1866
- return a`
2486
+ return c`
1867
2487
  <div class="bottom-bar">
1868
2488
  <div class="inner">
1869
2489
  <button type="button" class="btn-ghost" ?disabled=${e || this._phase === "pick"}
1870
- @click=${() => this.#M()}>← Back</button>
2490
+ @click=${() => this.#W()}>← Back</button>
1871
2491
  <button type="button" class="btn-ghost" ?disabled=${this._phase === "submitting"}
1872
- @click=${() => this.#k()}>Start over</button>
2492
+ @click=${() => this.#$()}>Start over</button>
1873
2493
  <span class="note">Your report goes to a person on the right desk.</span>
1874
2494
  </div>
1875
2495
  </div>
@@ -1879,7 +2499,7 @@ class at extends T {
1879
2499
  this.renderRoot?.querySelector(".chat")?.lastElementChild?.scrollIntoView?.({ block: "nearest" });
1880
2500
  }
1881
2501
  }
1882
- class ot extends T {
2502
+ class bs extends G {
1883
2503
  static properties = {
1884
2504
  files: { attribute: !1 },
1885
2505
  lostMeta: { attribute: !1 },
@@ -1887,7 +2507,7 @@ class ot extends T {
1887
2507
  required: { type: Boolean },
1888
2508
  label: { type: String }
1889
2509
  };
1890
- static styles = f`
2510
+ static styles = b`
1891
2511
  :host { display: block; }
1892
2512
  input[type=file] { font-family: inherit; font-size: 14px; }
1893
2513
  .file-list { margin: 8px 0 0; padding: 0; list-style: none; font-size: 13.5px; }
@@ -1909,64 +2529,64 @@ class ot extends T {
1909
2529
  constructor() {
1910
2530
  super(), this.files = [], this.lostMeta = [], this.budget = {}, this.required = !1, this.label = "Photos or video";
1911
2531
  }
1912
- get #l() {
2532
+ get #c() {
1913
2533
  return (this.budget?.allowedTypes || []).join(",");
1914
2534
  }
1915
- #a(e) {
2535
+ #l(e) {
1916
2536
  this.dispatchEvent(new CustomEvent("files-changed", {
1917
2537
  detail: { files: e },
1918
2538
  bubbles: !0,
1919
2539
  composed: !0
1920
2540
  }));
1921
2541
  }
1922
- #u(e) {
2542
+ #p(e) {
1923
2543
  const t = [...e.target.files || []];
1924
- this.#a([...this.files || [], ...t]), e.target.value = "";
2544
+ this.#l([...this.files || [], ...t]), e.target.value = "";
1925
2545
  }
1926
2546
  #t(e) {
1927
2547
  const t = [...this.files];
1928
- t.splice(e, 1), this.#a(t);
2548
+ t.splice(e, 1), this.#l(t);
1929
2549
  }
1930
2550
  render() {
1931
- const e = this.files || [], { errors: t } = C(e, this.budget, { required: !1 });
1932
- return a`
2551
+ const e = this.files || [], { errors: t } = Y(e, this.budget, { required: !1 });
2552
+ return c`
1933
2553
  <input type="file" multiple
1934
- accept=${this.#l || c}
2554
+ accept=${this.#c || h}
1935
2555
  aria-label=${this.label}
1936
- @change=${this.#u}>
1937
- ${e.length ? a`
2556
+ @change=${this.#p}>
2557
+ ${e.length ? c`
1938
2558
  <ul class="file-list">
1939
- ${e.map((s, i) => a`
2559
+ ${e.map((s, i) => c`
1940
2560
  <li>
1941
2561
  <span>${s.name}</span>
1942
- <span class="size">${et(s.size)}</span>
2562
+ <span class="size">${us(s.size)}</span>
1943
2563
  <button type="button" class="remove"
1944
2564
  aria-label="Remove ${s.name}"
1945
2565
  @click=${() => this.#t(i)}>✕</button>
1946
2566
  </li>
1947
2567
  `)}
1948
2568
  </ul>
1949
- ` : c}
1950
- ${(this.lostMeta || []).length ? a`
2569
+ ` : h}
2570
+ ${(this.lostMeta || []).length ? c`
1951
2571
  <div class="lost">
1952
2572
  Please re-attach your ${this.lostMeta.length === 1 ? "file" : "files"}
1953
2573
  (${this.lostMeta.map((s) => s.name).join(", ")}) —
1954
2574
  attachments can't be saved between visits.
1955
2575
  </div>
1956
- ` : c}
1957
- ${t.map((s) => a`<div class="err">${s.message}</div>`)}
2576
+ ` : h}
2577
+ ${t.map((s) => c`<div class="err">${s.message}</div>`)}
1958
2578
  `;
1959
2579
  }
1960
2580
  }
1961
- function et(r) {
2581
+ function us(r) {
1962
2582
  return Number.isFinite(r) ? r >= 1024 * 1024 ? `${(r / (1024 * 1024)).toFixed(1)} MB` : r >= 1024 ? `${Math.round(r / 1024)} KB` : `${r} B` : "";
1963
2583
  }
1964
- const tt = (r, e, t, s) => {
2584
+ const ps = (r, e, t, s) => {
1965
2585
  const i = e.target.value.replace(/\D/g, "").slice(-1), n = [...t];
1966
2586
  n[r] = i;
1967
- const o = n.join(""), l = n.every((d) => d !== "");
1968
- return s("code-change", { value: o, complete: l }), i && l && s("code-complete", { value: o }), n;
1969
- }, rt = (r, e, t, s) => {
2587
+ const o = n.join(""), a = n.every((l) => l !== "");
2588
+ return s("code-change", { value: o, complete: a }), i && a && s("code-complete", { value: o }), n;
2589
+ }, hs = (r, e, t, s) => {
1970
2590
  if (e.key === "Backspace") {
1971
2591
  const i = [...t];
1972
2592
  !i[r] && r > 0 ? i[r - 1] = "" : i[r] && (i[r] = "");
@@ -1974,23 +2594,23 @@ const tt = (r, e, t, s) => {
1974
2594
  return s("code-change", { value: n, complete: !1 }), i;
1975
2595
  }
1976
2596
  return t;
1977
- }, st = (r, e, t) => {
2597
+ }, fs = (r, e, t) => {
1978
2598
  r.preventDefault();
1979
2599
  const s = r.clipboardData.getData("text").replace(/\D/g, "").slice(0, 6);
1980
2600
  if (s.length === 0) return e;
1981
2601
  const i = [...e];
1982
- for (let l = 0; l < s.length && l < 6; l++)
1983
- i[l] = s[l];
1984
- const n = i.join(""), o = i.every((l) => l !== "");
2602
+ for (let a = 0; a < s.length && a < 6; a++)
2603
+ i[a] = s[a];
2604
+ const n = i.join(""), o = i.every((a) => a !== "");
1985
2605
  return t("code-change", { value: n, complete: o }), s.length === 6 && t("code-complete", { value: n }), i;
1986
2606
  };
1987
- class lt extends T {
2607
+ class ws extends G {
1988
2608
  static formAssociated = !0;
1989
2609
  static properties = {
1990
2610
  _values: { type: Array, state: !0 },
1991
2611
  disabled: { type: Boolean, reflect: !0 }
1992
2612
  };
1993
- static styles = f`
2613
+ static styles = b`
1994
2614
  :host {
1995
2615
  display: block;
1996
2616
  width: 100%;
@@ -2089,7 +2709,7 @@ class lt extends T {
2089
2709
  this.getInputs()[e]?.focus();
2090
2710
  }
2091
2711
  inputHandler(e, t) {
2092
- this._values = tt(
2712
+ this._values = ps(
2093
2713
  e,
2094
2714
  t,
2095
2715
  this._values,
@@ -2099,7 +2719,7 @@ class lt extends T {
2099
2719
  keydownHandler(e, t) {
2100
2720
  if (t.key === "Backspace") {
2101
2721
  const s = !this._values[e];
2102
- this._values = rt(
2722
+ this._values = hs(
2103
2723
  e,
2104
2724
  t,
2105
2725
  this._values,
@@ -2108,12 +2728,12 @@ class lt extends T {
2108
2728
  }
2109
2729
  }
2110
2730
  pasteHandler(e) {
2111
- this._values = st(e, this._values, this.dispatchCustomEvent.bind(this));
2731
+ this._values = fs(e, this._values, this.dispatchCustomEvent.bind(this));
2112
2732
  }
2113
2733
  render() {
2114
- return a`
2734
+ return c`
2115
2735
  <div class="code-inputs">
2116
- ${[0, 1, 2, 3, 4, 5].map((e) => a`
2736
+ ${[0, 1, 2, 3, 4, 5].map((e) => c`
2117
2737
  <input
2118
2738
  type = "text"
2119
2739
  inputmode = "numeric"
@@ -2133,10 +2753,10 @@ class lt extends T {
2133
2753
  }
2134
2754
  }
2135
2755
  export {
2136
- lt as W,
2137
- ot as a,
2138
- at as b,
2139
- ve as c,
2140
- xe as d,
2141
- ke as e
2756
+ ws as W,
2757
+ bs as a,
2758
+ ys as b,
2759
+ vt as c,
2760
+ ut as d,
2761
+ _t as e
2142
2762
  };