Nav umbenannt/umsortiert + Stimmen-Kachel und Zitat-Karten aufgewertet

Nutzer-Wuensche 20.08.2026 (2. Runde):
- Kategorie "DogFather" -> "Filipe", Kategorie "HasiDog" -> "Dogi&Hasi".
- Unterpunkt "Streamer" (streamer.html) aus "Filipe" heraus nach
  "Dogi&Hasi" verschoben, dort GANZ NACH OBEN (ueber "HasiDog") und in
  "DogFather" umbenannt.
- Unterpunkt "HasiDog-Welt" -> "HasiDog".
- Fusszeile zieht mit: Spaltenueberschrift nutzt jetzt dieselbe
  Kategorie-Bezeichnung wie die Nav ("Filipe" / "Dogi&Hasi & Manager"),
  streamer.html steht dort ebenfalls in der Dogi&Hasi-Spalte ganz oben.
  Die internen Schluesselnamen (nav_dogfather...) bleiben bewusst
  unveraendert -- reine Bezeichner, ein Umbenennen waere nur Fehlerquelle.

- "die kachel soll noch spezieller und geiler aussehen": Einreich-Kachel
  auf stimmen.html deutlich aufgewertet -- wandernder Farbverlauf-Rahmen
  (Zwei-Ebenen-/background-position-Technik, KEIN rotierender Ring: siehe
  dokumentierte Projekt-Lektion zu Verzerrungen auf eckigen Flaechen),
  schwebende Herz-Partikel, Medaillon statt nacktem Emoji,
  Farbverlauf-Ueberschrift, aufleuchtende Eingabefelder.
- "und auch die die danach kommen ... sollen viel geiler sein": freigegebene
  Stimmen sind jetzt echte Praesentationskarten -- farbige Akzentlinie oben,
  grosses Anfuehrungszeichen als Wasserzeichen, Avatar-Medaillon mit
  Anfangsbuchstabe, TikTok-Handle als eigener Chip, sanftes Anheben beim
  Ueberfahren.

