diff --git a/index.html b/index.html index 31e4dbf..536f5b7 100644 --- a/index.html +++ b/index.html @@ -2083,6 +2083,35 @@ color: var(--gold); } + #article-copy-link { + position: absolute; + top: 14px; + right: 58px; + width: 36px; + height: 36px; + border-radius: 50%; + border: none; + background: rgba(93, 64, 55, 0.08); + color: #8d6e63; + font-size: 1rem; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s, color 0.2s; + z-index: 2; + line-height: 1; + } + + #article-copy-link:hover { + background: rgba(230, 81, 0, 0.12); + color: var(--gold); + } + + #article-copy-link.copied { + color: var(--gold); + } + /* ── Article actions row (schedule + trial) ──────────────────── */ #article-actions { display: flex; @@ -2744,6 +2773,7 @@
+
@@ -3674,12 +3704,28 @@ var articleOverlay = document.getElementById('article-overlay'); var articleClose = document.getElementById('article-close'); + var articleCopyLink = document.getElementById('article-copy-link'); var articleTitle = document.getElementById('article-title'); var articleArea = document.getElementById('article-area'); var articleDate = document.getElementById('article-date'); var articleBody = document.getElementById('article-body'); var articleContent = document.getElementById('article-content'); + function slugify(title) { + return (title || '').toLowerCase() + .replace(/[^a-z0-9\s-]/g, '') + .replace(/\s+/g, '-') + .replace(/-+/g, '-') + .replace(/^-|-$/g, ''); + } + + function findPostIndexBySlug(slug) { + for (var i = 0; i < allPosts.length; i++) { + if (slugify(allPosts[i].title) === slug) return i; + } + return -1; + } + function openArticle(index) { var post = allPosts[index]; if (!post) return; @@ -3690,11 +3736,17 @@ articleBody.scrollTop = 0; articleOverlay.classList.add('is-open'); document.body.style.overflow = 'hidden'; + history.replaceState(null, '', '#post-' + slugify(post.title)); + if (articleCopyLink) { + articleCopyLink.innerHTML = '🔗'; + articleCopyLink.classList.remove('copied'); + } } function closeArticle() { articleOverlay.classList.remove('is-open'); document.body.style.overflow = ''; + history.replaceState(null, '', window.location.pathname + window.location.search); } articleClose.addEventListener('click', closeArticle); @@ -3705,6 +3757,32 @@ if (e.key === 'Escape' && articleOverlay.classList.contains('is-open')) closeArticle(); }); + if (articleCopyLink) { + articleCopyLink.addEventListener('click', function() { + var url = window.location.href; + function showCopied() { + articleCopyLink.textContent = '\u2713'; + articleCopyLink.classList.add('copied'); + setTimeout(function() { + articleCopyLink.innerHTML = '🔗'; + articleCopyLink.classList.remove('copied'); + }, 2000); + } + if (navigator.clipboard && navigator.clipboard.writeText) { + navigator.clipboard.writeText(url).then(showCopied, showCopied); + } else { + var ta = document.createElement('textarea'); + ta.value = url; + ta.style.cssText = 'position:fixed;opacity:0;pointer-events:none'; + document.body.appendChild(ta); + ta.select(); + try { document.execCommand('copy'); } catch(e) {} + document.body.removeChild(ta); + showCopied(); + } + }); + } + grid.addEventListener('click', function(e) { var btn = e.target.closest('.news-read-btn'); if (!btn) return; @@ -3720,6 +3798,12 @@ allPosts = Array.isArray(posts) ? posts : []; filteredPosts = allPosts.slice(); render(); + var hash = window.location.hash; + if (hash && hash.indexOf('#post-') === 0) { + var slug = hash.slice(6); + var idx = findPostIndexBySlug(slug); + if (idx !== -1) openArticle(idx); + } }) .catch(function () { grid.innerHTML = emptyMarkup(