diff --git a/news/static/view.html b/news/static/view.html
index e5de6d3..0ea6658 100644
--- a/news/static/view.html
+++ b/news/static/view.html
@@ -116,6 +116,11 @@
.paragraph-card:hover{
box-shadow:0 3px 8px rgba(0,0,0,.14);
}
+ .paragraph-card--active{
+ outline:3px solid #1565c0; /* blue focus ring */
+ outline-offset:2px;
+ box-shadow:0 0 6px rgba(21,101,192,.35); /* soft glow */
+ }
/* ─────────── Relevance badge ─────────── */
.relevance-badge{
@@ -138,6 +143,36 @@
text-align:center;
margin-top:2rem;
}
+ /* ─────────── Floating navigation arrows ─────────── */
+ .nav-arrow{
+ position:fixed;
+ top:50%;
+ transform:translateY(-50%);
+ width:42px;
+ height:42px;
+ border:none;
+ border-radius:50%;
+ background:#0d47a1;
+ color:#fff;
+ font-size:1.35rem;
+ line-height:1;
+ display:flex;
+ align-items:center;
+ justify-content:center;
+ cursor:pointer;
+ box-shadow:0 2px 6px rgba(0,0,0,.25);
+ z-index:110;
+ transition:background .2s ease;
+ }
+ .nav-arrow:hover{
+ background:#1565c0;
+ }
+ .nav-arrow:disabled{
+ opacity:.35;
+ cursor:default;
+ }
+ .nav-arrow--left {left:.75rem;}
+ .nav-arrow--right{right:.75rem;}
@@ -261,16 +296,106 @@
badge.textContent = pct + '% relevant';
card.appendChild(badge);
- /* store ratings for possible later use */
- card.dataset.summaryRating = pData.summary_rating ?? '';
- card.dataset.topicRatings = JSON.stringify(
- (pData.topic_ratings ?? []).map(r => !!r.rating)
- );
+ card.dataset.summaryRating = rating; /* keep numeric value for sorting */
elParagraphs.appendChild(card);
});
+
+ setupRelevanceNavigation();
}
+
+ /* ───────────────── Floating-arrow navigation ───────────────── */
+ let sortedCards = []; // cards sorted by relevance
+ let currentIdx = -1; // index of the active card
+ let previousIdx = -1;
+ let arrowPrev, arrowNext; // will be assigned in setup
+
+ function setupRelevanceNavigation(){
+ const cards = Array.from(document.querySelectorAll('.paragraph-card'));
+ if(!cards.length) return;
+
+ sortedCards = cards.sort(
+ (a,b) => parseFloat(b.dataset.summaryRating) - parseFloat(a.dataset.summaryRating)
+ );
+
+ /* grab the arrow buttons so helpers can reach them */
+ arrowPrev = document.getElementById('arrowPrev');
+ arrowNext = document.getElementById('arrowNext');
+
+ arrowPrev.addEventListener('click', () => goTo(currentIdx - 1));
+ arrowNext.addEventListener('click', () => goTo(currentIdx + 1));
+
+ /* start on the most-relevant paragraph */
+ // goTo(0, /*smooth*/false);
+ updateArrowState();
+ }
+
+ function goTo(idx, smooth = true, fromScroll = false){
+ if (idx < 0)
+ idx = sortedCards.length - 1;
+ else if (idx >= sortedCards.length)
+ idx = 0;
+ // if(idx < 0 || idx >= sortedCards.length) return;
+
+ currentIdx = idx;
+
+ /* only scroll the viewport when the user clicked an arrow */
+ if(!fromScroll){
+ sortedCards[currentIdx].scrollIntoView({
+ behavior: smooth ? 'smooth' : 'auto',
+ block: 'center'
+ });
+ }
+
+ updateArrowState();
+ highlightActive();
+ }
+
+ function updateArrowState(){
+ if (currentIdx < 0) {
+ arrowPrev.disabled = false;
+ arrowNext.disabled = false;
+ return;
+ }
+ arrowPrev.disabled = currentIdx === 0;
+ arrowNext.disabled = currentIdx === sortedCards.length - 1;
+ }
+
+ function highlightActive(){
+ if (currentIdx < 0) return;
+ if(previousIdx !== -1){
+ sortedCards[previousIdx].classList.remove('paragraph-card--active');
+ }
+ sortedCards[currentIdx].classList.add('paragraph-card--active');
+ previousIdx = currentIdx;
+ }
+
+ document.addEventListener('keydown', evt => {
+ /* ignore key presses while the user is typing in inputs / textareas */
+ const tag = (evt.target.tagName || '').toLowerCase();
+ if (tag === 'input' || tag === 'textarea' || evt.target.isContentEditable) {
+ return;
+ }
+
+ if (evt.key === 'ArrowLeft') {
+ /* same as clicking the left arrow */
+ if (typeof arrowPrev !== 'undefined' && !arrowPrev.disabled) {
+ evt.preventDefault();
+ arrowPrev.click();
+ }
+ }
+ else if (evt.key === 'ArrowRight') {
+ /* same as clicking the right arrow */
+ if (typeof arrowNext !== 'undefined' && !arrowNext.disabled) {
+ evt.preventDefault();
+ arrowNext.click();
+ }
+ }
+ });
+
})();
+
+