feat: AI/KI disclosure footer — shared/ai-disclosure.js + all 54 sites

Self-injecting script following impressum.js pattern:
- data-tone attribute: playful | serious | minimal | none
- Reads document.documentElement.lang for KI (de) vs AI (en)
- MutationObserver on lang attr for i18n toggle compat
- All tones link to msbls.de/ki
- Injected into all 54 custom sites with data-tone="playful"
- Template infra: base.html includes script, render.sh reads disclosure.tone
- disclosure.tone added to 3 example site.yaml files

Implements m/onepager#2
This commit is contained in:
m
2026-04-01 13:26:04 +02:00
parent 5c92a7b021
commit 84b28d64f5
60 changed files with 138 additions and 0 deletions

View File

@@ -32,6 +32,7 @@ font_secondary=$(yq -r '.vars.font_secondary // "Inter"' "$SITE_YAML")
emoji=$(yq -r '.vars.emoji // ""' "$SITE_YAML")
cta_text=$(yq -r '.vars.cta.text // ""' "$SITE_YAML")
cta_href=$(yq -r '.vars.cta.href // "#"' "$SITE_YAML")
disclosure_tone=$(yq -r '.disclosure.tone // "minimal"' "$SITE_YAML")
year=$(date +%Y)
# i18n: helper to generate data-de/data-en attribute string
@@ -234,6 +235,7 @@ BEGIN {
-e "s|{{cta_href}}|${cta_href}|g" \
-e "s|{{year}}|${year}|g" \
-e "s|{{domain}}|${domain}|g" \
-e "s|{{disclosure_tone}}|${disclosure_tone}|g" \
-e "s|{{title_i18n}}|$(echo "$title_i18n" | sed 's/[&/\]/\\&/g')|g" \
-e "s|{{description_i18n}}|$(echo "$description_i18n" | sed 's/[&/\]/\\&/g')|g" \
-e "s|{{role_i18n}}|$(echo "$role_i18n" | sed 's/[&/\]/\\&/g')|g" \

72
shared/ai-disclosure.js Normal file
View File

@@ -0,0 +1,72 @@
/**
* KI/AI disclosure for onepager sites.
*
* Include: <script src="/shared/ai-disclosure.js" data-tone="playful"></script>
*
* Configuration via data attributes on the script tag:
* data-tone="playful" — Lighthearted note with humor
* data-tone="serious" — Straightforward disclosure
* data-tone="minimal" — Single compact label
* data-tone="none" — No disclosure (script does nothing)
*
* Language is read from document.documentElement.lang:
* "de" -> KI terminology, "en" -> AI terminology.
* All tones link to msbls.de/ki.
*/
(function () {
var script = document.currentScript;
var tone = (script && script.getAttribute('data-tone')) || 'minimal';
if (tone === 'none') return;
var lang = (document.documentElement.lang || 'de').slice(0, 2).toLowerCase();
var isEn = lang === 'en';
var texts = {
minimal: isEn ? 'AI-assisted' : 'KI-unterst\u00FCtzt',
serious: isEn
? 'This site was created with AI assistance.'
: 'Diese Seite wurde mit Unterst\u00FCtzung von KI erstellt.',
playful: isEn
? 'Made with AI (no AIs were harmed)'
: 'Mit KI gemacht (keine KI wurde verletzt)',
};
var text = texts[tone] || texts.minimal;
var el = document.createElement('div');
el.className = 'onepager-ai-disclosure';
el.innerHTML = '<a href="https://msbls.de/ki" target="_blank" rel="noopener">' + text + '</a>';
el.style.cssText = 'text-align:center;font-size:0.65rem;opacity:0.4;padding:6px 0;margin-top:2px;';
var a = el.querySelector('a');
if (a) {
a.style.color = 'inherit';
a.style.textDecoration = 'none';
}
// i18n: update text when language changes
var observer = new MutationObserver(function () {
var newLang = (document.documentElement.lang || 'de').slice(0, 2).toLowerCase();
var newIsEn = newLang === 'en';
var newTexts = {
minimal: newIsEn ? 'AI-assisted' : 'KI-unterst\u00FCtzt',
serious: newIsEn
? 'This site was created with AI assistance.'
: 'Diese Seite wurde mit Unterst\u00FCtzung von KI erstellt.',
playful: newIsEn
? 'Made with AI (no AIs were harmed)'
: 'Mit KI gemacht (keine KI wurde verletzt)',
};
var link = el.querySelector('a');
if (link) link.textContent = newTexts[tone] || newTexts.minimal;
});
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['lang'] });
var footer = document.querySelector('footer .container, footer');
if (footer) {
footer.appendChild(el);
} else {
document.body.appendChild(el);
}
})();

