{% block titel %}{{ t.titel }}{% endblock %}
{# Skripte mit defer (07.11.2026, Ladezeit am Handy): Merker bis DOMContentLoaded. Die früher synchronen Skripte (navigation.js,
tagliste.js …) warten damit weiter auf DOMContentLoaded statt in der defer-Phase (readyState „interactive“) sofort zu starten. #}
{# Tonart-Schreibweise (07.11.2026): zentraler Helfer TimbreTonart vor allen anderen Skripten (liest ) #}
{% if not (nutzer and gesperrt) %}{% endif %}
{# Kopf-Skript (24.10.2026, static/tageszeit.js inline, VOR dem CSS): löst „Nach Tageszeit“ auf, übernimmt beim Besuch die
gemerkte Wahl (localStorage „timbre.erscheinungsbild“) und setzt theme-color – vor dem ersten Zeichnen, kein Flackern #}
{# Desktop-App v2: im App-Fenster nicht – der Besuch-Block würde Player, Stützwerte und aktive Tag List verwerfen, sobald
die Fenster-Sitzung kurz fehlt (Übergabe läuft). Kontowechsel erkennt dort static/desktop.js (Hash der sub). #}
{% if ist_besucher and not desktop_app %}{% endif %}
{# Live-Demo (23.10.2026): demo.js vor allen anderen Skripten – leitet die Lesewege auf /api/v1/demo/ um und hält die Tag List im Browser.
Alle externen Skripte tragen defer (07.11.2026): Der Browser führt sie nach dem Parsen in genau dieser Reihenfolge aus –
demo.js bleibt das erste. Was sofort laufen muss, steht inline oben (Klasse js, Merker, Kopf-Skript, Besuch-Block). #}
{% if demo %}
{% endif %}
{# Schrift (30.10.2026, JS je Seite): Inter trägt jeden Text im ersten Bild – früh holen, damit der Tausch (font-display: swap in
timbre.css) vor dem ersten Zeichnen fertig ist statt danach (kein Nachrücken). Die Dateien sind schon Teilmengen (Inter 48 KB). #}
{# App-Hülle ohne native_leiste_playlists (Kopf vor Menü C): das Flyout „Explorer · Library ▾“ steht in einer eigenen Datei – nicht im CSS jeder Seite #}
{% if not menue_c and nutzer and not gesperrt %}{% endif %}
{# Seitenleiste der Desktop-App (Variante C, 10.11.2026): eigene Datei, nur im App-Fenster – das CSS-Budget der Seiten bleibt #}
{% if menue_c and desktop_app and nutzer and not gesperrt %}{% endif %}
{# Vollbild vom Home-Bildschirm (29.10.2026): ältere iOS-Fassungen brauchen das Apple-Meta, Statusleiste „default“ (dunkle Schrift auf hell bzw. umgekehrt, die
Seite beginnt darunter – mit „black-translucent“ stünde weiße Schrift auf hellen Designs); static/vollbild.js öffnet fremde Verweise dort im Browser. #}
{% if not (nutzer and gesperrt) %}{% endif %}
{# Desktop-App v2 (28.10.2026): Brücke window.timbreDesktop (Feature-Erkennung, Downloads, Anmeldung im App-Fenster) – auf jeder Seite, klein #}
{% if not (nutzer and gesperrt) %}{% endif %}
{# Desktop v2 (Paket 2, Bitte 3): Desktop-Extras (Kopf verbunden/offline, Library, Export, Einstellungen) – nur im App-Fenster #}
{% if desktop_app and nutzer and not gesperrt %}
{% endif %}
{# Formulare im App-Fenster (30.10.2026, an-client-20261030-*-paket-formulare.md): Abmelden über die Brücke, Kniffe-Banner über die
API – der Kern der App reicht keine Formulare an Cookie-Routen durch. Nur im App-Fenster; im Browser bleiben die Formulare. #}
{% if desktop_app and nutzer and not gesperrt %}
{% endif %}
{# navigation.js auch auf der Besuchsseite (seit dem Sprachmenü, 16.10.2026): Esc und Klick daneben schließen die Aufklapper im
Kopf, angemeldet dazu Reiterleiste, „Mehr“ und Taste „/“. Die Warteseite (angemeldet, ohne Freigabe) bleibt bewusst ohne
Skript – ihre Aufklapper sind und gehen auch so. #}
{% if not (nutzer and gesperrt) %}{% endif %}
{# Handy schlank (06.11.2026, Phase 1): TimbreHandy – „?“ an langen Erklärungen und Tipp auf einen Wert (nur am Handy bzw. in der
iOS-App, data-app="ios"); früh (vor den Seitenskripten, defer hält die Reihenfolge), weil Library, Titelblatt und Set bauen es beim Zeichnen rufen. Speichert nichts. #}
{% if (nutzer and not gesperrt) or demo %}
{% endif %}
{# Wiederaufnahme nach Netzabbruch/Ruhezustand für lange Schreibwege (Upload, Tags schreiben, Rekordbox senden), 28.10.2026 #}
{# Ruhige Hinweise der Desktop-App (29.10.2026): 422 lokaler_pfad/lokal_nicht_moeglich, 503 bibliothek_fehlt – Texte für alle Seiten #}
{% if nutzer and not gesperrt %}
{% endif %}
{# DJ-Schalter (24.10.2026): Bauhilfe TimbreSchalter für alle Skripte, die Schalter selbst bauen (vu.js, titelblatt.js,
bibliothek.js, setbau.js) – deshalb früh (vor den Seitenskripten; defer hält die Reihenfolge). Konto und Analysen laden die Datei zusätzlich mit data-seite
(Sofort-Speichern der Benachrichtigungen auch nach weichem Wechsel). #}
{% if not (nutzer and gesperrt) %}{% endif %}
{# Lade-Wörter (28.10.2026): Baustein TimbreLadeWoerter für Library, Explorer, Set bauen, Export, Abgleich, Upload und Player-Puffer –
früh, vor den Seitenskripten (bibliothek.js, explorer_seite.js, setbau.js … rufen ihn beim Start; defer hält die Reihenfolge). Texte aus texte_lade.py, einmal je Seite. #}
{% if not (nutzer and gesperrt) %}
{% endif %}
{# Ampel (25.10.2026): eine Form für passt ● / geht ▲ / Sprung ◆ (TimbreAmpel) – früh, für setbau.js und tagliste.js #}
{% if not (nutzer and gesperrt) %}{% endif %}
{# Sprachfassungen für Suchmaschinen (app.SPRACHFASSUNGEN): kanonisch mit Sprache, je Sprache hreflang, x-default ohne #}
{% if sprachfassungen %}
{% for k, _ in sprachen %}{% endfor %}
{% endif %}{% block kopf %}{% endblock %}
{# Texte der Statuszeile; die zum Onlinespeicher nur mit verbundenem Speicher (ist die Funktion aus, nennt die Seite ihn nirgends) #}
{% if nutzer and not gesperrt %}{% if status_speicher %}{% endif %}
{% endif %}
{# Herkunftsmarke je Track (10.11.2026, static/herkunft.js): ein Baustein für Library, Tag List, Player, Track-Detail, Export-Vorschau #}
{% if (nutzer and not gesperrt) or demo %}
{% endif %}
{# Tag List (Paket 2): Knöpfe +/✓ und Taste T auf allen Seiten, Paneel in der Library. `konto`: Hash der Kontonummer für den
Schlüssel noch nicht gespeicherter Änderungen (localStorage) – ein anderes Konto am selben Gerät sieht sie nie. #}
{% if (nutzer and not gesperrt) or demo %}
{% endif %}
{# Navileiste am Handy (27.10.2026): das zentrale „+“ (static/plus.js) – bleibendes Skript wie tagliste.js; Texte in #plus-t an der Leiste #}
{% if nutzer and not gesperrt %}{% endif %}
{# Home „Teller“ (28.10.2026): bleibendes Skript – merkt auf jeder Seite den zuletzt gehörten Track (nur im Gerät) und füllt Home #}
{% if nutzer and not gesperrt %}{% endif %}
{# Oktagon im Fly-in, Pfad, Dig-Ebene und großer Player (24.10.2026): Komponente des Mix-Oktagons (auch fürs Titelblatt) und
dig.js (Pfad je Tab, Fly-in, großer Player). Texte: dig (texte_dig.py) und die Oktagon-Texte des Titelblatts (blatt.passt). #}
{# Ohne verbundenen Onlinespeicher nennt die Seite ihn nirgends (auch nicht im Textblock): „nicht im Onlinespeicher“ fällt dann weg. #}
{# Cover „A+“ (24.10.2026): Baustein für Liste, Fly-in, Pfad, großen Player, Leiste, „Jetzt läuft“ und Titelblatt – vor dig.js #}
{% if (nutzer and not gesperrt) or demo %}
{% endif %}
{% if (nutzer and not gesperrt) or demo %}
{# JS je Seite (30.10.2026): Oktagon, Dig und großer Player laden nur die Seiten gleich mit, die sie beim Start brauchen – Liste
`seiten_module` in der Vorlage der Seite ("dig": Oktagon + Dig, die Seiten mit Diagrammen; "buehne_verlauf": Explorer). Alle
anderen holen sie über static/lader.js bei Bedarf (vu.js und buehne_verlauf.js beim Öffnen des großen Players). data-modul:
zählt beim weichen Seitenwechsel nicht zu den bleibenden Skripten, der Lader bringt fehlende Module vor den Seitenskripten.
`lader_mehr` (12.11.2026): Adressen, die nur EINE Seite nachlädt, setzt deren Vorlage (regal_einlesen.html) – sonst leer. #}
{% set sm = seiten_module | default(()) %}
{% if "dig" in sm %}
{% endif %}
{% if "buehne_verlauf" in sm %}{% endif %}
{% endif %}
{# Tutorial „Kniffe“ (29.10.2026): Kniffe im Kontext und Taste ? (klein, defer); der Einstieg „Kurz reingehört“ nur, solange er fällig ist #}
{% if nutzer and not gesperrt %}
{% if einstieg_faellig(eb) %}
{% endif %}{% endif %}
{# Sprungmarke (H36) als erstes Element; in der Library stellt bibliothek.js sie auf „Zur Trackliste“ um. #}
{{ t.sprung_inhalt }}
{# Kopf (Navigation Runde 2): Makros in templates/kopf.html, gemeinsam mit messung_basis.html; hier mit den Stufen von
timbre.css (Zähler der Verwaltung ab 1100 px in der Leiste, Reiterleiste unter 760 px). #}
{% import "kopf.html" as kopfmakros with context %}{{ kopfmakros.kopfleiste("1100") }}
{# data-weich (Block „weich“): Die Seite kann weich gewechselt werden (static/navigation.js) – ihre Skripte stehen mit data-seite
und haben Start/Stopp über TimbreSeite.rahmen(). Ohne den Haken lädt der Wechsel von und zu ihr normal. #}
{% if beta_wartet and pfad != "/speicher-bereit" %}
{% endif %}
{# Neonlila (28.10.2026): einmal je freigeschaltetem Design ein warmer Hinweis im Kopf – Ausprobieren (wählt es) oder Später;
beides merkt sich das Konto (POST /konto/design-hinweis, timbre_api/aussehen.py). Geht ohne Skript. #}
{% if nutzer and not gesperrt and eb.designs_frei is defined %}{% for d in designs_neu(eb)[:1] %}{% endfor %}{% endif %}
{# Tutorial „Kniffe“ (29.10.2026): Bestandskonten (ohne Einstieg) einmal „Neu: Alle Kniffe an einem Ort“ – Ansehen oder Später, geht ohne Skript #}
{# Offline-Paket (30.10.2026): Das Paket kennt das Konto nicht – dort steht das Banner versteckt, static/app_wege.js zeigt es nur, wenn
GET /api/v1/konto es fällig nennt. Im App-Fenster schickt app_wege.js „Ansehen“/„Später“ an POST /api/v1/konto/kniffe-hinweis. #}
{% if nutzer and not gesperrt and kniffe_hinweis_faellig(eb) and not (eb.designs_frei is defined and designs_neu(eb)) %}{% endif %}
{# Quellen je Feld (31.10.2026): nach dem ersten Rekordbox-Import mit Vergleichswerten einmal „Sollen wir wie Rekordbox zeigen?“ –
Ja (Vorlage „Wie Rekordbox“) oder Nein; beides merkt sich das Konto (POST /konto/quellen-frage, quellen_wahl.py). Ohne Skript. #}
{% if nutzer and not gesperrt and not paket_seite and quellen_frage_faellig(eb) %}{% endif %}
{# Tonart-Schreibweise (07.11.2026, Entscheidung Maintainer, Weg 1): Vorgabe ist Open Key. Nutzen die Tags des Kontos überwiegend
1A–12B (tonart_notation.angebot), fragt Timbre einmal: „Deine Tags nutzen 1A–12B. So anzeigen?“ – „Ja“ wählt 1A–12B, „Nein“
speichert Open Key als eigene Wahl (nie wieder). static/tonart.js zeigt die Zeile nur, wenn sie auf diesem Gerät noch offen ist #}
{% if nutzer and not gesperrt and eb | tonart_angebot and pfad != "/konto" %}{% set tsw = t.tonart_sw %}