const markDetected = (optionId, cardId, messageId) => { document.getElementById(optionId).className = 'option--detected'; document.getElementById(cardId).className += ' card--detected'; document.getElementById(messageId).className += '--detected'; }; const detectAppleArchitecture = async () => { if (navigator.userAgentData?.getHighEntropyValues) { try { const { architecture } = await navigator.userAgentData.getHighEntropyValues([ 'architecture', ]); if (architecture === 'arm') return 'silicon'; if (architecture === 'x86') return 'intel'; } catch (_) { // Fall through to UA heuristics } } const ua = navigator.userAgent.toLowerCase(); if (ua.includes('arm64') || ua.includes('aarch64')) return 'silicon'; // Browsers often report "MacIntel" on Apple Silicon; leave both unmarked preferred path return null; }; // Size cards from the real viewport (100vh is unreliable in Qt webviews) const STACK_BREAKPOINT = 1024; const MIN_CARD_HEIGHT = 120; const MAX_CARD_HEIGHT = 300; let syncGeneration = 0; let resizeTimer = null; const applyCardMetrics = (cardHeight) => { const root = document.documentElement; root.style.setProperty('--card-height', `${cardHeight}px`); root.style.setProperty('--card-logo-size', `${Math.round(cardHeight * 0.3)}px`); root.style.setProperty('--card-logo-gap', `${Math.max(4, Math.round(cardHeight * 0.04))}px`); root.style.setProperty( '--card-pad', `${Math.max(8, Math.min(40, Math.round(cardHeight * 0.1)))}px` ); root.style.setProperty( '--card-btn-height', `${Math.max(24, Math.min(40, Math.round(cardHeight * 0.13)))}px` ); }; const visibleHeight = (el) => { if (!el) return 0; const style = window.getComputedStyle(el); if (style.display === 'none' || style.visibility === 'hidden') return 0; return el.offsetHeight; }; const computeCardHeight = () => { const stacked = window.innerWidth <= STACK_BREAKPOINT; const rows = stacked ? 2 : 1; const section = document.querySelector('section'); const title = document.querySelector('.download-cards-text'); const link = document.querySelector('.download-cards > a'); if (!section) return MAX_CARD_HEIGHT; const sectionHeight = section.clientHeight || window.innerHeight; const titleBlock = visibleHeight(title) + visibleHeight(link) + 6; // Per row: card margins + option border + detected-message slot const rowChrome = stacked ? 24 : 20; const usable = sectionHeight - titleBlock - rowChrome * rows - 8; return Math.max(MIN_CARD_HEIGHT, Math.min(MAX_CARD_HEIGHT, Math.floor(usable / rows))); }; const syncCardMetrics = () => { const generation = ++syncGeneration; const stacked = window.innerWidth <= STACK_BREAKPOINT; const rows = stacked ? 2 : 1; const section = document.querySelector('section'); const downloadCards = document.querySelector('.download-cards'); if (!section || !downloadCards) return; let cardHeight = computeCardHeight(); applyCardMetrics(cardHeight); // Single correction pass; ignore if a newer sync has started requestAnimationFrame(() => { if (generation !== syncGeneration) return; const overflow = downloadCards.scrollHeight - section.clientHeight; if (overflow > 0) { cardHeight = Math.max( MIN_CARD_HEIGHT, cardHeight - Math.ceil(overflow / rows) - 4 ); applyCardMetrics(cardHeight); } }); }; const scheduleSyncCardMetrics = () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(syncCardMetrics, 50); }; // Detect OS (() => { const os = navigator.userAgent; if (os.search('Windows') !== -1) { markDetected( 'windows-option', 'windows-card', 'windows-detected-message' ); } else if (os.search('Mac') !== -1) { detectAppleArchitecture().then((arch) => { if (arch === 'silicon') { markDetected( 'apple-silicon-option', 'apple-silicon-card', 'apple-silicon-detected-message' ); markDetected( 'apple-arm-option', 'apple-arm-card', 'apple-arm-detected-message' ); } else if (arch === 'intel') { markDetected( 'apple-intel-option', 'apple-intel-card', 'apple-intel-detected-message' ); } else { markDetected( 'apple-silicon-option', 'apple-silicon-card', 'apple-silicon-detected-message' ); markDetected( 'apple-arm-option', 'apple-arm-card', 'apple-arm-detected-message' ); markDetected( 'apple-intel-option', 'apple-intel-card', 'apple-intel-detected-message' ); } scheduleSyncCardMetrics(); }); } else if (os.search('Linux') !== -1 && os.search('X11') !== -1) { markDetected('linux-option', 'linux-card', 'linux-detected-message'); } })(); // QT conditional rendering if (window.qt) { document.body.classList.add('qt-embed'); } syncCardMetrics(); window.addEventListener('resize', scheduleSyncCardMetrics); window.addEventListener('load', scheduleSyncCardMetrics);