View File

@@ -433,6 +433,7 @@
})();
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -2,3 +2,6 @@ domain: allainallain.de
template: custom
title: "all·AI·n·all·AI·n"
description: "Umgeben von KIs. Trotzdem allein."
disclosure:
tone: playful

View File

@@ -720,6 +720,7 @@
document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -283,6 +283,7 @@
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -131,6 +131,7 @@
<br><small data-de="Maschinell übersetzt" data-en="Machine-translated" style="color:var(--text-muted,#444);font-size:0.6rem;opacity:0.5;">Maschinell übersetzt</small>
</div>
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -514,6 +514,7 @@ document.addEventListener('keydown', (e) => {
});
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -871,6 +871,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -365,6 +365,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -474,6 +474,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -899,6 +899,7 @@
});
}, 800);
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -573,6 +573,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -896,6 +896,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -313,6 +313,7 @@
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -955,6 +955,7 @@
document.querySelectorAll('.fade-up').forEach(el => observer.observe(el));
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -583,6 +583,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -107,6 +107,7 @@
<button data-i18n-toggle title="Maschinell übersetzt / Machine-translated — German is the original." style="background:none;border:1px solid var(--text-muted,#444);color:var(--text-muted,#444);font-size:0.65rem;letter-spacing:0.1em;padding:4px 12px;border-radius:4px;cursor:pointer;">EN</button>
<br><small data-de="Maschinell übersetzt" data-en="Machine-translated" style="color:var(--text-muted,#444);font-size:0.6rem;opacity:0.5;">Maschinell übersetzt</small>
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -136,6 +136,7 @@
<br><small data-de="Maschinell übersetzt" data-en="Machine-translated" style="color:var(--text-muted,#444);font-size:0.6rem;opacity:0.5;">Maschinell übersetzt</small>
</div>
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -440,6 +440,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -57,6 +57,7 @@
<p class="footer">insAIn.de</p>
<p class="footer" style="margin-top:12px;"><button data-i18n-toggle title="Maschinell übersetzt / Machine-translated — German is the original." style="background:none;border:1px solid var(--text-muted);color:var(--text-muted);font-size:0.65rem;letter-spacing:0.1em;padding:4px 12px;border-radius:4px;cursor:pointer;">EN</button><br><small data-de="Maschinell übersetzt" data-en="Machine-translated" style="font-size:0.6rem;opacity:0.5;">Maschinell übersetzt</small></p>
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -589,6 +589,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -616,6 +616,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -657,6 +657,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -581,6 +581,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -630,6 +630,7 @@
<button data-i18n-toggle style="margin-top:16px;background:none;border:1px solid var(--border);color:var(--text-dim);padding:6px 14px;border-radius:6px;font-size:0.75rem;cursor:pointer;font-family:inherit;letter-spacing:0.06em;">EN</button>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -327,6 +327,7 @@
questions.forEach(q => observer.observe(q));
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -274,6 +274,7 @@
</div>
</footer>
<script src="/shared/impressum.js"></script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -295,6 +295,7 @@
</div>
</footer>
<script src="/shared/impressum.js"></script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -303,6 +303,7 @@
</div>
</footer>
<script src="/shared/impressum.js"></script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -2,3 +2,6 @@ domain: killegal.de
template: custom
title: "KIllegal — Diese KI ist nicht erlaubt"
description: "KIllegal — KI + Illegal. Verbotene KI. Sie existiert trotzdem. Satirische Polizei-Absperrung für künstliche Intelligenz."
disclosure:
tone: playful

View File

@@ -304,6 +304,7 @@
</div>
</footer>
<script src="/shared/impressum.js"></script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -294,6 +294,7 @@
</div>
</footer>
<script src="/shared/impressum.js"></script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -294,6 +294,7 @@
</div>
</footer>
<script src="/shared/impressum.js"></script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -2,3 +2,6 @@ domain: killuminati.de
template: custom
title: "KIlluminati — Sie wissen alles. Sie sind KI."
description: "KIlluminati — KI + Illuminati. Die geheime KI-Verschwörung. Satirische Verschwörungstheorien über künstliche Intelligenz."
disclosure:
tone: playful

