/** * Reading Mode Toggle * Provides overview/standard/deep density modes for long research papers. * * Usage: Add data-reading-level="overview|standard|deep" to content sections. * Sections without the attribute are always visible. * * The toggle is auto-injected at the top of any page that includes this script * and has elements with data-reading-level attributes. */ (function() { 'use strict'; var STORAGE_KEY = 'tractatus-reading-mode'; var MODES = ['overview', 'standard', 'deep']; var MODE_LABELS = { overview: { label: 'Overview', desc: 'Key points only' }, standard: { label: 'Standard', desc: 'Main content' }, deep: { label: 'Deep', desc: 'Full detail' } }; function init() { // Only activate if page has reading-level content var leveledContent = document.querySelectorAll('[data-reading-level]'); if (leveledContent.length === 0) return; var savedMode = localStorage.getItem(STORAGE_KEY) || 'standard'; // Inject toggle UI after the first h1 or at the top of main content var heroOrH1 = document.querySelector('.hero-section, .page-hero, h1'); var insertPoint = (heroOrH1 && heroOrH1.parentElement) || document.querySelector('main') || document.body; var toggle = document.createElement('div'); toggle.className = 'reading-mode-toggle'; toggle.setAttribute('role', 'radiogroup'); toggle.setAttribute('aria-label', 'Reading depth'); toggle.innerHTML = 'Reading depth:' + MODES.map(function(mode) { return ''; }).join('') + ''; // Insert after the hero/h1 section if (insertPoint.nextSibling) { insertPoint.parentNode.insertBefore(toggle, insertPoint.nextSibling); } else { insertPoint.parentNode.appendChild(toggle); } // Apply initial mode applyMode(savedMode); // Handle clicks toggle.addEventListener('click', function(e) { var btn = e.target.closest('.reading-mode-btn'); if (!btn) return; var mode = btn.dataset.mode; localStorage.setItem(STORAGE_KEY, mode); // Update button states var buttons = toggle.querySelectorAll('.reading-mode-btn'); for (var i = 0; i < buttons.length; i++) { var b = buttons[i]; if (b.dataset.mode === mode) { b.classList.add('active'); b.setAttribute('aria-checked', 'true'); } else { b.classList.remove('active'); b.setAttribute('aria-checked', 'false'); } } applyMode(mode); }); } function applyMode(mode) { var elements = document.querySelectorAll('[data-reading-level]'); var modeIndex = MODES.indexOf(mode); for (var i = 0; i < elements.length; i++) { var el = elements[i]; var level = el.dataset.readingLevel; var levelIndex = MODES.indexOf(level); // overview shows only overview; standard shows overview+standard; deep shows all var visible = levelIndex <= modeIndex; el.style.display = visible ? '' : 'none'; el.setAttribute('aria-hidden', !visible); } // Update reading time estimate if present var counter = document.querySelector('.reading-mode-estimate'); if (counter) { var labels = { overview: '~3 min read', standard: '~12 min read', deep: '~25 min read' }; counter.textContent = labels[mode] || ''; } } // Init on DOM ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();