| 487 | toast.textContent = message; |
| 488 | toast.classList.add("is-visible"); |
| 489 | toastTimer = window.setTimeout(() => { |
| 490 | toast.classList.remove("is-visible"); |
| 491 | }, 2200); |
| 492 | } |
| 493 | |
| 494 | async function copyText(text) { |
| 495 | if (navigator.clipboard && window.isSecureContext) { |
| 496 | try { |
| 497 | await navigator.clipboard.writeText(text); |
| 498 | return; |
| 499 | } catch { |
| 500 | // Fall through to the selection-based copy path. |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | const textArea = document.createElement("textarea"); |
| 505 | textArea.value = text; |
| 506 | textArea.setAttribute("readonly", ""); |
| 507 | textArea.style.position = "fixed"; |
| 508 | textArea.style.opacity = "0"; |
| 509 | document.body.append(textArea); |
| 510 | textArea.select(); |
| 511 | const copied = document.execCommand("copy"); |
| 512 | textArea.remove(); |
| 513 | |
| 514 | if (!copied) { |
| 515 | throw new Error("Copy is unavailable."); |