/*! trentpower.fr · /app-enhance.js · generated · loaded after first paint · signed via /integrity.json */
(function () {
'use strict';
var I18N = window.I18N || null;
var siteContent = document.getElementById('main');
var supportsInert = 'inert' in document.documentElement;
function setInert(el, state) {
if (!el) return;
if (state) {
if (supportsInert) el.setAttribute('inert', '');
el.setAttribute('aria-hidden', 'true');
} else {
if (supportsInert) el.removeAttribute('inert');
el.removeAttribute('aria-hidden');
}
}
function focusableIn(el) {
return el.querySelectorAll('a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"]), input:not([disabled]), select:not([disabled]), textarea:not([disabled])');
}
var activeOverlay = null;
var activeTrigger = null;
var pushedHistoryState = false;
function openOverlay(overlay, trigger, opts) {
if (!overlay) return;
activeOverlay = overlay;
activeTrigger = trigger || null;
overlay.setAttribute('aria-hidden', 'false');
overlay.classList.add('active');
document.body.style.overflow = 'hidden';
setInert(siteContent, true);
if (trigger) trigger.setAttribute('aria-expanded', 'true');
var focusable = focusableIn(overlay);
if (focusable.length > 0) focusable[0].focus();
pushedHistoryState = false;
if (opts && opts.hash && !opts.fromPopstate &&
typeof history !== 'undefined' && typeof history.pushState === 'function') {
try {
history.pushState({ tp_overlay: opts.hash.replace(/^#/, '') }, '', opts.hash);
pushedHistoryState = true;
} catch (_) { }
}
}
function closeOverlay(opts) {
if (!activeOverlay) return;
var overlay = activeOverlay;
var trigger = activeTrigger;
overlay.classList.remove('active');
overlay.setAttribute('aria-hidden', 'true');
document.body.style.overflow = '';
setInert(siteContent, false);
if (trigger) {
trigger.setAttribute('aria-expanded', 'false');
trigger.focus();
}
activeOverlay = null;
activeTrigger = null;
if (pushedHistoryState && !(opts && opts.fromPopstate) &&
typeof history !== 'undefined' && typeof history.back === 'function') {
try { history.back(); } catch (_) { }
}
pushedHistoryState = false;
}
window.addEventListener('popstate', function () {
if (activeOverlay) {
var st = history.state;
var stillOpen = st && st.tp_overlay;
if (!stillOpen) closeOverlay({ fromPopstate: true });
}
});
document.addEventListener('keydown', function (e) {
if (!activeOverlay) return;
if (e.key === 'Escape') { closeOverlay(); return; }
if (e.key === 'Tab') {
var focusable = focusableIn(activeOverlay);
if (focusable.length === 0) return;
var first = focusable[0];
var last = focusable[focusable.length - 1];
if (e.shiftKey) {
if (document.activeElement === first) { e.preventDefault(); last.focus(); }
} else {
if (document.activeElement === last) { e.preventDefault(); first.focus(); }
}
}
});
window.TP_OVERLAY = { open: openOverlay, close: closeOverlay };
var modal = document.getElementById('modal');
var btn = document.getElementById('access-btn');
var closeBtn = document.getElementById('modal-close');
if (modal && btn && closeBtn) {
btn.addEventListener('click', function () { openOverlay(modal, btn); });
closeBtn.addEventListener('click', closeOverlay);
modal.addEventListener('click', function (e) {
if (e.target === modal) closeOverlay();
});
}
var savedDocTitle = null;
function onBeforePrint() {
var lang = document.documentElement.lang || 'en';
var t = (I18N && I18N[lang]) || (I18N && I18N.en) || null;
var page = (document.body && document.body.getAttribute('data-page')) || 'home';
var printTitle =
(page === 'privacy' && t && t.privacy && t.privacy.print && t.privacy.print.doc_title) ||
(page === 'integrity' && t && t.integrity && t.integrity.print && t.integrity.print.doc_title) ||
(page === 'security' && t && t.security && t.security.print && t.security.print.doc_title) ||
(page === 'source' && t && t.source && t.source.print && t.source.print.doc_title) ||
(page === 'releases' && t && t.releases && t.releases.print && t.releases.print.doc_title) ||
(page === 'forbidden' && t && t.error && t.error['403'] && t.error['403'].print && t.error['403'].print.doc_title) ||
(page === 'not-found' && t && t.error && t.error['404'] && t.error['404'].print && t.error['404'].print.doc_title) ||
(page === 'server-error' && t && t.error && t.error['500'] && t.error['500'].print && t.error['500'].print.doc_title) ||
(page === 'verify' && t && t.verify && t.verify.doc_title) ||
(t && t.print && t.print.doc_title);
if (printTitle) {
savedDocTitle = document.title;
document.title = printTitle;
}
var revealSelector = '.principle, .trajectory-item, .project-card, '
+ '.hero-name, .hero-statement, .hero-body, .trust-mark';
document.querySelectorAll(revealSelector).forEach(function (el) {
el.classList.add('visible');
});
document.documentElement.classList.add('is-printing');
}
function onAfterPrint() {
if (savedDocTitle !== null) {
document.title = savedDocTitle;
savedDocTitle = null;
}
document.documentElement.classList.remove('is-printing');
}
if (window.matchMedia) {
try {
window.matchMedia('print').addEventListener('change', function (e) {
if (e.matches) onBeforePrint(); else onAfterPrint();
});
} catch (_) { }
}
window.addEventListener('beforeprint', onBeforePrint);
window.addEventListener('afterprint', onAfterPrint);
(function _loadFullFonts() {
if (document.querySelector('link[data-tp-fonts-full]')) return;
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/fonts-full.css';
link.setAttribute('data-tp-fonts-full', '');
function paintFlip() {
if (typeof requestAnimationFrame === 'function') {
requestAnimationFrame(function () {
document.documentElement.classList.add('fonts-loaded');
});
} else {
document.documentElement.classList.add('fonts-loaded');
}
}
link.addEventListener('load', function () {
if (document.fonts && document.fonts.ready && typeof document.fonts.ready.then === 'function') {
document.fonts.ready.then(paintFlip);
} else {
setTimeout(paintFlip, 1500);
}
});
document.head.appendChild(link);
})();
(function () {
var line = document.getElementById('footerImprint');
if (!line) return;
function set(key, text, cls) {
var n = line.querySelector('[data-proof="' + key + '"]');
if (!n) return;
n.textContent = text;
n.setAttribute('data-proof-set', 'true');
if (cls) n.classList.add(cls);
}
function isPlaceholder(text) {
if (!text) return true;
var s = text.replace(/\s+/g, '');
if (s === '' || s === '—' || s === '-') return true;
var lower = s.toLowerCase();
return lower === 'sha256:—' || lower === 'sha256:-' || lower === 'sha256:';
}
function pruneUnsetSegments() {
var values = line.querySelectorAll('[data-proof]');
var visible = 0;
for (var i = 0; i < values.length; i++) {
var v = values[i];
var dd = v.closest('dd');
if (!dd) continue;
var dt = dd.previousElementSibling;
while (dt && dt.tagName !== 'DT') dt = dt.previousElementSibling;
var hide = !v.getAttribute('data-proof-set') || isPlaceholder(v.textContent);
if (hide) {
dd.hidden = true;
if (dt) dt.hidden = true;
} else {
visible++;
}
}
if (visible === 0) line.hidden = true;
}
function currentPagePath() {
var p = window.location.pathname;
if (!p || p === '/') return 'index.html';
p = p.replace(/^\/+/, '');
if (p.endsWith('/')) p += 'index.html';
return p;
}
function shortSha(value) {
var clean = String(value).replace(/^sha256-/, '').replace(/=+$/, '');
if (clean.length < 12) return 'sha256:' + clean;
return 'sha256:' + clean.slice(0, 5) + '…' + clean.slice(-4);
}
function relativeStrings() {
var lang = (document.documentElement.lang || 'en');
var bag = (window.I18N && window.I18N[lang] && window.I18N[lang].footer
&& window.I18N[lang].footer.proof && window.I18N[lang].footer.proof.relative) || {};
return {
today: bag.today || 'today',
yesterday: bag.yesterday || 'yesterday',
days: bag.days || '{n} days ago',
months: bag.months || '{n} months ago',
years: bag.years || '{n} years ago'
};
}
function daysAgo(iso) {
var t = Date.parse(iso);
if (isNaN(t)) return { text: '', fresh: false };
var d = Math.floor((Date.now() - t) / 86400000);
var r = relativeStrings();
if (d <= 0) return { text: r.today, fresh: true };
if (d === 1) return { text: r.yesterday, fresh: true };
if (d < 30) return { text: r.days.replace('{n}', d), fresh: false };
if (d < 365) return { text: r.months.replace('{n}', Math.round(d/30)), fresh: false };
return { text: r.years.replace('{n}', Math.round(d/365)), fresh: false };
}
fetch('/integrity.json', { cache: 'no-store' })
.then(function (r) { return r.ok ? r.text() : null; })
.then(function (text) {
if (!text) return null;
var json;
try { json = JSON.parse(text); } catch (_) { return null; }
var editionStamp = json.edition || json.generated;
if (editionStamp) set('edition', editionStamp);
var verifyStamp = json.generated || json.edition;
if (verifyStamp) {
var ago = daysAgo(verifyStamp);
if (ago.text) set('verified', ago.text, ago.fresh ? 'v--fresh' : null);
}
if (json.files) {
var entry = json.files[currentPagePath()];
if (entry) set('sha', shortSha(entry));
}
})
.catch(function () { })
.finally(function () {
line.classList.remove('is-loading');
pruneUnsetSegments();
});
})();
var canLog = window.console && typeof console.info === "function";
if (canLog) {
console.info("trentpower.fr · static, signed, inspectable · ctrl+u still works");
}
})();