Alles augenschonend gehalten (gedeckte Toene, langsame Bewegungen,
vollstaendiger Stillstand bei prefers-reduced-motion) und per Playwright
visuell geprueft, keine JS-Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-08-21 01:02:36 +02:00
co-authored by Claude Opus 5
parent 5146cef164
commit 1f87b54351
38 changed files with 441 additions and 282 deletions
+23 -8
View File
@@ -76,15 +76,22 @@
const I18N_CORE = {
nav_start: { de: "Start", "de-CH": "Start", en: "Home", fr: "Accueil", pt: "Início" },
nav_dogfather: { de: "DogFather", "de-CH": "DogFather", en: "DogFather", fr: "DogFather", pt: "DogFather" },
/* Umbenennungen 20.08.2026 (Nutzer-Wunsch): Kategorie "DogFather" -> "Filipe",
Kategorie "HasiDog" -> "Dogi&Hasi". Die Schlüsselnamen (nav_dogfather...)
bleiben bewusst unverändert — sie sind reine interne Bezeichner und werden
an mehreren Stellen (Nav, Fußzeile, Farbzuordnung) referenziert; ein
Umbenennen würde nur Fehlerquellen schaffen, ohne sichtbaren Nutzen. */
nav_dogfather: { de: "Filipe", "de-CH": "Filipe", en: "Filipe", fr: "Filipe", pt: "Filipe" },
nav_dogfather_person: { de: "Die Person", "de-CH": "D Person", en: "The Person", fr: "La personne", pt: "A pessoa" },
nav_dogfather_streamer: { de: "Streamer", "de-CH": "Streamer", en: "Streamer", fr: "Streamer", pt: "Streamer" },
/* Sitzt seit 20.08.2026 unter "Dogi&Hasi" (nicht mehr unter "Filipe") und heißt
dort "DogFather" statt "Streamer" — zeigt weiterhin auf streamer.html. */
nav_dogfather_streamer: { de: "DogFather", "de-CH": "DogFather", en: "DogFather", fr: "DogFather", pt: "DogFather" },
nav_dogfather_casper: { de: "Casper", "de-CH": "Casper", en: "Casper", fr: "Casper", pt: "Casper" },
nav_dogfather_vanvan: { de: "VanVan", "de-CH": "VanVan", en: "VanVan", fr: "VanVan", pt: "VanVan" },
nav_dogfather_zeitreise: { de: "Zeitreise", "de-CH": "Zytreis", en: "Timeline", fr: "Chronologie", pt: "Linha do tempo" },
nav_dogfather_ttmuddi: { de: "TT-Muddi", "de-CH": "TT-Muddi", en: "TT-Muddi", fr: "TT-Muddi", pt: "TT-Muddi" },
nav_hasidog: { de: "HasiDog", "de-CH": "HasiDog", en: "HasiDog", fr: "HasiDog", pt: "HasiDog" },
nav_hasidog_welt: { de: "HasiDog-Welt", "de-CH": "HasiDog-Wält", en: "HasiDog World", fr: "Monde HasiDog", pt: "Mundo HasiDog" },
nav_hasidog: { de: "Dogi&Hasi", "de-CH": "Dogi&Hasi", en: "Dogi&Hasi", fr: "Dogi&Hasi", pt: "Dogi&Hasi" },
nav_hasidog_welt: { de: "HasiDog", "de-CH": "HasiDog", en: "HasiDog", fr: "HasiDog", pt: "HasiDog" },
nav_hasidog_modi: { de: "Modi-Team", "de-CH": "Modi-Team", en: "Modi-Team", fr: "Modi-Team", pt: "Modi-Team" },
nav_hasidog_community: { de: "Community", "de-CH": "Community", en: "Community", fr: "Communauté", pt: "Comunidade" },
nav_hasidog_stimmen: { de: "Stimmen", "de-CH": "Stimme", en: "Voices", fr: "Témoignages", pt: "Depoimentos" },
@@ -125,7 +132,9 @@
fr: "Streamer. Communauté. HasiDog. Manager. Plus forts ensemble.",
pt: "Streamer. Comunidade. HasiDog. Manager. Mais fortes juntos.",
},
footer_h4_hasidog_manager: { de: "HasiDog & Manager", "de-CH": "HasiDog & Manager", en: "HasiDog & Manager", fr: "HasiDog et Manager", pt: "HasiDog e Manager" },
/* Fußzeilen-Überschrift zieht mit der Kategorie-Umbenennung mit (20.08.2026):
"HasiDog & Manager" -> "Dogi&Hasi & Manager". */
footer_h4_hasidog_manager: { de: "Dogi&Hasi & Manager", "de-CH": "Dogi&Hasi & Manager", en: "Dogi&Hasi & Manager", fr: "Dogi&Hasi et Manager", pt: "Dogi&Hasi e Manager" },
footer_h4_mehr: { de: "Mehr", "de-CH": "Meh", en: "More", fr: "Plus", pt: "Mais" },
footer_scouts: { de: "Scouts", "de-CH": "Scouts", en: "Scouts", fr: "Scouts", pt: "Scouts" },
footer_alle_links: { de: "Alle Links", "de-CH": "Alli Links", en: "All links", fr: "Tous les liens", pt: "Todos os links" },
@@ -199,7 +208,6 @@
key: "nav_dogfather",
children: [
{ key: "nav_dogfather_person", href: "dogfather.html" },
{ key: "nav_dogfather_streamer", href: "streamer.html" },
{ key: "nav_dogfather_casper", href: "casper.html" },
{ key: "nav_dogfather_vanvan", href: "vanvan.html" },
{ key: "nav_dogfather_ttmuddi", href: "tt-muddi.html" },
@@ -209,6 +217,10 @@
{
key: "nav_hasidog",
children: [
/* "DogFather" (streamer.html) hierher verschoben — Nutzer-Wunsch
20.08.2026: gehört unter "Dogi&Hasi" und dort GANZ NACH OBEN,
direkt über "HasiDog". */
{ key: "nav_dogfather_streamer", href: "streamer.html" },
{ key: "nav_hasidog_welt", href: "hasidog.html" },
{ key: "nav_hasidog_modi", href: "team-modis.html" },
{ key: "nav_hasidog_community", href: "community.html" },
@@ -592,10 +604,9 @@
<button type="button" id="pwa-install-btn" class="btn btn-outline" style="display:none;margin-top:1rem;">📲 ${t("footer_app_installieren")}</button>
</div>
<div>
<h4>DogFather</h4>
<h4>${t("nav_dogfather")}</h4>
<ul>
<li><a href="dogfather.html">${t("nav_dogfather_person")}</a></li>
<li><a href="streamer.html">${t("nav_dogfather_streamer")}</a></li>
<li><a href="casper.html">${t("nav_dogfather_casper")}</a></li>
<li><a href="vanvan.html">${t("nav_dogfather_vanvan")}</a></li>
<li><a href="tt-muddi.html">${t("nav_dogfather_ttmuddi")}</a></li>
@@ -605,6 +616,10 @@
<div>
<h4>${t("footer_h4_hasidog_manager")}</h4>
<ul>
<!-- "DogFather"/streamer.html steht seit 20.08.2026 auch in der
Fußzeile in dieser Spalte (und ganz oben), damit sie dieselbe
Struktur zeigt wie die Navigation darüber. -->
<li><a href="streamer.html">${t("nav_dogfather_streamer")}</a></li>
<li><a href="hasidog.html">${t("nav_hasidog_welt")}</a></li>
<li><a href="team-modis.html">${t("nav_hasidog_modi")}</a></li>
<li><a href="community.html">${t("nav_hasidog_community")}</a></li>
+15 -2
View File
@@ -51,6 +51,16 @@
return String(text ?? "").replace(/[&<>"']/g, (z) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[z]));
}
/* Erstes sichtbares Zeichen des Namens fürs Avatar-Medaillon. [...name]
statt name[0], damit auch Namen, die mit einem Emoji beginnen, nicht
mitten in einem Zeichen abgeschnitten werden (ein Emoji besteht in
JavaScript aus mehreren "Zeichen" — name[0] lieferte sonst nur ein
kaputtes Halb-Zeichen). */
function erstesZeichen(name) {
const zeichen = [...String(name || "").trim()];
return zeichen.length ? zeichen[0].toUpperCase() : "?";
}
function ladeEchteStimmen() {
fetch(`${API_BASE_URL}/testimonials`, { cache: "no-store" })
.then((res) => res.json())
@@ -64,8 +74,11 @@
(t) => `<div class="stimmen-karte">
<p class="stimmen-karte-text">${escapeHtml(t.nachricht)}</p>
<div class="stimmen-karte-fuss">
<span class="stimmen-karte-name">${escapeHtml(t.name)}</span>
${t.tiktokUsername ? `<span class="stimmen-karte-tiktok">@${escapeHtml(t.tiktokUsername)}</span>` : ""}
<span class="stimmen-karte-avatar" aria-hidden="true">${escapeHtml(erstesZeichen(t.name))}</span>
<span class="stimmen-karte-namen">
<span class="stimmen-karte-name">${escapeHtml(t.name)}</span>
${t.tiktokUsername ? `<span class="stimmen-karte-tiktok">@${escapeHtml(t.tiktokUsername)}</span>` : ""}
</span>
</div>
</div>`
)