Commit Graph

152 Commits

Author SHA1 Message Date
mAi
d6c579527a Merge branch 'mai/cronus/issue-13-light-dark-en': Light/Dark + EN/DE Toggle (#13) 2026-05-08 11:17:49 +02:00
mAi
a06a94ff58 feat: #13 Light/Dark + EN/DE Toggle — Shift-2 Rollout
Rollout des Toggle-Patterns auf alle 57 statischen Sites (dasbes.de + dumusst.com sind dynamic, kein index.html).

1. **Bulk-Wiring (53 Sites)** via tools/patch-theme.py:
   - Anti-FOUC inline IIFE im <head> (vor erstem Paint)
   - <link rel="stylesheet" href="/shared/css/theme.css">
   - <script src="/shared/theme.js"> + toggles.js (i18n.js bleibt, hängt sich ans neue Widget)

2. **Per-Site Light-Overrides (14 Sites)** via tools/patch-light-overrides.py:
   - 6034, allainallain, commanderkin, hallofraumaier, heygoldi, keinefreun, lexsiebels, machesdocheinfach, matthiasbreier, orakil, osterai, patentonkel, traihard, wartebitte
   - Pro Site nur die failing accent-vars darkened (--green-dim, --text-faint, --warm-dim, --gold-dim, etc.)
   - AA 4.5:1+ auf white bg gesichert; Brand-Akzent erhalten

3. **data-theme-lock="dark" (4 Sites)** auf <html>:
   - kilibri, killusion, killionaer, killuminati
   - Aesthetisch dark-only — toggles.js blendet Theme-Button automatisch aus, Lang-Button bleibt

4. **Footer-Toggle Removal (52 Sites)** via tools/remove-footer-toggle.py:
   - Bestehende footer [data-i18n-toggle] Buttons entfernt — top-right widget übernimmt
   - Disclaimer-Information in tooltip des neuen Buttons + ai-disclosure.js footer

QA:
- ./build.sh: 59/59 sites built clean
- contrast-audit.py --both: 0/59 dark fail, 0/59 light fail
- anti-ai-lint: 0/57 sites flagged

Tools committed (idempotent, für Wiederverwendung):
- tools/patch-theme.py (--all wired alle Sites)
- tools/patch-light-overrides.py (per-site OVERRIDES dict)
- tools/remove-footer-toggle.py (4 Patterns für versch. Footer-Strukturen)
2026-05-08 11:16:15 +02:00
mAi
8e23f5eed4 feat(freakifraiday): add freakyfriday.msbls.de alias as bridge until DENIC propagates 2026-05-07 20:19:41 +02:00
mAi
88814630b3 build: regenerate Caddyfile to include freakifraiday.de 2026-05-07 20:16:18 +02:00
mAi
794dd17696 feat(freakifraiday): mailto CTA + Recap section
- Themen-Vorschlag CTA pill linking mailto:freaki@msbls.de (catchall)
- Recap section with placeholder text + commented template for future
  per-session entries (date + 1-liner topic)
- Page stays info-only, no waitlist / form / login
2026-05-07 19:44:28 +02:00
mAi
315161531a feat(freakifraiday): both KI and AI in wordmark + event when-line
m's input: 'KI groß, AI groß - und das ist ne Veranstaltung für uns bei HL,
letzter Freitag im Monat, 17 Uhr, Ende offen.'

frea<KI>fr<AI>day. — both wordplay segments now highlighted in magenta.
Added event-when pill: 'Letzter Freitag im Monat · 17 Uhr · Open End'.
Page stays public-safe (no HL branding on a personally-owned domain);
HL-internal context is implicit, only visible to insiders.
2026-05-07 19:36:55 +02:00
mAi
e48a77bba0 feat: add freakifraiday.de — Friday + AI wordplay landing
🪩 freaki<accent>frAI</accent>day. — pink/magenta neon on dark, Space Grotesk,
spinning disco-ball, radial-gradient party-wash, frai-pattern punchline
'Endlich frAI. Endlich Wochenende.' Mirrors the sorgenfrai/kopffrai/
schulfrai mono-repo pattern; placeholder until m specifies the project
direction.
2026-05-07 19:30:11 +02:00
mAi
a221367c46 feat: #13 Light/Dark + EN/DE Toggle (Shift-1 Design + Pilot)
Architektur:
- shared/theme.js — Logik (data-theme attr auf <html>, localStorage, prefers-color-scheme fallback, data-theme-lock opt-out)
- shared/toggles.js — fixed top-right Pill mit Sun/Moon SVG + DE/EN Button (auto-injected, hängt sich an i18n.js's [data-i18n-toggle] Pattern)
- shared/css/theme.css — neutrale Light-Defaults (cream bg, AA-konforme grays)
- templates/base.html — Anti-FOUC inline IIFE im <head>, theme.css linked vor inline <style>, scripts in body
- tools/contrast-audit.py — neue --light/--dark/--both Modi, parsed [data-theme="light"] + shared fallback

Pilot auf 4 Sites:
- ichbinotto.de (Octopus rot/teal)
- paragraphenraiter.de (Gold)
- kilitaer.de (Olive)
- deinesei.de (Indigo)

Audit-Ergebnis:
- Dark mode: 0/59 Verstöße (regression-frei)
- Light mode: 14/59 Sites brauchen per-site overrides für sub-AA Akzent-Vars (Shift-2 follow-up)

Out of Scope (Shift-2):
- Rollout auf restliche 55 Sites
- Per-Site Light-Palette-Verfeinerung wo neutral-Default nicht trägt
- Per-Site Opt-Out (data-theme-lock) für aesthetisch dark-only Satire-Sites

Design-Doc: docs/plans/theme-toggle.md
2026-05-07 17:05:12 +02:00
mAi
5056d66453 Merge branch 'mai/brunel/issue-12-kontrast-fix': Kontrast-Fix für 33 Dark-BG Sites (#12) 2026-05-07 16:49:43 +02:00
mAi
b6d23f6d99 fix: #12 lift sub-WCAG-AA text colors on 33 dark-bg sites
Replaces FAIL-level (<3:1) and WEAK (<4.5:1) --text-muted/--text-dim/
--text-faint/--text-dimmer/--accent-dim/--gold-dim values across all
33 affected sites. Targets: text-muted >=4.6:1 (WCAG AA),
text-dim/text-faint >=7:1 (WCAG AAA).

Shared palette pattern (15 sites: deinesei, fragina, ichbinaufbali,
ichbinaufbarley, insain, kainstress, kinowhow, knzlmgmt, kopffrai,
legalais, martinsiebels, schulfrai, smartin3, sorgenfrai, vonschraitter):
  --text-muted #44444f -> #7a7a8e (2.06 -> 4.71)
  --text-dim   #6e6e7a -> #9a9aab (3.93 -> 7.14)

Otto/mai-otto pattern (purple-tinted): #404068 -> #7373bb,
#7070a0 -> #9797d8.

Per-site fixes for kainco, kainefrage, kilitaer (olive), killegal,
killionaer, killuminati, killusion, killions, orakil (warm),
paragraphenraiter (gold), keinefreun, julietensity, billableaua,
allaisonme, allainallain, slopschild — each preserves its tint while
crossing the AA threshold.

Audit before: 31 FAIL, 2 WEAK / 33 sites flagged.
Audit after:  0 FAIL, 0 WEAK / 0 sites flagged.

Adds tools/contrast-audit.py (lifted from /tmp) so future edits can
re-run the regression check from the repo.
2026-05-07 16:48:37 +02:00
mAi
4f25d74452 fix: whitelist intentional anti-ai-pattern hits in satire sites
killusion.de mocks the inflation of "revolutionär" claims; the word
appears in scare-quotes as the punchline. kilofant.de parodies AI
marketing-speak; "robust" is part of the joke. Both add an explicit
<!-- anti-ai-allow: ... --> directive so the lint stops flagging them.
2026-04-30 03:35:33 +02:00
mAi
b12352473c Merge branch 'mai/artemis/issue-10-anti-ai-lint': Anti-AI-Lint im Build (#10) 2026-04-30 02:53:39 +02:00
mAi
d3a2bdce97 Merge branch 'mai/hermes/issue-9-geo-schema-slot': GEO Schema-Slot (#9) 2026-04-30 02:53:30 +02:00
mAi
fdac496a6f mAi: #10 - Anti-AI-Text-Lint im Build
tools/anti-ai-lint.py: Python-Linter (stdlib + yq) prueft jede
build/<domain>/index.html gegen die Blacklist in
tools/anti-ai-blacklist.yaml. HTML wird via html.parser auf sichtbaren
Text reduziert (Skripte/Styles werden ignoriert), dann werden Vokabel-
Substrings (DE+EN, case-insensitive) und Regex-Patterns gematcht.
Severity warn = Build geht durch, fail = Build bricht ab.

Whitelist-Mechanismen:
- HTML-Kommentar im Markup: <!-- anti-ai-allow: term1, term2 -->
- Per-Site in site.yaml: anti_ai_allow: [term1, term2]

Integration in build.sh als Schritt 4/4, mit --skip-lint fuer
Notfaelle. Dockerfile installiert python3 zusaetzlich; nur im
Builder-Stage, kein Effekt aufs Caddy-Image.

Tests via tools/test-anti-ai-lint.sh: synthetische AI-Fixture wird
korrekt geflagged, Whitelists unterdruecken Hits, fail-Severity
triggert exit 1, neutraler Text exit 0.

Initial-Lauf auf 59 bestehenden Sites: 2 warn (killusion.de
"revolutionaer" in ironischem Kontext, kilofant.de "robust"),
0 fail. Cleanup ist Folge-Issue.

README + docs/geo-seo-guideline.md aktualisiert mit der konkreten
Tool-Position.
2026-04-30 02:50:50 +02:00
mAi
29965c1164 mAi: #9 - GEO Schema-Slot {{schema_jsonld}} in templates/base.html + render.sh
Schema-Markup-Mechanismus für templated Sites (custom Sites bleiben unberührt).

- templates/base.html: {{schema_jsonld}} Slot im <head>.
- site.yaml: optionaler `schema:` Block. `type:` -> `@type`, `@context`
  wird automatisch ergänzt. Fehlt der Block, bleibt der Slot leer.
- render.sh: liest schema via `yq -o=json`, transformiert mit jq, fügt
  Template-Default für `type` ein (person-* -> Person, product-* -> Product,
  editorial -> Article).
- render.sh: literal-string replace (lreplace) statt awk gsub für multiline-
  Substitution. Behebt nebenbei einen latenten Bug, bei dem `&copy;` im
  template_body als `{{body}}copy;` corrupted wurde (gsub interpretierte
  `&` als matched text).
- tests/schema-test.sh + 4 Fixtures: validiert explicit type, Template-
  Defaults für 3 Templates, leerer Slot ohne schema-Block.
- README.md: Schema.org-Konvention dokumentiert (Block-Format, Defaults,
  Custom-Sites-Hinweis, Schema.org-Validator-Link).

QA: ./build.sh -> 59 sites OK, custom Sites byte-identical zur Source,
3 templated Fixtures rendern valides JSON-LD (Person/Product/Article),
no-schema-Fixture produziert keinen <script>-Tag.

Closes #9 nicht - head reviewed + merged.
2026-04-30 02:50:08 +02:00
mAi
156f156aa7 Merge branch 'mai/curie/issue-8-research': GEO+SEO Guideline (#8) 2026-04-29 14:53:12 +02:00
mAi
d33ce9ea55 mAi: #8 - GEO+SEO Guideline für m's Web-Projekte
Recherche-Output: docs/geo-seo-guideline.md. Enthält:
- GEO-Grundlagen mit harten Zahlen (Princeton-Paper, +40% Sichtbarkeit;
  Top-Third-Regel 44.2% der ChatGPT-Citations)
- Konkrete Hebel: Schema.org/JSON-LD, E-E-A-T, llms.txt-Realitätscheck,
  Anti-AI-Text-Filter, Off-Site/Multi-Source, Crawler-Steuerung
- SEO 2026 Baseline (Helpful Content im Core, INP <200ms, EEAT)
- Stack-Übersetzung: onepager, flexsiebels.de, msbls.de, paliad.de,
  youpc.org mit konkreten Maßnahmen pro Stack
- Checkliste pro neuer Site
- Maintenance-Routinen (monatlich, quartalsweise, jährlich)
- 19 Quellen mit URLs

Implementierung nicht im Scope. Folge-Issues pro Stack später.
2026-04-29 14:30:37 +02:00
mAi
70d429e860 Merge branch 'mai/artemis/issue-6-revive-knuth': i18n-Rollout + AI-Disclosure auf alle Sites (#6) 2026-04-27 20:19:49 +02:00
mAi
e06d4938ce mAi: #6 - Revive knuth: i18n + AI/KI-Disclosure auf alle Sites
Merge mai/knuth/ai-ki-disclosure-footer (3 commits vom 2026-04-01) nach diesem
Branch. Bringt:
- i18n-Annotations (data-de/data-en) + Footer-Toggle auf 54 Custom-Sites
- shared/ai-disclosure.js (3 Tones: playful/serious/minimal, KI/AI nach lang)
- Template-Infrastruktur in render.sh + base.html (title_i18n, sections,
  ai-disclosure-Tag mit disclosure_tone)

Konflikt-Auflösung (Issue #6):
- shared/impressum.js: main behalten (theme-aware + msbls-alias aus #4)
- 10 Sites mit Marken-Setup aus #3 + #5: main's Brand-Konfiguration
  behalten, nur knuth's i18n-Annotations und ai-disclosure/i18n-Scripts
  übernommen.
  - heygoldi, lexsiebels, mai-otto: <script impressum.js data-owner=flexsiebels>
  - martinsiebels: <script impressum.js data-owner=martinsiebels>
  - 9 Satire (kilibri/kilitaer/killegal/killionaer/killions/killuminati/
    killusion/paragraphenraiter/patentonkel): KEIN impressum.js, dafür
    statischer onepager-msbls-link Footer.
- billableaua, smartin3, clemensplassmann: main's neuere Prosa/Struktur
  behalten (durch #1, #5, #7 nachträglich umgeschrieben). Knuth's i18n-
  Annotations dort verworfen, da auf altem Text. Toggle/Scripts kommen
  trotzdem rein (auto-merged), Re-Annotation später möglich.

QA: ./build.sh -> 59 sites OK. Smoke-Tests heygoldi/kilibri/ichbinotto:
korrekte Brand-Setup, ai-disclosure + i18n.js geladen, Footer-Toggle da.
2026-04-27 20:17:24 +02:00
mAi
f5d3637508 Merge branch 'mai/hermes/issue-7-smartin3-de': smartin3.de Mobile-Scroll-Fix (#7) 2026-04-27 20:08:42 +02:00
mAi
095ed0fccf mAi: #7 - Mobile-Gating: Touch-Fix nur unter 768px
CSS touch-action: pan-y und JS-Listener-Scope (wrapper statt hero,
ohne preventDefault) jetzt explizit per @media / matchMedia auf
max-width: 768px begrenzt. Über 768px bleibt das ursprüngliche
Verhalten erhalten — touchmove auf .hero mit preventDefault, falls
Touch-Hardware im Desktop-Layout im Spiel ist.
2026-04-27 20:08:25 +02:00
mAi
66d0203f55 mAi: #7 - smartin3.de Mobile: 3D-Animation-Touch auf Wrapper begrenzen
Touchmove-Listener von .hero auf .text3d-wrapper verschoben, sodass nur
Touches direkt auf der animierten Text-Komponente die Animation triggern.
preventDefault() entfernt + touch-action: pan-y auf den Wrapper —
vertical scroll funktioniert jetzt sowohl außerhalb als auch innerhalb
des Animations-Bereichs ungestört. Desktop-mousemove unverändert.
2026-04-27 20:05:45 +02:00
mAi
81a0837593 Merge branch 'mai/hermes/issue-4-impressum-als': Overlay theme-aware + frame-safe (#4) 2026-04-26 15:13:44 +02:00
mAi
dee1ac6e15 Merge branch 'mai/artemis/issue-5-marken': Marken-Konsequenz heygoldi+9× Satire (#5) 2026-04-26 15:10:38 +02:00
mAi
272cc7b5d1 mAi: #5 - Marken-Konsequenz: heygoldi → flexsiebels/full, 9× Satire → msbls.de-Link
Strukturelle Folge aus Marken-Klärung (msbls = Marke unter flexsiebels-Umbrella,
Rechtsträger ist flexsiebels):

- shared/impressum.js: default owner ist jetzt flexsiebels; owners.msbls als
  Legacy-Alias auf owners.flexsiebels (backward-compat). Header-Doku aktualisiert.
- heygoldi.de: Script-Tag auf data-owner="flexsiebels" data-variant="full".
- 9 Satire-Sites: Impressum-Script raus, statischer "Ein Projekt von msbls.de"-
  Link im Footer (color:inherit, dezent).
  Sites: patentonkel, paragraphenraiter, killuminati, kilitaer, killions,
  killusion, killegal, killionaer, kilibri.

Build: ./build.sh -> 59 sites OK. Andere Overlay-Sites (ichbinotto, lexsiebels,
mai-otto, smartin3, martinsiebels, zensiebels) unverändert.

Closes via done-label: m/onepager#5
2026-04-26 15:10:15 +02:00
mAi
59833b5d6d mAi: #4 - Impressum-Overlay theme-aware + frame-safe
- Trigger: <a>-Link mit identischer CSS-Hülle wie die inline-minimal-
  Variante (text-align:center; font-size:0.75rem; opacity:0.6;
  padding:12px 0; margin-top:4px). Kein Footer-Layout-Shift mehr,
  Höhe und Breite identisch zu vorher.
- Karte: nutzt --bg-card / --text / --accent / --border / --radius /
  --font-primary vom Host (shared/css/variables.css) — Dark-Fallbacks
  neutral. Auf hellen Themes greifen die CSS-Vars, auf Sites ohne
  Variablen bleibt es dezent dunkel.
- max-width: min(420px, calc(100vw - 32px)) + box-sizing:border-box
  + overflow-wrap:break-word — Karte kann Viewport nie sprengen,
  auch nicht bei langen unbreakable strings.
- Body-scroll-lock während Overlay offen ist; vorheriger overflow-
  Wert wird beim Schließen restauriert.
2026-04-26 10:34:33 +02:00
mAi
ef988a7630 Merge branch 'mai/hermes/issue-4-impressum-als': Impressum als Klick-Overlay (#4) 2026-04-26 01:39:38 +02:00
mAi
098a7ad99a mAi: #4 - Impressum als Klick-Overlay statt inline (full variant)
- variant=full: kleiner Footer-Trigger ("Impressum"), Klick öffnet Overlay
  mit § 5 TMG-Block. Schließen via × / ESC / Backdrop-Klick. Fade-in.
- variant=minimal: bleibt unveränderter Inline-Einzeiler.
- API unverändert: data-owner / data-variant am Script-Tag.
- Alles inline (kein neues Stylesheet, keine Abhängigkeiten).
2026-04-26 01:36:21 +02:00
mAi
7d731e8bcf chore(mcp): rename mai → supabase in .mcp.json
Project-scope `mai` server collided with the user-scope maimcp
orchestration binary registered in ~/.claude.json — silently rebinding
mcp__mai__* from list_tasks/update_task/send_message to Supabase SQL
tools. Renaming to `supabase` keeps the namespaces disjoint.

Refs: m/mAi#154
2026-04-26 00:37:35 +02:00
mAi
e4797aa532 Merge branch 'mai/hermes/issue-3-impressum': Impressum consolidation (#3)
- shared/impressum.js als Single-Source-of-Truth
- 3 Owner (msbls/flexsiebels/martinsiebels) × 2 Varianten (minimal/full)
- Name-Bug 'Matthias Flexsiebels' → 'Matthias Siebels' korrigiert
- 14 Sites final konfiguriert

Commits: a4e3773 + a5777ff + f85f4b4
2026-04-23 00:33:40 +02:00
mAi
f85f4b4e7f mAi: #3 - heygoldi/martinsiebels/zensiebels Impressum
- heygoldi.de: hardcoded "ein Projekt von msbls.de" Zeile entfernt, shared (msbls minimal) eingebunden
- martinsiebels.de: shared (martinsiebels full) — volles § 5 TMG
- zensiebels.de: shared (flexsiebels minimal)
- matthiasbreier.de: bewusst kein Impressum (m-Entscheidung)

Satire-Sites (kainco/kili*/kino* etc.) bleiben weiter ohne Impressum-Link.

Refs: #3
2026-04-23 00:26:18 +02:00
mAi
a5777ff65d mAi: #3 - mai-otto/lexsiebels Impressum + clemensplassmann Redirect
- mai-otto.de: shared Impressum (flexsiebels full)
- lexsiebels.de: shared Impressum (flexsiebels full)
- clemensplassmann.de: offline genommen, leitet per meta refresh + JS zur
  Hogan-Lovells-Profilseite weiter (https://www.hoganlovells.com/en/clemens-plassmann).
  Fallback-Link sichtbar, falls Redirect blockiert.

Refs: #3
2026-04-23 00:03:21 +02:00
mAi
a4e37735f8 mAi: #3 - Impressum-Konsistenz: shared als Single-Source-of-Truth
- shared/impressum.js: Name korrigiert (msbls/flexsiebels = Matthias Siebels, nicht Martin),
  echte Adresse aus youpc.org übernommen (c/o Online-Impressum.de #5892, Sankt Augustin).
  Neuer Owner 'flexsiebels', neuer Owner 'martinsiebels' (für Martin als separate Person
  mit eigener Adresse in Osnabrück). data-variant als offizielles Attribut, data-style
  weiterhin als Legacy-Alias. Rendert in #impressum falls vorhanden, sonst footer.

- paragraphenraiter.de: hardcoded "Ein Projekt von Matthias Flexsiebels" → shared (msbls minimal)
- patentonkel.de: hardcoded "Matthias Flexsiebels" + kaputter window.__impressum() → shared (msbls minimal)
- smartin3.de: inline Impressum-Text → shared (martinsiebels full) in #impressum Div
- ichbinotto.de: shared (flexsiebels full) mit echter § 5 TMG-Angabe

Caddyfile: Regenerierung hat fehlende Einträge für 6034.de, traihard.de, zensiebels.de ergänzt.

Refs: #3
2026-04-22 23:39:41 +02:00
m
dadfa0df7c feat: smartin3.de — mouse interaction covers full hero section width and depth 2026-04-18 21:20:56 +02:00
m
1caf12d801 fix: smartin3.de — remove noise overlay from body 2026-04-18 21:19:45 +02:00
m
f6c9eddfe4 fix: smartin3.de — tighten hero gradient, smaller radius to avoid page-wide glow 2026-04-18 21:19:31 +02:00
m
4315f4c2c0 fix: smartin3.de — larger mouse interaction area, gradient not clipped by container 2026-04-18 21:18:29 +02:00
m
8f615fd3d1 feat: smartin3.de — interactive 3D text, follows mouse/touch 2026-04-18 21:14:38 +02:00
m
6f2f150cb6 fix: smartin3.de — sweep -45° to 45° 2026-04-18 21:13:29 +02:00
m
3d457d6b42 feat: smartin3.de gallery — add Sonnenblendenhalter photo 2026-04-18 21:13:08 +02:00
m
d8e145a49d feat: smartin3.de — slow sweep 45° to 165°, no full rotation 2026-04-18 21:12:36 +02:00
m
8fc605c851 fix: smartin3.de — replace all fake umlauts with real ä ö ü ß 2026-04-18 21:12:11 +02:00
m
66166d979c feat: smartin3.de — 3D text gradient from orange to blue 2026-04-18 21:10:26 +02:00
m
b12b8e9068 feat: smartin3.de — 30 depth layers at 1px spacing for solid 3D extrusion 2026-04-18 21:08:50 +02:00
m
5a2416f3a6 feat: smartin3.de — solid text-shadow extrusion, no gaps between layers 2026-04-18 21:07:20 +02:00
m
5454f0fc27 feat: smartin3.de — lightbox on gallery click with caption 2026-04-18 21:06:39 +02:00
m
ab4003fb15 feat: smartin3.de — solid 3D block letters, remove duplicate h1 2026-04-18 21:05:32 +02:00
m
7d56e6a2fd feat: smartin3.de — full 360 rotation from diagonal angle, more depth 2026-04-18 21:03:42 +02:00
m
866d30476d fix: smartin3.de — missing closing brace on @keyframes rotateText 2026-04-18 21:02:39 +02:00
m
5240244a14 fix: smartin3.de — rename Schaltschrank Abdeckungshalter title 2026-04-18 21:01:53 +02:00