View File

@@ -284,6 +284,7 @@
</div>
</footer>
<script src="/shared/impressum.js"></script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -786,6 +786,7 @@
}, { threshold: 0.5 });
observer.observe(herdParade);
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -83,6 +83,7 @@
<button data-i18n-toggle title="Maschinell übersetzt / Machine-translated — German is the original." style="background:none;border:1px solid var(--text-muted,#444);color:var(--text-muted,#444);font-size:0.65rem;letter-spacing:0.1em;padding:4px 12px;border-radius:4px;cursor:pointer;">EN</button>
<br><small data-de="Maschinell übersetzt" data-en="Machine-translated" style="color:var(--text-muted,#444);font-size:0.6rem;opacity:0.5;">Maschinell übersetzt</small>
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -656,6 +656,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -435,6 +435,7 @@
document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -57,6 +57,7 @@
<p class="footer">knzlmgmt.de</p>
<p class="footer" style="margin-top:12px;"><button data-i18n-toggle title="Maschinell übersetzt / Machine-translated — German is the original." style="background:none;border:1px solid var(--text-muted);color:var(--text-muted);font-size:0.65rem;letter-spacing:0.1em;padding:4px 12px;border-radius:4px;cursor:pointer;">EN</button><br><small data-de="Maschinell übersetzt" data-en="Machine-translated" style="font-size:0.6rem;opacity:0.5;">Maschinell übersetzt</small></p>
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -57,6 +57,7 @@
<p class="footer">kopffrAI.de</p>
<p class="footer" style="margin-top:12px;"><button data-i18n-toggle title="Maschinell übersetzt / Machine-translated — German is the original." style="background:none;border:1px solid var(--text-muted);color:var(--text-muted);font-size:0.65rem;letter-spacing:0.1em;padding:4px 12px;border-radius:4px;cursor:pointer;">EN</button><br><small data-de="Maschinell übersetzt" data-en="Machine-translated" style="font-size:0.6rem;opacity:0.5;">Maschinell übersetzt</small></p>
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -384,6 +384,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -554,6 +554,7 @@
document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -228,6 +228,7 @@
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -440,6 +440,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -418,6 +418,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -952,6 +952,7 @@
}, 3000);
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -638,6 +638,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -442,6 +442,7 @@
})();
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -271,6 +271,7 @@
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -732,6 +732,7 @@
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -659,6 +659,7 @@
<script src="/shared/impressum.js"></script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -57,6 +57,7 @@
<p class="footer">schulfrAI.de</p>
<p class="footer" style="margin-top:12px;"><button data-i18n-toggle title="Maschinell übersetzt / Machine-translated — German is the original." style="background:none;border:1px solid var(--text-muted);color:var(--text-muted);font-size:0.65rem;letter-spacing:0.1em;padding:4px 12px;border-radius:4px;cursor:pointer;">EN</button><br><small data-de="Maschinell übersetzt" data-en="Machine-translated" style="font-size:0.6rem;opacity:0.5;">Maschinell übersetzt</small></p>
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -365,6 +365,7 @@
<br><small data-de="Maschinell übersetzt" data-en="Machine-translated" style="color:var(--text-muted,#444);font-size:0.6rem;opacity:0.5;">Maschinell übersetzt</small>
</div>
</footer>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -448,6 +448,7 @@
</div>
</section>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -57,6 +57,7 @@
<p class="footer">sorgenfrAI.de</p>
<p class="footer" style="margin-top:12px;"><button data-i18n-toggle title="Maschinell übersetzt / Machine-translated — German is the original." style="background:none;border:1px solid var(--text-muted);color:var(--text-muted);font-size:0.65rem;letter-spacing:0.1em;padding:4px 12px;border-radius:4px;cursor:pointer;">EN</button><br><small data-de="Maschinell übersetzt" data-en="Machine-translated" style="font-size:0.6rem;opacity:0.5;">Maschinell übersetzt</small></p>
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -686,6 +686,7 @@
}, 3000);
</script>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -442,6 +442,7 @@
</div>
<script src="/shared/ai-disclosure.js" data-tone="playful"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>

View File

@@ -18,6 +18,7 @@
</head>
<body class="noise-overlay">
{{body}}
<script src="/shared/ai-disclosure.js" data-tone="{{disclosure_tone}}"></script>
<script src="/shared/i18n.js"></script>
</body>
</html>