@sphoro/bugcatch-web-sdk 0.18.0 → 0.20.0
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.
- package/README.md +51 -3
- package/dist/bugcatch-call.es.js +201 -200
- package/dist/bugcatch-call.es.js.map +1 -1
- package/dist/bugcatch-call.umd.js +1 -1
- package/dist/bugcatch-call.umd.js.map +1 -1
- package/dist/bugcatch-core.es.js +1085 -1007
- package/dist/bugcatch-core.es.js.map +1 -1
- package/dist/bugcatch-panel.es.js +1337 -1067
- package/dist/bugcatch-panel.es.js.map +1 -1
- package/dist/bugcatch-panel.umd.js +427 -315
- package/dist/bugcatch-panel.umd.js.map +1 -1
- package/dist/bugcatch.standalone.umd.js +553 -429
- package/dist/bugcatch.standalone.umd.js.map +1 -1
- package/dist/bugcatch.umd.js +132 -120
- package/dist/bugcatch.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/accent.js +38 -0
- package/src/incoming-call.js +17 -15
- package/src/index.d.ts +52 -2
- package/src/index.js +26 -7
- package/src/panel/call.js +3 -2
- package/src/panel/compose.js +7 -3
- package/src/panel/icons.js +2 -0
- package/src/panel/index.js +26 -3
- package/src/panel/messages.js +2 -2
- package/src/panel/picks.js +6 -2
- package/src/panel/rate-due.js +155 -0
- package/src/panel/rating.js +87 -0
- package/src/panel/refs.js +1 -1
- package/src/panel/render.js +11 -3
- package/src/panel/signin.js +1 -1
- package/src/panel/styles.js +270 -186
- package/src/panel/thread.js +48 -7
- package/src/updates.js +77 -27
- package/src/widget.js +160 -141
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(){"use strict";const qe='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11.5a7.5 7 0 0 1 7.5-7h1a7.5 7 0 0 1 0 14H9l-4.2 2.6a.5.5 0 0 1-.76-.5l.5-3.1A7 7 0 0 1 4 11.5z"/><path d="M8.5 11.5h.01M12 11.5h.01M15.5 11.5h.01" stroke-width="2.6"/></svg>',_='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7.5v5.2M12 16.3h.01"/></svg>',J='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>',O='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.8l4.6 4.4L19 7"/></svg>',ue='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v5.5M12 7.7h.01"/></svg>',He='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.3 4.2a2 2 0 0 1 3.4 0l7.6 13.1a2 2 0 0 1-1.7 3H4.4a2 2 0 0 1-1.7-3z"/><path d="M12 9.5v4.2M12 17h.01"/></svg>',Ie='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8.5A1.5 1.5 0 0 1 4.5 7h2.2a1 1 0 0 0 .83-.45l.94-1.4A1 1 0 0 1 9.3 4.7h5.4a1 1 0 0 1 .83.45l.94 1.4a1 1 0 0 0 .83.45h2.2A1.5 1.5 0 0 1 21 8.5v9A1.5 1.5 0 0 1 19.5 19h-15A1.5 1.5 0 0 1 3 17.5z"/><circle cx="12" cy="13" r="3.4"/></svg>',Re='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="6" width="12.5" height="12" rx="2.2"/><path d="M15.5 10.8l4.2-2.6a.6.6 0 0 1 .92.5v6.6a.6.6 0 0 1-.92.5l-4.2-2.6z"/></svg>',he='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 11.5l-7.6 7.6a4.6 4.6 0 0 1-6.5-6.5l8-8a3.2 3.2 0 0 1 4.5 4.5l-8 8a1.8 1.8 0 0 1-2.5-2.5l7.1-7.1"/></svg>',be='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="2.5" width="6" height="11" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21M9 21h6"/></svg>',fe='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l16-8-6 16-2.6-6.2L4 12Z"/></svg>',Ae='<svg viewBox="0 0 24 24" fill="currentColor"><rect x="7" y="7" width="10" height="10" rx="2"/></svg>',De='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 5.5L8 12l6.5 6.5"/></svg>',ee='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.2 3.5h3l1.5 3.7-2 1.4a11.5 11.5 0 0 0 5.7 5.7l1.4-2 3.7 1.5v3a1.8 1.8 0 0 1-2 1.8A15.6 15.6 0 0 1 4.4 5.5a1.8 1.8 0 0 1 1.8-2z"/></svg>',Ve='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 12a8 8 0 1 1-2.6-5.9M20 4v4.5h-4.5"/></svg>',F='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.5c.5 4.6 2.9 7 7.5 7.5v.1c-4.6.5-7 2.9-7.5 7.5h-.1c-.5-4.6-2.9-7-7.5-7.5V10c4.6-.5 7-2.9 7.5-7.5z"/><path d="M18.6 15.2c.2 1.9 1.2 2.9 3.1 3.1v.1c-1.9.2-2.9 1.2-3.1 3.1h-.1c-.2-1.9-1.2-2.9-3.1-3.1v-.1c1.9-.2 2.9-1.2 3.1-3.1z" opacity=".7"/></svg>',je='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 6l6 6-6 6"/></svg>',Oe='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 13.5l2.6-7.2A1.5 1.5 0 0 1 7.5 5.3h9a1.5 1.5 0 0 1 1.4 1L20.5 13.5V18a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 18z"/><path d="M3.5 13.5h4.8l1.2 2.2h5l1.2-2.2h4.8"/></svg>',Be='<svg class="bc-brand" viewBox="0 0 254 60" fill="none" role="img" aria-label="sphoro BugCatch"><g fill="currentColor"><path transform="translate(0.00 40.00) scale(0.04000 -0.04000)" d="M276.00 -14.00Q179.00 -14.00 117.00 28.00Q55.00 70.00 42.00 148.00L158.00 178.00Q165.00 143.00 181.50 123.00Q198.00 103.00 222.50 94.50Q247.00 86.00 276.00 86.00Q320.00 86.00 341.00 101.50Q362.00 117.00 362.00 140.00Q362.00 163.00 342.00 175.50Q322.00 188.00 278.00 196.00L250.00 201.00Q198.00 211.00 155.00 228.50Q112.00 246.00 86.00 277.00Q60.00 308.00 60.00 357.00Q60.00 431.00 114.00 470.50Q168.00 510.00 256.00 510.00Q339.00 510.00 394.00 473.00Q449.00 436.00 466.00 376.00L349.00 340.00Q341.00 378.00 316.50 394.00Q292.00 410.00 256.00 410.00Q220.00 410.00 201.00 397.50Q182.00 385.00 182.00 363.00Q182.00 339.00 202.00 327.50Q222.00 316.00 256.00 310.00L284.00 305.00Q340.00 295.00 385.50 278.50Q431.00 262.00 457.50 231.50Q484.00 201.00 484.00 149.00Q484.00 71.00 427.50 28.50Q371.00 -14.00 276.00 -14.00Z"/><path transform="translate(19.56 40.00) scale(0.04000 -0.04000)" d="M70.00 -200.00V496.00H194.00V436.00H212.00Q229.00 465.00 265.00 487.50Q301.00 510.00 368.00 510.00Q428.00 510.00 479.00 480.50Q530.00 451.00 561.00 394.00Q592.00 337.00 592.00 256.00V240.00Q592.00 159.00 561.00 102.00Q530.00 45.00 479.00 15.50Q428.00 -14.00 368.00 -14.00Q323.00 -14.00 292.50 -3.50Q262.00 7.00 243.50 23.50Q225.00 40.00 214.00 57.00H196.00V-200.00ZM330.00 96.00Q389.00 96.00 427.50 133.50Q466.00 171.00 466.00 243.00V253.00Q466.00 325.00 427.00 362.50Q388.00 400.00 330.00 400.00Q272.00 400.00 233.00 362.50Q194.00 325.00 194.00 253.00V243.00Q194.00 171.00 233.00 133.50Q272.00 96.00 330.00 96.00Z"/><path transform="translate(43.68 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V700.00H196.00V435.00H214.00Q222.00 451.00 239.00 467.00Q256.00 483.00 284.50 493.50Q313.00 504.00 357.00 504.00Q415.00 504.00 458.50 477.50Q502.00 451.00 526.00 404.50Q550.00 358.00 550.00 296.00V0.00H424.00V286.00Q424.00 342.00 396.50 370.00Q369.00 398.00 318.00 398.00Q260.00 398.00 228.00 359.50Q196.00 321.00 196.00 252.00V0.00Z"/><path transform="translate(66.92 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/><path transform="translate(90.00 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V496.00H194.00V440.00H212.00Q223.00 470.00 248.50 484.00Q274.00 498.00 308.00 498.00H368.00V386.00H306.00Q258.00 386.00 227.00 360.50Q196.00 335.00 196.00 282.00V0.00Z"/><path transform="translate(104.44 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/></g><rect x="139.52" y="16" width="1.6" height="26" rx="0.8" fill="var(--bc-brand-mark, #5647ee)" opacity="0.4"/><g fill="var(--bc-brand-mark, #5647ee)"><path transform="translate(154.52 35.00) scale(0.01400 -0.01400)" d="M46.35 0.00V105.85H139.75V594.15H46.35V700.00H404.08Q467.38 700.00 514.79 678.41Q562.20 656.83 588.70 617.33Q615.20 577.83 615.20 523.35V513.70Q615.20 465.52 597.03 434.76Q578.85 404.00 553.91 387.24Q528.98 370.48 506.28 363.30V346.35Q528.98 340.35 555.24 323.50Q581.50 306.65 600.00 275.48Q618.50 244.30 618.50 194.48V184.48Q618.50 126.65 591.41 85.24Q564.33 43.83 516.83 21.91Q469.33 0.00 406.85 0.00ZM259.85 109.15H392.60Q441.20 109.15 469.80 132.60Q498.40 156.05 498.40 198.55V208.20Q498.40 250.70 470.21 274.15Q442.02 297.60 392.60 297.60H259.85ZM259.85 406.75H391.65Q437.55 406.75 466.32 430.11Q495.10 453.48 495.10 493.80V503.80Q495.10 544.95 466.74 567.90Q438.37 590.85 391.65 590.85H259.85Z"/><path transform="translate(167.00 35.00) scale(0.01400 -0.01400)" d="M335.30 -14.00Q251.22 -14.00 190.60 16.63Q129.97 47.25 97.56 104.96Q65.15 162.68 65.15 243.03V700.00H185.25V239.73Q185.25 170.48 224.03 131.99Q262.80 93.50 335.30 93.50Q407.80 93.50 446.57 131.99Q485.35 170.48 485.35 239.73V700.00H605.45V243.03Q605.45 162.68 573.13 104.96Q540.80 47.25 480.09 16.63Q419.38 -14.00 335.30 -14.00Z"/><path transform="translate(179.60 35.00) scale(0.01400 -0.01400)" d="M311.85 -14.00Q238.45 -14.00 179.69 18.50Q120.92 51.00 86.69 113.67Q52.45 176.35 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.23 645.59Q598.33 577.17 598.33 460.87V456.70H479.87V464.52Q479.87 504.67 463.76 536.86Q447.65 569.05 414.99 587.77Q382.32 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 138.89Q257.63 91.85 334.00 91.85Q410.02 91.85 445.12 132.83Q480.22 173.80 480.22 237.92V249.67H302.85V351.88H598.33V0.00H487.52V69.10H470.57Q462.70 50.87 446.06 31.44Q429.42 12.00 397.64 -1.00Q365.85 -14.00 311.85 -14.00Z"/><path transform="translate(192.05 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(204.25 35.00) scale(0.01400 -0.01400)" d="M19.75 0.00 211.62 700.00H421.33L613.20 0.00H489.27L447.42 159.60H185.53L143.68 0.00ZM214.25 270.40H418.70L324.95 624.87H308.00Z"/><path transform="translate(216.31 35.00) scale(0.01400 -0.01400)" d="M233.95 0.00V590.85H24.70V700.00H563.30V590.85H354.05V0.00Z"/><path transform="translate(227.75 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(239.95 35.00) scale(0.01400 -0.01400)" d="M69.50 0.00V700.00H189.60V405.58H466.40V700.00H586.50V0.00H466.40V296.42H189.60V0.00Z"/></g></svg>',Ne=`
|
|
1
|
+
(function(){"use strict";const Ie='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11.5a7.5 7 0 0 1 7.5-7h1a7.5 7 0 0 1 0 14H9l-4.2 2.6a.5.5 0 0 1-.76-.5l.5-3.1A7 7 0 0 1 4 11.5z"/><path d="M8.5 11.5h.01M12 11.5h.01M15.5 11.5h.01" stroke-width="2.6"/></svg>',De='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4.2"/><path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.4 5.4l1.6 1.6M17 17l1.6 1.6M18.6 5.4L17 7M7 17l-1.6 1.6"/></svg>',je='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13.4A8.2 8.2 0 1 1 10.6 4a6.6 6.6 0 0 0 9.4 9.4z"/></svg>',Ve='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="2.8" y="4.4" width="18.4" height="12.6" rx="2.2"/><path d="M8.6 20.2h6.8"/><path d="M12 4.4v12.6"/><path d="M12 7.2a3.6 3.6 0 0 1 0 7.2z" fill="currentColor" stroke="none"/></svg>',F='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7.5v5.2M12 16.3h.01"/></svg>',J='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>',O='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.8l4.6 4.4L19 7"/></svg>',ue='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v5.5M12 7.7h.01"/></svg>',Oe='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.3 4.2a2 2 0 0 1 3.4 0l7.6 13.1a2 2 0 0 1-1.7 3H4.4a2 2 0 0 1-1.7-3z"/><path d="M12 9.5v4.2M12 17h.01"/></svg>',Be='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8.5A1.5 1.5 0 0 1 4.5 7h2.2a1 1 0 0 0 .83-.45l.94-1.4A1 1 0 0 1 9.3 4.7h5.4a1 1 0 0 1 .83.45l.94 1.4a1 1 0 0 0 .83.45h2.2A1.5 1.5 0 0 1 21 8.5v9A1.5 1.5 0 0 1 19.5 19h-15A1.5 1.5 0 0 1 3 17.5z"/><circle cx="12" cy="13" r="3.4"/></svg>',Ne='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="6" width="12.5" height="12" rx="2.2"/><path d="M15.5 10.8l4.2-2.6a.6.6 0 0 1 .92.5v6.6a.6.6 0 0 1-.92.5l-4.2-2.6z"/></svg>',he='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 11.5l-7.6 7.6a4.6 4.6 0 0 1-6.5-6.5l8-8a3.2 3.2 0 0 1 4.5 4.5l-8 8a1.8 1.8 0 0 1-2.5-2.5l7.1-7.1"/></svg>',fe='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="2.5" width="6" height="11" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21M9 21h6"/></svg>',be='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l16-8-6 16-2.6-6.2L4 12Z"/></svg>',We='<svg viewBox="0 0 24 24" fill="currentColor"><rect x="7" y="7" width="10" height="10" rx="2"/></svg>',Pe='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 5.5L8 12l6.5 6.5"/></svg>',ee='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.2 3.5h3l1.5 3.7-2 1.4a11.5 11.5 0 0 0 5.7 5.7l1.4-2 3.7 1.5v3a1.8 1.8 0 0 1-2 1.8A15.6 15.6 0 0 1 4.4 5.5a1.8 1.8 0 0 1 1.8-2z"/></svg>',Ye='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 12a8 8 0 1 1-2.6-5.9M20 4v4.5h-4.5"/></svg>',Fe='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 6l6 6-6 6"/></svg>',ge='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.9l2.75 5.82 6.37.76-4.7 4.37 1.24 6.3L12 17.03l-5.66 3.12 1.24-6.3-4.7-4.37 6.37-.76z"/></svg>',_e='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 13.5l2.6-7.2A1.5 1.5 0 0 1 7.5 5.3h9a1.5 1.5 0 0 1 1.4 1L20.5 13.5V18a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 18z"/><path d="M3.5 13.5h4.8l1.2 2.2h5l1.2-2.2h4.8"/></svg>',Ke='<svg class="bc-brand" viewBox="0 0 254 60" fill="none" role="img" aria-label="sphoro BugCatch"><g fill="currentColor"><path transform="translate(0.00 40.00) scale(0.04000 -0.04000)" d="M276.00 -14.00Q179.00 -14.00 117.00 28.00Q55.00 70.00 42.00 148.00L158.00 178.00Q165.00 143.00 181.50 123.00Q198.00 103.00 222.50 94.50Q247.00 86.00 276.00 86.00Q320.00 86.00 341.00 101.50Q362.00 117.00 362.00 140.00Q362.00 163.00 342.00 175.50Q322.00 188.00 278.00 196.00L250.00 201.00Q198.00 211.00 155.00 228.50Q112.00 246.00 86.00 277.00Q60.00 308.00 60.00 357.00Q60.00 431.00 114.00 470.50Q168.00 510.00 256.00 510.00Q339.00 510.00 394.00 473.00Q449.00 436.00 466.00 376.00L349.00 340.00Q341.00 378.00 316.50 394.00Q292.00 410.00 256.00 410.00Q220.00 410.00 201.00 397.50Q182.00 385.00 182.00 363.00Q182.00 339.00 202.00 327.50Q222.00 316.00 256.00 310.00L284.00 305.00Q340.00 295.00 385.50 278.50Q431.00 262.00 457.50 231.50Q484.00 201.00 484.00 149.00Q484.00 71.00 427.50 28.50Q371.00 -14.00 276.00 -14.00Z"/><path transform="translate(19.56 40.00) scale(0.04000 -0.04000)" d="M70.00 -200.00V496.00H194.00V436.00H212.00Q229.00 465.00 265.00 487.50Q301.00 510.00 368.00 510.00Q428.00 510.00 479.00 480.50Q530.00 451.00 561.00 394.00Q592.00 337.00 592.00 256.00V240.00Q592.00 159.00 561.00 102.00Q530.00 45.00 479.00 15.50Q428.00 -14.00 368.00 -14.00Q323.00 -14.00 292.50 -3.50Q262.00 7.00 243.50 23.50Q225.00 40.00 214.00 57.00H196.00V-200.00ZM330.00 96.00Q389.00 96.00 427.50 133.50Q466.00 171.00 466.00 243.00V253.00Q466.00 325.00 427.00 362.50Q388.00 400.00 330.00 400.00Q272.00 400.00 233.00 362.50Q194.00 325.00 194.00 253.00V243.00Q194.00 171.00 233.00 133.50Q272.00 96.00 330.00 96.00Z"/><path transform="translate(43.68 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V700.00H196.00V435.00H214.00Q222.00 451.00 239.00 467.00Q256.00 483.00 284.50 493.50Q313.00 504.00 357.00 504.00Q415.00 504.00 458.50 477.50Q502.00 451.00 526.00 404.50Q550.00 358.00 550.00 296.00V0.00H424.00V286.00Q424.00 342.00 396.50 370.00Q369.00 398.00 318.00 398.00Q260.00 398.00 228.00 359.50Q196.00 321.00 196.00 252.00V0.00Z"/><path transform="translate(66.92 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/><path transform="translate(90.00 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V496.00H194.00V440.00H212.00Q223.00 470.00 248.50 484.00Q274.00 498.00 308.00 498.00H368.00V386.00H306.00Q258.00 386.00 227.00 360.50Q196.00 335.00 196.00 282.00V0.00Z"/><path transform="translate(104.44 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/></g><rect x="139.52" y="16" width="1.6" height="26" rx="0.8" fill="var(--bc-brand-mark, #5647ee)" opacity="0.4"/><g fill="var(--bc-brand-mark, #5647ee)"><path transform="translate(154.52 35.00) scale(0.01400 -0.01400)" d="M46.35 0.00V105.85H139.75V594.15H46.35V700.00H404.08Q467.38 700.00 514.79 678.41Q562.20 656.83 588.70 617.33Q615.20 577.83 615.20 523.35V513.70Q615.20 465.52 597.03 434.76Q578.85 404.00 553.91 387.24Q528.98 370.48 506.28 363.30V346.35Q528.98 340.35 555.24 323.50Q581.50 306.65 600.00 275.48Q618.50 244.30 618.50 194.48V184.48Q618.50 126.65 591.41 85.24Q564.33 43.83 516.83 21.91Q469.33 0.00 406.85 0.00ZM259.85 109.15H392.60Q441.20 109.15 469.80 132.60Q498.40 156.05 498.40 198.55V208.20Q498.40 250.70 470.21 274.15Q442.02 297.60 392.60 297.60H259.85ZM259.85 406.75H391.65Q437.55 406.75 466.32 430.11Q495.10 453.48 495.10 493.80V503.80Q495.10 544.95 466.74 567.90Q438.37 590.85 391.65 590.85H259.85Z"/><path transform="translate(167.00 35.00) scale(0.01400 -0.01400)" d="M335.30 -14.00Q251.22 -14.00 190.60 16.63Q129.97 47.25 97.56 104.96Q65.15 162.68 65.15 243.03V700.00H185.25V239.73Q185.25 170.48 224.03 131.99Q262.80 93.50 335.30 93.50Q407.80 93.50 446.57 131.99Q485.35 170.48 485.35 239.73V700.00H605.45V243.03Q605.45 162.68 573.13 104.96Q540.80 47.25 480.09 16.63Q419.38 -14.00 335.30 -14.00Z"/><path transform="translate(179.60 35.00) scale(0.01400 -0.01400)" d="M311.85 -14.00Q238.45 -14.00 179.69 18.50Q120.92 51.00 86.69 113.67Q52.45 176.35 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.23 645.59Q598.33 577.17 598.33 460.87V456.70H479.87V464.52Q479.87 504.67 463.76 536.86Q447.65 569.05 414.99 587.77Q382.32 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 138.89Q257.63 91.85 334.00 91.85Q410.02 91.85 445.12 132.83Q480.22 173.80 480.22 237.92V249.67H302.85V351.88H598.33V0.00H487.52V69.10H470.57Q462.70 50.87 446.06 31.44Q429.42 12.00 397.64 -1.00Q365.85 -14.00 311.85 -14.00Z"/><path transform="translate(192.05 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(204.25 35.00) scale(0.01400 -0.01400)" d="M19.75 0.00 211.62 700.00H421.33L613.20 0.00H489.27L447.42 159.60H185.53L143.68 0.00ZM214.25 270.40H418.70L324.95 624.87H308.00Z"/><path transform="translate(216.31 35.00) scale(0.01400 -0.01400)" d="M233.95 0.00V590.85H24.70V700.00H563.30V590.85H354.05V0.00Z"/><path transform="translate(227.75 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(239.95 35.00) scale(0.01400 -0.01400)" d="M69.50 0.00V700.00H189.60V405.58H466.40V700.00H586.50V0.00H466.40V296.42H189.60V0.00Z"/></g></svg>',Ue=`
|
|
2
2
|
@keyframes bc-fade-in { from { opacity: 0 } to { opacity: 1 } }
|
|
3
3
|
@keyframes bc-fade-out { to { opacity: 0 } }
|
|
4
4
|
@keyframes bc-panel-in { from { opacity: 0; transform: translateY(14px) scale(.965) } to { opacity: 1; transform: none } }
|
|
@@ -14,9 +14,12 @@
|
|
|
14
14
|
@keyframes bc-shimmer { from { background-position: 200% 0 } to { background-position: -200% 0 } }
|
|
15
15
|
|
|
16
16
|
/* ---------- scrim + panel ---------- */
|
|
17
|
+
/* Still modal — focus stays in the panel and a click outside closes it — but
|
|
18
|
+
the host's page only dims enough to say so. It is their product, and the
|
|
19
|
+
visitor is reporting something about what is on it. */
|
|
17
20
|
.scrim {
|
|
18
21
|
position: fixed; inset: 0; z-index: 2147483001;
|
|
19
|
-
background: rgba(
|
|
22
|
+
background: rgba(14,14,16,.14);
|
|
20
23
|
animation: bc-fade-in 200ms ease both;
|
|
21
24
|
}
|
|
22
25
|
.scrim.closing { animation: bc-fade-out 170ms ease both; }
|
|
@@ -28,12 +31,11 @@
|
|
|
28
31
|
.panel {
|
|
29
32
|
position: fixed;
|
|
30
33
|
display: flex; flex-direction: column;
|
|
31
|
-
width: calc(100vw - 40px); max-width:
|
|
34
|
+
width: calc(100vw - 40px); max-width: 400px;
|
|
32
35
|
max-height: calc(100vh - var(--bc-dock-h, 84px) - 52px);
|
|
33
36
|
overflow: hidden;
|
|
34
37
|
background: var(--bc-bg); color: var(--bc-fg);
|
|
35
38
|
border-radius: var(--bc-r-xl); box-shadow: var(--bc-shadow);
|
|
36
|
-
border: 1px solid color-mix(in srgb, var(--bc-border) 70%, transparent);
|
|
37
39
|
animation: bc-panel-in 340ms var(--bc-ease) both;
|
|
38
40
|
}
|
|
39
41
|
/* A conversation wants a height of its own, so the thread fills the panel
|
|
@@ -48,57 +50,58 @@
|
|
|
48
50
|
/* ---------- header ---------- */
|
|
49
51
|
.head {
|
|
50
52
|
flex: none; position: relative;
|
|
51
|
-
display: flex; align-items: center; gap:
|
|
52
|
-
padding:
|
|
53
|
-
background:
|
|
53
|
+
display: flex; align-items: center; gap: 11px;
|
|
54
|
+
padding: 14px 10px 13px var(--bc-pad);
|
|
55
|
+
background: var(--bc-bg);
|
|
54
56
|
border-bottom: 1px solid var(--bc-border);
|
|
55
57
|
}
|
|
56
|
-
.head .mark
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
background: linear-gradient(140deg, var(--bc-accent), color-mix(in srgb, var(--bc-accent) 60%, #fff));
|
|
60
|
-
color: var(--bc-on-accent); font-size: 19px;
|
|
61
|
-
box-shadow: 0 4px 12px color-mix(in srgb, var(--bc-accent) 30%, transparent);
|
|
62
|
-
}
|
|
63
|
-
/* The little "online" dot says someone — or something — is on the other end. */
|
|
64
|
-
.head .mark::after {
|
|
65
|
-
content: ''; position: absolute; right: -1px; bottom: -1px;
|
|
66
|
-
width: 11px; height: 11px; border-radius: 50%;
|
|
67
|
-
background: #22c55e; border: 2px solid var(--bc-bg);
|
|
68
|
-
}
|
|
58
|
+
.head .mark { width: 32px; }
|
|
59
|
+
/* The assistant asking its one follow-up wears the same orb, smaller. */
|
|
60
|
+
.avatar.orb { width: 26px; }
|
|
69
61
|
.head .titles { flex: 1; min-width: 0; }
|
|
70
62
|
.head h2 {
|
|
71
|
-
margin: 0 0
|
|
63
|
+
margin: 0 0 1px; font-size: var(--bc-fs-lg); font-weight: 600; letter-spacing: -.015em; line-height: 1.3;
|
|
64
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
65
|
+
}
|
|
66
|
+
.head p {
|
|
67
|
+
margin: 0; font-size: var(--bc-fs-sm); line-height: 1.4; color: var(--bc-muted);
|
|
72
68
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
73
69
|
}
|
|
74
|
-
.head p { margin: 0; font-size: var(--bc-fs-sm); line-height: 1.45; color: var(--bc-muted); }
|
|
75
70
|
.icon-btn {
|
|
76
71
|
flex: none; display: grid; place-items: center;
|
|
77
72
|
width: 32px; height: 32px; padding: 0; font-size: 16px;
|
|
78
|
-
border: none; border-radius:
|
|
73
|
+
border: none; border-radius: 999px; background: none; color: var(--bc-muted);
|
|
79
74
|
cursor: pointer; transition: background 160ms, color 160ms, transform 160ms var(--bc-ease);
|
|
80
75
|
}
|
|
81
76
|
.icon-btn:hover { background: color-mix(in srgb, var(--bc-fg) 7%, transparent); color: var(--bc-fg); }
|
|
82
77
|
.icon-btn:active { transform: scale(.92); }
|
|
83
78
|
.icon-btn.back { margin: 0 -6px 0 -8px; }
|
|
79
|
+
/* The theme button holds all three glyphs; the host's class picks one. */
|
|
80
|
+
.icon-btn.theme { font-size: 15px; margin-right: -4px; }
|
|
81
|
+
.icon-btn.theme > span { display: none; }
|
|
82
|
+
:host(.bc-light) .icon-btn.theme .m-light,
|
|
83
|
+
:host(.bc-dark) .icon-btn.theme .m-dark,
|
|
84
|
+
:host(.bc-auto) .icon-btn.theme .m-auto { display: block; }
|
|
84
85
|
|
|
85
86
|
.body {
|
|
86
87
|
flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
|
|
87
|
-
padding:
|
|
88
|
+
padding: 14px var(--bc-pad) 4px;
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
label { display: block; font-size:
|
|
91
|
+
label { display: block; font-size: 13px; font-weight: 560; color: var(--bc-fg); margin-bottom: 6px; letter-spacing: -.005em; }
|
|
91
92
|
label .opt { font-weight: 450; color: var(--bc-faint); }
|
|
93
|
+
/* Fields are stone wells that turn white when you are in them, the way the
|
|
94
|
+
rest of the product's forms do. */
|
|
92
95
|
input[type=text], input[type=email], textarea {
|
|
93
|
-
width: 100%; padding:
|
|
94
|
-
color: var(--bc-fg); background: var(--bc-
|
|
95
|
-
border: 1px solid
|
|
96
|
+
width: 100%; padding: 10px 12px; font-size: var(--bc-fs-md); line-height: 1.45;
|
|
97
|
+
color: var(--bc-fg); background: var(--bc-stone);
|
|
98
|
+
border: 1px solid transparent; border-radius: var(--bc-r-md);
|
|
96
99
|
transition: border-color 160ms, box-shadow 160ms, background 160ms;
|
|
97
100
|
}
|
|
98
101
|
input[type=text]::placeholder, input[type=email]::placeholder, textarea::placeholder { color: var(--bc-faint); }
|
|
99
|
-
input[type=text]:hover, input[type=email]:hover, textarea:hover { border-color:
|
|
102
|
+
input[type=text]:hover, input[type=email]:hover, textarea:hover { border-color: var(--bc-border); }
|
|
100
103
|
input[type=text]:focus, input[type=email]:focus, textarea:focus {
|
|
101
|
-
outline: none; border-color: var(--bc-accent); box-shadow: var(--bc-ring);
|
|
104
|
+
outline: none; background: var(--bc-bg); border-color: var(--bc-accent); box-shadow: var(--bc-ring);
|
|
102
105
|
}
|
|
103
106
|
input.invalid, input.invalid:focus, textarea.invalid {
|
|
104
107
|
border-color: var(--bc-danger); animation: bc-nudge 240ms ease;
|
|
@@ -110,8 +113,8 @@ input.invalid, input.invalid:focus, textarea.invalid {
|
|
|
110
113
|
animation: bc-rise 200ms var(--bc-ease) both;
|
|
111
114
|
}
|
|
112
115
|
.field-err svg { font-size: 13px; flex: none; }
|
|
113
|
-
textarea { min-height:
|
|
114
|
-
.field { margin-bottom:
|
|
116
|
+
textarea { min-height: 76px; resize: vertical; }
|
|
117
|
+
.field { margin-bottom: 14px; }
|
|
115
118
|
.field-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
|
|
116
119
|
.field-head .count { font-size: var(--bc-fs-xs); color: var(--bc-faint); font-variant-numeric: tabular-nums; }
|
|
117
120
|
|
|
@@ -121,15 +124,15 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
121
124
|
.compose > .note:has(button) {
|
|
122
125
|
display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
|
|
123
126
|
margin: 0 0 14px; padding: 10px 12px; border-radius: var(--bc-r-md);
|
|
124
|
-
background: var(--bc-
|
|
127
|
+
background: var(--bc-subtle); border: 1px solid var(--bc-border);
|
|
125
128
|
font-size: var(--bc-fs-sm); color: var(--bc-fg);
|
|
126
129
|
}
|
|
127
130
|
.compose > .note button {
|
|
128
|
-
padding: 5px 11px; font: inherit; font-size: var(--bc-fs-xs); font-weight:
|
|
131
|
+
padding: 5px 11px; font: inherit; font-size: var(--bc-fs-xs); font-weight: 600;
|
|
129
132
|
border-radius: 999px; cursor: pointer;
|
|
130
133
|
border: 1px solid var(--bc-accent); background: var(--bc-accent); color: var(--bc-on-accent);
|
|
131
134
|
}
|
|
132
|
-
.compose > .note button[data-discard] { background:
|
|
135
|
+
.compose > .note button[data-discard] { background: var(--bc-bg); color: var(--bc-fg); border-color: var(--bc-border); }
|
|
133
136
|
|
|
134
137
|
/* ---------- what is already known ----------
|
|
135
138
|
A help surface in front of the form, not a step in it. Everything here is
|
|
@@ -137,58 +140,57 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
137
140
|
leave, tap "this is happening to me too" and leave, or type straight past all
|
|
138
141
|
of it and file the report they came to file. Nothing is ever in their way,
|
|
139
142
|
because a reporter who feels handled rather than helped stops reporting. */
|
|
140
|
-
|
|
141
|
-
.known .known-h {
|
|
142
|
-
margin: 0 0
|
|
143
|
+
/* One small eyebrow style for every group above the form. */
|
|
144
|
+
.known .known-h, .picks .picks-h {
|
|
145
|
+
margin: 0 0 7px; font-size: 11px; font-weight: 600; letter-spacing: .07em;
|
|
143
146
|
text-transform: uppercase; color: var(--bc-faint);
|
|
144
147
|
}
|
|
148
|
+
.known { margin-bottom: 14px; }
|
|
149
|
+
/* Hairline rows on the panel's own white, so they read as a list to scan
|
|
150
|
+
rather than more coloured cards to wade through. */
|
|
145
151
|
.known .issue {
|
|
146
152
|
display: flex; align-items: center; gap: 10px;
|
|
147
|
-
padding:
|
|
148
|
-
background: var(--bc-
|
|
153
|
+
padding: 8px 8px 8px 12px; margin-bottom: 6px;
|
|
154
|
+
background: var(--bc-bg); border: 1px solid var(--bc-border); border-radius: var(--bc-r-md);
|
|
149
155
|
animation: bc-rise 240ms var(--bc-ease) both;
|
|
150
156
|
}
|
|
151
|
-
.known .issue.is-joined {
|
|
157
|
+
.known .issue.is-joined { background: color-mix(in srgb, var(--bc-ok) 6%, var(--bc-bg)); }
|
|
152
158
|
.known .issue .who { flex: 1; min-width: 0; }
|
|
153
159
|
.known .issue .t {
|
|
154
|
-
display: block; font-size: 13px; font-weight:
|
|
160
|
+
display: block; font-size: 13px; font-weight: 560; line-height: 1.4;
|
|
155
161
|
color: var(--bc-fg); overflow-wrap: anywhere;
|
|
156
162
|
}
|
|
157
163
|
.known .issue .meta {
|
|
158
|
-
display: block; margin-top:
|
|
164
|
+
display: block; margin-top: 2px; font-size: var(--bc-fs-xs); line-height: 1.45; color: var(--bc-muted);
|
|
159
165
|
}
|
|
160
166
|
.known .issue .join {
|
|
161
|
-
flex: none; padding:
|
|
162
|
-
color: var(--bc-
|
|
163
|
-
border:
|
|
164
|
-
transition: background 160ms,
|
|
167
|
+
flex: none; height: 30px; padding: 0 12px; font: inherit; font-size: 12px; font-weight: 560;
|
|
168
|
+
color: var(--bc-fg); background: var(--bc-stone);
|
|
169
|
+
border: 0; border-radius: 999px; cursor: pointer;
|
|
170
|
+
transition: background 160ms, color 160ms;
|
|
165
171
|
}
|
|
166
|
-
.known .issue .join:hover {
|
|
167
|
-
.known .issue .join:disabled { color: var(--bc-ok);
|
|
172
|
+
.known .issue .join:hover { background: color-mix(in srgb, var(--bc-fg) 12%, var(--bc-stone)); }
|
|
173
|
+
.known .issue .join:disabled { color: var(--bc-ok); background: transparent; cursor: default; opacity: 1; }
|
|
168
174
|
.known .ask { display: flex; gap: 8px; margin: 2px 0 8px; }
|
|
169
175
|
.known .ask input { flex: 1; min-width: 0; }
|
|
170
176
|
.known .ask button { flex: none; }
|
|
171
177
|
.known .err { margin: 6px 0 0; font-size: 12px; line-height: 1.45; color: var(--bc-danger); }
|
|
172
178
|
|
|
173
179
|
/* ---------- questions the assistant answers by itself ---------- */
|
|
174
|
-
.picks { margin-bottom:
|
|
175
|
-
.picks .picks-
|
|
176
|
-
margin: 0 0 8px; font-size: 11px; font-weight: 680; letter-spacing: .06em;
|
|
177
|
-
text-transform: uppercase; color: var(--bc-faint);
|
|
178
|
-
}
|
|
179
|
-
.picks .picks-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px; }
|
|
180
|
+
.picks { margin-bottom: 14px; }
|
|
181
|
+
.picks .picks-grid { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
180
182
|
.picks .pick {
|
|
181
|
-
display: flex;
|
|
182
|
-
padding:
|
|
183
|
-
color: var(--bc-fg); background: var(--bc-
|
|
184
|
-
border: 1px solid
|
|
185
|
-
transition: background 160ms, border-color 160ms, transform 160ms;
|
|
183
|
+
display: inline-flex; align-items: center; max-width: 100%;
|
|
184
|
+
min-height: 32px; padding: 6px 13px; text-align: left; cursor: pointer; font: inherit;
|
|
185
|
+
color: var(--bc-fg); background: var(--bc-stone);
|
|
186
|
+
border: 1px solid transparent; border-radius: 999px;
|
|
187
|
+
transition: background 160ms, border-color 160ms, color 160ms, transform 160ms var(--bc-ease);
|
|
186
188
|
animation: bc-rise 240ms var(--bc-ease) both;
|
|
187
189
|
}
|
|
188
|
-
.picks .pick:hover {
|
|
189
|
-
.picks .pick
|
|
190
|
-
.picks .pick
|
|
191
|
-
.picks .pick .
|
|
190
|
+
.picks .pick:hover { background: color-mix(in srgb, var(--bc-fg) 10%, var(--bc-stone)); }
|
|
191
|
+
.picks .pick:active { transform: scale(.97); }
|
|
192
|
+
.picks .pick[aria-pressed="true"] { background: var(--bc-accent); color: var(--bc-on-accent); }
|
|
193
|
+
.picks .pick .t { font-size: 13px; font-weight: 520; line-height: 1.35; overflow-wrap: anywhere; }
|
|
192
194
|
.picks .picks-note {
|
|
193
195
|
display: flex; gap: 6px; align-items: flex-start; margin: 8px 0 0;
|
|
194
196
|
font-size: 12px; line-height: 1.45; color: var(--bc-muted);
|
|
@@ -202,18 +204,21 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
202
204
|
strip is the whole panel. */
|
|
203
205
|
.whoami {
|
|
204
206
|
display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
|
|
205
|
-
margin-bottom:
|
|
207
|
+
margin-bottom: 14px; padding: 9px 12px;
|
|
206
208
|
font-size: var(--bc-fs-sm); line-height: 1.45; color: var(--bc-muted);
|
|
207
209
|
background: var(--bc-subtle); border: 1px solid var(--bc-border); border-radius: var(--bc-r-md);
|
|
208
210
|
}
|
|
209
211
|
.whoami.asking { display: block; padding: 14px; }
|
|
212
|
+
.whoami.asking .row input { background: var(--bc-bg); border-color: var(--bc-border); }
|
|
210
213
|
.whoami .who { flex: 1; min-width: 0; }
|
|
211
214
|
.whoami .who strong { color: var(--bc-fg); font-weight: 620; word-break: break-all; }
|
|
212
215
|
.link {
|
|
213
|
-
padding: 0; font: inherit; font-size: var(--bc-fs-sm); font-weight:
|
|
214
|
-
color: var(--bc-
|
|
216
|
+
padding: 0; font: inherit; font-size: var(--bc-fs-sm); font-weight: 560; line-height: 1.45;
|
|
217
|
+
color: var(--bc-fg); background: none; border: none; cursor: pointer; border-radius: 4px;
|
|
218
|
+
text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--bc-fg) 30%, transparent);
|
|
219
|
+
text-underline-offset: 3px;
|
|
215
220
|
}
|
|
216
|
-
.link:hover { text-decoration
|
|
221
|
+
.link:hover { text-decoration-color: currentColor; }
|
|
217
222
|
.link:disabled { color: var(--bc-faint); cursor: default; text-decoration: none; }
|
|
218
223
|
.whoami .why { margin: 0 0 10px; font-size: var(--bc-fs-sm); line-height: 1.5; color: var(--bc-muted); }
|
|
219
224
|
.whoami .why strong { color: var(--bc-fg); font-weight: 620; word-break: break-all; }
|
|
@@ -230,18 +235,17 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
230
235
|
assistant asking one friendly follow-up, not as a form field that appeared. */
|
|
231
236
|
.refs {
|
|
232
237
|
position: relative;
|
|
233
|
-
margin-bottom:
|
|
238
|
+
margin-bottom: 14px; padding: 14px;
|
|
234
239
|
font-size: var(--bc-fs-sm); line-height: 1.45; color: var(--bc-muted);
|
|
235
|
-
background: var(--bc-
|
|
236
|
-
border: 1px solid var(--bc-
|
|
240
|
+
background: var(--bc-subtle);
|
|
241
|
+
border: 1px solid var(--bc-border); border-radius: var(--bc-r-lg);
|
|
237
242
|
animation: bc-item-in 280ms var(--bc-ease) both;
|
|
238
243
|
}
|
|
239
244
|
.refs .ask-head { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 11px; }
|
|
240
|
-
.refs .ask-head
|
|
241
|
-
.refs .ask-head strong { display: block; font-size: 13.5px; font-weight: 650; color: var(--bc-fg); margin-bottom: 1px; }
|
|
245
|
+
.refs .ask-head strong { display: block; font-size: 13.5px; font-weight: 600; color: var(--bc-fg); margin-bottom: 1px; }
|
|
242
246
|
.refs .why { margin: 0; font-size: var(--bc-fs-sm); line-height: 1.5; color: var(--bc-muted); }
|
|
243
247
|
.refs .row { display: flex; gap: 8px; align-items: stretch; }
|
|
244
|
-
.refs .row input { flex: 1; min-width: 0; background: var(--bc-bg); }
|
|
248
|
+
.refs .row input { flex: 1; min-width: 0; background: var(--bc-bg); border-color: var(--bc-border); }
|
|
245
249
|
.refs select {
|
|
246
250
|
flex: none; max-width: 45%; padding: 10px 10px; font-size: 13px;
|
|
247
251
|
color: var(--bc-fg); background: var(--bc-bg);
|
|
@@ -269,40 +273,44 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
269
273
|
.ref-found svg { width: 14px; height: 14px; flex: none; color: var(--bc-ok); }
|
|
270
274
|
.ref-found b { font-weight: 600; color: var(--bc-fg); }
|
|
271
275
|
|
|
272
|
-
/* ---------- severity ----------
|
|
273
|
-
|
|
276
|
+
/* ---------- severity ----------
|
|
277
|
+
The segmented control from the product: a stone track, the choice lifted out
|
|
278
|
+
of it on white. */
|
|
279
|
+
.seg { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px; padding: 3px; background: var(--bc-stone); border-radius: 999px; }
|
|
274
280
|
.seg button {
|
|
275
281
|
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
276
|
-
padding:
|
|
277
|
-
color: var(--bc-muted); background: none; border: none; border-radius:
|
|
282
|
+
height: 30px; padding: 0 4px; font: inherit; font-size: var(--bc-fs-sm); font-weight: 520; line-height: 1;
|
|
283
|
+
color: var(--bc-muted); background: none; border: none; border-radius: 999px;
|
|
278
284
|
cursor: pointer; transition: background 180ms var(--bc-ease), color 180ms, box-shadow 180ms;
|
|
279
285
|
}
|
|
280
|
-
.seg button::before { content: ''; width:
|
|
281
|
-
.seg button[data-prio="LOW"] { --sev:
|
|
282
|
-
.seg button[data-prio="MEDIUM"] { --sev:
|
|
283
|
-
.seg button[data-prio="HIGH"] { --sev:
|
|
284
|
-
.seg button[data-prio="CRITICAL"] { --sev:
|
|
286
|
+
.seg button::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--sev, var(--bc-faint)); opacity: .5; transition: opacity 180ms; }
|
|
287
|
+
.seg button[data-prio="LOW"] { --sev: var(--bc-ok); }
|
|
288
|
+
.seg button[data-prio="MEDIUM"] { --sev: var(--bc-info); }
|
|
289
|
+
.seg button[data-prio="HIGH"] { --sev: var(--bc-warn); }
|
|
290
|
+
.seg button[data-prio="CRITICAL"] { --sev: var(--bc-danger); }
|
|
285
291
|
.seg button:hover { color: var(--bc-fg); }
|
|
286
292
|
.seg button[aria-pressed=true] {
|
|
287
|
-
background: var(--bc-raised); color: var(--bc-fg); font-weight:
|
|
288
|
-
box-shadow: 0 1px
|
|
293
|
+
background: var(--bc-raised); color: var(--bc-fg); font-weight: 600;
|
|
294
|
+
box-shadow: 0 1px 2px rgba(20,18,14,.10), 0 0 0 .5px rgba(20,18,14,.08);
|
|
289
295
|
}
|
|
290
296
|
.seg button[aria-pressed=true]::before { opacity: 1; }
|
|
291
297
|
.seg button:focus-visible { outline-offset: -2px; }
|
|
292
298
|
|
|
293
|
-
/* ---------- attachments ----------
|
|
294
|
-
|
|
299
|
+
/* ---------- attachments ----------
|
|
300
|
+
Three ring pills in a row: optional, so they take one line, not a band of
|
|
301
|
+
dashed drop zones. */
|
|
302
|
+
.tools { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
295
303
|
.tool {
|
|
296
|
-
display: inline-flex;
|
|
297
|
-
padding:
|
|
298
|
-
color: var(--bc-fg); background: var(--bc-
|
|
299
|
-
border: 1px
|
|
304
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
305
|
+
height: 32px; padding: 0 11px 0 9px; font: inherit; font-size: 12.5px; font-weight: 520; line-height: 1; white-space: nowrap;
|
|
306
|
+
color: var(--bc-fg); background: var(--bc-bg);
|
|
307
|
+
border: 1px solid var(--bc-border); border-radius: 999px; cursor: pointer;
|
|
300
308
|
transition: border-color 160ms, background 160ms, color 160ms, transform 160ms var(--bc-ease);
|
|
301
309
|
}
|
|
302
|
-
.tool svg { font-size:
|
|
303
|
-
.tool:hover:not(:disabled) {
|
|
304
|
-
.tool:hover:not(:disabled) svg { color: var(--bc-
|
|
305
|
-
.tool:active:not(:disabled) { transform:
|
|
310
|
+
.tool svg { font-size: 15px; color: var(--bc-muted); transition: color 160ms; }
|
|
311
|
+
.tool:hover:not(:disabled) { background: var(--bc-subtle); border-color: color-mix(in srgb, var(--bc-fg) 20%, var(--bc-border)); }
|
|
312
|
+
.tool:hover:not(:disabled) svg { color: var(--bc-fg); }
|
|
313
|
+
.tool:active:not(:disabled) { transform: scale(.97); }
|
|
306
314
|
.tool:disabled { opacity: .45; cursor: not-allowed; }
|
|
307
315
|
.attach-hint { margin: 8px 0 0; font-size: var(--bc-fs-xs); color: var(--bc-faint); }
|
|
308
316
|
|
|
@@ -353,7 +361,7 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
353
361
|
.foot {
|
|
354
362
|
flex: none;
|
|
355
363
|
display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
|
|
356
|
-
padding: 12px var(--bc-pad); border-top: 1px solid var(--bc-border);
|
|
364
|
+
padding: 12px 14px 12px var(--bc-pad); border-top: 1px solid var(--bc-border);
|
|
357
365
|
background: var(--bc-bg);
|
|
358
366
|
}
|
|
359
367
|
.foot .spacer { flex: 1; }
|
|
@@ -366,36 +374,39 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
366
374
|
size, and dimming it on top of that left it as a smudge in both themes. */
|
|
367
375
|
.powered {
|
|
368
376
|
flex: none; display: flex; align-items: center; justify-content: center; gap: 6px;
|
|
369
|
-
padding:
|
|
370
|
-
background: var(--bc-
|
|
377
|
+
padding: 0 var(--bc-pad) 10px; font-size: 10.5px; color: var(--bc-faint);
|
|
378
|
+
background: var(--bc-bg);
|
|
371
379
|
}
|
|
372
380
|
.brand-credit { display: flex; align-items: center; transition: color 0.15s; border-radius: 4px; }
|
|
373
|
-
.bc-brand { height:
|
|
381
|
+
.bc-brand { height: 15px; width: auto; display: block; color: var(--bc-brand-ink); }
|
|
374
382
|
.brand-credit:hover .bc-brand { color: var(--bc-fg); }
|
|
383
|
+
/* The product's two pills: ink for the one thing to do, a white ring for the
|
|
384
|
+
alternative. Flat — no glow, no lift. */
|
|
375
385
|
button.ghost, button.primary {
|
|
376
386
|
display: inline-flex; align-items: center; justify-content: center; gap: 7px;
|
|
377
|
-
height: 38px; padding: 0 15px; font: inherit; font-size:
|
|
387
|
+
height: 38px; padding: 0 15px; font: inherit; font-size: 13.5px; font-weight: 560; line-height: 1;
|
|
378
388
|
border-radius: 999px; cursor: pointer; white-space: nowrap;
|
|
379
389
|
transition: transform 160ms var(--bc-ease), filter 160ms, background 160ms, border-color 160ms, color 160ms, box-shadow 160ms;
|
|
380
390
|
}
|
|
381
|
-
button.ghost { background: var(--bc-bg); border:
|
|
382
|
-
button.ghost:hover:not(:disabled) { background: var(--bc-subtle);
|
|
391
|
+
button.ghost { background: var(--bc-bg); border: 0; color: var(--bc-fg); box-shadow: 0 0 0 1px var(--bc-border), 0 1px 2px rgba(20,18,14,.05); }
|
|
392
|
+
button.ghost:hover:not(:disabled) { background: var(--bc-subtle); }
|
|
383
393
|
button.ghost svg, button.primary svg { font-size: 15px; }
|
|
384
394
|
button.primary {
|
|
385
395
|
padding: 0 18px;
|
|
386
|
-
background: var(--bc-accent); border:
|
|
387
|
-
box-shadow: 0
|
|
396
|
+
background: var(--bc-accent); border: 0; color: var(--bc-on-accent);
|
|
397
|
+
box-shadow: 0 1px 2px rgba(0,0,0,.14);
|
|
388
398
|
}
|
|
389
|
-
button.primary:hover:not(:disabled) {
|
|
390
|
-
button.primary:active:not(:disabled) { transform:
|
|
391
|
-
button:disabled { opacity: .
|
|
399
|
+
button.primary:hover:not(:disabled) { filter: brightness(1.12) contrast(.96); }
|
|
400
|
+
button.primary:active:not(:disabled) { transform: scale(.98); }
|
|
401
|
+
button:disabled { opacity: .45; cursor: not-allowed; }
|
|
392
402
|
button.primary:disabled { box-shadow: none; }
|
|
393
|
-
button.primary .spinner { border-color:
|
|
403
|
+
button.primary .spinner { border-color: color-mix(in srgb, var(--bc-on-accent) 40%, transparent); border-top-color: var(--bc-on-accent); width: 14px; height: 14px; }
|
|
394
404
|
button.quiet {
|
|
395
|
-
padding: 0 4px; height: 38px; font: inherit; font-size: 13px; font-weight:
|
|
405
|
+
padding: 0 4px; height: 38px; font: inherit; font-size: 13px; font-weight: 520;
|
|
396
406
|
border: none; background: none; color: var(--bc-muted); cursor: pointer; border-radius: 8px;
|
|
407
|
+
text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 3px;
|
|
397
408
|
}
|
|
398
|
-
button.quiet:hover { color: var(--bc-
|
|
409
|
+
button.quiet:hover { color: var(--bc-fg); text-decoration-color: color-mix(in srgb, var(--bc-fg) 35%, transparent); }
|
|
399
410
|
|
|
400
411
|
/* ---------- your reports ---------- */
|
|
401
412
|
.history {
|
|
@@ -415,13 +426,13 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
415
426
|
.history .row:last-child { border-bottom: 0; }
|
|
416
427
|
.history .who { flex: 1; min-width: 0; }
|
|
417
428
|
.history .ttl {
|
|
418
|
-
display: block; font-size: 13.5px; font-weight:
|
|
429
|
+
display: block; font-size: 13.5px; font-weight: 560; color: var(--bc-fg);
|
|
419
430
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
420
431
|
}
|
|
421
432
|
.history .sub { display: block; margin-top: 3px; font-size: var(--bc-fs-xs); color: var(--bc-faint); }
|
|
422
433
|
.history .row-ico {
|
|
423
434
|
flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 10px;
|
|
424
|
-
background: var(--bc-
|
|
435
|
+
background: var(--bc-stone); color: var(--bc-muted); font-size: 16px;
|
|
425
436
|
}
|
|
426
437
|
.history .chev { flex: none; color: var(--bc-faint); font-size: 15px; transition: transform 160ms var(--bc-ease), color 160ms; }
|
|
427
438
|
.empty {
|
|
@@ -430,7 +441,7 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
430
441
|
}
|
|
431
442
|
.empty .empty-ico {
|
|
432
443
|
display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%;
|
|
433
|
-
background: var(--bc-
|
|
444
|
+
background: var(--bc-stone); color: var(--bc-fg); font-size: 20px;
|
|
434
445
|
}
|
|
435
446
|
.skel {
|
|
436
447
|
display: block; height: 12px; border-radius: 6px; margin: 6px 0;
|
|
@@ -446,7 +457,7 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
446
457
|
animation: bc-rise 260ms var(--bc-ease) both;
|
|
447
458
|
}
|
|
448
459
|
.history button.row:hover { background: var(--bc-subtle); }
|
|
449
|
-
.history button.row:hover .chev { transform: translateX(2px); color: var(--bc-
|
|
460
|
+
.history button.row:hover .chev { transform: translateX(2px); color: var(--bc-fg); }
|
|
450
461
|
.history button.row:focus-visible { outline-offset: -2px; }
|
|
451
462
|
|
|
452
463
|
/* ---------- one report, and what happened to it ---------- */
|
|
@@ -456,7 +467,7 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
456
467
|
padding: 10px var(--bc-pad); border-bottom: 1px solid var(--bc-border);
|
|
457
468
|
background: var(--bc-bg);
|
|
458
469
|
}
|
|
459
|
-
.report-head .ttl { font-size:
|
|
470
|
+
.report-head .ttl { font-size: 13.5px; font-weight: 600; color: var(--bc-fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
460
471
|
.report-head .sub { font-size: var(--bc-fs-xs); color: var(--bc-faint); }
|
|
461
472
|
.report-head .pill { grid-row: 1 / span 2; grid-column: 2; align-self: center; }
|
|
462
473
|
|
|
@@ -490,9 +501,9 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
490
501
|
border-radius: 50%; background: var(--bc-muted); vertical-align: middle;
|
|
491
502
|
}
|
|
492
503
|
.sys .t { color: var(--bc-faint); }
|
|
493
|
-
.sys.k-status .dot { background:
|
|
494
|
-
.sys.k-severity .dot { background:
|
|
495
|
-
.sys.k-assignment .dot { background:
|
|
504
|
+
.sys.k-status .dot { background: var(--bc-info); }
|
|
505
|
+
.sys.k-severity .dot { background: var(--bc-warn); }
|
|
506
|
+
.sys.k-assignment .dot { background: var(--bc-brand-mark); }
|
|
496
507
|
.sys.k-filed .dot { background: var(--bc-faint); }
|
|
497
508
|
|
|
498
509
|
/* ---------- the conversation ----------
|
|
@@ -525,24 +536,21 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
525
536
|
.msg-row.mine > * { grid-column: 1; }
|
|
526
537
|
.av {
|
|
527
538
|
display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%;
|
|
528
|
-
font-size: 11px; font-weight:
|
|
529
|
-
background:
|
|
530
|
-
}
|
|
531
|
-
.av.bot {
|
|
532
|
-
background: linear-gradient(140deg, var(--bc-accent), color-mix(in srgb, var(--bc-accent) 60%, #fff));
|
|
533
|
-
color: var(--bc-on-accent); font-size: 14px;
|
|
539
|
+
font-size: 11px; font-weight: 650; letter-spacing: .02em;
|
|
540
|
+
background: var(--bc-stone); color: var(--bc-fg);
|
|
534
541
|
}
|
|
535
|
-
.
|
|
536
|
-
.msg-who
|
|
542
|
+
.av.bot { width: 28px; }
|
|
543
|
+
.msg-who { font-size: var(--bc-fs-xs); font-weight: 560; color: var(--bc-muted); padding: 0 4px 4px; }
|
|
544
|
+
.msg-who.auto { color: var(--bc-fg); display: inline-flex; align-items: center; gap: 5px; }
|
|
537
545
|
.msg-who .tag {
|
|
538
|
-
padding: 1px 6px; border-radius: 999px; font-size: 9.5px; font-weight:
|
|
539
|
-
text-transform: uppercase; background: var(--bc-
|
|
546
|
+
padding: 1px 6px; border-radius: 999px; font-size: 9.5px; font-weight: 650; letter-spacing: .05em;
|
|
547
|
+
text-transform: uppercase; background: var(--bc-stone); color: var(--bc-muted);
|
|
540
548
|
}
|
|
541
549
|
.bubble {
|
|
542
550
|
justify-self: start; max-width: 100%;
|
|
543
551
|
padding: 9px 13px; border-radius: 18px; font-size: 13.5px; line-height: 1.5;
|
|
544
|
-
background: var(--bc-
|
|
545
|
-
border: 1px solid
|
|
552
|
+
background: var(--bc-stone); color: var(--bc-fg);
|
|
553
|
+
border: 1px solid transparent;
|
|
546
554
|
border-bottom-left-radius: 6px;
|
|
547
555
|
}
|
|
548
556
|
/* pre-wrap belongs to the text, not the box — on the box it would also render
|
|
@@ -555,9 +563,10 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
555
563
|
}
|
|
556
564
|
.msg-row.cont.theirs .bubble { border-top-left-radius: 6px; }
|
|
557
565
|
.msg-row.cont.mine .bubble { border-top-right-radius: 6px; }
|
|
558
|
-
/* A reply nobody wrote:
|
|
559
|
-
it, so it reads the same to someone who cannot
|
|
560
|
-
|
|
566
|
+
/* A reply nobody wrote: drawn on white with a hairline, beside the orb and
|
|
567
|
+
labelled "Assistant" above it, so it reads the same to someone who cannot
|
|
568
|
+
see the difference at all. */
|
|
569
|
+
.msg-row.auto .bubble { background: var(--bc-bg); border-color: var(--bc-border); }
|
|
561
570
|
/* An attachment-only message has no text to wrap, so the bubble would be an
|
|
562
571
|
empty coloured box around it. */
|
|
563
572
|
.bubble.silent { padding: 0; background: none !important; border: 0; }
|
|
@@ -571,7 +580,7 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
571
580
|
/* The assistant, thinking. Three dots in a bubble where its next message will be. */
|
|
572
581
|
.typing { display: inline-flex; align-items: center; gap: 4px; padding: 12px 14px; justify-self: start; }
|
|
573
582
|
.typing i {
|
|
574
|
-
width:
|
|
583
|
+
width: 6px; height: 6px; border-radius: 50%; background: var(--bc-muted); opacity: .45;
|
|
575
584
|
animation: bc-typing 1.2s ease-in-out infinite;
|
|
576
585
|
}
|
|
577
586
|
.typing i:nth-child(2) { animation-delay: .15s; }
|
|
@@ -607,30 +616,29 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
607
616
|
background: var(--bc-subtle);
|
|
608
617
|
transition: background 400ms ease, border-color 400ms ease;
|
|
609
618
|
}
|
|
610
|
-
.assistant.
|
|
611
|
-
background: var(--bc-accent-soft); border-color: var(--bc-accent-line);
|
|
612
|
-
}
|
|
613
|
-
.assistant.resolved { background: color-mix(in srgb, var(--bc-ok) 9%, var(--bc-bg)); border-color: color-mix(in srgb, var(--bc-ok) 35%, var(--bc-border)); }
|
|
619
|
+
.assistant.resolved { background: color-mix(in srgb, var(--bc-ok) 7%, var(--bc-bg)); border-color: color-mix(in srgb, var(--bc-ok) 30%, var(--bc-border)); }
|
|
614
620
|
/* On a call: the call's own card is what they are watching. This one states
|
|
615
|
-
what is happening and stops moving — no
|
|
621
|
+
what is happening and stops moving — no breathing orb, no travelling bar. */
|
|
616
622
|
.assistant.calling { background: var(--bc-bg); }
|
|
617
623
|
.assistant.calling .as-progress i { transition: none; }
|
|
618
624
|
.as-body.entering { animation: bc-rise 360ms var(--bc-ease) both; }
|
|
619
625
|
.as-top { display: flex; gap: 11px; align-items: center; }
|
|
626
|
+
/* The orb, while the assistant is at work; a plain disc with a glyph once it
|
|
627
|
+
is on a call or has finished. */
|
|
620
628
|
.as-orb {
|
|
621
629
|
flex: none; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
|
|
622
|
-
color: var(--bc-on-accent); font-size: 15px;
|
|
623
|
-
background: linear-gradient(140deg, var(--bc-accent), color-mix(in srgb, var(--bc-accent) 60%, #fff));
|
|
630
|
+
color: var(--bc-on-accent); font-size: 15px; background: var(--bc-accent);
|
|
624
631
|
}
|
|
625
|
-
.
|
|
626
|
-
.assistant.
|
|
627
|
-
|
|
628
|
-
|
|
632
|
+
.as-orb.orb { background: var(--bc-o2); }
|
|
633
|
+
.assistant.analyzing .as-orb.orb { animation: as-breathe 2.4s ease-in-out infinite; }
|
|
634
|
+
@keyframes as-breathe { 50% { transform: scale(.88); } }
|
|
635
|
+
.assistant.resolved .as-orb { background: var(--bc-ok); color: #fff; }
|
|
636
|
+
.assistant.reviewing .as-orb.orb { filter: saturate(.35); }
|
|
629
637
|
.as-text { min-width: 0; flex: 1; }
|
|
630
|
-
.as-title { font-weight:
|
|
638
|
+
.as-title { font-weight: 600; font-size: 13.5px; letter-spacing: -.01em; color: var(--bc-fg); }
|
|
631
639
|
.as-detail { font-size: 12px; line-height: 1.45; color: var(--bc-muted); margin-top: 2px; }
|
|
632
640
|
.as-progress {
|
|
633
|
-
height:
|
|
641
|
+
height: 3px; margin: 12px 0 0; border-radius: 999px; overflow: hidden;
|
|
634
642
|
background: color-mix(in srgb, var(--bc-fg) 9%, transparent);
|
|
635
643
|
}
|
|
636
644
|
.as-progress i {
|
|
@@ -639,39 +647,42 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
639
647
|
}
|
|
640
648
|
.assistant.resolved .as-progress i { background: var(--bc-ok); }
|
|
641
649
|
.assistant.analyzing .as-progress i {
|
|
642
|
-
background: linear-gradient(90deg, var(--bc-accent) 0%, color-mix(in srgb, var(--bc-accent)
|
|
650
|
+
background: linear-gradient(90deg, var(--bc-accent) 0%, color-mix(in srgb, var(--bc-accent) 35%, var(--bc-bg)) 50%, var(--bc-accent) 100%);
|
|
643
651
|
background-size: 200% 100%; animation: bc-shimmer 1.6s linear infinite;
|
|
644
652
|
}
|
|
653
|
+
/* Four short labels under the bar. Allowed to wrap rather than be cut: at this
|
|
654
|
+
width "Report received" ellipsised to "Report recei…". */
|
|
645
655
|
.as-steps {
|
|
646
|
-
list-style: none; display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px;
|
|
647
|
-
margin: 8px 0 0; padding: 0; font-size: 10.5px; color: var(--bc-faint);
|
|
656
|
+
list-style: none; display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px 6px;
|
|
657
|
+
margin: 8px 0 0; padding: 0; font-size: 10.5px; line-height: 1.3; color: var(--bc-faint);
|
|
648
658
|
}
|
|
649
|
-
.as-steps li { display: flex; align-items:
|
|
650
|
-
.as-steps li .lbl { min-width: 0; overflow
|
|
651
|
-
.as-steps li .dot { flex: none; width:
|
|
659
|
+
.as-steps li { display: flex; align-items: flex-start; gap: 5px; min-width: 0; }
|
|
660
|
+
.as-steps li .lbl { min-width: 0; overflow-wrap: anywhere; }
|
|
661
|
+
.as-steps li .dot { flex: none; width: 7px; height: 7px; margin-top: 3px; border-radius: 50%; border: 1.5px solid currentColor; }
|
|
652
662
|
.as-steps li.done { color: var(--bc-muted); }
|
|
653
663
|
.as-steps li.done .dot { background: var(--bc-accent); border-color: var(--bc-accent); }
|
|
654
664
|
.assistant.resolved .as-steps li.done .dot { background: var(--bc-ok); border-color: var(--bc-ok); }
|
|
655
|
-
.as-steps li.active { color: var(--bc-fg); font-weight:
|
|
665
|
+
.as-steps li.active { color: var(--bc-fg); font-weight: 600; }
|
|
656
666
|
.as-steps li.active .dot { border-color: var(--bc-accent); background: var(--bc-bg); animation: as-pulse 1.2s ease-in-out infinite; }
|
|
657
|
-
@keyframes as-pulse { 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--bc-accent)
|
|
658
|
-
@media (prefers-reduced-motion: reduce) { .as-
|
|
667
|
+
@keyframes as-pulse { 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--bc-accent) 18%, transparent); } }
|
|
668
|
+
@media (prefers-reduced-motion: reduce) { .as-orb, .as-steps li.active .dot, .assistant.analyzing .as-progress i, .typing i { animation: none; } }
|
|
659
669
|
|
|
660
670
|
/* Quick answers under the confirm question — only on the latest message. */
|
|
661
671
|
.msg-row .quick { display: none; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
|
|
662
672
|
.msg-row:last-child .quick { display: flex; }
|
|
663
673
|
.quick button {
|
|
664
674
|
display: inline-flex; align-items: center; gap: 6px;
|
|
665
|
-
font: inherit; font-size: 13px; font-weight:
|
|
666
|
-
border:
|
|
675
|
+
font: inherit; font-size: 13px; font-weight: 560; height: 34px; padding: 0 14px; border-radius: 999px; cursor: pointer;
|
|
676
|
+
border: 0; background: var(--bc-bg); color: var(--bc-fg); box-shadow: 0 0 0 1px var(--bc-border);
|
|
667
677
|
transition: background 160ms, color 160ms, transform 160ms var(--bc-ease);
|
|
668
678
|
animation: bc-item-in 300ms var(--bc-ease) both;
|
|
669
679
|
}
|
|
670
|
-
.quick button:first-child { background: var(--bc-accent); color: var(--bc-on-accent); }
|
|
680
|
+
.quick button:first-child { background: var(--bc-accent); color: var(--bc-on-accent); box-shadow: none; }
|
|
671
681
|
.quick button:nth-child(2) { animation-delay: 60ms; }
|
|
672
682
|
.quick button svg { font-size: 13px; }
|
|
673
|
-
.quick button:hover {
|
|
674
|
-
.quick button:first-child:hover { background: var(--bc-accent); filter: brightness(1.
|
|
683
|
+
.quick button:hover { background: var(--bc-subtle); }
|
|
684
|
+
.quick button:first-child:hover { background: var(--bc-accent); filter: brightness(1.12) contrast(.96); }
|
|
685
|
+
.quick button:active { transform: scale(.97); }
|
|
675
686
|
|
|
676
687
|
/* ---------- the composer ---------- */
|
|
677
688
|
.composer {
|
|
@@ -688,10 +699,10 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
688
699
|
.composer .row {
|
|
689
700
|
display: flex; align-items: flex-end; gap: 4px;
|
|
690
701
|
padding: 5px; border-radius: 22px;
|
|
691
|
-
background: var(--bc-
|
|
692
|
-
transition: border-color 160ms, box-shadow 160ms;
|
|
702
|
+
background: var(--bc-stone); border: 1px solid transparent;
|
|
703
|
+
transition: border-color 160ms, box-shadow 160ms, background 160ms;
|
|
693
704
|
}
|
|
694
|
-
.composer .row:focus-within { border-color: var(--bc-accent); box-shadow: var(--bc-ring); }
|
|
705
|
+
.composer .row:focus-within { background: var(--bc-bg); border-color: var(--bc-accent); box-shadow: var(--bc-ring); }
|
|
695
706
|
.composer textarea {
|
|
696
707
|
flex: 1; min-width: 0; min-height: 34px; max-height: 120px; resize: none; padding: 7px 6px;
|
|
697
708
|
font: inherit; font-size: 13.5px; line-height: 1.45;
|
|
@@ -716,8 +727,8 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
716
727
|
display: grid; place-items: center;
|
|
717
728
|
transition: transform 160ms var(--bc-ease), opacity 160ms, filter 160ms;
|
|
718
729
|
}
|
|
719
|
-
.composer .send:hover:not(:disabled) { filter: brightness(1.
|
|
720
|
-
.composer .send:disabled { opacity: .
|
|
730
|
+
.composer .send:hover:not(:disabled) { filter: brightness(1.12) contrast(.96); transform: scale(1.04); }
|
|
731
|
+
.composer .send:disabled { opacity: .3; cursor: default; background: var(--bc-faint); }
|
|
721
732
|
.composer .staged { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 0 8px; }
|
|
722
733
|
.composer .chip {
|
|
723
734
|
display: flex; align-items: center; gap: 6px; max-width: 200px;
|
|
@@ -740,23 +751,16 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
740
751
|
lands on — which is what someone opening this screen came to check. */
|
|
741
752
|
.pill {
|
|
742
753
|
flex: none; display: inline-flex; align-items: center; gap: 5px;
|
|
743
|
-
font-size: 11px; font-weight:
|
|
754
|
+
font-size: 11px; font-weight: 600;
|
|
744
755
|
padding: 3px 9px; border-radius: 999px;
|
|
745
|
-
color: var(--bc-muted); background: var(--bc-
|
|
756
|
+
color: var(--bc-muted); background: var(--bc-stone);
|
|
746
757
|
}
|
|
747
758
|
.pill::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
|
748
|
-
|
|
749
|
-
.pill.
|
|
750
|
-
.pill.
|
|
759
|
+
/* The theme's own status colours, which already have a dark cut. */
|
|
760
|
+
.pill.open { color: var(--bc-warn); background: color-mix(in srgb, var(--bc-warn) 12%, var(--bc-bg)); }
|
|
761
|
+
.pill.in_progress { color: var(--bc-info); background: color-mix(in srgb, var(--bc-info) 12%, var(--bc-bg)); }
|
|
762
|
+
.pill.resolved { color: var(--bc-ok); background: color-mix(in srgb, var(--bc-ok) 12%, var(--bc-bg)); }
|
|
751
763
|
.pill.closed { color: var(--bc-muted); }
|
|
752
|
-
:host(.bc-dark) .pill.open { color: #fbbf24; }
|
|
753
|
-
:host(.bc-dark) .pill.in_progress { color: #7cb8ff; }
|
|
754
|
-
:host(.bc-dark) .pill.resolved { color: #4ade9a; }
|
|
755
|
-
@media (prefers-color-scheme: dark) {
|
|
756
|
-
:host(.bc-auto) .pill.open { color: #fbbf24; }
|
|
757
|
-
:host(.bc-auto) .pill.in_progress { color: #7cb8ff; }
|
|
758
|
-
:host(.bc-auto) .pill.resolved { color: #4ade9a; }
|
|
759
|
-
}
|
|
760
764
|
|
|
761
765
|
/* ---------- does the fix work ---------- */
|
|
762
766
|
.fix-verification {
|
|
@@ -776,6 +780,75 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
776
780
|
.fix-verification .feedback-status { margin: 6px 0 0; font-weight: 450; color: var(--bc-danger); font-size: var(--bc-fs-xs); }
|
|
777
781
|
.fix-verification .feedback-status:empty { display: none; }
|
|
778
782
|
|
|
783
|
+
/* ---------- how did we do ----------
|
|
784
|
+
Quieter than the card above it: that one asks whether the fix works, which
|
|
785
|
+
the team acts on; this asks how it felt, which they learn from. The stars
|
|
786
|
+
carry the only colour, so the one thing to do here is the thing you see. */
|
|
787
|
+
.fix-rating {
|
|
788
|
+
--bc-star: #f0a81c;
|
|
789
|
+
flex: none; margin: 10px 12px 0; padding: 12px 14px;
|
|
790
|
+
border-radius: var(--bc-r-lg); border: 1px solid var(--bc-border); background: var(--bc-bg);
|
|
791
|
+
font-size: var(--bc-fs-sm); color: var(--bc-fg);
|
|
792
|
+
animation: bc-rise 280ms var(--bc-ease) both;
|
|
793
|
+
}
|
|
794
|
+
.fix-rating .fr-q { margin: 0 0 6px; font-weight: 620; }
|
|
795
|
+
.fix-rating .stars { display: flex; gap: 2px; margin: 0 0 2px -4px; }
|
|
796
|
+
.fix-rating .stars button {
|
|
797
|
+
display: inline-grid; place-items: center; width: 34px; height: 34px; padding: 0;
|
|
798
|
+
border: 0; border-radius: 8px; background: transparent; cursor: pointer;
|
|
799
|
+
color: color-mix(in srgb, var(--bc-fg) 18%, transparent);
|
|
800
|
+
transition: color 120ms ease, transform 120ms var(--bc-ease);
|
|
801
|
+
}
|
|
802
|
+
.fix-rating .stars button svg { width: 24px; height: 24px; }
|
|
803
|
+
.fix-rating .stars button.on { color: var(--bc-star); }
|
|
804
|
+
.fix-rating .stars button:hover:not(:disabled) { transform: scale(1.08); }
|
|
805
|
+
.fix-rating .stars button:focus-visible { outline: none; box-shadow: var(--bc-ring); }
|
|
806
|
+
.fix-rating .stars button:disabled { cursor: default; }
|
|
807
|
+
.fix-rating .fr-hint { margin: 2px 0 0; font-size: var(--bc-fs-xs); color: var(--bc-faint); }
|
|
808
|
+
.fix-rating .fr-said { margin: 6px 0 0; font-size: 13px; color: var(--bc-muted); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
809
|
+
.fix-rating .fr-note { margin-top: 8px; }
|
|
810
|
+
.fix-rating .fr-note textarea { min-height: 52px; margin-bottom: 8px; font-size: 13px; }
|
|
811
|
+
.fix-rating .fr-note button {
|
|
812
|
+
padding: 7px 13px; font: inherit; font-size: 12.5px; font-weight: 620; border-radius: 999px; cursor: pointer;
|
|
813
|
+
border: 1px solid var(--bc-border); background: var(--bc-bg); color: var(--bc-fg);
|
|
814
|
+
}
|
|
815
|
+
.fix-rating .feedback-status { margin: 6px 0 0; color: var(--bc-danger); font-size: var(--bc-fs-xs); }
|
|
816
|
+
.fix-rating .feedback-status:empty { display: none; }
|
|
817
|
+
@media (prefers-reduced-motion: reduce) { .fix-rating .stars button { transition: none; } .fix-rating .stars button:hover { transform: none; } }
|
|
818
|
+
|
|
819
|
+
/* The rating on a history row: the score given, or a nudge to give one. */
|
|
820
|
+
.history .sub .rated { display: inline-flex; align-items: center; gap: 2px; color: var(--bc-muted); font-weight: 600; }
|
|
821
|
+
.history .sub .rated svg { width: 11px; height: 11px; color: #f0a81c; }
|
|
822
|
+
.history .sub .rate-ask { color: var(--bc-fg); font-weight: 600; }
|
|
823
|
+
|
|
824
|
+
/* ---------- a settled report waiting for its rating ----------
|
|
825
|
+
Above the form on the first screen: the same stars as under a report's
|
|
826
|
+
conversation, with the report they are about named on top. */
|
|
827
|
+
.rate-due { margin: 0 0 14px; }
|
|
828
|
+
.rate-due:focus { outline: none; }
|
|
829
|
+
.rate-due:focus-visible { box-shadow: var(--bc-ring); }
|
|
830
|
+
.rate-due .rd-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 0 0 8px; }
|
|
831
|
+
.rate-due .rd-eyebrow {
|
|
832
|
+
font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--bc-faint);
|
|
833
|
+
}
|
|
834
|
+
.rate-due.is-required .rd-eyebrow { color: var(--bc-fg); }
|
|
835
|
+
.rate-due .rd-later { font-size: var(--bc-fs-xs); color: var(--bc-muted); }
|
|
836
|
+
.rate-due .rd-report {
|
|
837
|
+
display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 9px; align-items: center;
|
|
838
|
+
margin: 0 0 10px; padding: 0 0 10px; border-bottom: 1px solid var(--bc-border);
|
|
839
|
+
}
|
|
840
|
+
.rate-due .rd-ico {
|
|
841
|
+
grid-row: span 2; display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 999px;
|
|
842
|
+
background: color-mix(in srgb, var(--bc-ok) 14%, transparent); color: var(--bc-ok);
|
|
843
|
+
}
|
|
844
|
+
.rate-due .rd-ico svg { width: 13px; height: 13px; }
|
|
845
|
+
.rate-due .rd-ttl { font-weight: 620; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
846
|
+
.rate-due .rd-sub { font-size: var(--bc-fs-xs); color: var(--bc-muted); }
|
|
847
|
+
|
|
848
|
+
/* What a required rating is holding: still in sight, plainly not yet. */
|
|
849
|
+
.held { opacity: .42; transition: opacity 200ms ease; }
|
|
850
|
+
@media (prefers-reduced-motion: reduce) { .held { transition: none; } }
|
|
851
|
+
|
|
779
852
|
/* A call in progress, in place of the form.
|
|
780
853
|
---------------------------------------------------------------------------
|
|
781
854
|
Deliberately not styled as a chat. Nothing arrives here to read — the
|
|
@@ -825,13 +898,13 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
825
898
|
and this screen's padding was landing on every one of them. */
|
|
826
899
|
div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 240ms ease both; }
|
|
827
900
|
.done .tick {
|
|
828
|
-
width:
|
|
829
|
-
display: grid; place-items: center; font-size:
|
|
830
|
-
background:
|
|
831
|
-
box-shadow: 0 0 0
|
|
901
|
+
width: 52px; height: 52px; margin: 0 auto 16px; border-radius: 50%;
|
|
902
|
+
display: grid; place-items: center; font-size: 24px;
|
|
903
|
+
background: var(--bc-ok); color: #fff;
|
|
904
|
+
box-shadow: 0 0 0 7px color-mix(in srgb, var(--bc-ok) 12%, transparent);
|
|
832
905
|
animation: bc-pop 420ms var(--bc-ease) both;
|
|
833
906
|
}
|
|
834
|
-
.done h3 { margin: 0 0 6px; font-size:
|
|
907
|
+
.done h3 { margin: 0 0 6px; font-size: 18px; font-weight: 600; letter-spacing: -.02em; }
|
|
835
908
|
.done p { margin: 0; font-size: 13px; line-height: 1.5; color: var(--bc-muted); }
|
|
836
909
|
.done code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; padding: 1px 5px; border-radius: 5px; background: var(--bc-subtle); color: var(--bc-fg); }
|
|
837
910
|
/* The likely wait. Set apart from the reference line above it by a rule rather
|
|
@@ -895,7 +968,7 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
895
968
|
is open — the sheet has its own close button, and a launcher floating over
|
|
896
969
|
the send button would be in the way of the one thing that matters. */
|
|
897
970
|
@media (max-width: 480px) {
|
|
898
|
-
.scrim { background: rgba(
|
|
971
|
+
.scrim { background: rgba(14,14,16,.4); }
|
|
899
972
|
.panel, .scrim.at-right .panel, .scrim.at-left .panel, .scrim.at-bottom .panel, .scrim.at-top .panel {
|
|
900
973
|
inset: 0; width: 100%; max-width: none; height: 100%; max-height: none;
|
|
901
974
|
border-radius: 0; border: 0;
|
|
@@ -910,6 +983,16 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
910
983
|
.foot:has(+ .powered) { padding-bottom: 12px; }
|
|
911
984
|
.recbar .hint { display: none; }
|
|
912
985
|
.msg-row, .typing-row { max-width: 92%; }
|
|
986
|
+
/* The question chips are one row that scrolls sideways, edge to edge, rather
|
|
987
|
+
than three stacked rows pushing the form down the screen. */
|
|
988
|
+
.picks .picks-grid {
|
|
989
|
+
flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
|
|
990
|
+
margin: 0 calc(var(--bc-pad) * -1); padding: 0 var(--bc-pad) 2px;
|
|
991
|
+
scroll-snap-type: x proximity; scroll-padding: 0 var(--bc-pad);
|
|
992
|
+
}
|
|
993
|
+
.picks .picks-grid::-webkit-scrollbar { display: none; }
|
|
994
|
+
.picks .pick { flex: none; scroll-snap-align: start; }
|
|
995
|
+
.picks .pick .t { white-space: nowrap; }
|
|
913
996
|
}
|
|
914
997
|
|
|
915
998
|
@media (pointer: coarse) {
|
|
@@ -924,7 +1007,8 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
924
1007
|
under it, on the one surface in the product designed for someone who is
|
|
925
1008
|
not an operator and gets no second attempt. */
|
|
926
1009
|
.seg button { min-height: 44px; }
|
|
927
|
-
.tool { min-height:
|
|
1010
|
+
.tool, .known .issue .join { min-height: 44px; }
|
|
1011
|
+
.picks .pick { min-height: 40px; }
|
|
928
1012
|
button.primary, button.ghost { height: 44px; }
|
|
929
1013
|
.composer .send, .composer .tool { width: 40px; height: 40px; min-height: 0; }
|
|
930
1014
|
textarea { min-height: 104px; }
|
|
@@ -933,7 +1017,7 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
933
1017
|
/* The close button and the thumbnails' remove buttons are small glyphs whose
|
|
934
1018
|
boxes cannot grow without moving what is beside them, so each keeps its
|
|
935
1019
|
size and gets an invisible target drawn around it instead. The theme
|
|
936
|
-
|
|
1020
|
+
button in the header is one of these. */
|
|
937
1021
|
.head .icon-btn, .thumb .drop, .brand-credit { position: relative; }
|
|
938
1022
|
.thumb .drop { position: absolute; opacity: 1; }
|
|
939
1023
|
.head .icon-btn::after, .thumb .drop::after, .brand-credit::after {
|
|
@@ -947,26 +1031,28 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
947
1031
|
@media (hover: none) {
|
|
948
1032
|
.tool:hover:not(:disabled) { transform: none; }
|
|
949
1033
|
}
|
|
950
|
-
`;function
|
|
1034
|
+
`;function re({title:e,sub:t,id:a="",back:r=!1,theme:s=""}){return`
|
|
951
1035
|
<div class="head">
|
|
952
|
-
${
|
|
953
|
-
<
|
|
1036
|
+
${r?`<button class="icon-btn back" type="button" data-act="back" aria-label="Back to your reports">${Pe}</button>`:""}
|
|
1037
|
+
<span class="orb mark" aria-hidden="true"></span>
|
|
954
1038
|
<div class="titles">
|
|
955
1039
|
<h2${a?` id="${a}"`:""}>${k(e)}</h2>
|
|
956
1040
|
<p>${k(t)}</p>
|
|
957
1041
|
</div>
|
|
1042
|
+
${s?`<button class="icon-btn theme" type="button" data-act="theme" title="Theme: ${k(s)}"
|
|
1043
|
+
aria-label="Theme: ${k(s)}. Change theme"><span class="m-light">${De}</span><span class="m-dark">${je}</span><span class="m-auto">${Ve}</span></button>`:""}
|
|
958
1044
|
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${J}</button>
|
|
959
|
-
</div>`}function
|
|
1045
|
+
</div>`}function ie(e,t){return`<div class="empty"><span class="empty-ico" aria-hidden="true">${t}</span>${k(e)}</div>`}function Ze(e){return Array.from({length:e},()=>`
|
|
960
1046
|
<div class="row" aria-hidden="true">
|
|
961
1047
|
<span class="row-ico"></span>
|
|
962
1048
|
<span class="who"><span class="skel" style="width:70%"></span><span class="skel" style="width:40%;height:9px"></span></span>
|
|
963
|
-
</div>`).join("")+'<span class="sr-only">Loading…</span>'}function
|
|
1049
|
+
</div>`).join("")+'<span class="sr-only">Loading…</span>'}function Ge(){return`
|
|
964
1050
|
<div aria-hidden="true" style="display:flex;flex-direction:column;gap:10px;padding-top:6px">
|
|
965
1051
|
<span class="skel" style="width:42%;height:34px;border-radius:16px;align-self:center"></span>
|
|
966
1052
|
<span class="skel" style="width:66%;height:52px;border-radius:18px"></span>
|
|
967
1053
|
<span class="skel" style="width:48%;height:38px;border-radius:18px;align-self:flex-end"></span>
|
|
968
1054
|
</div>
|
|
969
|
-
<span class="sr-only">Loading…</span>`}function
|
|
1055
|
+
<span class="sr-only">Loading…</span>`}function Xe(e){const t=String(e).trim().split(/\s+/).filter(Boolean);return t.length?(t[0][0]+(t.length>1?t[t.length-1][0]:"")).toUpperCase():"?"}function K(e){const t=new Date(e);return Number.isFinite(t.getTime())?`${t.getFullYear()}-${t.getMonth()}-${t.getDate()}`:null}function Je(e){const t=new Date(e),a=new Date,r=new Date(a.getFullYear(),a.getMonth(),a.getDate()-1);if(K(t)===K(a))return"Today";if(K(t)===K(r))return"Yesterday";try{return t.toLocaleDateString(void 0,{weekday:"short",day:"numeric",month:"short",...t.getFullYear()!==a.getFullYear()?{year:"numeric"}:{}})}catch{return Z(e)}}function me(e){const t=new Date(e);if(!Number.isFinite(t.getTime()))return"";try{return t.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit"})}catch{return""}}function ve(e){return e.scrollHeight-e.scrollTop-e.clientHeight<40}function U(e,{smooth:t=!1}={}){const a=typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches;t&&!a&&e.scrollTo?e.scrollTo({top:e.scrollHeight,behavior:"smooth"}):e.scrollTop=e.scrollHeight}function se(e){return{OPEN:"Open",IN_PROGRESS:"In progress",RESOLVED:"Fixed",CLOSED:"Closed"}[e]||String(e||"").toLowerCase()}function Z(e){const t=new Date(e).getTime();if(!Number.isFinite(t))return"";const a=Math.floor((Date.now()-t)/864e5);if(a<=0)return"today";if(a===1)return"yesterday";if(a<30)return`${a} days ago`;const r=Math.floor(a/30);return r===1?"a month ago":`${r} months ago`}function k(e){return String(e).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}typeof window<"u"&&window.fetch&&window.fetch.bind(window);const we=["image/png","image/jpeg","image/webp","image/gif","video/webm","video/mp4","audio/webm","audio/ogg","audio/mpeg","audio/mp4","audio/wav","application/pdf","text/plain","text/csv","application/json","application/zip","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],ye=["image/png","image/jpeg","image/webp","video/webm","video/mp4"],et=()=>{var e;return!!((e=navigator==null?void 0:navigator.mediaDevices)!=null&&e.getUserMedia&&typeof MediaRecorder<"u")},tt=()=>{var e;return!!((e=navigator==null?void 0:navigator.mediaDevices)!=null&&e.getDisplayMedia&&typeof MediaRecorder<"u")},at=()=>{var e;return!!((e=navigator==null?void 0:navigator.mediaDevices)!=null&&e.getDisplayMedia)};function nt(e,t=we){const a=String(e||"").split(";")[0].trim().toLowerCase();return t.includes(a)?a:null}async function ot(){const e=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:1},audio:!1});try{const t=e.getVideoTracks()[0],a=document.createElement("video");a.srcObject=e,a.muted=!0,a.playsInline=!0,await a.play(),await new Promise(c=>requestAnimationFrame(()=>requestAnimationFrame(c)));const{width:r,height:s}=t.getSettings(),h=document.createElement("canvas");h.width=r||a.videoWidth,h.height=s||a.videoHeight,h.getContext("2d").drawImage(a,0,0,h.width,h.height);const b=await new Promise(c=>h.toBlob(c,"image/png"));if(!b)throw new Error("The browser returned an empty screenshot.");return{blob:b,mime:"image/png",kind:"SCREENSHOT"}}finally{e.getTracks().forEach(t=>t.stop())}}async function rt({maxMs:e=12e4,onTick:t,onAutoStop:a}={}){const r=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:15},audio:!1}),s=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm"].find(d=>MediaRecorder.isTypeSupported(d))||"video/webm",h=new MediaRecorder(r,{mimeType:s,videoBitsPerSecond:25e5}),b=[];h.ondataavailable=d=>{d.data.size&&b.push(d.data)},h.start(1e3);const c=Date.now(),m=setInterval(()=>t==null?void 0:t(Math.floor((Date.now()-c)/1e3)),500),u=()=>{clearInterval(m),clearTimeout(i),r.getTracks().forEach(d=>d.stop())},f=new Promise(d=>{h.onstop=()=>{u(),d(new Blob(b,{type:s}))}}),S=()=>{h.state!=="inactive"&&h.stop(),a==null||a()};r.getVideoTracks()[0].addEventListener("ended",S);const i=setTimeout(S,e);return{mime:s,maxMs:e,async stop(){return clearTimeout(i),h.state!=="inactive"&&h.stop(),{blob:await f,mime:s,kind:"VIDEO"}},cancel(){u(),h.state!=="inactive"&&h.stop()}}}async function it({maxMs:e=12e4,onTick:t,onAutoStop:a}={}){const r=await navigator.mediaDevices.getUserMedia({audio:!0}),s=["audio/webm;codecs=opus","audio/webm","audio/mp4","audio/ogg"].find(d=>MediaRecorder.isTypeSupported(d))||"",h=new MediaRecorder(r,s?{mimeType:s}:void 0),b=[];h.ondataavailable=d=>{d.data.size&&b.push(d.data)},h.start(1e3);const c=Date.now(),m=setInterval(()=>t==null?void 0:t(Math.floor((Date.now()-c)/1e3)),500),u=()=>{clearInterval(m),clearTimeout(i),r.getTracks().forEach(d=>d.stop())},f=new Promise(d=>{h.onstop=()=>{u(),d(new Blob(b,{type:h.mimeType||s}))}}),i=setTimeout(()=>{h.state!=="inactive"&&h.stop(),a==null||a()},e);return{mime:h.mimeType||s,maxMs:e,async stop(){clearTimeout(i),h.state!=="inactive"&&h.stop();const d=await f;return{blob:d,mime:d.type||h.mimeType||s,kind:"AUDIO"}},cancel(){u(),h.state!=="inactive"&&h.stop()}}}function _(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(0)} KB`:`${(e/1024/1024).toFixed(1)} MB`}function te(e){const t=Math.floor(e/60),a=e%60;return`${t}:${String(a).padStart(2,"0")}`}const st=7*24*60*60*1e3;let ae;function lt(){return ae||(ae=new Promise((e,t)=>{const a=indexedDB.open("bugcatch-drafts",1);a.onupgradeneeded=()=>a.result.createObjectStore("drafts"),a.onsuccess=()=>e(a.result),a.onerror=()=>t(a.error),a.onblocked=()=>t(new Error("Draft storage is blocked."))}).catch(e=>{throw ae=null,e})),ae}function ct(e,t){var a,r;return JSON.stringify([e.apiBase,e.projectId,t||((a=e.user)==null?void 0:a.email)||((r=e.user)==null?void 0:r.id)||"anonymous"])}async function ne(e,t){const a=await lt();return new Promise((r,s)=>{const h=a.transaction("drafts",t===void 0?"readonly":"readwrite"),b=h.objectStore("drafts"),c=t===void 0?b.get(e):t===null?b.delete(e):b.put({...t,savedAt:Date.now()},e);h.oncomplete=()=>r(c.result),h.onerror=()=>s(h.error),h.onabort=()=>s(h.error||new Error("Draft was not saved."))})}async function dt(e){const t=await ne(e);return t&&Date.now()-t.savedAt>st?(await ne(e,null),null):t||null}const xe=[{value:"LOW",label:"Low"},{value:"MEDIUM",label:"Medium"},{value:"HIGH",label:"High"},{value:"CRITICAL",label:"Critical"}],ke="MEDIUM";function pt(e){const t=e.attachments!==!1,a=t&&at(),r=t&&tt();return`
|
|
970
1056
|
<div class="compose">
|
|
971
1057
|
<div class="field">
|
|
972
1058
|
<label for="bc-title">What went wrong?</label>
|
|
@@ -986,8 +1072,8 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
986
1072
|
<div class="field">
|
|
987
1073
|
<label id="bc-prio-l">How much is it getting in your way?</label>
|
|
988
1074
|
<div class="seg" role="group" aria-labelledby="bc-prio-l">
|
|
989
|
-
${
|
|
990
|
-
<button type="button" data-prio="${
|
|
1075
|
+
${xe.map(s=>`
|
|
1076
|
+
<button type="button" data-prio="${s.value}" aria-pressed="${s.value===ke}">${s.label}</button>
|
|
991
1077
|
`).join("")}
|
|
992
1078
|
</div>
|
|
993
1079
|
</div>
|
|
@@ -998,220 +1084,246 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
998
1084
|
<span class="count" aria-live="polite"></span>
|
|
999
1085
|
</div>
|
|
1000
1086
|
<div class="tools" role="group" aria-labelledby="bc-att-l">
|
|
1001
|
-
${a?`<button class="tool" type="button" data-act="shot">${
|
|
1002
|
-
${
|
|
1087
|
+
${a?`<button class="tool" type="button" data-act="shot">${Be}Screenshot</button>`:""}
|
|
1088
|
+
${r?`<button class="tool" type="button" data-act="rec">${Ne}Record screen</button>`:""}
|
|
1003
1089
|
<button class="tool" type="button" data-act="file">${he}Upload file</button>
|
|
1004
1090
|
</div>
|
|
1005
1091
|
<div class="thumbs"></div>
|
|
1006
|
-
<input type="file" accept="${
|
|
1092
|
+
<input type="file" accept="${ye.join(",")}" multiple hidden />
|
|
1007
1093
|
</div>`:""}
|
|
1008
|
-
</div>`}function
|
|
1009
|
-
${
|
|
1010
|
-
<span class="kind">${
|
|
1011
|
-
<button class="drop" type="button" data-act="drop" aria-label="Remove ${
|
|
1012
|
-
${
|
|
1094
|
+
</div>`}function ut(e){var pe,G,X,q;const{client:t,cfg:a,root:r,host:s,dock:h,scrim:b,$:c,say:m,titleInput:u,descInput:f,compose:S,sendBtn:i,note:d}=e,v=c(".thumbs"),E=b.querySelector("input[type=file]"),p=[];let o=ke,l=null;const n=document.createElement("div");n.setAttribute("role","status"),n.className="note",S.prepend(n);const $=ct(a,(pe=t.signedInAs())==null?void 0:pe.email);let x=a.drafts===!1,y=!1,g=Promise.resolve(),L;function M(){if(clearTimeout(L),!x||y||a.drafts===!1)return g;const w=u.value||f.value||p.length?{title:u.value,description:f.value,priority:o,items:p.map(({blob:Q,mime:R,kind:A})=>({blob:Q,mime:R,kind:A}))}:null;return g=g.catch(()=>{}).then(()=>ne($,w)).then(()=>{n.textContent=w?"Draft saved on this device":""}).catch(()=>{n.textContent="Draft could not be saved. Keep this tab open."}),g}function C(){clearTimeout(L),L=setTimeout(M,250)}S.addEventListener("input",C),S.addEventListener("change",C);const B=()=>{M()};window.addEventListener("pagehide",B);function N(){p.filter(w=>w.status==="failed").forEach(j)}window.addEventListener("online",N),a.drafts!==!1&&(S.inert=!0,dt($).then(w=>{e.closed||!w||(n.innerHTML='<span>You have an unfinished report on this device.</span> <button type="button" data-resume>Resume report</button> <button type="button" data-discard>Discard</button>',n.querySelector("[data-resume]").onclick=()=>{u.value=w.title||"",f.value=w.description||"",o=xe.some(Q=>Q.value===w.priority)?w.priority:"MEDIUM",b.querySelectorAll("[data-prio]").forEach(Q=>Q.setAttribute("aria-pressed",String(Q.dataset.prio===o)));for(const Q of(w.items||[]).slice(0,a.maxAttachments??5))P(Q);x=!0,M()},n.querySelector("[data-discard]").onclick=()=>{x=!0,M()})}).catch(()=>{n.textContent="Draft storage is unavailable. Keep this tab open."}).finally(()=>{S.inert=e.mustRate(),n.querySelector("[data-resume]")||(x=!0)})),e.onDestroy(()=>{var w;M(),clearTimeout(L),window.removeEventListener("pagehide",B),window.removeEventListener("online",N),l==null||l.cancel(),p.forEach(Q=>Q.previewUrl&&URL.revokeObjectURL(Q.previewUrl)),(w=r.querySelector(".recbar"))==null||w.remove()}),b.querySelectorAll("[data-prio]").forEach(w=>{w.addEventListener("click",()=>{o=w.dataset.prio,C(),b.querySelectorAll("[data-prio]").forEach(Q=>{Q.setAttribute("aria-pressed",String(Q===w))})})});const W=c("#bc-title-err");function T(w){W.hidden=!w,W.innerHTML=w?`${F}<span>${k(w)}</span>`:"",u.classList.toggle("invalid",!!w),u.setAttribute("aria-invalid",String(!!w))}u.addEventListener("input",()=>{u.value.trim()&&T("")});function H(){const w=p.some(I=>I.status==="uploading"),Q=e.mustRate();i.disabled=e.sending||w||Q||p.some(I=>I.status==="failed"),d.textContent=Q?"Rate your last report to send a new one.":w?"Waiting for the upload to finish…":p.some(I=>I.status==="failed")?"Retry or remove failed attachments before sending.":"";const R=a.maxAttachments??5;b.querySelectorAll(".tool").forEach(I=>{I.disabled=e.sending||p.length>=R});const A=c(".field-head .count");A&&(A.textContent=p.length?`${p.length} of ${R}`:"")}e.refreshSendState=H;function z(w){var Y;const Q=w.el,R=w.kind==="VIDEO"?"Video":"Shot",A=w.kind==="VIDEO"?`<video src="${w.previewUrl}" muted playsinline preload="metadata"></video>`:`<img src="${w.previewUrl}" alt="" />`;let I="";w.status==="uploading"?I=`<div class="veil"><div class="spinner"></div><div class="bar"><i style="width:${Math.round(w.progress*100)}%"></i></div></div>`:w.status==="failed"&&(I=`<div class="veil err"><button type="button" data-act="retry" aria-label="Retry upload">${Ye}</button>Failed</div>`),Q.innerHTML=`
|
|
1095
|
+
${A}
|
|
1096
|
+
<span class="kind">${R} · ${_(w.size)}</span>
|
|
1097
|
+
<button class="drop" type="button" data-act="drop" aria-label="Remove ${R.toLowerCase()}">${J}</button>
|
|
1098
|
+
${I}`,Q.querySelector('[data-act="drop"]').addEventListener("click",()=>D(w)),(Y=Q.querySelector('[data-act="retry"]'))==null||Y.addEventListener("click",()=>j(w))}function D(w){const Q=p.indexOf(w);Q>=0&&p.splice(Q,1),w.previewUrl&&URL.revokeObjectURL(w.previewUrl),w.el.remove(),M(),H()}async function j(w){w.status="uploading",w.progress=0,z(w),H();try{const{storageKey:Q,mime:R}=await t.uploadAttachment(w.blob,w.mime,A=>{w.progress=A;const I=w.el.querySelector(".bar i");I&&(I.style.width=`${Math.round(A*100)}%`)});w.storageKey=Q,w.mime=R,w.status="ready"}catch(Q){w.status="failed",m(Q.message.replace("[BugCatch] ",""))}z(w),H()}function P({blob:w,mime:Q,kind:R}){const A=a.maxAttachmentBytes??26214400;if(w.size>A){m(`That file is ${_(w.size)} — the limit is ${_(A)}.`);return}const I=nt(Q||w.type,ye);if(!I){m("Only PNG, JPEG, WebP, WebM and MP4 files can be attached to a report.");return}const Y={blob:w,kind:R,mime:I,size:w.size,previewUrl:URL.createObjectURL(w),status:"uploading",progress:0,storageKey:null,el:document.createElement("div")};Y.el.className="thumb",p.push(Y),v.appendChild(Y.el),m(""),M(),j(Y)}async function oe(w){s.style.opacity="0",s.style.pointerEvents="none",await new Promise(Q=>requestAnimationFrame(()=>requestAnimationFrame(Q)));try{return await w()}finally{s.style.opacity="",s.style.pointerEvents=""}}(G=b.querySelector('[data-act="shot"]'))==null||G.addEventListener("click",async()=>{try{const w=await oe(ot);P(w)}catch(w){(w==null?void 0:w.name)!=="NotAllowedError"&&m(`Screenshot failed: ${w.message}`)}}),(X=b.querySelector('[data-act="file"]'))==null||X.addEventListener("click",()=>E.click()),E==null||E.addEventListener("change",()=>{const w=(a.maxAttachments??5)-p.length;[...E.files].slice(0,Math.max(w,0)).forEach(Q=>{P({blob:Q,mime:Q.type,kind:Q.type.startsWith("video/")?"VIDEO":"SCREENSHOT"})}),E.value=""}),(q=b.querySelector('[data-act="rec"]'))==null||q.addEventListener("click",async()=>{const w=a.maxRecordingMs??12e4;let Q;try{l=await rt({maxMs:w,onTick:R=>{Q&&(Q.querySelector(".time").textContent=te(R))},onAutoStop:()=>{l&&V({keep:!0})}})}catch(R){(R==null?void 0:R.name)!=="NotAllowedError"&&m(`Recording failed: ${R.message}`);return}b.style.display="none",h.hidden=!0,Q=document.createElement("div"),Q.className="recbar",Q.innerHTML=`
|
|
1013
1099
|
<span class="dot"></span>
|
|
1014
1100
|
<span class="time">0:00</span>
|
|
1015
|
-
<span class="hint">Recording — up to ${
|
|
1101
|
+
<span class="hint">Recording — up to ${te(Math.round(w/1e3))}</span>
|
|
1016
1102
|
<button class="stop" type="button">Stop</button>
|
|
1017
|
-
<button class="ghost" type="button">Discard</button>`,
|
|
1103
|
+
<button class="ghost" type="button">Discard</button>`,Q.querySelector(".stop").addEventListener("click",()=>V({keep:!0})),Q.querySelector(".ghost").addEventListener("click",()=>V({keep:!1})),r.appendChild(Q),Q.querySelector(".stop").focus()});async function V({keep:w}){var R;const Q=l;if(Q){if(l=null,(R=r.querySelector(".recbar"))==null||R.remove(),b.style.display="",h.hidden=!1,!w){Q.cancel(),u.focus();return}try{const A=await Q.stop();A.blob.size?P(A):m("That recording came back empty — nothing was captured.")}catch(A){m(`Recording failed: ${A.message}`)}u.focus()}}e.isRecording=()=>!!l,e.stopRecording=V,i.addEventListener("click",async()=>{var R;const w=u.value;if(!w.trim()){T("Add a few words about what went wrong — a short sentence is plenty."),u.focus();return}if(e.holdForReference())return;e.sending=!0,m(""),H();const Q=i.innerHTML;i.innerHTML='<span class="spinner" aria-hidden="true"></span>Sending…';try{const A=await t.report({title:w,description:f.value,priority:o,references:e.answeredReference(),issue:((R=e.pickedIssue())==null?void 0:R.key)||null,attachments:p.filter(I=>I.status==="ready").map(I=>({type:I.kind,storageKey:I.storageKey,mime:I.mime}))});if(A!=null&&A.cancelled){e.sending=!1,i.innerHTML=Q,H();return}y=!0,clearTimeout(L),await g,a.drafts!==!1&&await ne($,null).catch(()=>{}),e.succeed(A)}catch(A){e.sending=!1,i.innerHTML=Q,m(A.message.replace("[BugCatch] ","")),H(),e.recheckSignIn()}})}const ht=2e4,$e=120,le=200;function Se(e){if(typeof e!="string"||!e.trim()||e.length>400)return null;try{return new RegExp(e.trim(),"gi")}catch{return null}}const Le=e=>String(e).replace(/\s+/g," ").trim().slice(0,$e);function Ee(e,t){const a=e&&e.normalize;if(a==="phone"){const r=t.replace(/\D/g,"");return r.length===10?r:r.length===12&&r.startsWith("91")?r.slice(2):r.length===11&&r.startsWith("0")?r.slice(1):t}return a==="upper"?t.toUpperCase():t}function Me(e){const t=e.length>1&&e[1]!==void 0?e[1]:e[0];return typeof t!="string"||!t.trim()?null:{value:Le(t),start:e.index,end:e.index+e[0].length}}function ft(e,t){return((e.slice(t.start,t.valueStart)+e.slice(t.valueEnd,t.end)).match(/[a-z]/gi)||[]).length}const bt=/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[A-Za-z0-9][\w-]{5,40}/gi,Te=/[\w-]/;function gt(e,t){const a=(e||[]).filter(i=>i&&i.scan!==!1&&i.pattern),r=[],s=[],h=(t||[]).map(i=>typeof i=="string"?i.slice(0,ht):"");h.forEach((i,d)=>{i&&a.forEach((v,E)=>{const p=Se(v.pattern);if(!p)return;let o,l=0;for(p.lastIndex=0;(o=p.exec(i))!==null&&!(++l>le);){if(o[0]===""){p.lastIndex+=1;continue}const n=Me(o);if(!n)continue;const $=o.length>1&&o[1]!==void 0?o[1]:o[0],x=o.index+Math.max(0,o[0].indexOf($)),y={block:d,order:E,key:v.key,label:v.label,value:Ee(v,n.value),start:n.start,end:n.end,valueStart:x,valueEnd:x+$.length};y.weight=ft(i,y),r.push(y)}})});const b=r.filter(i=>!r.some(d=>d!==i&&d.block===i.block&&d.key!==i.key&&d.valueStart<=i.valueStart&&d.valueEnd>=i.valueEnd&&d.weight>i.weight)),c=new Map;for(const i of b){const d=i.value.toLowerCase();c.has(d)||c.set(d,{value:i.value,keys:new Map});const v=c.get(d);v.keys.has(i.key)||v.keys.set(i.key,{key:i.key,label:i.label,order:i.order})}const m=[],u=[],f=new Map;for(const i of c.values()){const d=[...i.keys.values()].sort((p,o)=>p.order-o.order);if(d.length>1){u.push({value:i.value,kinds:d.map(({key:p,label:o})=>({key:p,label:o}))});continue}const[{key:v,label:E}]=d;f.has(v)||f.set(v,[]),f.get(v).push({key:v,label:E,value:i.value})}for(const i of f.values())if(i.length===1)m.push(i[0]);else for(const d of i)u.push({value:d.value,kinds:[{key:d.key,label:d.label}]});const S=new Set(c.keys());return h.forEach((i,d)=>{if(!i)return;const v=r.filter(l=>l.block===d),E=new RegExp(bt.source,"gi");let p,o=0;for(;(p=E.exec(i))!==null&&++o<=le;){const l=p.index,n=l+p[0].length;if(v.some(M=>l<M.end&&n>M.start))continue;const $=i[l-1]||"",x=i[n]||"";if(Te.test($)||Te.test(x)||$==="/"||$==="@"||x==="@"||$==="."||x==="."&&/\w/.test(i[n+1]||"")||!/\d/.test(p[0]))continue;const y=Le(p[0]),g=y.toLowerCase();if(S.has(g))continue;const L=(e||[]).filter(M=>M&&Qe(M,y)).map(({key:M,label:C})=>({key:M,label:C}));L.length&&(S.add(g),s.push({value:y,kinds:L}))}}),{found:m,conflicts:u,loose:s}}function Qe(e,t){const a=typeof t=="string"?t.trim():"";if(!a||a.length>$e)return null;const r=Se(e&&(e.valuePattern||e.pattern));if(!r)return null;let s,h=0;for(r.lastIndex=0;(s=r.exec(a))!==null&&!(++h>le);){if(s[0]===""){r.lastIndex+=1;continue}const b=s.index+s[0].length===a.length,c=s.index===0||s.index===1;if(b&&c){const m=Me(s);if(m)return Ee(e,m.value)}}return null}function mt(e){const{client:t,say:a,titleInput:r,descInput:s,sendBtn:h,refsBox:b}=e;let c={policy:"off",fields:[]},m=!1,u=null,f="",S="",i=[],d="ask",v=!1,E=!1;t.referenceFields().then(T=>{c=T,x()}).catch(()=>{});function p(){return c.policy==="off"||!c.fields.length?{found:[],conflicts:[],loose:[]}:gt(c.fields,[r.value,s.value])}function o(T=p()){return T.found.length>0&&T.conflicts.length===0}function l(){return!u||!f.trim()?[]:[{key:u,value:f.trim().slice(0,120)}]}const n=document.createElement("p");n.className="ref-found",n.setAttribute("aria-live","polite"),n.hidden=!0,s.closest(".field").after(n);let $;function x(){const T=p();if(o(T)){const H=T.found.slice(0,2).map(z=>`${k(z.label)} <b>${k(g(z.value))}</b>`).join(", ");n.innerHTML=`${O}<span>Found your ${H} — no need to add it again.</span>`,n.hidden=!1,m&&!l().length&&(m=!1,C())}else n.hidden=!0,n.innerHTML=""}const y=()=>{clearTimeout($),$=setTimeout(x,250)};r.addEventListener("input",y),s.addEventListener("input",y);function g(T){return T.length>20?`${T.slice(0,8)}…${T.slice(-4)}`:T}function L(T){const H=T.trim().toLowerCase();return i.find(z=>z.value.toLowerCase()===H)||null}function M(T){f=T.value,T.kinds.length===1?u=T.kinds[0].key:T.kinds.some(H=>H.key===u)||(u=null),S="",E=!1}function C(){var G,X;if(!m){b.hidden=!0,b.innerHTML="";return}const T=c.fields.find(q=>q.key===u)||null,H=c.policy!=="required",z=L(f),D=z&&z.kinds.length>1?c.fields.filter(q=>z.kinds.some(w=>w.key===q.key)):c.fields,j=i.length>1&&i.every(q=>q.kinds.length===1&&q.kinds[0].key===i[0].kinds[0].key),P={confirm:i.length>1?["Which one is this about?","We found more than one ID in your message. Pick the one this problem is about."]:["Is this the right ID?","This could be more than one kind of ID. Tell us which it is."],suggest:["Is this your ID?","We spotted this in your message. Tell us what it is so we can find your record."],ask:H?["One more thing","So we can find your record — this helps us answer faster."]:["We need one detail","We need one of these to look this up."]}[d];b.hidden=!1;const oe=D.length>6;b.innerHTML=`
|
|
1018
1104
|
<div class="ask-head">
|
|
1019
|
-
<span class="avatar" aria-hidden="true"
|
|
1105
|
+
<span class="avatar orb" aria-hidden="true"></span>
|
|
1020
1106
|
<div>
|
|
1021
1107
|
<strong>${k(P[0])}</strong>
|
|
1022
1108
|
<p class="why">${k(P[1])}</p>
|
|
1023
1109
|
</div>
|
|
1024
1110
|
</div>
|
|
1025
|
-
${
|
|
1111
|
+
${i.length>1?`
|
|
1026
1112
|
<div class="chips cands" role="group" aria-label="IDs found in your message">
|
|
1027
|
-
${
|
|
1028
|
-
<button type="button" data-ref-cand="${
|
|
1029
|
-
aria-pressed="${!!
|
|
1113
|
+
${i.map((q,w)=>`
|
|
1114
|
+
<button type="button" data-ref-cand="${w}" title="${k(q.value)}"
|
|
1115
|
+
aria-pressed="${!!z&&z===q}">${k(g(q.value))}</button>
|
|
1030
1116
|
`).join("")}
|
|
1031
1117
|
</div>`:""}
|
|
1032
|
-
${D.length>1&&!
|
|
1118
|
+
${D.length>1&&!oe&&!j?`
|
|
1033
1119
|
<div class="chips" role="group" aria-label="Which detail you are giving">
|
|
1034
|
-
${D.map(
|
|
1035
|
-
<button type="button" data-ref-kind="${k(
|
|
1120
|
+
${D.map(q=>`
|
|
1121
|
+
<button type="button" data-ref-kind="${k(q.key)}" aria-pressed="${!!T&&q.key===T.key}">${k(q.label)}</button>
|
|
1036
1122
|
`).join("")}
|
|
1037
1123
|
</div>`:""}
|
|
1038
1124
|
<div class="row">
|
|
1039
|
-
${
|
|
1125
|
+
${oe?`
|
|
1040
1126
|
<select class="ref-kind" aria-label="Which detail you are giving">
|
|
1041
|
-
${
|
|
1042
|
-
${D.map(
|
|
1043
|
-
<option value="${k(
|
|
1127
|
+
${T?"":'<option value="" selected disabled>What is it?</option>'}
|
|
1128
|
+
${D.map(q=>`
|
|
1129
|
+
<option value="${k(q.key)}" ${T&&q.key===T.key?"selected":""}>${k(q.label)}</option>
|
|
1044
1130
|
`).join("")}
|
|
1045
1131
|
</select>`:""}
|
|
1046
|
-
<input class="ref-value${
|
|
1047
|
-
inputmode="${k((
|
|
1048
|
-
value="${k(
|
|
1049
|
-
placeholder="${k(
|
|
1050
|
-
aria-label="${k(
|
|
1132
|
+
<input class="ref-value${S?" invalid":""}" type="${(T==null?void 0:T.inputMode)==="email"?"email":"text"}"
|
|
1133
|
+
inputmode="${k((T==null?void 0:T.inputMode)==="numeric"||(T==null?void 0:T.inputMode)==="tel"?"numeric":"text")}"
|
|
1134
|
+
value="${k(f)}"
|
|
1135
|
+
placeholder="${k(T?T.placeholder||T.label:"Your ID")}"
|
|
1136
|
+
aria-label="${k(T?T.label:"Your ID")}" ${S?'aria-invalid="true"':""} />
|
|
1051
1137
|
</div>
|
|
1052
|
-
${
|
|
1053
|
-
${
|
|
1054
|
-
${
|
|
1138
|
+
${T!=null&&T.hint?`<p class="hint">${k(T.hint)}</p>`:""}
|
|
1139
|
+
${S?`<p class="field-err" role="alert">${F}<span>${k(S)}</span></p>`:""}
|
|
1140
|
+
${H?`<button type="button" class="link" data-act="ref-skip">${d==="ask"?"I don't have this — send without it":"Not sure — send as it is"}</button>`:""}`,b.querySelectorAll("[data-ref-cand]").forEach(q=>{q.addEventListener("click",()=>{M(i[Number(q.dataset.refCand)]),C()})}),b.querySelectorAll("[data-ref-kind]").forEach(q=>{q.addEventListener("click",()=>{u=q.dataset.refKind,S="",E=!1,C()})});const V=b.querySelector(".ref-value");V.addEventListener("input",()=>{f=V.value,S="",E=!1}),V.addEventListener("keydown",q=>{q.key==="Enter"&&(q.preventDefault(),h.click())}),(G=b.querySelector(".ref-kind"))==null||G.addEventListener("change",q=>{var w;u=q.target.value,S="",C(),(w=b.querySelector(".ref-value"))==null||w.focus()}),(X=b.querySelector('[data-act="ref-skip"]'))==null||X.addEventListener("click",()=>{v=!0,m=!1,u=null,f="",S="",E=!1,C(),a("")}),((!T&&f?b.querySelector("[data-ref-kind], .ref-kind"):null)||V).focus()}function B(T){if(i=T.conflicts.length?T.conflicts:T.loose.slice(0,4),d=T.conflicts.length?"confirm":T.loose.length?"suggest":"ask",m=!0,i.length)if(i.length===1)M(i[0]);else{f="";const[H]=i;u=i.every(D=>D.kinds.length===1&&D.kinds[0].key===H.kinds[0].key)?H.kinds[0].key:null}else u=u||c.fields[0].key;C()}function N(){if(c.policy==="off"||!c.fields.length||l().length)return!1;const T=p();return o(T)||v&&c.policy!=="required"?!1:T}function W(){if(m&&f.trim()&&!u)return S="Pick what this ID is.",C(),!0;const T=N();if(T)return m?C():B(T),a(""),!0;if(u&&f.trim()){const H=c.fields.find(z=>z.key===u);if(!E&&H&&!Qe(H,f))return S=`That does not look like a ${H.label.toLowerCase()}. Press Send again to use it anyway.`,E=!0,C(),!0}return!1}e.holdForReference=W,e.answeredReference=l}const vt={info:ue,success:O,warning:Oe,critical:F};function wt(e,{where:t,onDismiss:a}){const r=document.createElement("div");r.className=`notice tone-${e.tone} at-${t}`,r.setAttribute("role","status");const s=document.createElement("span");s.className="notice-ico",s.setAttribute("aria-hidden","true"),s.innerHTML=vt[e.tone]||ue;const h=document.createElement("div");h.className="notice-text";const b=document.createElement("strong");if(b.textContent=e.title,h.append(b),e.body){const c=document.createElement("p");c.textContent=e.body,h.append(c)}if(e.ctaHref&&e.ctaLabel){const c=document.createElement("a");c.className="notice-cta",c.href=e.ctaHref,c.textContent=e.ctaLabel,/^https?:/i.test(e.ctaHref)&&(c.target="_blank",c.rel="noopener noreferrer"),h.append(c)}if(r.append(s,h),e.dismissible&&a){const c=document.createElement("button");c.type="button",c.className="notice-x",c.setAttribute("aria-label","Dismiss this notice"),c.innerHTML=J,c.addEventListener("click",()=>a(e)),r.append(c)}return r}const yt=3;function xt(e){const{client:t,cfg:a,notices:r}=e;let s=[];function h(){const c=s.slice(0,yt);r.replaceChildren(...c.map(m=>wt(m,{where:"panel",onDismiss:b}))),r.hidden=c.length===0}function b(c){t.dismissAnnouncement(c),s=s.filter(m=>m!==c),h(),e.titleInput.focus()}a.announcements!==!1&&typeof t.announcements=="function"&&t.announcements().then(c=>{e.closed||(s=c,h())}).catch(()=>{})}function kt(e){const{client:t,cfg:a,titleInput:r,known:s}=e;let h=[],b="",c=null,m=null;function u(){a.knownIssues!==!1&&t.knownIssues().then(v=>{h=v,i()}).catch(()=>{})}let f=null;function S(v){if(a.knownIssues===!1)return;clearTimeout(f),m==null||m.abort();const E=(v||"").trim();if(E.length<3){u();return}f=setTimeout(()=>{m=new AbortController,t.matchKnownIssues(E,{signal:m.signal}).then(p=>{p.length&&(h=p,i())}).catch(()=>{})},250)}function i(){if(!h.length){s.hidden=!0,s.innerHTML="";return}s.hidden=!1,s.innerHTML=`
|
|
1055
1141
|
<p class="known-h">Already reported</p>
|
|
1056
|
-
${
|
|
1057
|
-
<div class="issue ${
|
|
1142
|
+
${h.map(v=>`
|
|
1143
|
+
<div class="issue ${v.joined?"is-joined":""}">
|
|
1058
1144
|
<span class="who">
|
|
1059
|
-
<span class="t">${k(
|
|
1060
|
-
<span class="meta">${k(
|
|
1145
|
+
<span class="t">${k(v.title)}</span>
|
|
1146
|
+
<span class="meta">${k(d(v))}</span>
|
|
1061
1147
|
</span>
|
|
1062
|
-
<button class="join" type="button" data-join="${k(
|
|
1063
|
-
${
|
|
1148
|
+
<button class="join" type="button" data-join="${k(v.id)}"
|
|
1149
|
+
${v.joined?"disabled":""}>${v.joined?"Following":"Me too"}</button>
|
|
1064
1150
|
</div>
|
|
1065
|
-
${
|
|
1151
|
+
${c===v.id?`
|
|
1066
1152
|
<div class="ask">
|
|
1067
1153
|
<input type="email" class="join-email" placeholder="you@example.com"
|
|
1068
1154
|
aria-label="Your email, so we can tell you when this is fixed" />
|
|
1069
|
-
<button class="ghost" type="button" data-join-confirm="${k(
|
|
1155
|
+
<button class="ghost" type="button" data-join-confirm="${k(v.id)}">Follow</button>
|
|
1070
1156
|
</div>`:""}
|
|
1071
1157
|
`).join("")}
|
|
1072
|
-
${
|
|
1158
|
+
${b?`<p class="err">${k(b)}</p>`:""}`}function d(v){const E=v.status==="IN_PROGRESS"?"Being worked on now":"Not fixed yet",p=v.affectedCount===0?"":` · ${v.affectedCount} ${v.affectedCount===1?"person has":"people have"} said this is happening to them`;return`${E} · reported ${Z(v.since)}${p}`}s.addEventListener("click",async v=>{var n,$,x,y,g;const E=v.target.closest("[data-join]"),p=v.target.closest("[data-join-confirm]");if(!E&&!p)return;const o=(p||E).getAttribute(p?"data-join-confirm":"data-join");b="";const l=(($=(n=s.querySelector(".join-email"))==null?void 0:n.value)==null?void 0:$.trim())||((x=t.signedInAs())==null?void 0:x.email)||((y=t.config.user)==null?void 0:y.email);if(!l){c=o,i(),(g=s.querySelector(".join-email"))==null||g.focus();return}try{const L=await t.meToo(o,{email:l});c=null,h=h.map(M=>M.id===o?{...M,joined:!0,affectedCount:L.affectedCount??M.affectedCount}:M),i()}catch(L){b=L.message.replace("[BugCatch] ",""),i()}}),u(),r.addEventListener("input",()=>S(r.value))}function $t(e){const{client:t,cfg:a,titleInput:r,descInput:s,picks:h}=e;let b=[],c=null;function m(){if(!b.length){h.hidden=!0,h.innerHTML="";return}h.hidden=!1,h.innerHTML=`
|
|
1073
1159
|
<p class="picks-h">Get an answer right away</p>
|
|
1074
1160
|
<div class="picks-grid" role="group" aria-label="Common questions">
|
|
1075
|
-
${
|
|
1076
|
-
<button type="button" class="pick" data-pick="${k(
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1161
|
+
${b.map((u,f)=>`
|
|
1162
|
+
<button type="button" class="pick" data-pick="${k(u.key)}"
|
|
1163
|
+
${u.hint?`title="${k(u.hint)}" aria-describedby="bc-pick-h${f}"`:""}
|
|
1164
|
+
aria-pressed="${(c==null?void 0:c.key)===u.key}">
|
|
1165
|
+
<span class="t">${k(u.title)}</span>
|
|
1166
|
+
${u.hint?`<span class="h sr-only" id="bc-pick-h${f}">${k(u.hint)}</span>`:""}
|
|
1080
1167
|
</button>`).join("")}
|
|
1081
1168
|
</div>
|
|
1082
|
-
${
|
|
1169
|
+
${c?`<p class="picks-note">${O}<span>Our assistant will check your account and reply here. Add anything else below, then send.</span></p>`:""}`}h.addEventListener("click",u=>{const f=u.target.closest("[data-pick]");if(!f)return;const S=b.find(d=>d.key===f.dataset.pick);if(!S)return;const i=c&&r.value.trim()===c.title;(c==null?void 0:c.key)===S.key?(c=null,i&&(r.value="")):(c=S,(!r.value.trim()||i)&&(r.value=S.title)),r.dispatchEvent(new Event("input",{bubbles:!0})),m(),c&&s.focus()}),a.agentIssues!==!1&&typeof t.agentIssues=="function"&&t.agentIssues().then(u=>{b=u,m()}).catch(()=>{}),e.pickedIssue=()=>c}function St(e){const{client:t,scrim:a,say:r,callBtn:s,close:h}=e;let b=!1;function c(){t.callKind().then(f=>{f&&(b=!0,e.preloadCall(),s.hidden=e.mustSignIn()||e.mustRate())}).catch(()=>{})}c(),s.addEventListener("click",async()=>{e.sending=!0,r(""),e.refreshSendState(),s.disabled=!0,s.innerHTML='<span class="spinner"></span>Ringing…';try{const f=await t.startCall();m(f)}catch(f){e.sending=!1,s.disabled=!1,s.innerHTML=`${ee}Talk to the team`,e.refreshSendState(),f.filed?e.succeed(f.filed,{callFailed:f.reason||"The call could not be started."}):(r(f.message.replace("[BugCatch] ","")),e.recheckSignIn())}});function m(f){const S=a.querySelector(".panel"),i=f!=null&&f.bugId?String(f.bugId).slice(0,8):null;S.innerHTML=`
|
|
1083
1170
|
<div class="call">
|
|
1084
1171
|
<div class="call-head">
|
|
1085
1172
|
<span class="call-dot" aria-hidden="true"></span>
|
|
1086
1173
|
<strong class="call-state">Ringing…</strong>
|
|
1087
1174
|
</div>
|
|
1088
1175
|
<p class="call-note">
|
|
1089
|
-
We're ringing the team now. Someone will pick up if they're free — your report${
|
|
1176
|
+
We're ringing the team now. Someone will pick up if they're free — your report${i?` <code>${k(i)}</code>`:""} is already filed either way, so nothing is lost if nobody answers.
|
|
1090
1177
|
</p>
|
|
1091
1178
|
<div class="foot">
|
|
1092
1179
|
<span class="spacer"></span>
|
|
1093
1180
|
<button class="primary" type="button" data-act="hangup">Cancel</button>
|
|
1094
1181
|
</div>
|
|
1095
|
-
</div>`;const
|
|
1182
|
+
</div>`;const d=S.querySelector(".call-state"),v=S.querySelector(".call-dot"),E={ringing:"Ringing the team…",connecting:"Someone answered — connecting…",connected:"Connected",missed:"Nobody was free",ended:"Call ended",failed:"The call dropped"},p=["ended","failed","missed"],o=t.on("call",({state:l})=>{if(d.textContent=E[l]||l,v.classList.toggle("off",p.includes(l)),p.includes(l)&&(S.querySelector('[data-act="hangup"]').textContent="Close",l==="missed")){const n=S.querySelector(".call-note");n&&(n.textContent="Nobody was free to pick up just now. Your report is filed and the team will reply in the chat.")}});S.querySelector('[data-act="hangup"]').addEventListener("click",()=>{o(),t.endCall(),h()})}function u(f,S,i){const d=document.createElement("div");d.className="livecall",d.innerHTML=`
|
|
1096
1183
|
<span class="call-dot" aria-hidden="true"></span>
|
|
1097
1184
|
<span class="who" role="status" aria-live="polite">Calling the team…</span>
|
|
1098
1185
|
<span class="secs" hidden></span>
|
|
1099
|
-
${
|
|
1186
|
+
${i!=null&&i.recorded?'<span class="call-kept">This call is recorded.</span>':""}
|
|
1100
1187
|
<button class="act" type="button" data-act="mute" hidden>Mute</button>
|
|
1101
|
-
<button class="act danger" type="button" data-act="hangup">Cancel</button>`,
|
|
1188
|
+
<button class="act danger" type="button" data-act="hangup">Cancel</button>`,f.insertBefore(d,S);const v=d.querySelector(".who"),E=d.querySelector(".secs"),p=d.querySelector(".call-dot"),o=d.querySelector('[data-act="mute"]'),l=d.querySelector('[data-act="hangup"]');let n=null;const $=()=>{n&&(clearInterval(n),n=null)},x=g=>{$(),p.classList.add("off"),d.classList.add("over"),v.textContent=g,E.hidden=!0,o.hidden=!0,l.textContent="Dismiss",l.classList.remove("danger")},y=t.on("call",({state:g})=>{if(g==="ringing"&&(v.textContent="Calling the team…"),g==="connecting"&&(v.textContent="Someone answered — connecting…"),g==="connected"){v.textContent="You're on a call with the team",o.hidden=!1,E.hidden=!1;const L=Date.now();$(),n=setInterval(()=>{E.textContent=te(Math.floor((Date.now()-L)/1e3))},1e3),E.textContent="0s"}g==="missed"&&x("Nobody was free. Send a message instead and the team will pick it up."),g==="ended"&&x("Call ended."),g==="failed"&&x("The call dropped.")});o.addEventListener("click",()=>{const g=i.setMuted(!i.isMuted());o.textContent=g?"Unmute":"Mute",v.textContent=g?"You're muted":"You're on a call with the team"}),l.addEventListener("click",()=>{y(),$(),t.endCall(),d.remove(),e.refreshThread(e.openReportId())})}e.offerCall=c,e.callOffered=()=>b,e.showLiveCall=u}function Lt(e){var y;const{client:t,say:a,compose:r,sendBtn:s,historyBtn:h,callBtn:b,whoami:c}=e;let m={mode:t.lastLoginMode||"off",signedIn:null},u="idle",f=((y=t.config.user)==null?void 0:y.email)||"",S="",i=!1,d="";const v=()=>m.mode==="required"&&!m.signedIn;function E(){const g=v();r.hidden=g,s.hidden=g,h&&(h.hidden=g),g?b.hidden=!0:e.callOffered()&&!e.mustRate()&&(b.hidden=!1)}function p(){var L;if(m.mode==="off"){c.hidden=!0,c.innerHTML="";return}c.hidden=!1,c.classList.toggle("asking",u!=="idle");const g=d?`<div class="after err">${k(d)}</div>`:"";if(u==="idle"){if(m.signedIn){c.innerHTML=`<span class="who">Signed in as <strong>${k(m.signedIn.email)}</strong></span><button type="button" class="link" data-act="signout">Sign out</button>`;return}const M=(L=t.config.user)==null?void 0:L.email;c.innerHTML=`<span class="who">${m.mode==="required"?"Sign in to report a bug here.":M?`Reporting as <strong>${k(M)}</strong>.`:"Reporting anonymously — sign in and we can tell you what happens next."}</span><button type="button" class="link" data-act="signin">Sign in</button>`;return}if(u==="email"){c.innerHTML=`
|
|
1102
1189
|
<p class="why">Sign in with any email address — we'll send you a code.
|
|
1103
|
-
It's how you hear back about this report${
|
|
1190
|
+
It's how you hear back about this report${m.mode==="required"?", and this project asks for it":""}.</p>
|
|
1104
1191
|
<div class="row">
|
|
1105
|
-
<input type="email" data-fld="email" value="${k(
|
|
1192
|
+
<input type="email" data-fld="email" value="${k(f)}"
|
|
1106
1193
|
placeholder="you@example.com" autocomplete="email" spellcheck="false"
|
|
1107
|
-
aria-label="Your email address" ${
|
|
1108
|
-
<button type="button" class="primary" data-act="code" ${
|
|
1109
|
-
${
|
|
1194
|
+
aria-label="Your email address" ${i?"disabled":""} />
|
|
1195
|
+
<button type="button" class="primary" data-act="code" ${i?"disabled":""}>
|
|
1196
|
+
${i?"Sending…":"Send code"}
|
|
1110
1197
|
</button>
|
|
1111
1198
|
</div>
|
|
1112
|
-
${
|
|
1113
|
-
${
|
|
1114
|
-
<p class="why">We sent a code to <strong>${k(
|
|
1199
|
+
${g}
|
|
1200
|
+
${m.mode==="optional"?'<div class="after"><button type="button" class="link" data-act="skip">Not now</button></div>':""}`;return}c.innerHTML=`
|
|
1201
|
+
<p class="why">We sent a code to <strong>${k(f)}</strong>. It expires in ten minutes.</p>
|
|
1115
1202
|
<div class="row">
|
|
1116
|
-
<input type="text" class="code" data-fld="code" value="${k(
|
|
1203
|
+
<input type="text" class="code" data-fld="code" value="${k(S)}"
|
|
1117
1204
|
placeholder="123456" inputmode="numeric" autocomplete="one-time-code"
|
|
1118
|
-
maxlength="8" aria-label="The code we emailed you" ${
|
|
1119
|
-
<button type="button" class="primary" data-act="confirm" ${
|
|
1120
|
-
${
|
|
1205
|
+
maxlength="8" aria-label="The code we emailed you" ${i?"disabled":""} />
|
|
1206
|
+
<button type="button" class="primary" data-act="confirm" ${i?"disabled":""}>
|
|
1207
|
+
${i?"Checking…":"Sign in"}
|
|
1121
1208
|
</button>
|
|
1122
1209
|
</div>
|
|
1123
|
-
${
|
|
1210
|
+
${g}
|
|
1124
1211
|
<div class="after">
|
|
1125
|
-
<button type="button" class="link" data-act="resend" ${
|
|
1126
|
-
<button type="button" class="link" data-act="signin-back" ${
|
|
1127
|
-
</div>`}function
|
|
1212
|
+
<button type="button" class="link" data-act="resend" ${i?"disabled":""}>Send it again</button>
|
|
1213
|
+
<button type="button" class="link" data-act="signin-back" ${i?"disabled":""}>Use another address</button>
|
|
1214
|
+
</div>`}function o({focus:g=!1}={}){var M;if(p(),E(),!g||i)return;const L=c.querySelector("[data-fld]");L&&(L.focus(),(M=L.setSelectionRange)==null||M.call(L,L.value.length,L.value.length))}c.addEventListener("input",g=>{const L=g.target.closest("[data-fld]");L&&(L.dataset.fld==="email"?f=L.value:S=L.value)}),c.addEventListener("keydown",g=>{g.key!=="Enter"||!g.target.closest("[data-fld]")||(g.preventDefault(),u==="email"?l():n())});async function l({resent:g=!1}={}){const L=f.trim();if(!L){d="Enter the address to send the code to.",o({focus:!0});return}i=!0,d="",o();try{await t.signIn(L),f=L,g||(S=""),u="code"}catch(M){d=M.message}finally{i=!1,o({focus:!0})}}async function n(){const g=S.trim();if(!g){d="Enter the code we emailed you.",o({focus:!0});return}i=!0,d="",o();try{const L=await t.confirmSignIn(f.trim(),g);m.signedIn=L,u="idle",S="",a(""),e.offerCall()}catch(L){d=L.message}finally{i=!1,o({focus:u!=="idle"})}}c.addEventListener("click",async g=>{const L=g.target.closest("button[data-act]");if(!L)return;const M=L.dataset.act;if(M==="signin"){u="email",d="",o({focus:!0});return}if(M==="skip"){u="idle",d="",o();return}if(M==="signin-back"){u="email",d="",S="",o({focus:!0});return}if(M==="code"){l();return}if(M==="resend"){l({resent:!0});return}if(M==="confirm"){n();return}if(M==="signout"){i=!0,o();try{await t.signOut()}finally{m.signedIn=null,i=!1,u=m.mode==="required"?"email":"idle",o({focus:u!=="idle"})}}});async function $({announce:g=!1}={}){const L=await t.loginState();m={mode:L.mode,signedIn:L.signedIn},t.lastLoginMode=L.mode,v()&&u==="idle"&&(u="email"),m.signedIn&&(u="idle"),g&&L.signedOutReason&&a(L.signedOutReason,"info"),o()}$({announce:!0}).catch(()=>{});function x(){m.mode!=="off"&&$().catch(()=>{})}e.mustSignIn=v,e.recheckSignIn=x}const Et=/Did this answer your question\?/i;function qe(e){const t=e||[];if(!t.length)return"";let a=null,r=null;return t.map(s=>{var f,S,i,d;const h=K(s.at),b=h&&h!==a?`<div class="day-sep" role="separator">${k(Je(s.at))}</div>`:"";if(b&&(a=h,r=null),!s.from)return r=null,b+Tt(s);const c={from:s.from,author:(f=s.reply)==null?void 0:f.author,automated:(S=s.reply)==null?void 0:S.automated,body:(i=s.reply)==null?void 0:i.body,at:s.at,attachments:(d=s.reply)==null?void 0:d.attachments},m=Mt(c),u=r&&r.who===m&&Math.abs(new Date(s.at).getTime()-new Date(r.at).getTime())<5*6e4;return r={who:m,at:s.at},b+ze(c,u?"cont":"")}).join("")}function Mt(e){return e.from==="reporter"?"me":e.automated?"assistant":`team:${e.author||""}`}function Tt(e){const t=me(e.at);return`
|
|
1128
1215
|
<div class="sys k-${k(e.kind)}">
|
|
1129
1216
|
<span class="dot" aria-hidden="true"></span>${k(e.summary||"")}${t?`
|
|
1130
1217
|
<span class="t">· ${k(t)}</span>`:""}
|
|
1131
|
-
</div>`}function ze(e,t=""){const a=e.from==="reporter",
|
|
1218
|
+
</div>`}function ze(e,t=""){const a=e.from==="reporter",r=e.body||"",s=e.attachments||[],h=!a&&!!e.automated,b=r?`<span class="msg-text">${k(r)}</span>`:"",c=s.length?`<div class="att">${s.map(qt).join("")}</div>`:"";let m="",u="";if(h)m='<span class="msg-who auto">Assistant <span class="tag">AI</span></span>',u='<span class="av bot orb" aria-hidden="true"></span>';else if(!a){const S=e.author||"Support team";m=`<span class="msg-who">${k(S)}</span>`,u=`<span class="av" aria-hidden="true">${k(Xe(S))}</span>`}t.includes("cont")&&(m="");const f=h&&/it goes to the same person/i.test(r)?`<div class="quick" role="group" aria-label="Answer">
|
|
1132
1219
|
<button type="button" data-quick="Yes, this is the problem">${O}That's right</button>
|
|
1133
1220
|
<button type="button" data-quick="No, that is not the problem">That's not it</button>
|
|
1134
|
-
</div>`:
|
|
1221
|
+
</div>`:h&&Et.test(r)?`<div class="quick" role="group" aria-label="Did this answer your question?">
|
|
1135
1222
|
<button type="button" data-quick="Yes, that answers it">${O}Yes, that answers it</button>
|
|
1136
1223
|
<button type="button" data-quick="No, I still need help">No, I still need help</button>
|
|
1137
1224
|
</div>`:"";return`
|
|
1138
|
-
<div class="msg-row ${a?"mine":"theirs"} ${
|
|
1139
|
-
${
|
|
1140
|
-
${
|
|
1141
|
-
<div class="bubble ${
|
|
1142
|
-
${
|
|
1143
|
-
<span class="msg-when">${k(
|
|
1144
|
-
</div>`}function
|
|
1225
|
+
<div class="msg-row ${a?"mine":"theirs"} ${h?"auto":""} ${t}">
|
|
1226
|
+
${u}
|
|
1227
|
+
${m}
|
|
1228
|
+
<div class="bubble ${r?"":"silent"}">${b}${c}</div>
|
|
1229
|
+
${f}
|
|
1230
|
+
<span class="msg-when">${k(me(e.at)||Z(e.at))}</span>
|
|
1231
|
+
</div>`}function Qt(){return`
|
|
1145
1232
|
<div class="typing-row">
|
|
1146
|
-
<span class="av bot" aria-hidden="true"
|
|
1233
|
+
<span class="av bot orb" aria-hidden="true"></span>
|
|
1147
1234
|
<span class="msg-who auto">Assistant <span class="tag">AI</span></span>
|
|
1148
1235
|
<div class="bubble typing" role="img" aria-label="The assistant is working on it"><i></i><i></i><i></i></div>
|
|
1149
|
-
</div>`}function
|
|
1236
|
+
</div>`}function qt(e){const t=k(e.name||"attachment");if(!e.url)return`<span class="file"><span class="nm">${t}</span></span>`;const a=k(e.url);return e.type==="SCREENSHOT"?`<a href="${a}" target="_blank" rel="noopener noreferrer"><img src="${a}" alt="${t}" loading="lazy"></a>`:e.type==="AUDIO"?`<audio controls preload="metadata" src="${a}"></audio>`:e.type==="VIDEO"?`<video controls preload="metadata" src="${a}"></video>`:`
|
|
1150
1237
|
<a class="file" href="${a}" target="_blank" rel="noopener noreferrer" download>
|
|
1151
1238
|
<span class="nm">${t}</span>
|
|
1152
|
-
${e.size?`<span class="sz">${k(
|
|
1153
|
-
</a>`}function
|
|
1239
|
+
${e.size?`<span class="sz">${k(_(e.size))}</span>`:""}
|
|
1240
|
+
</a>`}function zt(e,t,a,r){var x;const{client:s,cfg:h}=e,b=document.createElement("div");b.className="composer",b.innerHTML=`
|
|
1154
1241
|
<div class="staged" hidden></div>
|
|
1155
1242
|
<div class="row">
|
|
1156
1243
|
<div class="tools">
|
|
1157
|
-
${
|
|
1244
|
+
${h.attachments===!1?"":`
|
|
1158
1245
|
<button class="tool" type="button" data-act="attach" title="Attach a file" aria-label="Attach a file">${he}</button>
|
|
1159
|
-
<button class="tool" type="button" data-act="voice" title="Record a voice note" aria-label="Record a voice note">${
|
|
1246
|
+
<button class="tool" type="button" data-act="voice" title="Record a voice note" aria-label="Record a voice note">${fe}</button>`}
|
|
1160
1247
|
<button class="tool" type="button" data-act="livecall" title="Call the team" aria-label="Call the team" hidden>${ee}</button>
|
|
1161
1248
|
</div>
|
|
1162
1249
|
<textarea rows="1" placeholder="Write a reply…" aria-label="Write a reply"></textarea>
|
|
1163
|
-
<button class="send" type="button" data-act="send" title="Send" aria-label="Send" disabled>${
|
|
1250
|
+
<button class="send" type="button" data-act="send" title="Send" aria-label="Send" disabled>${be}</button>
|
|
1164
1251
|
</div>
|
|
1165
1252
|
<div class="note" hidden></div>
|
|
1166
|
-
<input type="file" hidden multiple accept="${
|
|
1167
|
-
<span class="chip ${
|
|
1168
|
-
<span class="nm">${k(
|
|
1169
|
-
<span class="sz">${
|
|
1170
|
-
<button type="button" data-drop="${L}" aria-label="Remove ${k(
|
|
1171
|
-
</span>`).join("");for(const
|
|
1253
|
+
<input type="file" hidden multiple accept="${we.join(",")}">`,t.appendChild(b);const c=b.querySelector(".staged"),m=b.querySelector("textarea"),u=b.querySelector('[data-act="send"]'),f=b.querySelector('[data-act="voice"]'),S=b.querySelector('[data-act="livecall"]'),i=b.querySelector("input[type=file]"),d=b.querySelector(".note"),v=[];let E=null,p=!1;function o(y,g=""){d.hidden=!y,d.className=`note ${g}`,d.textContent=y||""}function l(){const y=v.filter(g=>g.storageKey);u.disabled=p||!m.value.trim()&&!y.length,c.hidden=!v.length,c.innerHTML=v.map((g,L)=>`
|
|
1254
|
+
<span class="chip ${g.storageKey?"":"uploading"}">
|
|
1255
|
+
<span class="nm">${k(g.name)}</span>
|
|
1256
|
+
<span class="sz">${g.storageKey?_(g.size):"sending…"}</span>
|
|
1257
|
+
<button type="button" data-drop="${L}" aria-label="Remove ${k(g.name)}">${J}</button>
|
|
1258
|
+
</span>`).join("");for(const g of c.querySelectorAll("[data-drop]"))g.addEventListener("click",()=>{v.splice(Number(g.dataset.drop),1),l()})}async function n(y,g,L){const M={name:L,size:y.size,storageKey:null};v.push(M),l();try{const{storageKey:C,mime:B}=await s.uploadAttachment(y,g);M.storageKey=C,M.mime=B}catch(C){v.splice(v.indexOf(M),1),o(C.message||"That file could not be sent.","err")}l()}m.addEventListener("input",()=>{m.style.height="auto",m.style.height=`${Math.min(m.scrollHeight,120)}px`,l()}),m.addEventListener("keydown",y=>{y.key==="Enter"&&!y.shiftKey&&!y.isComposing&&(y.preventDefault(),$())}),(x=b.querySelector('[data-act="attach"]'))==null||x.addEventListener("click",()=>i.click()),i.addEventListener("change",()=>{o("");for(const y of i.files){if(y.size>s.config.maxAttachmentBytes){o(`${y.name} is larger than ${_(s.config.maxAttachmentBytes)}.`,"err");continue}n(y,y.type,y.name)}i.value=""}),f&&!et()&&(f.disabled=!0,f.title="This browser cannot record audio"),f==null||f.addEventListener("click",async()=>{if(E){const y=E;E=null,f.classList.remove("recording"),f.innerHTML=fe,o("");const{blob:g,mime:L}=await y.stop();g.size&&n(g,L,"Voice note");return}try{o(""),E=await it({maxMs:s.config.maxRecordingMs,onTick:y=>o(`Recording — ${te(y)}. Tap the mic to stop.`),onAutoStop:()=>f.click()}),f.classList.add("recording"),f.innerHTML=We}catch{E=null,o("The microphone is not available — check the browser permission.","err")}}),s.canCallTeam(r).then(y=>{y&&(S.hidden=!1,e.preloadCall())}).catch(()=>{}),S.addEventListener("click",async()=>{S.disabled=!0,o("");try{const y=await s.startLiveCall(r);e.showLiveCall(t,a,y)}catch(y){o(y.message.replace("[BugCatch] ",""),"err")}finally{S.disabled=!1}}),u.addEventListener("click",$),a.addEventListener("click",y=>{var L,M;const g=(M=(L=y.target).closest)==null?void 0:M.call(L,"[data-quick]");!g||p||(m.value=g.dataset.quick,$())});async function $(){var L;const y=m.value.trim(),g=v.filter(M=>M.storageKey);if(!(p||!y&&!g.length)){p=!0,l(),o(""),a.insertAdjacentHTML("beforeend",ze({from:"reporter",body:y,at:new Date().toISOString(),attachments:g.map(M=>({type:"FILE",name:M.name,size:M.size}))},"pending")),U(a,{smooth:!0});try{await s.replyToReport(r,{body:y,attachments:g.map(M=>({storageKey:M.storageKey,mime:M.mime,name:M.name,size:M.size}))}),m.value="",m.style.height="auto",v.length=0,await e.refreshThread(r)}catch(M){(L=a.querySelector(".msg-row.pending"))==null||L.classList.replace("pending","failed"),o(M.message||"That could not be sent — try again.","err")}finally{p=!1,l()}}}l()}function Ce(e){return JSON.stringify(e?[e.score,e.current,e.comment||null]:null)}function ce(e,{client:t,report:a,rating:r,justRated:s=!1,question:h=null,onRated:b=null,onError:c=null}){var p;e.dataset.key=Ce(r);const m=r!=null&&r.current?r.score:0,u=r?r.current?s?"Thanks — the team will see that.":`You rated this ${r.score} out of 5.`:`You rated an earlier fix ${r.score} out of 5. How did this one go?`:h||"How did we do?",f=s&&(r==null?void 0:r.current)&&!r.comment;e.innerHTML=`
|
|
1259
|
+
<p class="fr-q">${k(u)}</p>
|
|
1260
|
+
<div class="stars" role="group" aria-label="Rate how this was handled, 1 to 5">${[1,2,3,4,5].map(o=>`
|
|
1261
|
+
<button type="button" data-score="${o}" aria-pressed="${o===m}" aria-label="${o} out of 5${o===1?", poor":o===5?", great":""}" class="${o<=m?"on":""}">${ge}</button>`).join("")}
|
|
1262
|
+
</div>
|
|
1263
|
+
${r!=null&&r.current&&r.comment?`<p class="fr-said">“${k(r.comment)}”</p>`:""}
|
|
1264
|
+
${f?`
|
|
1265
|
+
<div class="fr-note">
|
|
1266
|
+
<textarea maxlength="2000" aria-label="Add a note to your rating" placeholder="${r.score<=2?"What went wrong? (optional)":"Anything to add? (optional)"}"></textarea>
|
|
1267
|
+
<button type="button" data-act="rating-note">Add note</button>
|
|
1268
|
+
</div>`:""}
|
|
1269
|
+
${r?"":'<p class="fr-hint">1 is poor, 5 is great.</p>'}
|
|
1270
|
+
<p class="feedback-status" role="status"></p>`;const S=[...e.querySelectorAll("[data-score]")],i=o=>S.forEach(l=>l.classList.toggle("on",Number(l.dataset.score)<=o)),d=o=>e.querySelectorAll("button, textarea").forEach(l=>{l.disabled=o}),v=e.querySelector(".feedback-status");async function E(o,l){var n;d(!0),v.textContent="";try{const $=await t.rate(a.id,{score:o,comment:l});ce(e,{client:t,report:a,rating:$,justRated:!0,question:h,onRated:b,onError:c}),(n=e.querySelector(".fr-note textarea"))==null||n.focus(),b==null||b($)}catch($){v.textContent=$.message,d(!1),i(m),c==null||c($)}}for(const o of S){const l=Number(o.dataset.score);o.addEventListener("mouseenter",()=>i(l)),o.addEventListener("focus",()=>i(l)),o.addEventListener("blur",()=>i(m)),o.addEventListener("click",()=>E(l))}e.querySelector(".stars").addEventListener("mouseleave",()=>i(m)),(p=e.querySelector('[data-act="rating-note"]'))==null||p.addEventListener("click",()=>{var l;const o=e.querySelector(".fr-note textarea").value.trim();if(!o){(l=e.querySelector(".fr-note"))==null||l.remove();return}E(r.score,o)})}const de=new WeakMap;function Ct(e){return e.rating?` · <span class="rated" aria-label="You rated this ${Number(e.rating)} out of 5">${ge}${Number(e.rating)}</span>`:e.ratingAsked?' · <span class="rate-ask">Rate it</span>':""}function Ht(e){var E;const{client:t,scrim:a,close:r}=e;let s=null;function h(p,{callFailed:o=null}={}){if(p!=null&&p.id&&!o){m(p.id,{fresh:!0}).then(l=>{l||b(p,{callFailed:o})});return}b(p,{callFailed:o})}function b(p,{callFailed:o=null}={}){var x;const l=p!=null&&p.id?String(p.id).slice(0,8):null,n=(x=p==null?void 0:p.estimate)!=null&&x.label?String(p.estimate.label):null,$=o?`<p class="eta">${k(o)} Your report is filed, and the team will reply in the chat.</p>`:"";a.querySelector(".panel").innerHTML=`
|
|
1172
1271
|
<div class="done">
|
|
1173
1272
|
<div class="tick">${O}</div>
|
|
1174
1273
|
<h3>Thanks — that's on its way.</h3>
|
|
1175
|
-
<p>${
|
|
1176
|
-
${
|
|
1177
|
-
${
|
|
1178
|
-
</div>`,setTimeout(
|
|
1179
|
-
${
|
|
1180
|
-
<div class="history" aria-busy="true">${
|
|
1181
|
-
<button class="row" type="button" data-report="${k(
|
|
1182
|
-
<span class="row-ico" aria-hidden="true">${
|
|
1274
|
+
<p>${l?`Filed as <code>${k(l)}</code>.`:"The team has what they need to reproduce it."}</p>
|
|
1275
|
+
${$}
|
|
1276
|
+
${n?`<p class="eta">Reports like this usually take <strong>${k(n)}</strong>. We'll let you know when it moves.</p>`:""}
|
|
1277
|
+
</div>`,setTimeout(r,$?6e3:n?4e3:2e3)}async function c(){const p=a.querySelector(".panel");clearTimeout(u),s=null,p.classList.remove("is-chat"),p.innerHTML=`
|
|
1278
|
+
${re({title:"Your reports",sub:"Where each one has got to.",theme:e.themeLabel()})}
|
|
1279
|
+
<div class="history" aria-busy="true">${Ze(3)}</div>`,p.querySelector('[data-act="close"]').addEventListener("click",r);let o=[];try{({reports:o}=await t.myReports())}catch{const n=p.querySelector(".history");n&&(n.innerHTML=ie("Couldn't load your reports just now.",F));return}const l=p.querySelector(".history");if(l){l.removeAttribute("aria-busy"),l.innerHTML=o.length?o.map((n,$)=>`
|
|
1280
|
+
<button class="row" type="button" data-report="${k(n.id)}" style="animation-delay:${Math.min($,8)*30}ms">
|
|
1281
|
+
<span class="row-ico" aria-hidden="true">${Ie}</span>
|
|
1183
1282
|
<span class="who">
|
|
1184
|
-
<span class="ttl">${k(
|
|
1185
|
-
<span class="sub">${k(
|
|
1283
|
+
<span class="ttl">${k(n.title)}</span>
|
|
1284
|
+
<span class="sub">${k(n.reference)} · ${k(Z(n.createdAt))}${Ct(n)}</span>
|
|
1186
1285
|
</span>
|
|
1187
|
-
<span class="pill ${k(String(
|
|
1188
|
-
<span class="chev" aria-hidden="true">${
|
|
1189
|
-
</button>`).join(""):
|
|
1190
|
-
${
|
|
1191
|
-
<div class="history chatting" aria-busy="true"><div class="thread">${
|
|
1286
|
+
<span class="pill ${k(String(n.status).toLowerCase())}">${k(se(n.status))}</span>
|
|
1287
|
+
<span class="chev" aria-hidden="true">${Fe}</span>
|
|
1288
|
+
</button>`).join(""):ie("You haven't reported anything yet.",_e);for(const n of l.querySelectorAll("[data-report]"))n.addEventListener("click",()=>m(n.dataset.report))}}async function m(p,{fresh:o=!1}={}){var g;const l=a.querySelector(".panel");clearTimeout(u),l.classList.add("is-chat"),l.innerHTML=`
|
|
1289
|
+
${re({back:!0,title:o?"Looking into it":"Your report",sub:o?"It may ask you a question here.":"Updates, and a way to reply.",theme:e.themeLabel()})}
|
|
1290
|
+
<div class="history chatting" aria-busy="true"><div class="thread">${Ge()}</div></div>`,l.querySelector('[data-act="close"]').addEventListener("click",r),l.querySelector('[data-act="back"]').addEventListener("click",c);let n=null;try{n=await t.myReport(p)}catch{n=null}const $=l.querySelector(".history");if(!$||!l.querySelector('[data-act="back"]'))return!1;if(!n)return o?(l.classList.remove("is-chat"),!1):($.removeAttribute("aria-busy"),$.innerHTML=ie("Couldn't load that report just now.",F),!1);s=p,t.markReportRead(p);const x=qe(n.timeline);$.classList.add("chatting"),$.removeAttribute("aria-busy"),$.innerHTML=`
|
|
1192
1291
|
<div class="report-head">
|
|
1193
|
-
<span class="ttl">${k(
|
|
1194
|
-
<span class="sub">${k(
|
|
1195
|
-
<span class="pill ${k(String(
|
|
1196
|
-
${(
|
|
1292
|
+
<span class="ttl">${k(n.title)}</span>
|
|
1293
|
+
<span class="sub">${k(n.reference)} · ${k(n.project||"")}</span>
|
|
1294
|
+
<span class="pill ${k(String(n.status).toLowerCase())}">${k(se(n.status))}</span>
|
|
1295
|
+
${(g=n.estimate)!=null&&g.label?`<span class="eta-line">Usually takes ${k(String(n.estimate.label))}</span>`:""}
|
|
1197
1296
|
</div>
|
|
1198
|
-
<div class="thread" role="log" aria-live="polite" aria-label="Conversation">${
|
|
1199
|
-
<div class="as-body${
|
|
1297
|
+
<div class="thread" role="log" aria-live="polite" aria-label="Conversation">${x}</div>`;const y=$.querySelector(".thread");return de.set(y,x),U(y),S($,n),i($,n),n.canReply&&zt(e,$,y,p),f($,n,p),U(y),!0}let u=null;function f(p,o,l){var W,T,H;clearTimeout(u);const n=o.assistant,$=p.querySelector(".thread");let x=p.querySelector(".assistant");if(!n){x==null||x.remove(),(W=$==null?void 0:$.querySelector(".typing-row"))==null||W.remove();return}const y=(x==null?void 0:x.dataset.phase)||null;x||(x=document.createElement("div"),x.setAttribute("role","status"),x.setAttribute("aria-live","polite"),(T=p.querySelector(".report-head"))==null||T.after(x)),x.className=`assistant ${k(n.phase)}`,x.dataset.phase=n.phase;const g=n.steps||[],L=g.filter(z=>z.state==="done").length,M=g.some(z=>z.state==="active")?.5:0,C=g.length?Math.round((L+M)/g.length*100):0,B=`
|
|
1298
|
+
<div class="as-body${y&&y!==n.phase?" entering":""}">
|
|
1200
1299
|
<div class="as-top">
|
|
1201
|
-
<span class="as-orb"
|
|
1300
|
+
<span class="as-orb${n.phase==="calling"||n.phase==="resolved"?"":" orb"}" aria-hidden="true">${n.phase==="calling"?ee:n.phase==="resolved"?O:""}</span>
|
|
1202
1301
|
<div class="as-text">
|
|
1203
|
-
<div class="as-title">${k(
|
|
1204
|
-
<div class="as-detail">${k(
|
|
1302
|
+
<div class="as-title">${k(n.title)}</div>
|
|
1303
|
+
<div class="as-detail">${k(n.detail)}</div>
|
|
1205
1304
|
</div>
|
|
1206
1305
|
</div>
|
|
1207
1306
|
</div>
|
|
1208
|
-
${
|
|
1209
|
-
<div class="as-progress" role="progressbar" aria-label="Progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${
|
|
1210
|
-
<ol class="as-steps">${
|
|
1307
|
+
${g.length?`
|
|
1308
|
+
<div class="as-progress" role="progressbar" aria-label="Progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${C}"><i style="width:${C}%"></i></div>
|
|
1309
|
+
<ol class="as-steps">${g.map(z=>`<li class="${k(z.state)}"${z.state==="active"?' aria-current="step"':""}><span class="dot"></span><span class="lbl">${k(z.label)}</span></li>`).join("")}</ol>`:""}`,N=JSON.stringify([n.phase,n.title,n.detail,g]);if(x.dataset.key!==N){const z=x.querySelector(".as-progress i"),D=z==null?void 0:z.style.width;x.innerHTML=B,x.dataset.key=N;const j=x.querySelector(".as-progress i");j&&D&&(j.style.width=D,requestAnimationFrame(()=>{j.style.width=`${C}%`}))}if($){const z=ve($),D=$.querySelector(".typing-row");n.phase!=="analyzing"?D==null||D.remove():(!D||D!==$.lastElementChild)&&(D==null||D.remove(),$.insertAdjacentHTML("beforeend",Qt()),z&&U($))}n.phase==="analyzing"?u=setTimeout(()=>d(l),3e3):n.phase==="calling"?u=setTimeout(()=>d(l),1e4):n.phase==="needs_info"&&y!=="needs_info"&&((H=p.querySelector(".composer textarea"))==null||H.focus())}function S(p,o){var n,$;if((n=p.querySelector(".fix-verification"))==null||n.remove(),!o.resolvedAt||!["RESOLVED","CLOSED"].includes(o.status))return;const l=document.createElement("div");l.className="fix-verification",o.verification?l.textContent=o.verification==="CONFIRMED"?"You confirmed that this fix works.":"Your feedback was recorded.":(l.innerHTML='<p>Does the fix work for you?</p><textarea maxlength="4000" aria-label="Fix feedback" placeholder="What happens when you try again? (optional)"></textarea><button type="button" data-result="CONFIRMED">It works now</button> <button type="button" data-result="STILL_HAPPENING">Still happening</button><p class="feedback-status" role="status"></p>',l.querySelectorAll("[data-result]").forEach(x=>{x.onclick=async()=>{l.querySelectorAll("button").forEach(y=>{y.disabled=!0});try{await t.verifyFix(o.id,{result:x.dataset.result,resolvedAt:o.resolvedAt,note:l.querySelector("textarea").value}),await m(o.id)}catch(y){l.querySelector(".feedback-status").textContent=y.message,l.querySelectorAll("button").forEach(g=>{g.disabled=!1})}}})),($=p.querySelector(".report-head"))==null||$.after(l)}function i(p,o){var $;let l=p.querySelector(".fix-rating");if(!["RESOLVED","CLOSED"].includes(o.status)||!o.ratingAsked){l==null||l.remove();return}l&&l.dataset.key===Ce(o.rating)||(l||(l=document.createElement("div"),l.className="fix-rating",($=p.querySelector(".fix-verification")||p.querySelector(".report-head"))==null||$.after(l)),ce(l,{client:t,report:o,rating:o.rating||null}))}async function d(p){const o=a.querySelector(".history.chatting"),l=o==null?void 0:o.querySelector(".thread");if(!l||s!==p)return;let n=null;try{n=await t.myReport(p)}catch{}if(e.closed||!n||s!==p)return;S(o,n),i(o,n);const $=ve(l),x=qe(n.timeline);de.get(l)!==x&&(l.innerHTML=x,de.set(l,x)),f(o,n,p),$&&U(l);const y=o.querySelector(".report-head .pill");y&&(y.className=`pill ${String(n.status).toLowerCase()}`,y.textContent=se(n.status))}const v=t.on("update",p=>{!s||(p==null?void 0:p.bugId)!==s||(t.markReportRead(s),d(s))});e.onDestroy(()=>{v(),clearTimeout(u)}),(E=a.querySelector('[data-act="history"]'))==null||E.addEventListener("click",c),e.succeed=h,e.refreshThread=d,e.openReportId=()=>s}const He="bugcatch.rateLater",Rt=50;function Re(){try{const e=JSON.parse(window.localStorage.getItem(He)||"[]");return Array.isArray(e)?e:[]}catch{return[]}}function At(e){try{const t=Re().filter(a=>a!==e);t.push(e),window.localStorage.setItem(He,JSON.stringify(t.slice(-Rt)))}catch{}}function It(e,t=Re()){const a=new Set(t),r=(e||[]).filter(h=>h.ratingDue==="require"||h.ratingDue==="ask"&&!a.has(h.id));if(!r.length)return null;const s=h=>new Date(h.resolvedAt||h.updatedAt||0).getTime()||0;return r.reduce((h,b)=>s(b)>s(h)?b:h)}function Dt(e){const{client:t,rateDue:a,compose:r,picks:s,known:h,callBtn:b,titleInput:c,scrim:m}=e;let u=!1;e.mustRate=()=>u;function f(v){u=v;for(const E of[r,s,h])E.classList.toggle("held",v),E.inert=v;v?b.hidden=!0:e.callOffered()&&!e.mustSignIn()&&(b.hidden=!1),e.refreshSendState()}function S(){u&&f(!1)}function i(){a.hidden=!0,a.replaceChildren(),S(),c.focus()}function d(v){var l;const E=v.ratingDue==="require",p=v.resolvedAt?Z(v.resolvedAt):"",o=v.status==="CLOSED"?"closed":"fixed";if(a.hidden=!1,a.classList.toggle("is-required",E),a.innerHTML=`
|
|
1310
|
+
<div class="rd-head">
|
|
1311
|
+
<span class="rd-eyebrow">${E?"Before you report something new":`Your report was ${o}`}</span>
|
|
1312
|
+
${E?"":'<button type="button" class="link rd-later" data-act="rate-later">Not now</button>'}
|
|
1313
|
+
</div>
|
|
1314
|
+
<p class="rd-report">
|
|
1315
|
+
<span class="rd-ico" aria-hidden="true">${O}</span>
|
|
1316
|
+
<span class="rd-ttl">${k(v.title)}</span>
|
|
1317
|
+
<span class="rd-sub">${k(v.reference)}${p?` · ${o} ${k(p)}`:""}</span>
|
|
1318
|
+
</p>
|
|
1319
|
+
<div class="rd-stars"></div>`,(l=a.querySelector('[data-act="rate-later"]'))==null||l.addEventListener("click",()=>{At(v.id),i()}),ce(a.querySelector(".rd-stars"),{client:t,report:v,rating:null,question:E?"How did we handle it? Rate it to send a new one.":"How did we do?",onRated:()=>{var n;a.querySelector(".rd-eyebrow").textContent=`Your report was ${o}`,(n=a.querySelector('[data-act="skip"]'))==null||n.remove(),a.classList.remove("is-required"),S()},onError:()=>{if(!u||a.querySelector('[data-act="skip"]'))return;const n=document.createElement("button");n.type="button",n.className="link rd-later",n.dataset.act="skip",n.textContent="Skip for now",n.addEventListener("click",i),a.querySelector(".rd-head").append(n)}}),E){f(!0);const n=m.getRootNode().activeElement;(!n||!a.contains(n))&&a.focus()}}t.hasReports()&&t.myReports().then(({reports:v})=>{if(e.closed)return;const E=It(v);E&&d(E)}).catch(()=>{})}function jt({root:e,host:t,dock:a,client:r,onClose:s,preloadCall:h=()=>{},themeControls:b=null}){Vt(e);const c=r.config,m=()=>(b==null?void 0:b.label())||"",u=document.createElement("div");u.className=`scrim ${a.classList.contains("at-left")?"at-left":"at-right"} ${a.classList.contains("at-top")?"at-top":"at-bottom"}`,u.style.setProperty("--bc-dock-h",`${Math.round(a.getBoundingClientRect().height)}px`),u.innerHTML=`
|
|
1211
1320
|
<div class="panel" role="dialog" aria-modal="true" aria-labelledby="bc-h">
|
|
1212
|
-
${
|
|
1321
|
+
${re({id:"bc-h",title:"Report a bug",sub:"We attach the page details for you.",theme:m()})}
|
|
1213
1322
|
<div class="body">
|
|
1214
1323
|
<div class="slot" role="alert"></div>
|
|
1324
|
+
<!-- A settled report still waiting for its rating. Drawn only when the
|
|
1325
|
+
project asks for one here; see rate-due.js. -->
|
|
1326
|
+
<div class="rate-due fix-rating" tabindex="-1" hidden></div>
|
|
1215
1327
|
<!-- What the project's team is telling visitors. Drawn only when it
|
|
1216
1328
|
has published something. -->
|
|
1217
1329
|
<div class="notices" hidden></div>
|
|
@@ -1220,21 +1332,21 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
1220
1332
|
close by itself. Drawn only when the project offers any. -->
|
|
1221
1333
|
<div class="picks" hidden></div>
|
|
1222
1334
|
<div class="known" hidden></div>
|
|
1223
|
-
${
|
|
1335
|
+
${pt(c)}
|
|
1224
1336
|
</div>
|
|
1225
1337
|
<div class="foot">
|
|
1226
1338
|
<span class="note" aria-live="polite"></span>
|
|
1227
|
-
${
|
|
1339
|
+
${r.hasReports()?'<button class="quiet" type="button" data-act="history">Your reports</button>':""}
|
|
1228
1340
|
<span class="spacer"></span>
|
|
1229
1341
|
<!-- Hidden until the API confirms this project can take a call, which
|
|
1230
1342
|
most cannot. Drawn here rather than as a second launcher because it
|
|
1231
1343
|
is the same errand as Send report — the difference is only whether
|
|
1232
1344
|
the reporter would rather say it than type it. -->
|
|
1233
1345
|
<button class="ghost" type="button" data-act="call" hidden>${ee}Talk to the team</button>
|
|
1234
|
-
<button class="primary" type="button" data-act="send">Send report ${
|
|
1346
|
+
<button class="primary" type="button" data-act="send">Send report ${be}</button>
|
|
1235
1347
|
</div>
|
|
1236
1348
|
<div class="powered">Powered by
|
|
1237
|
-
<a class="brand-credit" href="https://bugcatch.sphoro.com" target="_blank" rel="noopener noreferrer" aria-label="BugCatch">${
|
|
1349
|
+
<a class="brand-credit" href="https://bugcatch.sphoro.com" target="_blank" rel="noopener noreferrer" aria-label="BugCatch">${Ke}</a>
|
|
1238
1350
|
</div>
|
|
1239
|
-
</div>`;const
|
|
1351
|
+
</div>`;const f=x=>u.querySelector(x),S=f(".slot"),i=[],d={client:r,cfg:c,root:e,host:t,dock:a,scrim:u,$:f,titleInput:f("#bc-title"),descInput:f("#bc-desc"),compose:f(".compose"),sendBtn:f('[data-act="send"]'),callBtn:f('[data-act="call"]'),historyBtn:f('[data-act="history"]'),note:f(".foot .note"),whoami:f(".whoami"),refsBox:f(".refs"),notices:f(".notices"),known:f(".known"),picks:f(".picks"),rateDue:f(".rate-due"),sending:!1,closed:!1,say:$,close:l,preloadCall:h,themeLabel:m,onDestroy:x=>{i.push(x)},refreshSendState:null,isRecording:null,stopRecording:null,holdForReference:null,answeredReference:null,pickedIssue:null,offerCall:null,callOffered:null,showLiveCall:null,mustSignIn:null,recheckSignIn:null,mustRate:()=>!1,succeed:null,refreshThread:null,openReportId:null};ut(d),mt(d),xt(d),kt(d),$t(d),St(d),Lt(d),Ht(d),Dt(d);const v=document.activeElement,E=document.documentElement.style,p=E.overflow;E.overflow="hidden";function o(){d.closed||(i.forEach(x=>x()),d.closed=!0,E.overflow=p,document.removeEventListener("keydown",n,!0),u.remove(),a.hidden=!1,t.style.opacity="",s==null||s())}function l(){var x;if(!d.closed){u.classList.add("closing"),setTimeout(o,160);try{(x=v==null?void 0:v.focus)==null||x.call(v)}catch{}}}function n(x){if(x.key==="Escape"){if(x.stopPropagation(),d.isRecording()){d.stopRecording({keep:!1});return}d.sending||l();return}if(x.key!=="Tab"||d.isRecording())return;const y=[...u.querySelectorAll("button:not(:disabled), input:not([hidden]), textarea, select, [href]")].filter(C=>C.offsetParent!==null||C===document.activeElement);if(!y.length)return;const g=y[0],L=y[y.length-1],M=u.getRootNode().activeElement;x.shiftKey&&M===g?(x.preventDefault(),L.focus()):!x.shiftKey&&M===L&&(x.preventDefault(),g.focus())}document.addEventListener("keydown",n,!0),u.addEventListener("click",x=>{x.target===u&&!d.sending&&l()}),f('[data-act="close"]').addEventListener("click",l),u.addEventListener("click",x=>{const y=x.target.closest('[data-act="theme"]');if(!y||!b)return;const g=b.cycle();y.title=`Theme: ${g.label}`,y.setAttribute("aria-label",`Theme: ${g.label}. Change theme`)});function $(x,y="err"){S.innerHTML=x?`<div class="msg ${y}">${y==="err"?F:""}<span>${k(x)}</span></div>`:""}return e.appendChild(u),d.refreshSendState(),d.titleInput.focus(),{destroy:o,close:l}}function Vt(e){if(e.querySelector("style[data-panel]"))return;const t=document.createElement("style");t.setAttribute("data-panel",""),t.textContent=Ue;const a=e.querySelector("style");a?a.after(t):e.prepend(t)}const Ot=Object.freeze(Object.defineProperty({__proto__:null,openPanel:jt},Symbol.toStringTag,{value:"Module"})),Bt="0.20.0",Ae="__bugcatchChunks",Nt=e=>`${e}@${Bt}`;function Wt(e,t){const a=window[Ae]||(window[Ae]={});a[Nt(e)]=t}Wt("panel",Ot)})();
|
|
1240
1352
|
//# sourceMappingURL=bugcatch-panel.umd.js.map
|