/* PRABA accessibility text scaling — STAGING v2.4.0 */ (() => { 'use strict'; const STORAGE_KEY = 'prabaTextSizePreferenceV1'; const LEVELS = { standard: { label: '標準', factor: 1 }, large: { label: '大きめ', factor: 1.15 }, xlarge: { label: '特大', factor: 1.3 } }; let systemRootSizePx = 16; function readSavedLevel() { try { const saved = window.localStorage.getItem(STORAGE_KEY); return Object.prototype.hasOwnProperty.call(LEVELS, saved) ? saved : 'standard'; } catch (error) { return 'standard'; } } function saveLevel(level) { try { window.localStorage.setItem(STORAGE_KEY, level); } catch (error) { // Storage can be unavailable in restrictive WebView/private modes. } } function updateButtons(level) { document.querySelectorAll('[data-praba-text-size-level]').forEach((button) => { const active = button.dataset.prabaTextSizeLevel === level; button.setAttribute('aria-pressed', active ? 'true' : 'false'); }); } function applyLevel(level, persist = true) { const safeLevel = Object.prototype.hasOwnProperty.call(LEVELS, level) ? level : 'standard'; const factor = LEVELS[safeLevel].factor; const root = document.documentElement; root.dataset.prabaTextSize = safeLevel; root.style.fontSize = `${systemRootSizePx * factor}px`; updateButtons(safeLevel); if (persist) saveLevel(safeLevel); window.dispatchEvent(new CustomEvent('praba:textsizechange', { detail: { level: safeLevel, factor } })); } function createControl() { if (document.querySelector('.praba-text-size-control')) return; const control = document.createElement('div'); control.className = 'praba-text-size-control'; control.setAttribute('role', 'group'); control.setAttribute('aria-label', '文字サイズ'); const label = document.createElement('span'); label.className = 'praba-text-size-label'; label.textContent = '文字サイズ'; control.appendChild(label); Object.entries(LEVELS).forEach(([level, config]) => { const button = document.createElement('button'); button.type = 'button'; button.className = 'praba-text-size-button'; button.dataset.prabaTextSizeLevel = level; button.textContent = config.label; button.setAttribute('aria-pressed', 'false'); button.addEventListener('click', () => applyLevel(level)); control.appendChild(button); }); const anchor = document.querySelector('.header') || document.querySelector('.top-bar'); if (anchor && anchor.parentNode) { anchor.insertAdjacentElement('afterend', control); } else { document.body.insertAdjacentElement('afterbegin', control); } } function init() { const computedRootSize = Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize); systemRootSizePx = Number.isFinite(computedRootSize) && computedRootSize > 0 ? computedRootSize : 16; createControl(); applyLevel(readSavedLevel(), false); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init, { once: true }); } else { init(); } })();