{# Kopf-Makros für beide Grundgerüste (konzept.md Stufe 2 §6): basis.html (Arbeitsansichten, timbre.css) und messung_basis.html (Leitseite und Infoseiten, start.css). Struktur, Klassen und Texte (t.nav.*) sind gleich, nur das Aussehen kommt aus der jeweiligen CSS-Datei. Einbinden mit `{% import "kopf.html" as k with context %}` – die Makros lesen t, nutzer, gesperrt, pfad, bereich, sprache, sprachen, verwaltung, verwaltung_wartet und start_marke aus dem Kontext der Seite. Navigation seit 10.11.2026: Menü Variante C „Drei Orte“ (Library · Diggen · Playlists, Zahnrad rechts) – siehe kopfleiste() und timbre_api/menue.py; Flyout „Explorer · Library ▾“, „03 Export“, Hilfe/Konto ▾/Sprache ▾ oben sind entfallen. Bis dahin: Navigation (16.10.2026, konzept.md Runde 2; Stand 27.10.2026): Fluss „01 Explore · 02 Review & Edit · 03 Export“ (Maintainer 27.10.2026; 25.10. „Import → Explore → Review & Edit & Export“ ohne Nummern; davor „01 Genres → 02 Library → 03 Playlists“). Import steht im Onboarding, im Konto-Menü und in den Einstellungen (bzw. als „Import · Start“, solange keine Quelle da ist), daneben „Hilfe und Konto“. Import ist die Seite /quellen. Genres ist kein eigener Punkt mehr, nur noch Karte im Explore-Menü. „Explore“ (Maintainer 25.10.2026, vorher „02 Library“) ist ein Verweis plus Aufklapper: Hover (nur Maus, mit kurzer Verzögerung), Klick auf ▾, Pfeil ↓ oder Touch öffnen das Flyout mit drei Karten – Explorer (groß, zuerst), Library, Genres (die Linse). Esc schließt (Fokus zurück), Klick daneben und Tab hinaus auch; aria-expanded am Knopf ▾. Klick auf „Explore“ selbst öffnet die zuletzt genutzte Ansicht (Explorer oder Library, je Gerät in localStorage timbre.explore.zuletzt), beim ersten Mal den Explorer; der Server schreibt /explorer, navigation.js setzt das gemerkte Ziel (data-rahmen-href hält den Server-Wert für den weichen Wechsel). „Explore“ trägt aria-current="true" auf allen Explore-Seiten (/explorer, /bibliothek und Unterseiten, /genres), die Karte der Seite selbst aria-current="page". Chip „Neu“ und leuchtende LED nur bis EINST.explorer_neu_bis (explorer_neu()). Mobil öffnet der Reiter „Explore“ das Blatt #ex-blatt mit denselben Karten (ohne : normaler Verweis). Die aktuelle Seite trägt aria-current="page" (H20); `pfad` setzt seite() bzw. die Seite selbst, `bereich` die Playlists-Seiten (alle Unterseiten zählen zum Schritt). Die Sprache ist auf allen Breiten ein Menü „DE ▾“ (Maintainer, 16.10.2026) mit den vollen Namen (Deutsch, English …, die aktuelle mit ✓); in den Mobil-Menüs und im Blatt „Mehr“ stehen die Namen offen untereinander, im Fuß bleibt die kurze Liste (ohne Skript, für die Suche). Konto ▾, Sprache ▾ und das Menü der Besuchsseite sind
– sie gehen auch ohne Skript; navigation.js schließt sie mit Esc (Fokus zurück auf den Knopf) und Klick daneben. `stufe`: Breite, ab der der Zähler der Verwaltung neben „Konto ▾“ in die Leiste wandert (Klassen ab…/bis…). basis.html bleibt bei 1100 (timbre.css), messung_basis.html nimmt die Stufe des Rasters, 1184 (Maintainer 22.10.2026). Der Inhalt eines `{% call %}`-Blocks (der Lampen-Schalter der neuen Seiten) steht vor dem Mobil-Menü bzw. am Ende der Leiste. #} {% from "schalter.html" import schalter %}{% macro nav(href, text) %}{{ text }}{% endmacro %} {% macro sprachlinks(trenner=true) %}
{% for k, name in sprachen %}{% if trenner and not loop.first %}{% endif %}{{ k | upper }}{% endfor %}
{% endmacro %} {% macro sprachliste() %}
{% for k, name in sprachen %}{{ name }}{% if k == sprache %} {% endif %}{% endfor %}
{% endmacro %} {% macro sprachknopf() %}{% set nv = t.nav %}{% for k, name in sprachen %}{% if k == sprache %}
{{ k | upper }}
{{ sprachliste() }}
{% endif %}{% endfor %}{% endmacro %} {% macro _wartet_text() %}{% set nv = t.nav %}{{ (nv.verwaltung_wartet_eins if verwaltung_wartet == 1 else nv.verwaltung_wartet | replace('{n}', verwaltung_wartet | string)) if verwaltung_wartet else '' }}{% endmacro %} {% macro _zaehler_name() %}{% set nv = t.nav %}{{ (nv.zaehler_name_eins if verwaltung_wartet == 1 else nv.zaehler_name | replace('{n}', verwaltung_wartet | string)) if verwaltung_wartet else '' }}{% endmacro %} {% macro analysen_link(klasse) %}{% set ber = bereich or pfad %}{{ t.analysen.nav }}{% if ana and ana.name %} – {{ ana.name }}{% endif %}{% if klasse == "analysen-mehr" %} {{ t.analysen.mehr_hinweis }}{% endif %}{% endmacro %} {# Bis Menü C (und in App-Hüllen ohne native_leiste_playlists weiter): Explore-Flyout #} {# Explore (25.10.2026): Oktagon-Symbol und die drei Karten – im Flyout des Kopfs und im Blatt „Explore“ der Reiterleiste #} {% macro oktagon_symbol(klasse="ex-okt") %}{% endmacro %} {% macro explore_karten() %}{% set ex = t.nav.explore %}{% set ex_neu = explorer_neu() %} {{ t.explorer.explorer }}{% if ex_neu %} {{ ex.neu }}{% endif %}{{ ex.explorer_zeile }} {{ t.bibliothek }}{{ ex.library_zeile }} {{ t.genres }}{{ ex.genres_zeile }} {# Jukebox 2.0 (08.11.2026): Name nur aus texte_jukebox.py (`kurz` in der Navigation) #} {{ t.jukebox.kurz }}{{ t.jukebox.einstieg_hilfe }} {% endmacro %} {% macro jukebox_symbol(klasse="ex-ico") %}{% endmacro %} {% macro zahnrad_symbol() %}{% endmacro %} {# Seitenleiste der Desktop-App (Variante C, 10.11.2026, Mockup docs/konzepte/2026-11-10-menue/c-app.html): nur im App-Fenster (desktop_app – DMG und Mac-App-Store-Fassung), ab 1000 px statt der Punkte im Kopf (static/dk_leiste.css, werkzeuge/tokens_menue.py; lädt nur im App-Fenster). Oben „Rein“, dann die drei Orte mit ihren Ansichten, die Playlists (dk_listen, höchstens 12), unten Analyse und Einstellungen. Steht im Kopf, damit sie beim weichen Wechsel stehen bleibt und navigation.js aria-current abgleicht. Store-Apps: nichts Angekündigtes (Mithören erst mit MITHOEREN_LIVE, nie „kommt“). #} {% macro dk_leiste() %}{% if menue_c and desktop_app and nutzer and not gesperrt %}{% set mn = t.menue %}{% set ort = menue_ort(pfad, bereich) %} {% endif %}{% endmacro %} {% macro kopfleiste(stufe="1100") %}{% set nv = t.nav %}{% set ber = bereich or pfad %}{% set zaehler_name = _zaehler_name() %}{% set wartet_text = _wartet_text() %}
timbre. {# Desktop v2 (Bitte 3): verbunden/offline – nur im App-Fenster; static/desktop_extras.js zeigt und hält es aktuell #} {% if desktop_app and nutzer and not gesperrt %}{% endif %} {% if nutzer and gesperrt %} {# angemeldet, aber nicht freigegeben: nur das, was ohne Freigabe geht – der Fluss steht als Text auf der Seite #} {# mobil wie im Konzept: Marke · Hilfe · ≡ (Hilfe an derselben Stelle wie beim Besuch, Durchsicht K10) #} {{ t.hilfe.nav }} {%- if caller %}{{ caller() }}{% endif %} {% elif nutzer %} {# App-Hülle ohne Fähigkeit native_leiste_playlists (iOS 1.0/Mac 1.0 in der Prüfung): Kopf genau wie vor Menü C (menue_c, timbre_api/menue.py) #} {% if menue_c %} {# Menü Variante C „Drei Orte“ (Maintainer 10.11.2026, docs/konzepte/2026-11-10-menue.md, timbre_api/menue.py): Library · Diggen · Playlists – links → rechts = sammeln → suchen → packen, ohne Unterebene. Vorher „01 Explorer · Library ▾ · 02 Playlists · 03 Export“ (27.10.–10.11.2026). Rein steht links im Kopf der Library, Export an Library und Playlist; Regal und Genres sind Ansichten der Library, Jukebox eine Ansicht beim Diggen. aria-current: "page" auf dem Ziel des Orts, "true" auf seinen übrigen Seiten (menue.aktuell). Die Klasse ex-kopf am Diggen trägt die LED „Neu“ wie früher am Explorer. #} {% set mn = t.menue %} {% else %} {% endif %} {%- if caller %}{{ caller() }}{% endif %} {# Zahnrad (27.10.2026, nur am Handy, solange die Navileiste steht): öffnet das Blatt #mehr mit Import, Review, Analysen, Hilfe, Konto, Sprache und Abmelden. Marken wie vorher am Knopf „Mehr“: Start (neues Konto), Speicher wartet, Analysen, Verwaltung. Symbol seit 06.11.2026: Lucide „settings“ (ISC-Lizenz, Lizenztext in static/symbole/ISC-Lucide.txt wie die Schriften in static/schrift/OFL-*.txt), Strich 1.7 wie die übrigen Kopf-Symbole (iOS-Notiz TP2 0725). #} {% set mehr_beschr = (["mehr-zaehler"] if verwaltung and verwaltung_wartet else []) + (["mehr-analysen"] if ana and ana.zustand else []) %} {% else %} {# Wartung (Fehlerseiten 23.10.2026): kein „Anmelden“ – es führt nur in dieselbe Wartung #} {% if not ohne_anmelden %}{{ t.anmelden }}{% endif %} {%- if caller %}{{ caller() }}{% endif %} {% endif %}
{{ dk_leiste() }} {# Statuszeile: läuft eine Analyse oder liest Timbre den Onlinespeicher ein, füllt status.js sie (Phase, n von m, Restzeit). #} {# Die Zeile liegt außerhalb des Flusses unter der Kopfleiste (eine Zeile hoch): erscheint oder verschwindet sie, rückt der Inhalt nicht. Hilfstechnik hört nur #status-ansage (Wechsel der Phase und das Ende), nicht jede neue Restzeit. #} {% if nutzer and not gesperrt %}{% endif %}
{% endmacro %} {# Navileiste am Handy (27.10.2026, Schritt 1 des Mobil-Umbaus, Plan binary-sauteeing-pelican; seit Variante C 10.11.2026 Home · Library · [+] · Diggen · Playlists, siehe unten): fünf Plätze, bis 10.11.2026 Home (/home, „Teller“ seit Schritt 4, 28.10.2026) · Explorer · [+] · Suche (Library mit Fokus im Suchfeld) · Library. Links die beiden Hörwege, in der Mitte das „+“ (Mitte = jetzt): es zeigt das Cover des Tracks, auf den es wirkt, und darunter die Ziel-Zeile „→ Liste“ (Tipp = Ziel wechseln, ebenso langes Drücken auf +). static/plus.js bedient beides; Texte in #plus-t (texte_plus.py). Was vorher in der Leiste stand (Import, Review, „Mehr“), liegt im Blatt #mehr hinter dem Zahnrad oben rechts im Kopf (bis Schritt 4 „Home Teller“). Höhe als --reiter (CSS); Player, Tag-List-Leiste, Sheet, Toast und scroll-padding rechnen sie mit (2.4.11). Bei offener Bildschirmtastatur blendet navigation.js die Leiste aus (html.tastatur). Sichtbar unter 744 px (timbre.css und start.css, Tablet-Stufe werkzeuge/tokens_tablet.py). #} {% macro reiter() %}{% set nv = t.nav %}{% set px = t.plus %}{% set ber = bereich or pfad %}{% set zaehler_name = _zaehler_name() %}{% set wartet_text = _wartet_text() %} {% if nutzer and not gesperrt %} {% if menue_c %}{% set mn = t.menue %}{% set an_suche = pfad == "/bibliothek" and fokus_suche %}{% set ort = menue_ort(pfad, bereich) %} {# Variante C (10.11.2026): Home · Library · [+] · Diggen · Playlists. „Suche“ ist kein Reiter mehr: das Suchfeld steht oben in der Library, ein zweiter Tipp auf „Library“ (auf der Library) fokussiert es (static/plus.js). Der Verweis a.r-suche bleibt verborgen in der Leiste – Vertrag der iOS-App (`TimbreApp.navigation.zu("suche")`, Meldung route "suche", static/app_leiste.js) und alte Einsprünge (/bibliothek?fokus=suche) gehen unverändert. Klassen r-home/r-explorer/r-library bleiben (Vertrag, einstieg.js). #} {% else %}{% set an_suche = pfad == "/bibliothek" and fokus_suche %}{% set an_lib = pfad.startswith("/bibliothek") and not an_suche %} {# Sichtfund A2 (12.11.2026): In den Playlists ist kein Reiter markiert – diese Leiste hat keinen dafür (vorher leuchtete „Library“, auch in der nativen Leiste der App: static/app_leiste.js meldet, was hier markiert ist, jetzt route null wie in den Einstellungen). #} {% endif %} {# Texte und Konto-Hash für static/plus.js (das Skript selbst steht im Kopf von basis.html bzw. messung_basis.html, bleibt beim weichen Wechsel). Paket „Gefühl“ (11.11.2026): `gefuehl` nur mit Menü C – damit zählt das + sofort und kennt „Das erste +“ (static/plus.js); App-Hüllen ohne die Fähigkeit bekommen den Schlüssel nicht (#plus-t Zeichen für Zeichen wie vorher) und verhalten sich wie vorher #} {# Zahnrad-Blatt (Einstellungen): alles Einrichten und Nachsehen – Import, Review, Genres, Analysen, Hilfe, Konto, Beta, Verwaltung, Sprache, Abmelden. Der Knopf steht im Kopf (#zahn-knopf, nur am Handy). #}

{{ px.einstellungen }}

{# Handy schlank (06.11.2026, Phase 1): Am Handy entfällt die Fußzeile – Rechtstexte und Kontakt stehen hier (Zahnrad, dann ein Tipp) #}

{{ t.home.e_recht }}

{{ t.sprache_wahl }}

{{ sprachliste() }}
{% endif %}{% endmacro %} {% macro player(cover=false) %}{# Player (N22): feste Leiste am unteren Rand, sichtbar, sobald ein Track gewählt ist. player.js füllt und bedient sie; sie steht außerhalb von Kopf und Fuß, damit sie bedienbar bleibt, wenn das Fly-in der Bibliothek die Seite sperrt. #} {# Nur mit verbundenem Onlinespeicher: ohne ihn gibt es nichts abzuspielen (und ist die Funktion aus, nennt die Seite ihn nirgends). #} {# Live-Demo: auch ohne Konto (`demo`), dann immer mit Datensparen (player.js liest html[data-demo]) #} {# Desktop v2 (28.10.2026): im App-Fenster auch ohne Onlinespeicher – lokale Tracks spielt der native Player des Kerns (AbspielQuelle in player.js) #} {% if ((nutzer and not gesperrt) or demo) and (abspielen_an or (desktop_app and not demo)) %}{% set pl = t.player %}{% if passt_jetzt() %}{% endif %} {# Großer Player (24.10.2026): modaler Dialog in der Player-Hülle (außerhalb von
, übersteht weiche Seitenwechsel); dig.js baut den Inhalt: links der laufende Track, rechts Pfad und Oktagon. #} {# Desktop v2: Texte für „lokal“ und Audio-Ausgabe (player.js) – nur im App-Fenster #} {% if desktop_app %}{% endif %} {# Warteschlange und Hörmodus (24.10.2026): vor player.js (dessen Media Session fragt TimbreWarteschlange.msAktionen); Merker je Gerät und Konto (`konto`: Hash wie bei der Tag List) – nie auf dem Server. #} {# Auto-Listening (28.10.2026): „Danach: Auto-Listening“ in der Warteschlange – vor warteschlange.js; Regeln je Gerät und Konto (wie oben), nie auf dem Server #} {# Dig-Controller (28.10.2026): Explorer am Handy als Controller (Richtung → Liste → vorhören), auch aus Auto-Listening „Ersetzen – diggen“ #} {% if passt_jetzt() %} {% endif %}{# „Durchgehört“ (12.11.2026): nur mit dem Schalter TIMBRE_DURCHGEHOERT (app._durchgehoert: nie Store-Fassungen, Live-Demo, Offline-Paket) – ist er aus, steht hier nichts. Der Haken lädt static/hoer_mass.js und static/durchgehoert.js nach; Marken, Knopf und Dialog baut das Modul. Was gehört wurde, bleibt im Browser (localStorage). #}{% if durchgehoert() %} {% endif %}{# Set-Rückblick (12.11.2026): nur mit dem Schalter TIMBRE_RUECKBLICK (app._rueckblick: nie Store-Fassungen, Live-Demo, Offline-Paket) – ist er aus, steht hier nichts. Der Haken lädt static/hoer_mass.js und static/rueckblick.js nach; Knopf und Dialog baut das Modul. Die Session bleibt im Tab (sessionStorage). #}{% if rueckblick() %} {% endif %} {% endif %}{% endmacro %}