Studio-Visitenkarte im Footer (Standorte, Kontakt-Tabs, Ortszeit)
Footer als Visitenkarte einer Interaction-Designerin aus Hannover: Kontakt-Tabs mit rollender E-Mail und Kopier-Rückmeldung, Adresse, Ortszeit je Standort und Ausgabe-Zeile.
Freelancer, kleine Studios und Büros mit einem oder zwei Orten: Kontaktwege nach Anliegen als Tabs, Ortszeit, Nebenprojekte, Text in Lesegröße.
Der Footer zeigt das Studio als greifbaren Ort: Adresse mit Kartenlink, Ortszeit je Standort und Telefon. Kontaktwege sind nach Anliegen getrennt, zum Beispiel Neues Projekt, Allgemeines und Vorträge oder Karriere. Als Tabs wechseln sie die sichtbare E-Mail. Dazu kommen eine Ausgabe- oder Versionszeile, Credits und Links zu Nebenprojekten wie Newsletter, Store, Labs oder Open Source.
Adresse, Ortszeit und Telefon machen das Studio greifbar und schaffen Vertrauen. Getrennte Ansprechwege senken die Hemmschwelle, weil klar ist, wohin eine Anfrage gehört. Ausgabe-Zeile und Credits zeigen Stolz aufs Handwerk.
Wann einsetzen
Agenturen, Studios, Büros, Praxen und Freelancer mit festem Standort.
Wann nicht
Rein digitale Produkte ohne Ortsbezug.
Varianten
- Kontakt-Tabs: Anliegen wechseln die sichtbare E-Mail (Unseen: New Business und General)
- Zwei Standorte mit eigener Ortszeit (Cuberto: Alexandria und Prag)
- Liste ohne Tabs: alle Adressen untereinander, zugleich der Zustand ohne JavaScript
- Ausgabe- oder Versionszeile (Dennis Snellenberg: „2022 © Edition“)
- Credits und Nebenprojekte (Lusion: Built by Lusion und R&D-Seite; basement.studio: Ventures)
- Praxis oder Handwerk: Telefon zuerst, Sprechzeiten mit Live-Status („schließt in 40 Min.“), Anfahrt nach Bus und Bahn, Auto, Barrierefrei, Notfallnummern
- Studio-Bühne: Mail-Adresse als Schlagzeile mit Zeichen-Roll, Ansprechpersonen je Anliegen, zwei Studios mit Ortszeit, Wortmarke über die volle Breite
- Gastgeber (Hotel, Gasthof, Eventlocation): Adresse mit Anreise in einem Satz, Telefon und E-Mail groß, Check-in- und Check-out-Zeiten mit Schlüssel-Hinweis, Social-Links, Saisonbrief optional
Umsetzung
Adresse in <address>, Kartenlink erst auf Klick laden. Ortszeit über Intl.DateTimeFormat mit timeZone je Standort, Zeitzonenname über timeZoneName: 'short'. Kontakt-Tabs als ARIA-Tabs (tablist, tab, tabpanel, Pfeiltasten, Pos1/Ende); alle E-Mails stehen als echte mailto:-Links im HTML, ohne JavaScript untereinander. Der Roll: jede Zeile sitzt in einem Fenster mit overflow: clip und einer Zeilenhöhe, die alte fährt um 100 % hinaus, die neue hinein. Kopieren über navigator.clipboard.writeText mit sichtbarer Rückmeldung und aria-live. E-Mail-Adressen nicht per JavaScript zusammensetzen, Spam lieber serverseitig filtern.
Robust umsetzen
Telefon. Spalten untereinander, Telefonnummer als tel:-Link mit großem Tippziel, Kopieren-Knopf immer sichtbar.
Ohne Bewegung. Tab-Wechsel ohne Roll, die E-Mail tauscht sofort.
Barrierefrei. <address>, tel:- und mailto:-Links, Tabs mit Pfeiltasten oder eine einfache Liste. Inaktive Tafeln sind inert. Kopieren meldet sich über aria-live. Fokus-Ring in der Akzentfarbe.
Code
<!DOCTYPE html>
<!--
Studio-Visitenkarte im Footer (Standorte, Kontakt-Tabs, Ortszeit)
Fundus · Footer · https://cecodesign.de/lab/fundus/footer/studio-visitenkarte-footer/
Eigenständige Datei. Bilder liegen hier unter bilder/ – eigene einsetzen.
-->
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Studio-Visitenkarte im Footer · Fundus-Demo</title>
<script>document.documentElement.classList.add('js');if(matchMedia('(prefers-reduced-motion: reduce)').matches)document.documentElement.classList.add('reduziert')</script>
<style>
@font-face { font-family: 'Host Grotesk'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/host-grotesk:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 300 800; font-display: swap; }
@font-face { font-family: 'Newsreader'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/newsreader:vf@latest/latin-opsz-italic.woff2') format('woff2-variations'); font-weight: 200 800; font-style: italic; font-display: swap; }
@font-face { font-family: 'Newsreader'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/newsreader:vf@latest/latin-opsz-normal.woff2') format('woff2-variations'); font-weight: 200 800; font-style: normal; font-display: swap; }
@font-face { font-family: 'Mona Sans'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/mona-sans:vf@latest/latin-wdth-normal.woff2') format('woff2-variations'); font-weight: 200 900; font-stretch: 75% 125%; font-display: swap; }
@font-face { font-family: 'Hedvig Letters Serif'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/hedvig-letters-serif:vf@latest/latin-opsz-normal.woff2') format('woff2-variations'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Google Sans Flex'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/google-sans-flex:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 100 1000; font-display: swap; }
@font-face { font-family: 'TikTok Sans'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/tiktok-sans:vf@latest/latin-wdth-normal.woff2') format('woff2-variations'); font-weight: 300 900; font-stretch: 75% 150%; font-display: swap; }
@font-face { font-family: 'DM Mono'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/dm-mono@latest/latin-400-normal.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Geist Mono'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/geist-mono:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 100 900; font-display: swap; }
:root {
/* Rezept „Stille Visitenkarte“: Graustufen, eine Farbe nur für Fokus und Link-Zustände */
--grund: #fcfcfc; --text: #0b0b09; --leise: #646464; --linie: #e8e8e8; --flaeche: #f0f0f0;
--akzent: #2f5bea;
--kurve: cubic-bezier(0.165, 0.84, 0.44, 1); /* easeOutQuart, gemessen bei Paco Coursey und Emil Kowalski */
--roll: 240ms; /* Text-Roll beim Wechsel der E-Mail */
--ui: 120ms; /* Hover, Farbe */
--rand: clamp(20px, 4vw, 48px);
color-scheme: light;
}
:root[data-thema='dunkel'] {
--grund: #0b0b09; --text: #e5e5e5; --leise: #989898; --linie: #252525; --flaeche: #181816;
--akzent: #7d9bff;
color-scheme: dark;
}
* { box-sizing: border-box; margin: 0; }
html { background: var(--grund); color: var(--text); font: 400 16px/1.6 'Host Grotesk', system-ui, sans-serif; -webkit-font-smoothing: antialiased; font-variant-numeric: tabular-nums; }
body { min-height: 100svh; display: flex; flex-direction: column; overflow-x: hidden; }
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
em { font-family: 'Newsreader', Georgia, serif; font-style: italic; font-weight: 400; font-size: 1.07em; font-variation-settings: 'opsz' 24; letter-spacing: 0; }
:focus-visible { outline: 2px solid var(--akzent); outline-offset: 3px; border-radius: 2px; }
.mono { font: 500 11px/1.4 'Geist Mono', ui-monospace, monospace; letter-spacing: .14em; text-transform: uppercase; color: var(--leise); }
.seite { width: 100%; max-width: calc(1072px + 2 * var(--rand)); margin: 0 auto; padding: 0 var(--rand); }
/* ---------- Seite über dem Footer ---------- */
.kopf { display: flex; justify-content: space-between; align-items: baseline; padding-top: clamp(20px, 3vw, 36px); }
.kopf .name { font-weight: 500; text-decoration: none; }
.kopf nav { display: flex; gap: 20px; }
.kopf nav a { color: var(--leise); text-decoration: none; font-size: 15px; transition: color var(--ui) var(--kurve); }
.kopf nav a:hover { color: var(--text); }
.jetzt { max-width: 640px; padding: clamp(40px, 5vw, 64px) 0 clamp(28px, 3.5vw, 40px); }
.jetzt h2, .fuss h2 { font-size: 1rem; font-weight: 500; color: var(--leise); margin-bottom: 10px; }
.jetzt p + p { margin-top: 12px; }
.leise { color: var(--leise); }
/* Umschalter der Demo (steht im Fluss, nicht fest) */
.pult { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px; padding: 0 0 18px; }
.pult button { letter-spacing: inherit; text-transform: inherit; color: var(--leise); padding: 6px 0; border-bottom: 1px solid transparent; transition: color var(--ui) var(--kurve), border-color var(--ui) var(--kurve); }
.pult button:hover { color: var(--text); }
.pult button[aria-pressed='true'] { color: var(--text); border-color: currentColor; }
.pult .werte { margin-left: auto; text-transform: none; letter-spacing: .02em; }
/* ---------- Footer: die Visitenkarte ---------- */
.fuss { border-top: 1px solid var(--linie); padding: clamp(40px, 5vw, 64px) 0 clamp(24px, 3vw, 32px); flex: 1; }
.satz { font-size: clamp(1.25rem, 1rem + 1vw, 1.5rem); font-weight: 500; line-height: 1.4; letter-spacing: -.01em; max-width: 30ch; text-wrap: balance; }
.raster { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 3.2fr) minmax(0, 2.8fr); gap: 48px clamp(28px, 4vw, 64px); }
.kontakt .satz { margin-bottom: clamp(36px, 4.5vw, 56px); }
.orte, .anderswo { padding-top: 6px; }
/* Kontakt-Tabs */
.reiter { position: relative; display: flex; gap: 22px; border-bottom: 1px solid var(--linie); margin-bottom: 22px; }
.reiter [role='tab'] { position: relative; padding: 4px 0 12px; color: var(--leise); font-size: 15px; transition: color var(--ui) var(--kurve); }
.reiter [role='tab']:hover { color: var(--text); }
.reiter [role='tab'][aria-selected='true'] { color: var(--text); font-weight: 500; }
.reiter [role='tab']:focus-visible { outline-offset: 1px; }
.strich { position: absolute; left: 0; bottom: -1px; height: 1px; width: 1px; background: var(--text); transform-origin: 0 0; transition: transform var(--roll) var(--kurve); }
.fenster { display: grid; grid-template-columns: minmax(0, 1fr); }
.tafel { grid-area: 1 / 1; visibility: hidden; transition: visibility 0s var(--roll); }
.tafel.an { visibility: visible; transition-delay: 0s; }
.etikett { display: none; }
.zeile { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
/* Das Fenster für den Roll: genau eine Zeilenhöhe hoch */
.rolle { display: block; overflow: clip; overflow-clip-margin: 4px; min-width: 0; line-height: 1.35; padding-block: 2px; }
.mail { display: block; font-size: clamp(1.125rem, .9rem + 1vw, 1.5rem); font-weight: 500; letter-spacing: -.01em; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .22em; text-decoration-color: var(--linie);
transform: translateY(var(--y, 100%)); transition: transform var(--roll) var(--kurve), color var(--ui) var(--kurve), text-decoration-color var(--ui) var(--kurve); }
.tafel.an .mail { --y: 0%; }
.tafel.oben .mail { --y: -100%; }
.mail:hover { color: var(--akzent); text-decoration-color: var(--akzent); }
.hinweis { color: var(--leise); margin-top: 14px; max-width: 46ch; opacity: 0; transition: opacity var(--roll) var(--kurve); }
.tafel.an .hinweis { opacity: 1; }
.kopieren { flex: none; display: inline-flex; align-items: center; gap: 7px; height: 30px; padding: 0 12px; border: 1px solid var(--linie); border-radius: 999px; font-size: 14px; color: var(--leise);
opacity: 0; transition: opacity var(--roll) var(--kurve), background-color var(--ui) var(--kurve), color var(--ui) var(--kurve), border-color var(--ui) var(--kurve); }
.tafel.an .kopieren { opacity: 1; }
.kopieren:hover { background: var(--flaeche); color: var(--text); }
.kopieren svg { width: 13px; height: 13px; flex: none; }
.kr { display: inline-grid; overflow: clip; line-height: 1.2; }
.kr > span { grid-area: 1 / 1; transition: transform var(--roll) var(--kurve); }
.kr > span + span { transform: translateY(100%); }
.kopieren.fertig { color: var(--text); border-color: var(--leise); }
.kopieren.fertig .kr > span:first-child { transform: translateY(-100%); }
.kopieren.fertig .kr > span + span { transform: translateY(0); }
.kopieren .haken { display: none; }
.kopieren.fertig .haken { display: block; }
.kopieren.fertig .blatt { display: none; }
/* Standorte */
.standort + .standort { margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--linie); }
.ortname { font-weight: 500; display: flex; justify-content: space-between; gap: 12px; }
.ortname span { font-weight: 400; color: var(--leise); font-size: 14px; }
address { font-style: normal; color: var(--leise); margin-top: 4px; }
.uhr { margin-top: 10px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.uhr time { font-weight: 500; }
.uhr .zone, .uhr .status { color: var(--leise); }
.punkt { width: 7px; height: 7px; border-radius: 50%; background: var(--leise); flex: none; }
.standort.offen .punkt { background: #2fa36b; }
.saison { display: none; }
.fuss[data-variante='orte'] .saison { display: inline; }
.fuss[data-variante='orte'] .standort:not(.hier) :is(.ortname, time) { color: var(--leise); }
.verweis { display: inline-block; margin-top: 10px; font-size: 15px; color: var(--leise); text-decoration: none; transition: color var(--ui) var(--kurve); }
.verweis:hover { color: var(--akzent); }
.tel { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--linie); }
.tel a { text-decoration: none; font-weight: 500; transition: color var(--ui) var(--kurve); }
.tel a:hover { color: var(--akzent); }
.tel span { display: block; color: var(--leise); font-size: 14px; }
.zweit { display: none; }
.fuss[data-variante='orte'] .zweit { display: block; }
.titel-zwei { display: none; }
.fuss[data-variante='orte'] .titel-eins { display: none; }
.fuss[data-variante='orte'] .titel-zwei { display: inline; }
/* Anderswo: Nebenprojekte */
.anderswo ul { list-style: none; padding: 0; }
.anderswo li { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--linie); }
.anderswo li:first-child { padding-top: 0; }
.anderswo a { text-decoration: none; transition: color var(--ui) var(--kurve); }
.anderswo a:hover { color: var(--akzent); }
.anderswo li span { color: var(--leise); font-size: 14px; text-align: right; }
/* Unterkante: Rechtliches, Ausgabe, Darstellung */
.unterkante { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 12px 32px; margin-top: clamp(48px, 5vw, 64px); padding-top: 18px; border-top: 1px solid var(--linie); font-size: 14px; color: var(--leise); }
.unterkante a { text-decoration: none; transition: color var(--ui) var(--kurve); }
.unterkante a:hover { color: var(--text); }
.edition b { font-weight: 500; color: var(--text); }
.thema { display: inline-flex; padding: 2px; border: 1px solid var(--linie); border-radius: 999px; }
.thema button { height: 26px; padding: 0 12px; border-radius: 999px; font-size: 13px; color: var(--leise); transition: background-color var(--ui) var(--kurve), color var(--ui) var(--kurve); }
.thema button:hover { color: var(--text); }
.thema button[aria-pressed='true'] { background: var(--flaeche); color: var(--text); }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 320ms; animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1); }
/* Variante „Liste ohne Tabs“ (zugleich der Zustand ohne JavaScript) */
.fuss[data-variante='liste'] .reiter, html:not(.js) .reiter { display: none; }
.fuss[data-variante='liste'] .fenster, html:not(.js) .fenster { display: block; }
.fuss[data-variante='liste'] .tafel, html:not(.js) .tafel { visibility: visible; transition: none; }
.fuss[data-variante='liste'] .tafel + .tafel, html:not(.js) .tafel + .tafel { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--linie); }
.fuss[data-variante='liste'] .etikett, html:not(.js) .etikett { display: block; color: var(--leise); font-size: 14px; margin-bottom: 2px; }
.fuss[data-variante='liste'] .mail, html:not(.js) .mail { --y: 0%; font-size: clamp(1.0625rem, .95rem + .5vw, 1.25rem); }
.fuss[data-variante='liste'] .hinweis, .fuss[data-variante='liste'] .kopieren, html:not(.js) .hinweis { opacity: 1; }
.fuss[data-variante='liste'] .hinweis { margin-top: 6px; font-size: 14px; }
/* Gedachter Zeiger in der Vorführung */
.zeiger { position: fixed; left: 0; top: 0; z-index: 6; width: 18px; height: 18px; pointer-events: none; display: none; transition: transform .7s var(--kurve); }
.zeiger path { fill: var(--text); stroke: var(--grund); }
.vorfuehrung .zeiger { display: block; }
.zeiger.klick { scale: .82; transition: transform .7s var(--kurve), scale 80ms var(--kurve); }
/* =========================================================================
Varianten (Regel 13): ?v=basis | praxis | buehne
========================================================================= */
html[data-v="praxis"] [data-welt]:not([data-welt="praxis"]), html:not([data-v="praxis"]) [data-welt="praxis"], html[data-v="buehne"] [data-welt]:not([data-welt="buehne"]), html:not([data-v="buehne"]) [data-welt="buehne"], html[data-v="gastgeber"] [data-welt]:not([data-welt="gastgeber"]), html:not([data-v="gastgeber"]) [data-welt="gastgeber"] { display: none !important; }
html:not([data-v="basis"]) .pult { padding-top: 16px; }
.pult .gruppe { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px 18px; }
html:not([data-v="basis"]) .pult [data-teil="basis"] { display: none; }
html:not([data-v="gastgeber"]) .pult [data-teil="gastgeber"] { display: none; }
html[data-v="praxis"] { --grund: #f5f7f7; --text: #363b3b; --leise: #596666; --linie: #dfe3e2; --flaeche: #e2e0de; --akzent: #005450; color-scheme: light; }
html[data-v="buehne"] { --grund: #0b0b0b; --text: #f2f2f2; --leise: #8a8a8a; --linie: #262626; --flaeche: #1a1a1a; --akzent: #ff5a1f; color-scheme: dark; }
/* ---------- Praxis: Sprechzeiten mit Live-Status, Anfahrt nach Verkehrsmittel (Rezept praxis-gesundheit-ruhig) ---------- */
.px { --k: cubic-bezier(0.2, 0, 0.38, 0.9); --petrol: #005450; --petrol-tief: #00403d; --creme: #f5f7f7; --apricot: #ffc776;
font-family: 'Google Sans Flex', system-ui, sans-serif; color: var(--text); }
.px :focus-visible { outline: 2px solid var(--apricot); outline-offset: 3px; }
.px-termin { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 18px 32px; padding: clamp(28px, 4vw, 48px) 0 clamp(32px, 4vw, 52px); }
.px-termin h2 { font: 400 clamp(1.75rem, 1.3rem + 1.6vw, 2.75rem)/1.12 'Hedvig Letters Serif', Georgia, serif; font-variation-settings: 'opsz' 24; letter-spacing: -.01em; max-width: 22ch; text-wrap: balance; }
.px-termin p { margin-top: 10px; font-size: 1.0625rem; line-height: 1.6; color: var(--leise); max-width: 52ch; }
.px-knoepfe { display: flex; flex-wrap: wrap; gap: 10px; }
.px-knopf { display: inline-flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 22px; border-radius: 999px; font-weight: 500; font-size: 1rem; text-decoration: none; transition: background-color 200ms var(--k), color 200ms var(--k); }
.px-knopf.voll { background: var(--petrol); color: #fff; }
.px-knopf.voll:hover { background: var(--petrol-tief); }
.px-knopf.rand { border: 1.5px solid var(--petrol); color: var(--petrol); }
.px-knopf.rand:hover { background: #e3eceb; }
.px-fuss { background: var(--petrol); color: var(--creme); padding: clamp(40px, 5vw, 64px) 0 26px; }
.px-raster { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .9fr) minmax(0, 1.1fr); gap: 40px clamp(28px, 4vw, 64px); }
.px h3 { font: 400 1.375rem/1.2 'Hedvig Letters Serif', Georgia, serif; font-variation-settings: 'opsz' 24; margin-bottom: 14px; }
.px-status { display: inline-flex; align-items: center; gap: 9px; min-height: 34px; padding: 0 14px 0 12px; margin-bottom: 16px; border-radius: 999px; background: rgba(245, 247, 247, .1); font-weight: 500; font-size: .9375rem; }
.px-status i { width: 9px; height: 9px; border-radius: 50%; background: #9fb3b0; flex: none; }
.px-status.offen i { background: #7fe0a6; box-shadow: 0 0 0 4px rgba(127, 224, 166, .18); }
.px-status.bald i { background: var(--apricot); box-shadow: 0 0 0 4px rgba(255, 199, 118, .2); }
.px-status .px-roll { display: inline-grid; overflow: clip; }
.px-status .px-roll > span { grid-area: 1 / 1; }
.px-zeiten { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; font-size: 1rem; }
.px-zeiten th { text-align: left; font-weight: 400; color: rgba(245, 247, 247, .72); padding: 7px 0; width: 7.5em; }
.px-zeiten td { padding: 7px 0; }
.px-zeiten tr { border-top: 1px solid rgba(245, 247, 247, .16); }
.px-zeiten tr.heute th, .px-zeiten tr.heute td { color: #fff; font-weight: 600; }
.px-zeiten tr.heute th::after { content: ' · heute'; font-weight: 400; color: var(--apricot); }
.px-sonder { margin-top: 16px; padding: 12px 14px; border-radius: 12px; background: rgba(255, 199, 118, .14); border-left: 3px solid var(--apricot); font-size: .9375rem; line-height: 1.5; }
.px-tel { display: block; font: 400 clamp(1.625rem, 1.2rem + 1.4vw, 2.125rem)/1.15 'Hedvig Letters Serif', Georgia, serif; color: #fff; text-decoration: none; font-variant-numeric: tabular-nums; }
.px-tel:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .18em; }
.px-klein { margin-top: 6px; font-size: .9375rem; line-height: 1.55; color: rgba(245, 247, 247, .78); }
.px-wege { margin-top: 18px; display: grid; gap: 8px; }
.px-wege a { display: flex; justify-content: space-between; gap: 12px; padding: 12px 0; border-top: 1px solid rgba(245, 247, 247, .16); color: #fff; text-decoration: none; font-size: 1rem; }
.px-wege a span { color: rgba(245, 247, 247, .7); font-size: .875rem; }
.px-wege a:hover { color: var(--apricot); }
.px-notfall { margin-top: 18px; font-size: .9375rem; line-height: 1.55; color: rgba(245, 247, 247, .85); }
.px-notfall b { color: #fff; font-weight: 600; }
address.px-adresse { font-style: normal; font-size: 1.0625rem; line-height: 1.55; color: #fff; margin-bottom: 16px; }
.px-reiter { display: flex; gap: 4px; padding: 4px; border-radius: 999px; background: rgba(245, 247, 247, .1); margin-bottom: 14px; }
.px-reiter [role="tab"] { flex: 1; min-height: 38px; padding: 0 10px; border-radius: 999px; color: rgba(245, 247, 247, .8); font-size: .9375rem; font-weight: 500; transition: background-color 200ms var(--k), color 200ms var(--k); }
.px-reiter [role="tab"]:hover { color: #fff; }
.px-reiter [role="tab"][aria-selected="true"] { background: var(--creme); color: var(--petrol); }
.px-fenster { position: relative; overflow: hidden; transition: height 250ms var(--k); }
.px-tafel { font-size: 1rem; line-height: 1.6; color: rgba(245, 247, 247, .9); }
.px-tafel[hidden] { display: none; }
.px-tafel ul { list-style: none; padding: 0; display: grid; gap: 8px; }
.px-tafel li { display: grid; grid-template-columns: 22px 1fr; gap: 10px; }
.px-tafel li svg { width: 20px; height: 20px; margin-top: 3px; }
.px-tafel.ein { animation: px-ein 400ms var(--k) both; }
@keyframes px-ein { from { opacity: 0; transform: translateY(8px); } }
.px-karte { display: inline-block; margin-top: 14px; color: #fff; font-size: .9375rem; text-underline-offset: 3px; }
.px-unten { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px 28px; margin-top: clamp(40px, 5vw, 56px); padding-top: 18px; border-top: 1px solid rgba(245, 247, 247, .16); font-size: .875rem; color: rgba(245, 247, 247, .72); }
.px-unten a { color: inherit; text-decoration: none; }
.px-unten a:hover { color: #fff; }
@media (max-width: 980px) { .px-raster { grid-template-columns: 1fr 1fr; } .px-raster > :first-child { grid-column: 1 / -1; } }
@media (max-width: 640px) { .px-raster { grid-template-columns: 1fr; } .px-knoepfe { width: 100%; } .px-knopf { flex: 1; justify-content: center; } }
/* ---------- Studio-Bühne: Anliegen als Liste, zwei Studios mit Ortszeit, Riesen-Wortmarke (Rezept kreativstudio-buehne) ---------- */
.bu { --k: cubic-bezier(0.16, 1, 0.3, 1); --signal: #ff5a1f; font-family: 'TikTok Sans', system-ui, sans-serif; font-stretch: 100%; color: var(--text); overflow: clip; }
.bu :focus-visible { outline: 2px solid var(--signal); outline-offset: 4px; }
.bu-mono { font: 400 .75rem/1.4 'DM Mono', ui-monospace, monospace; letter-spacing: .04em; text-transform: uppercase; color: var(--leise); }
.bu-cta { padding: clamp(36px, 6vw, 88px) 0 clamp(40px, 6vw, 80px); border-bottom: 1px solid var(--linie); }
.bu-cta h2 { margin: 16px 0 22px; font: 600 clamp(2rem, 4.5vw, 4.5rem)/.98 'TikTok Sans', sans-serif; letter-spacing: -.02em; max-width: 16ch; text-wrap: balance; }
.bu-mail { display: inline-block; font: 800 clamp(1.75rem, 5.2vw, 5.25rem)/1 'TikTok Sans', sans-serif; font-stretch: 75%; letter-spacing: -.03em; color: var(--text); text-decoration: none; }
.bu-mail .z { display: inline-block; height: 1.06em; overflow: clip; vertical-align: top; }
.bu-mail .z > span, .bu-mail .z > span::after { line-height: 1.06; }
.bu-mail .z > span { display: block; transition: transform 400ms var(--k); transition-delay: calc(var(--i) * 12ms); }
.bu-mail .z > span::after { content: attr(data-z); display: block; color: var(--signal); }
.bu-mail:is(:hover, :focus-visible, .rollt) .z > span { transform: translateY(-50%); }
.bu-mitte { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, .7fr); gap: 36px clamp(28px, 4vw, 64px); padding: clamp(32px, 4vw, 56px) 0; }
.bu-anliegen { list-style: none; padding: 0; margin-top: 14px; }
.bu-anliegen li + li { border-top: 1px solid var(--linie); }
.bu-anliegen a { display: grid; grid-template-columns: 1fr auto; gap: 2px 16px; padding: 14px 0; color: var(--text); text-decoration: none; }
.bu-anliegen b { font-weight: 600; font-size: 1.125rem; letter-spacing: -.01em; }
.bu-anliegen span { grid-column: 1; color: var(--leise); font-size: .9375rem; transition: color 300ms var(--k); }
.bu-anliegen i { grid-row: 1 / span 2; grid-column: 2; align-self: center; font-style: normal; font-size: 1.25rem; transition: transform 300ms var(--k), color 300ms var(--k); }
.bu-anliegen a:is(:hover, .hv) span, .bu-anliegen a:is(:hover, .hv) i { color: var(--signal); }
.bu-anliegen a:is(:hover, .hv) i { transform: translate(4px, -4px); }
.bu-studio + .bu-studio { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--linie); }
.bu-studio p { font-size: 1rem; line-height: 1.5; }
.bu-studio .bu-zeit { display: flex; align-items: baseline; gap: 10px; margin: 12px 0 4px; }
.bu-studio time { font: 800 2.75rem/1 'TikTok Sans', sans-serif; font-stretch: 75%; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.bu-studio .bu-sek { color: var(--signal); }
.bu-studio .bu-sek.aus { opacity: .25; }
:root.reduziert .bu-studio .bu-sek.aus { opacity: 1; }
.bu-sozial { list-style: none; padding: 0; margin-top: 14px; display: grid; gap: 8px; }
.bu-sozial a { color: var(--text); text-decoration: none; font-size: 1.0625rem; }
.bu-sozial a:hover { color: var(--signal); }
.bu-marke { position: relative; width: max-content; margin-top: clamp(8px, 2vw, 24px); line-height: .8; font: 800 20vw/.8 'TikTok Sans', sans-serif; font-stretch: 75%; letter-spacing: -.03em; white-space: nowrap; user-select: none; }
.bu-marke span { display: inline-block; transform: translateY(var(--y, 0%)); transition: transform 1100ms var(--k); transition-delay: calc(var(--i) * 70ms); }
.bu-marke.warten span { --y: 105%; }
.bu-marke-maske { overflow: clip; padding-top: .04em; }
.bu-unten { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px 28px; padding: 16px 0 24px; border-top: 1px solid var(--linie); }
.bu-unten a { color: inherit; text-decoration: none; }
.bu-unten a:hover { color: var(--signal); }
@media (max-width: 980px) { .bu-mitte { grid-template-columns: 1fr 1fr; } .bu-mitte > :first-child { grid-column: 1 / -1; } }
@media (max-width: 640px) { .bu-mitte { grid-template-columns: 1fr; } .bu-studio time { font-size: 2.25rem; } }
:root.reduziert .bu-marke span { transition: opacity 200ms linear !important; }
:root.reduziert .bu-marke.warten span { --y: 0%; opacity: 0; }
.vorschau .px-termin, .vorschau .px-unten, .vorschau .bu-cta h2, .vorschau .bu-unten, .vorschau .bu-sozial, .vorschau .bu-mitte > :last-child { display: none; }
.vorschau .px-fuss { padding-top: 40px; min-height: 100vh; }
.vorschau .bu-cta { padding: 34px 0 30px; }
.vorschau .bu-mitte { grid-template-columns: 1.3fr 1fr; padding: 28px 0; }
.vorschau .bu-mitte > :first-child { grid-column: auto; }
/* ---------- Gastgeber: Hotel, Gasthof, Eventlocation (Rezept boutique-hotel-gastgeber) ----------
Adresse mit Anreise in einem Satz, Telefon und E-Mail groß, An- und Abreisezeiten, Social-Links, Saisonbrief optional.
UI-Tempo token-toggle-asymmetrisch: auf 300 ms cubic-bezier(0.16, 1, 0.3, 1), zu 200 ms cubic-bezier(0.7, 0, 0.84, 0). */
html[data-v="gastgeber"] { --grund: #f3eee7; --text: #3e3a37; --leise: #646661; --linie: #d5d1c8; --flaeche: #e9e2d7; --akzent: #6e5a47; color-scheme: light; }
.gg { --auf: cubic-bezier(0.16, 1, 0.3, 1); --zu: cubic-bezier(0.7, 0, 0.84, 0); --t-auf: 300ms; --t-zu: 200ms; --t-ui: 150ms;
--creme: #fef2e3; --dunkel: #3e3a37; --creme-leise: rgba(254, 242, 227, .74); --creme-linie: rgba(254, 242, 227, .18); --haus: #6e5a47;
font: 400 1.0625rem/1.6 'Mona Sans', system-ui, sans-serif; font-stretch: 100%; color: var(--text); }
.gg :focus-visible { outline: 2px solid var(--creme); outline-offset: 3px; }
.gg-label { font: 500 .75rem/1.3 'Mona Sans', sans-serif; font-stretch: 118%; letter-spacing: .06em; text-transform: uppercase; color: var(--creme-leise); margin-bottom: 12px; }
.gg-serif { font-family: 'Newsreader', Georgia, serif; font-weight: 300; font-variation-settings: 'opsz' 36; letter-spacing: -.01em; }
.gg-vor { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: end; gap: 16px 40px; padding: clamp(28px, 4vw, 48px) 0 clamp(24px, 3vw, 36px); }
.gg-vor h2 { font: 300 clamp(2rem, 1.4rem + 2.4vw, 3.5rem)/1.05 'Newsreader', Georgia, serif; font-variation-settings: 'opsz' 72; letter-spacing: -.015em; max-width: 16ch; }
.gg-vor h2 em { font-size: 1em; font-weight: 300; }
.gg-vor p { color: var(--leise); max-width: 40ch; }
.gg-bild { display: block; width: 100%; height: clamp(200px, 26vw, 340px); object-fit: cover; object-position: 50% 62%; }
.gg-fuss { background: var(--dunkel); color: var(--creme); padding: clamp(40px, 5vw, 64px) 0 24px; }
.gg-raster { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.25fr) minmax(0, .95fr); gap: 40px clamp(28px, 4vw, 64px); }
.gg address { font-style: normal; font-size: 1.375rem; line-height: 1.35; color: var(--creme); }
.gg-anreise { margin-top: 14px; color: var(--creme-leise); max-width: 34ch; }
.gg-wege { display: flex; flex-wrap: wrap; gap: 4px 20px; margin-top: 12px; padding: 0; list-style: none; }
.gg-wege a, .gg-sozial a, .gg-unten a { display: inline-flex; align-items: center; min-height: 44px; color: var(--creme); text-decoration: underline; text-decoration-color: var(--creme-linie); text-underline-offset: .22em; transition: text-decoration-color var(--t-ui) var(--auf); }
.gg-wege a:hover, .gg-sozial a:hover, .gg-unten a:hover { text-decoration-color: currentColor; }
.gg-tel, .gg-mail { display: block; color: var(--creme); text-decoration: none; font-family: 'Newsreader', Georgia, serif; font-weight: 300; font-variation-settings: 'opsz' 48; font-variant-numeric: tabular-nums; }
.gg-tel { font-size: clamp(2rem, 1.5rem + 1.6vw, 2.75rem); line-height: 1.1; }
.gg-mailzeile { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-top: 8px; }
.gg-mail { font-size: clamp(1.375rem, 1.15rem + .7vw, 1.75rem); line-height: 1.2; overflow-wrap: anywhere; }
.gg-tel:hover, .gg-mail:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .16em; }
.gg-kopieren { display: inline-flex; align-items: center; gap: 8px; min-height: 36px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--creme-linie); font-size: .8125rem; font-stretch: 112%; letter-spacing: .04em; text-transform: uppercase; color: var(--creme); transition: background-color var(--t-ui) var(--auf), border-color var(--t-ui) var(--auf); }
.gg-kopieren:hover { background: rgba(254, 242, 227, .08); border-color: var(--creme-leise); }
.gg-kopieren .gg-roll { display: inline-grid; overflow: clip; height: 1.3em; line-height: 1.3; }
.gg-kopieren .gg-roll span { grid-area: 1 / 1; transition: transform var(--t-zu) var(--zu); }
.gg-kopieren .gg-roll span + span { transform: translateY(105%); }
.gg-kopieren.fertig .gg-roll span:first-child { transform: translateY(-105%); }
.gg-kopieren.fertig .gg-roll span + span { transform: none; transition: transform var(--t-auf) var(--auf); }
.gg-status { display: inline-flex; align-items: center; gap: 9px; margin-top: 18px; min-height: 34px; padding: 0 14px 0 12px; border-radius: 999px; background: rgba(254, 242, 227, .09); font-size: .9375rem; }
.gg-status i { width: 8px; height: 8px; border-radius: 50%; background: #b9ad9c; flex: none; }
.gg-status.offen i { background: #9fd7a6; box-shadow: 0 0 0 4px rgba(159, 215, 166, .16); }
.gg-status .gg-st { display: inline-grid; overflow: clip; }
.gg-status .gg-st > span { grid-area: 1 / 1; }
.gg-st > span.raus { animation: gg-raus var(--t-zu) var(--zu) both; }
.gg-st > span.rein { animation: gg-rein var(--t-auf) var(--auf) both; }
@keyframes gg-raus { to { transform: translateY(-100%); opacity: 0; } }
@keyframes gg-rein { from { transform: translateY(100%); opacity: 0; } }
.gg-zeiten { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px 18px; margin: 0; }
.gg-zeiten dt { color: var(--creme-leise); }
.gg-zeiten dd { margin: 0; font-variant-numeric: tabular-nums; }
.gg-hinweis { margin-top: 14px; font-size: .9375rem; line-height: 1.5; color: var(--creme-leise); }
.gg-zweit { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 32px clamp(28px, 4vw, 64px); margin-top: clamp(40px, 5vw, 56px); padding-top: 28px; border-top: 1px solid var(--creme-linie); }
.gg-ohne-brief .gg-zweit { grid-template-columns: minmax(0, 1fr); }
.gg-brief h3, .gg-sozial h3 { font: 300 1.5rem/1.2 'Newsreader', Georgia, serif; font-variation-settings: 'opsz' 36; }
.gg-brief p { margin-top: 6px; color: var(--creme-leise); max-width: 46ch; }
.gg-form { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.gg-form label { flex-basis: 100%; font-size: .875rem; color: var(--creme-leise); }
.gg-form input { flex: 1 1 220px; min-width: 0; min-height: 48px; padding: 0 16px; border-radius: 999px; border: 1px solid rgba(254, 242, 227, .5); background: transparent; color: var(--creme); font: inherit; }
.gg-form input::placeholder { color: rgba(254, 242, 227, .6); }
.gg-form input[aria-invalid="true"] { border-color: #f2b8a0; }
.gg-form button { min-height: 48px; padding: 0 22px; border-radius: 999px; background: var(--creme); color: var(--dunkel); font-weight: 500; font-stretch: 112%; transition: background-color var(--t-ui) var(--auf); }
.gg-form button:hover { background: #fff; }
.gg-fehler { flex-basis: 100%; color: #f6c8b4; font-size: .9375rem; }
.gg-fehler:empty { display: none; }
.gg-danke { margin-top: 14px; padding: 14px 16px; border-left: 2px solid var(--creme); background: rgba(254, 242, 227, .07); }
.gg-danke.ein { animation: gg-ein var(--t-auf) var(--auf) both; }
@keyframes gg-ein { from { opacity: 0; transform: translateY(8px); } }
.gg-klein { margin-top: 10px; font-size: .8125rem; color: var(--creme-leise); }
.gg-sozial ul { display: flex; flex-wrap: wrap; gap: 0 22px; margin-top: 8px; padding: 0; list-style: none; }
.gg-ohne-brief .gg-brief { display: none; }
.gg-unten { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 4px 28px; margin-top: clamp(32px, 4vw, 48px); padding-top: 12px; border-top: 1px solid var(--creme-linie); font-size: .875rem; color: var(--creme-leise); }
.gg-unten ul { display: flex; flex-wrap: wrap; gap: 0 18px; padding: 0; list-style: none; }
.gg-unten a { color: var(--creme-leise); }
.gg :is(a, button):focus-visible { outline-color: var(--creme); }
.gg-vor :focus-visible { outline-color: var(--haus); }
@media (max-width: 980px) { .gg-raster { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } .gg-raster > :nth-child(2) { grid-column: 1 / -1; order: -1; } .gg-zweit { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 640px) { .gg-raster { grid-template-columns: minmax(0, 1fr); } .gg-form button { flex: 1 1 100%; } }
:root.reduziert .gg-st > span { animation: none !important; }
:root.reduziert .gg-danke.ein { animation: none; }
.vorschau .gg-vor, .vorschau .gg-zweit, .vorschau .gg-unten { display: none; }
.vorschau .gg-bild { height: 170px; }
.vorschau .gg-fuss { min-height: calc(100vh - 170px); padding-top: 44px; }
@media (forced-colors: active) { .gg-form input, .gg-kopieren, .gg-form button { border: 1px solid ButtonText; } }
/* ---------- Reduzierte Bewegung: kein Roll, sofortiger Wechsel ---------- */
:root.reduziert * { transition-duration: .01ms !important; animation-duration: .01ms !important; transition-delay: 0s !important; }
:root.reduziert .mail { transition: none; }
/* ---------- Schmal ---------- */
@media (max-width: 980px) {
.raster { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.kontakt { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
.kopf nav a:not(:last-child) { display: none; }
.jetzt { padding: 40px 0 32px; }
.pult .werte { margin-left: 0; flex-basis: 100%; }
.raster { grid-template-columns: minmax(0, 1fr); gap: 40px; }
.reiter { gap: 18px; }
.unterkante { flex-direction: column; align-items: flex-start; }
}
/* Zugang: 320 px ohne Querscrollen, Adresse bleibt ganz sichtbar */
@media (max-width: 360px) { .zeile { flex-wrap: wrap; row-gap: 8px; } .mail { overflow-wrap: anywhere; } .anderswo li { flex-wrap: wrap; } }
@media (forced-colors: active) { button, [role=button], [role=tab], [role=switch] { border: 1px solid ButtonText !important; } }
/* ---------- Touch: keine Hover-Zustände nötig, größere Ziele ---------- */
@media (hover: none) {
.reiter [role='tab'] { min-height: 44px; padding-top: 10px; }
.kopieren { height: 40px; padding: 0 16px; }
.tel a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 16px; margin-left: -1px; border: 1px solid var(--linie); border-radius: 999px; }
.tel span { margin-top: 6px; }
.thema button { height: 36px; }
.anderswo li { padding: 11px 0; }
.px-reiter [role="tab"] { min-height: 44px; }
.px-wege a { min-height: 44px; align-items: center; }
}
/* ---------- Vorschau 960 × 720: nur der Footer, größer gesetzt ---------- */
.vorschau body { overflow: hidden; height: 100vh; }
.vorschau .kopf, .vorschau .jetzt, .vorschau .pult, .vorschau .anderswo, .vorschau .thema, .vorschau .verweis { display: none; }
.vorschau .fuss { border-top: 0; display: grid; align-content: center; padding: 0; }
.vorschau .seite { padding: 0 60px; }
.vorschau .raster { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); gap: 56px; }
.vorschau .kontakt { grid-column: auto; }
.vorschau .satz { font-size: 32px; max-width: 21ch; }
.vorschau .reiter [role='tab'] { font-size: 18px; }
.vorschau .mail { font-size: 30px; }
.vorschau .kopieren .kr { display: none; }
.vorschau .kopieren { width: 36px; height: 36px; padding: 0; justify-content: center; }
.vorschau .kopieren svg { width: 15px; height: 15px; }
.vorschau .orte { padding-top: 10px; }
.vorschau .hinweis { font-size: 17px; }
.vorschau .ortname, .vorschau address, .vorschau .uhr { font-size: 18px; }
.vorschau .unterkante { margin-top: 64px; font-size: 15px; }
</style>
</head>
<body>
<div class="seite">
<header class="kopf" data-welt="basis">
<a class="name" href="#jetzt">Ida Brenneke</a>
<nav aria-label="Hauptmenü"><a href="#arbeiten">Arbeiten</a><a href="#notizen">Notizen</a><a href="#jetzt">Jetzt</a><a href="#kontakt">Kontakt</a></nav>
</header>
<section class="jetzt" id="jetzt" aria-labelledby="jetzt-titel" data-welt="basis">
<h2 id="jetzt-titel">Jetzt</h2>
<p>Bis Januar gestalte ich für einen Verbund von Stadtteilbüchereien die Ausleihe neu, vom Rückgabeautomaten bis zur App. Daneben schreibe ich an einer kleinen Sammlung <em>ruhiger</em> Fehlermeldungen für Formulare.</p>
<p class="leise">Ab Februar 2027 habe ich wieder Platz für ein Projekt. Stand: 28. Oktober.</p>
</section>
<div class="pult mono">
<span class="gruppe" role="group" aria-label="Variante der Demo">
<span>Variante</span>
<button type="button" data-welt-wahl="basis" aria-pressed="true">Visitenkarte</button>
<button type="button" data-welt-wahl="praxis" aria-pressed="false">Praxis</button>
<button type="button" data-welt-wahl="buehne" aria-pressed="false">Studio-Bühne</button>
<button type="button" data-welt-wahl="gastgeber" aria-pressed="false">Gastgeber</button>
</span>
<span class="gruppe" role="group" aria-label="Saisonbrief" data-teil="gastgeber">
<span>Saisonbrief</span>
<button type="button" data-gg-brief-wahl="mit" aria-pressed="true">mit</button>
<button type="button" data-gg-brief-wahl="ohne" aria-pressed="false">ohne</button>
</span>
<span class="gruppe" role="group" aria-label="Kontakt-Darstellung" data-umschalter data-teil="basis">
<span>Kontakt</span>
<button type="button" data-variante="tabs" aria-pressed="true">Tabs</button>
<button type="button" data-variante="orte" aria-pressed="false">Zwei Orte</button>
<button type="button" data-variante="liste" aria-pressed="false">Liste</button>
</span>
<span class="werte" data-werte></span>
</div>
</div>
<footer class="fuss" id="kontakt" data-fuss data-variante="tabs" data-welt="basis">
<div class="seite">
<div class="raster">
<section class="kontakt" aria-labelledby="kontakt-titel">
<p class="satz">Ich arbeite allein und antworte selbst. Schreib mir, worum es geht, gern auch <em>unfertig</em>.</p>
<h2 id="kontakt-titel">Kontakt</h2>
<div class="reiter" role="tablist" aria-label="Anliegen" data-reiter>
<button type="button" role="tab" id="r-projekt" aria-controls="p-projekt" aria-selected="true">Neues Projekt</button>
<button type="button" role="tab" id="r-allgemein" aria-controls="p-allgemein" aria-selected="false" tabindex="-1">Allgemeines</button>
<button type="button" role="tab" id="r-vortrag" aria-controls="p-vortrag" aria-selected="false" tabindex="-1">Vorträge</button>
<span class="strich" data-strich aria-hidden="true"></span>
</div>
<div class="fenster">
<div class="tafel an" role="tabpanel" id="p-projekt" aria-labelledby="r-projekt">
<p class="etikett">Neues Projekt</p>
<div class="zeile">
<span class="rolle"><a class="mail" href="mailto:projekte@idabrenneke.de">projekte@idabrenneke.de</a></span>
<button type="button" class="kopieren" data-kopieren="projekte@idabrenneke.de" aria-label="Adresse projekte@idabrenneke.de kopieren"><svg class="blatt" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.2" aria-hidden="true"><rect x="4.5" y="4.5" width="7.5" height="7.5" rx="1.5"/><path d="M9.5 2.5V2a.5.5 0 0 0-.5-.5H3A1.5 1.5 0 0 0 1.5 3v6a.5.5 0 0 0 .5.5h.5"/></svg><svg class="haken" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><path d="m2.5 7.5 3 3 6-7"/></svg><span class="kr" aria-hidden="true"><span>Kopieren</span><span>Kopiert</span></span></button>
</div>
<p class="hinweis">Zwei Sätze zu Vorhaben, Zeitraum und Budgetrahmen reichen. Antwort innerhalb von zwei Werktagen.</p>
</div>
<div class="tafel" role="tabpanel" id="p-allgemein" aria-labelledby="r-allgemein" inert>
<p class="etikett">Allgemeines</p>
<div class="zeile">
<span class="rolle"><a class="mail" href="mailto:hallo@idabrenneke.de">hallo@idabrenneke.de</a></span>
<button type="button" class="kopieren" data-kopieren="hallo@idabrenneke.de" aria-label="Adresse hallo@idabrenneke.de kopieren"><svg class="blatt" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.2" aria-hidden="true"><rect x="4.5" y="4.5" width="7.5" height="7.5" rx="1.5"/><path d="M9.5 2.5V2a.5.5 0 0 0-.5-.5H3A1.5 1.5 0 0 0 1.5 3v6a.5.5 0 0 0 .5.5h.5"/></svg><svg class="haken" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><path d="m2.5 7.5 3 3 6-7"/></svg><span class="kr" aria-hidden="true"><span>Kopieren</span><span>Kopiert</span></span></button>
</div>
<p class="hinweis">Fragen zu einem Text, einem Paket aus dem Kleinkram oder einfach ein Hallo aus der Nachbarschaft.</p>
</div>
<div class="tafel" role="tabpanel" id="p-vortrag" aria-labelledby="r-vortrag" inert>
<p class="etikett">Vorträge</p>
<div class="zeile">
<span class="rolle"><a class="mail" href="mailto:vortraege@idabrenneke.de">vortraege@idabrenneke.de</a></span>
<button type="button" class="kopieren" data-kopieren="vortraege@idabrenneke.de" aria-label="Adresse vortraege@idabrenneke.de kopieren"><svg class="blatt" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.2" aria-hidden="true"><rect x="4.5" y="4.5" width="7.5" height="7.5" rx="1.5"/><path d="M9.5 2.5V2a.5.5 0 0 0-.5-.5H3A1.5 1.5 0 0 0 1.5 3v6a.5.5 0 0 0 .5.5h.5"/></svg><svg class="haken" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><path d="m2.5 7.5 3 3 6-7"/></svg><span class="kr" aria-hidden="true"><span>Kopieren</span><span>Kopiert</span></span></button>
</div>
<p class="hinweis">Zwei Termine im Halbjahr, am liebsten zu Formularen, Fehlern und leisen Oberflächen. Bitte mit Datum und Publikum.</p>
</div>
</div>
</section>
<section class="orte" aria-labelledby="ort-titel">
<h2 id="ort-titel"><span class="titel-eins">Standort</span><span class="titel-zwei">Standorte</span></h2>
<div class="standort" data-ort="hannover" data-tz="Europe/Berlin" data-saison="4-10">
<p class="ortname">Hannover-Linden <span class="saison">Apr – Okt</span></p>
<address>Kötnerholzweg 41, Hinterhaus<br>30451 Hannover</address>
<p class="uhr"><span class="punkt" aria-hidden="true"></span><time data-uhr>--:--</time><span class="zone" data-zone></span><span class="status" data-status></span></p>
<a class="verweis" href="#karte-hannover">Karte öffnen ↗</a>
</div>
<div class="standort zweit" data-ort="lissabon" data-tz="Europe/Lisbon" data-saison="11-3">
<p class="ortname">Lissabon, Graça <span class="saison">Nov – Mär</span></p>
<address>Calçada do Monte 22, 2.º<br>1170-250 Lissabon</address>
<p class="uhr"><span class="punkt" aria-hidden="true"></span><time data-uhr>--:--</time><span class="zone" data-zone></span><span class="status" data-status></span></p>
<a class="verweis" href="#karte-lissabon">Karte öffnen ↗</a>
</div>
<p class="tel"><a href="tel:+495114870221">+49 511 487 022 1</a><span>Mo bis Do, 10 bis 16 Uhr</span></p>
</section>
<section class="anderswo" aria-labelledby="anderswo-titel">
<h2 id="anderswo-titel">Anderswo</h2>
<ul>
<li><a href="#notizen">Notizen</a><span>Brief, monatlich</span></li>
<li><a href="#kleinkram">Kleinkram</a><span>6 Pakete, quelloffen</span></li>
<li><a href="#lesezeichen">Lesezeichen</a><span>214 Links</span></li>
<li><a href="#fotos">Fotos</a><span>Linden, analog</span></li>
</ul>
</section>
</div>
<div class="unterkante">
<p>© 2026 Ida Brenneke · <a href="#impressum">Impressum</a> · <a href="#datenschutz">Datenschutz</a></p>
<p class="edition">Ausgabe <b>2026</b> · Rev. 41 · gesetzt in Host Grotesk und <em>Newsreader</em>, ohne Tracking</p>
<div class="thema" role="group" aria-label="Darstellung" data-thema>
<button type="button" data-wahl="hell" aria-pressed="true">Hell</button>
<button type="button" data-wahl="dunkel" aria-pressed="false">Dunkel</button>
</div>
</div>
</div>
</footer>
<!-- ===== Variante Praxis: Sprechzeiten mit Live-Status, Telefon zuerst, Anfahrt nach Verkehrsmittel ===== -->
<div class="px" data-welt="praxis">
<div class="seite">
<section class="px-termin" aria-labelledby="px-termin-titel">
<div>
<h2 id="px-termin-titel">Akute Beschwerden? Wir finden heute noch einen Termin.</h2>
<p>Rufen Sie uns an oder buchen Sie online. Neue Patientinnen und Patienten nehmen wir auf, bitte Versichertenkarte mitbringen.</p>
</div>
<div class="px-knoepfe"><a class="px-knopf voll" href="tel:+494213490220">Anrufen</a><a class="px-knopf rand" href="#online-termin">Online-Termin</a></div>
</section>
</div>
<footer class="px-fuss" aria-label="Praxis am Kirchgarten, Kontakt und Sprechzeiten">
<div class="seite">
<div class="px-raster">
<section aria-labelledby="px-zeiten-titel">
<h3 id="px-zeiten-titel">Sprechzeiten</h3>
<p class="px-status" data-px-status aria-live="polite"><i aria-hidden="true"></i><span class="px-roll"><span data-px-status-text>Sprechzeiten werden geladen</span></span></p>
<table class="px-zeiten" data-px-zeiten>
<tbody>
<tr data-tag="1"><th scope="row">Montag</th><td>8 bis 12 und 15 bis 18 Uhr</td></tr>
<tr data-tag="2"><th scope="row">Dienstag</th><td>8 bis 12 und 15 bis 18 Uhr</td></tr>
<tr data-tag="3"><th scope="row">Mittwoch</th><td>8 bis 12 Uhr</td></tr>
<tr data-tag="4"><th scope="row">Donnerstag</th><td>8 bis 12 und 15 bis 19 Uhr</td></tr>
<tr data-tag="5"><th scope="row">Freitag</th><td>8 bis 13 Uhr</td></tr>
</tbody>
</table>
<p class="px-sonder"><b>Praxisurlaub 24. Dezember bis 1. Januar.</b> Vertretung: Praxis Dr. Wessels, Hemmstraße 188, Telefon 0421 349 118.</p>
</section>
<section aria-labelledby="px-tel-titel">
<h3 id="px-tel-titel">Telefon</h3>
<a class="px-tel" href="tel:+494213490220">0421 349 02 20</a>
<p class="px-klein">Erreichbar in den Sprechzeiten. Rückruf am selben Tag, wenn Sie auf Band sprechen.</p>
<div class="px-wege">
<a href="#online-termin">Online-Termin <span>auch für heute</span></a>
<a href="mailto:rezept@praxis-am-kirchgarten.de">Rezept bestellen <span>per Mail, abholbar ab dem nächsten Tag</span></a>
<a href="#formulare">Formulare <span>Anamnese, Datenschutz</span></a>
</div>
<p class="px-notfall">Nachts und am Wochenende: <b>Bereitschaftsdienst 116 117</b>. Im Notfall <b>112</b>.</p>
</section>
<section aria-labelledby="px-weg-titel">
<h3 id="px-weg-titel">Anfahrt</h3>
<address class="px-adresse">Hausarztpraxis Am Kirchgarten<br>Hemmstraße 212, 1. Stock<br>28215 Bremen-Findorff</address>
<div class="px-reiter" role="tablist" aria-label="Anfahrt" data-px-reiter>
<button type="button" role="tab" id="px-r-bahn" aria-controls="px-t-bahn" aria-selected="true">Bus & Bahn</button>
<button type="button" role="tab" id="px-r-auto" aria-controls="px-t-auto" aria-selected="false" tabindex="-1">Auto & Rad</button>
<button type="button" role="tab" id="px-r-frei" aria-controls="px-t-frei" aria-selected="false" tabindex="-1">Barrierefrei</button>
</div>
<div class="px-fenster" data-px-fenster>
<div class="px-tafel" role="tabpanel" id="px-t-bahn" aria-labelledby="px-r-bahn">
<ul><li><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><rect x="4" y="2.5" width="12" height="12" rx="3"/><path d="M4 9h12M7 17.5l1.5-3M13 17.5l-1.5-3"/><circle cx="7.5" cy="12" r=".8" fill="currentColor"/><circle cx="12.5" cy="12" r=".8" fill="currentColor"/></svg><span>Straßenbahn 6 und Bus 26, Haltestelle Hemmstraße, zwei Minuten zu Fuß</span></li><li><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><rect x="4" y="2.5" width="12" height="12" rx="3"/><path d="M4 9h12M7 17.5l1.5-3M13 17.5l-1.5-3"/><circle cx="7.5" cy="12" r=".8" fill="currentColor"/><circle cx="12.5" cy="12" r=".8" fill="currentColor"/></svg><span>Vom Hauptbahnhof zehn Minuten mit der Linie 6</span></li></ul>
</div>
<div class="px-tafel" role="tabpanel" id="px-t-auto" aria-labelledby="px-r-auto" hidden>
<ul><li><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><rect x="3" y="3" width="14" height="14" rx="3"/><path d="M8 14V6h3a2.5 2.5 0 0 1 0 5H8"/></svg><span>Vier Patientenparkplätze im Hof, Einfahrt neben der Apotheke</span></li><li><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><path d="M3 13V9.5L5 5h10l2 4.5V13z"/><path d="M3 13v2.5h2.5V13M14.5 13v2.5H17V13M3 9.5h14"/></svg><span>Ab Autobahnzubringer Findorff etwa fünf Minuten</span></li><li><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><circle cx="5" cy="13.5" r="3"/><circle cx="15" cy="13.5" r="3"/><path d="M5 13.5 8 7h5l2 6.5M8 7 10.5 13.5 13 7M7 5h3"/></svg><span>Fahrradbügel direkt vor dem Eingang</span></li></ul>
</div>
<div class="px-tafel" role="tabpanel" id="px-t-frei" aria-labelledby="px-r-frei" hidden>
<ul><li><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><path d="M5 17.5V3h10v14.5M3 17.5h14"/><circle cx="12" cy="10.5" r=".9" fill="currentColor"/></svg><span>Ebenerdiger Eingang, Tür öffnet automatisch</span></li><li><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><rect x="3.5" y="2.5" width="13" height="15" rx="2"/><path d="M7.5 8.5 10 6l2.5 2.5M7.5 11.5 10 14l2.5-2.5"/></svg><span>Aufzug in den 1. Stock, Behandlungsräume rollstuhlgerecht</span></li><li><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><path d="M6 8a4.5 4.5 0 0 1 9 0c0 3-3 3.5-3 6.5a2.5 2.5 0 0 1-5 0"/><path d="M9 8.5a1.5 1.5 0 0 1 3 0"/></svg><span>Induktive Höranlage am Empfang, Assistenzhunde willkommen</span></li></ul>
</div>
</div>
<a class="px-karte" href="#karte">Karte öffnen (lädt Kartendienst) ↗</a>
</section>
</div>
<div class="px-unten"><span>© 2026 Dr. med. Leonie Haberland und Tarek Aydın, Fachärzte für Allgemeinmedizin</span><span><a href="#impressum">Impressum</a> · <a href="#datenschutz">Datenschutz</a> · <a href="#barrierefreiheit">Barrierefreiheit</a></span></div>
</div>
</footer>
</div>
<!-- ===== Variante Studio-Bühne: Anliegen als Liste, zwei Studios mit Ortszeit, Riesen-Wortmarke ===== -->
<div class="bu" data-welt="buehne">
<footer class="seite" aria-label="Studio Wucht, Kontakt">
<section class="bu-cta" aria-labelledby="bu-titel">
<p class="bu-mono">Neues Projekt · Antwort in 24 Stunden</p>
<h2 id="bu-titel">Eine Marke, die laut sein darf? Erzählt uns davon.</h2>
<a class="bu-mail" href="mailto:hallo@wucht.studio" data-bu-mail aria-label="hallo@wucht.studio">hallo@wucht.studio</a>
</section>
<div class="bu-mitte">
<section aria-labelledby="bu-anliegen-titel">
<h3 class="bu-mono" id="bu-anliegen-titel">Wer antwortet</h3>
<ul class="bu-anliegen">
<li><a href="mailto:projekte@wucht.studio"><b>Neues Projekt</b><span>Merle Oduya, Geschäftsführung · projekte@wucht.studio</span><i aria-hidden="true">↗</i></a></li>
<li><a href="mailto:presse@wucht.studio"><b>Presse und Vorträge</b><span>Jan Reck · presse@wucht.studio</span><i aria-hidden="true">↗</i></a></li>
<li><a href="#jobs"><b>Jobs</b><span>2 offene Stellen: Motion Design, Frontend</span><i aria-hidden="true">↗</i></a></li>
</ul>
</section>
<section aria-labelledby="bu-studios-titel">
<h3 class="bu-mono" id="bu-studios-titel">Studios</h3>
<div class="bu-studio" data-bu-tz="Europe/Berlin">
<p class="bu-zeit"><time data-bu-uhr>--:--</time><span class="bu-mono" data-bu-zone></span></p>
<p>Leipzig · Spinnereistraße 7, Halle 14</p>
</div>
<div class="bu-studio" data-bu-tz="Europe/Helsinki">
<p class="bu-zeit"><time data-bu-uhr>--:--</time><span class="bu-mono" data-bu-zone></span></p>
<p>Helsinki · Kallio, Vaasankatu 12</p>
</div>
</section>
<section aria-labelledby="bu-sozial-titel">
<h3 class="bu-mono" id="bu-sozial-titel">Anderswo</h3>
<ul class="bu-sozial"><li><a href="#instagram">Instagram</a></li><li><a href="#vimeo">Vimeo</a></li><li><a href="#linkedin">LinkedIn</a></li><li><a href="#labor">Labor ↗</a></li></ul>
</section>
</div>
<div class="bu-marke-maske" aria-hidden="true"><p class="bu-marke warten" data-bu-marke>WUCHT</p></div>
<div class="bu-unten bu-mono"><span>© 2026 Studio Wucht GmbH</span><span><a href="#impressum">Impressum</a> · <a href="#datenschutz">Datenschutz</a></span><a href="#oben">Nach oben ↑</a></div>
</footer>
</div>
<!-- ===== Variante Gastgeber: Hotel, Gasthof, Eventlocation (Anreise, Kontakt groß, An- und Abreise, Saisonbrief optional) ===== -->
<div class="gg" data-welt="gastgeber" data-gg>
<div class="seite">
<section class="gg-vor" aria-labelledby="gg-vor-titel">
<h2 id="gg-vor-titel">Bis bald am <em>Plauer See</em>.</h2>
<p>Fragen zu Zimmern, Hunden oder Ihrer Feier beantworten wir gern am Telefon. Buchen geht auch online.</p>
</section>
</div>
<picture>
<source media="(max-width: 640px)" srcset="bilder/hotel-haus-am-see-hoch.webp" width="900" height="1200">
<img class="gg-bild" src="bilder/hotel-haus-am-see.webp" alt="Das Hotel am Abend: Backsteinhaus mit erleuchteten Fenstern am Ufer, davor der Steg, alles spiegelt sich im See" width="1920" height="1200" loading="lazy">
</picture>
<footer class="gg-fuss" aria-label="Hotel Rohrdommel, Kontakt und Anreise">
<div class="seite">
<div class="gg-raster">
<section aria-labelledby="gg-anreise-titel">
<h3 class="gg-label" id="gg-anreise-titel">Anreise</h3>
<address>Hotel Rohrdommel<br>Seestraße 31<br>19395 Plau am See</address>
<p class="gg-anreise">Mit der Bahn bis Karow, dort holen wir Sie ab; mit dem Auto über die A 19, Abfahrt Malchow, Parkplätze direkt am Haus.</p>
<ul class="gg-wege"><li><a href="#route">Route planen ↗</a></li><li><a href="#bahn">Bahnverbindung ↗</a></li></ul>
</section>
<section aria-labelledby="gg-kontakt-titel">
<h3 class="gg-label" id="gg-kontakt-titel">Kontakt</h3>
<a class="gg-tel" href="tel:+493873560410">038735 604 10</a>
<p class="gg-mailzeile"><a class="gg-mail" href="mailto:willkommen@hotel-rohrdommel.de">willkommen@hotel-rohrdommel.de</a>
<button type="button" class="gg-kopieren" data-gg-kopieren data-text="willkommen@hotel-rohrdommel.de"><span class="gg-roll"><span>Kopieren</span><span aria-hidden="true">Kopiert</span></span></button></p>
<p class="gg-status" data-gg-status aria-live="polite"><i aria-hidden="true"></i><span class="gg-st"><span data-gg-st>Rezeption täglich 7 bis 21 Uhr</span></span></p>
</section>
<section aria-labelledby="gg-zeiten-titel">
<h3 class="gg-label" id="gg-zeiten-titel">Ankommen und Abreisen</h3>
<dl class="gg-zeiten">
<dt>Check-in</dt><dd>ab 15 Uhr</dd>
<dt>Check-out</dt><dd>bis 11 Uhr</dd>
<dt>Rezeption</dt><dd>7 bis 21 Uhr</dd>
<dt>Frühstück</dt><dd>7.30 bis 10.30 Uhr</dd>
</dl>
<p class="gg-hinweis">Später da? Ihr Schlüssel liegt im Schlüsselkasten am Eingang, den Code schicken wir am Anreisetag per SMS.</p>
</section>
</div>
<div class="gg-zweit">
<section class="gg-brief" aria-labelledby="gg-brief-titel" data-gg-brief>
<h3 id="gg-brief-titel">Der Seebrief, zweimal im Jahr</h3>
<p>Saisonstart, Konzerte auf dem Steg und Zimmer in der Nebensaison. Kein Werbe-Takt, Abmelden jederzeit.</p>
<form class="gg-form" data-gg-form novalidate>
<label for="gg-mail-feld">E-Mail-Adresse</label>
<input id="gg-mail-feld" name="email" type="email" autocomplete="email" placeholder="name@beispiel.de" aria-describedby="gg-fehler gg-klein" required>
<button type="submit">Eintragen</button>
<p class="gg-fehler" id="gg-fehler" data-gg-fehler></p>
</form>
<p class="gg-klein" id="gg-klein">Sie bekommen erst eine Mail zum Bestätigen. Hinweise im <a href="#datenschutz" style="color: inherit">Datenschutz</a>.</p>
</section>
<section class="gg-sozial" aria-labelledby="gg-sozial-titel">
<h3 id="gg-sozial-titel">Vom See</h3>
<ul><li><a href="#instagram">Instagram</a></li><li><a href="#facebook">Facebook</a></li><li><a href="#touren">Radtouren ums Haus</a></li></ul>
</section>
</div>
<div class="gg-unten">
<span>© 2026 Hotel Rohrdommel · Familie Tiedemann</span>
<ul><li><a href="#impressum">Impressum</a></li><li><a href="#datenschutz">Datenschutz</a></li><li><a href="#agb">AGB und Storno</a></li><li><a href="#barrierefreiheit">Barrierefreiheit</a></li></ul>
</div>
</div>
</footer>
</div>
<p class="nur-sr" aria-live="polite" data-ansage style="position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap"></p>
<svg class="zeiger" data-zeiger viewBox="0 0 18 18" aria-hidden="true"><path d="M2 1.5 15.5 9.2l-6 1.3-2.9 5.6Z" stroke-width="1.2" stroke-linejoin="round"/></svg>
<script>
(() => {
const html = document.documentElement;
const reduziert = () => html.classList.contains('reduziert');
const $ = (s, el = document) => el.querySelector(s);
const $$ = (s, el = document) => [...el.querySelectorAll(s)];
const fuss = $('[data-fuss]');
const reiter = $$('[role="tab"]');
const tafeln = $$('[role="tabpanel"]');
const strich = $('[data-strich]');
const werteEl = $('[data-werte]');
const ansage = $('[data-ansage]');
const zeiger = $('[data-zeiger]');
let welt = 'basis';
/* Werte (Rezept freelancer-stille-visitenkarte, Muster: Tab-Wechsel 200–300 ms, Roll 100 % Zeilenhöhe) */
const WERTE = {
tabs: 'Roll 240 ms · 100 % Zeilenhöhe · cubic-bezier(0.165, 0.84, 0.44, 1) · Hover 120 ms',
orte: 'Ortszeit per Intl.DateTimeFormat · Europe/Berlin + Europe/Lisbon · Roll 240 ms',
liste: 'Ohne Tabs · alle Adressen sichtbar · Kopieren 240 ms Roll · Hover 120 ms',
};
/* ---------- Kontakt-Tabs mit Text-Roll ---------- */
let aktiv = 0;
function strichSetzen() {
const r = reiter[aktiv], l = r.parentElement.getBoundingClientRect(), b = r.getBoundingClientRect();
strich.style.transform = `translateX(${b.left - l.left}px) scaleX(${b.width})`;
}
function waehle(i, fokus) {
if (i === aktiv) return;
const alt = aktiv, dir = i > alt ? 1 : -1;
aktiv = i;
reiter.forEach((r, k) => { r.setAttribute('aria-selected', k === i ? 'true' : 'false'); r.tabIndex = k === i ? 0 : -1; });
if (fokus) reiter[i].focus();
const neu = tafeln[i], weg = tafeln[alt];
/* neue Zeile ohne Übergang auf die Startseite legen: von unten bei „weiter“, von oben bei „zurück“ */
if (!reduziert()) {
neu.classList.remove('an', 'oben');
neu.querySelector('.mail').style.transition = 'none';
if (dir < 0) neu.classList.add('oben');
neu.offsetWidth;
neu.querySelector('.mail').style.transition = '';
}
neu.classList.remove('oben'); neu.classList.add('an'); neu.inert = false;
weg.classList.remove('an'); weg.classList.toggle('oben', dir > 0); weg.inert = true;
tafeln.forEach((t, k) => { if (k !== i && k !== alt) { t.classList.remove('an', 'oben'); t.inert = true; } });
strichSetzen();
}
reiter.forEach((r, i) => {
r.addEventListener('click', () => { stopVorfuehrung(); waehle(i); });
r.addEventListener('keydown', e => {
const n = reiter.length;
let z = null;
if (e.key === 'ArrowRight') z = (i + 1) % n;
if (e.key === 'ArrowLeft') z = (i - 1 + n) % n;
if (e.key === 'Home') z = 0;
if (e.key === 'End') z = n - 1;
if (z !== null) { e.preventDefault(); stopVorfuehrung(); waehle(z, true); }
});
});
/* ---------- Kopieren mit Rückmeldung ---------- */
const uhren = new Map();
function kopiere(knopf, echt = true) {
const adresse = knopf.dataset.kopieren;
if (echt && navigator.clipboard) navigator.clipboard.writeText(adresse).catch(() => {});
knopf.classList.add('fertig');
ansage.textContent = `${adresse} kopiert`;
clearTimeout(uhren.get(knopf));
uhren.set(knopf, setTimeout(() => knopf.classList.remove('fertig'), 1600));
}
$$('[data-kopieren]').forEach(k => k.addEventListener('click', () => { stopVorfuehrung(); kopiere(k); }));
/* ---------- Ortszeit je Standort ---------- */
const orte = $$('[data-tz]').map(el => {
const tz = el.dataset.tz;
const [von, bis] = el.dataset.saison.split('-').map(Number);
return {
el, von, bis,
zeit: new Intl.DateTimeFormat('de-DE', { timeZone: tz, hour: '2-digit', minute: '2-digit' }),
zone: new Intl.DateTimeFormat('de-DE', { timeZone: tz, timeZoneName: 'short' }),
teile: new Intl.DateTimeFormat('en-GB', { timeZone: tz, weekday: 'short', hour: 'numeric', hourCycle: 'h23', month: 'numeric' }),
};
});
function inSaison(o, monat) { return o.von <= o.bis ? monat >= o.von && monat <= o.bis : monat >= o.von || monat <= o.bis; }
function uhrStellen() {
const jetzt = new Date();
orte.forEach(o => {
const t = Object.fromEntries(o.teile.formatToParts(jetzt).map(p => [p.type, p.value]));
const monat = +t.month, stunde = +t.hour, wochenende = t.weekday === 'Sat' || t.weekday === 'Sun';
/* Mit einem Ort ist Hannover immer „hier“; mit zwei Orten entscheidet die Saison */
const hier = fuss.dataset.variante === 'orte' ? inSaison(o, monat) : o.el.dataset.ort === 'hannover';
const offen = hier && !wochenende && stunde >= 9 && stunde < 18;
o.el.classList.toggle('hier', hier);
o.el.classList.toggle('offen', offen);
$('[data-uhr]', o.el).textContent = o.zeit.format(jetzt);
$('[data-uhr]', o.el).setAttribute('datetime', jetzt.toISOString());
$('[data-zone]', o.el).textContent = o.zone.formatToParts(jetzt).find(p => p.type === 'timeZoneName').value;
let status;
if (!hier) status = o.von === 4 ? 'wieder ab April' : 'wieder ab November';
else if (wochenende) status = 'Wochenende';
else if (offen) status = 'am Schreibtisch';
else status = 'Feierabend';
$('[data-status]', o.el).textContent = '· ' + status;
});
}
uhrStellen();
setInterval(uhrStellen, 15000);
/* ---------- Varianten ---------- */
const knoepfe = $$('[data-variante]', $('[data-umschalter]'));
function variante(v) {
fuss.dataset.variante = v;
knoepfe.forEach(b => b.setAttribute('aria-pressed', b.dataset.variante === v ? 'true' : 'false'));
if (welt === 'basis') werteEl.textContent = WERTE[v];
uhrStellen();
const liste = v === 'liste';
tafeln.forEach((t, k) => {
t.inert = liste ? false : k !== aktiv;
if (liste) { t.removeAttribute('role'); } else { t.setAttribute('role', 'tabpanel'); }
});
if (!liste) requestAnimationFrame(strichSetzen);
}
knoepfe.forEach(b => b.addEventListener('click', () => { stopVorfuehrung(); variante(b.dataset.variante); }));
/* ---------- Darstellung hell/dunkel (View Transition, wo verfügbar) ---------- */
const themaKnoepfe = $$('[data-wahl]');
function thema(w, sanft) {
const setzen = () => {
if (w === 'dunkel') html.dataset.thema = 'dunkel'; else delete html.dataset.thema;
themaKnoepfe.forEach(b => b.setAttribute('aria-pressed', b.dataset.wahl === w ? 'true' : 'false'));
};
if (sanft && document.startViewTransition && !reduziert()) document.startViewTransition(setzen); else setzen();
}
themaKnoepfe.forEach(b => b.addEventListener('click', () => thema(b.dataset.wahl, true)));
if (matchMedia('(prefers-color-scheme: dark)').matches) thema('dunkel');
variante('tabs');
addEventListener('resize', strichSetzen);
if (document.fonts) document.fonts.ready.then(strichSetzen);
/* ---------- Vorführung: ein gedachter Zeiger klickt Tabs und Kopieren, dann zeigt die Karte zwei Orte ---------- */
let zeitgeber = [];
const spaeter = (fn, ms) => zeitgeber.push(setTimeout(fn, ms));
function zeigerZu(el, dx = .5, dy = .5) {
const r = el.getBoundingClientRect();
zeiger.style.transform = `translate(${r.left + r.width * dx - 2}px, ${r.top + r.height * dy - 1}px)`;
}
function klick() { zeiger.classList.add('klick'); spaeter(() => zeiger.classList.remove('klick'), 120); }
function runde() {
if (welt !== 'basis') return rundeWelt();
variante('tabs'); waehle(0);
const kopierKnopf = i => $('.kopieren', tafeln[i]);
zeiger.style.transition = 'none'; zeigerZu(reiter[0], .5, 1.6); zeiger.offsetWidth; zeiger.style.transition = '';
spaeter(() => zeigerZu(reiter[1]), 500);
spaeter(() => { klick(); waehle(1); }, 1250);
spaeter(() => zeigerZu(reiter[2]), 2200);
spaeter(() => { klick(); waehle(2); }, 2950);
spaeter(() => zeigerZu(kopierKnopf(2)), 3900);
spaeter(() => { klick(); kopiere(kopierKnopf(2), false); }, 4650);
spaeter(() => { variante('orte'); zeigerZu($('.zweit [data-uhr]'), .5, 1.4); }, 5900);
spaeter(() => zeigerZu(reiter[0]), 7600);
spaeter(() => { klick(); waehle(0); }, 8350);
spaeter(runde, 10400);
}
function stopVorfuehrung() {
if (!html.classList.contains('vorfuehrung')) return;
pause(); html.classList.remove('vorfuehrung');
}
function neustart() {
pause(); html.classList.remove('vorfuehrung');
$$('.kopieren').forEach(k => k.classList.remove('fertig'));
variante('tabs'); waehle(0); strichSetzen();
if (welt === 'praxis') { pxWaehle(0); pxStatus(); }
if (welt === 'buehne') { buMail.classList.remove('rollt'); buFit(); buMarke.classList.remove('warten'); }
if (welt === 'gastgeber') { ggZuruecksetzen(); ggStatus(); }
}
function vorfuehren() { pause(); html.classList.add('vorfuehrung'); runde(); }
function pause() { zeitgeber.forEach(clearTimeout); zeitgeber = []; }
function weiter() { if (!zeitgeber.length) vorfuehren(); }
/* =====================================================================
Varianten nach Regel 13: ?v=basis | praxis | buehne | gastgeber
===================================================================== */
const WELTEN = ['basis', 'praxis', 'buehne', 'gastgeber'];
const WERTE_WELT = {
praxis: 'Status per Intl · Europe/Berlin · Takt 30 s · Reiter 200 ms, Höhe 250 ms, Einblenden 400 ms / 8 px · cubic-bezier(0.2, 0, 0.38, 0.9)',
gastgeber: 'Auf 300 ms cubic-bezier(0.16, 1, 0.3, 1) · zu 200 ms cubic-bezier(0.7, 0, 0.84, 0) · UI 150 ms · Status per Intl, Rezeption 7 bis 21 Uhr',
buehne: 'Wortmarke volle Breite, 1100 ms, 70 ms versetzt · Mail-Roll 400 ms, 12 ms je Zeichen · Hover 300 ms · cubic-bezier(0.16, 1, 0.3, 1) · Ortszeit Europe/Berlin + Europe/Helsinki',
};
const weltKnoepfe = $$('[data-welt-wahl]');
function setzeWelt(w, url = true) {
welt = w; html.dataset.v = w;
weltKnoepfe.forEach(b => b.setAttribute('aria-pressed', String(b.dataset.weltWahl === w)));
if (url) { const u = new URL(location.href); u.searchParams.set('v', w); history.replaceState(history.state, '', u); }
werteEl.textContent = w === 'basis' ? WERTE[fuss.dataset.variante] : WERTE_WELT[w];
if (w === 'praxis') pxStatus();
if (w === 'buehne') { buUhren(); requestAnimationFrame(() => { buFit(); buBeobachten(); }); }
if (w === 'basis') requestAnimationFrame(strichSetzen);
if (w === 'gastgeber') { ggStatus(); ggBriefSetzen(!gg.classList.contains('gg-ohne-brief')); }
}
weltKnoepfe.forEach(b => b.addEventListener('click', () => { stopVorfuehrung(); setzeWelt(b.dataset.weltWahl); }));
/* ---------- Praxis: Live-Status aus Sprechzeiten, Feiertagen und Praxisurlaub ---------- */
const SPRECHZEITEN = { 1: [[480, 720], [900, 1080]], 2: [[480, 720], [900, 1080]], 3: [[480, 720]], 4: [[480, 720], [900, 1140]], 5: [[480, 780]] };
const FEIERTAGE = ['2026-10-31', '2026-12-25', '2026-12-26', '2027-01-01', '2027-03-26', '2027-03-29'];
const URLAUB = ['2026-12-24', '2027-01-01'];
const TAGNAME = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];
const pxTeile = new Intl.DateTimeFormat('en-CA', { timeZone: 'Europe/Berlin', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hourCycle: 'h23', weekday: 'short' });
const WT = { Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6 };
const uhrText = m => (m % 60 ? `${Math.floor(m / 60)}.${String(m % 60).padStart(2, '0')}` : `${m / 60}`) + ' Uhr';
const pxStatusEl = $('[data-px-status]'); let pxText = $('[data-px-status-text]');
function pxJetzt(d = new Date()) {
const t = Object.fromEntries(pxTeile.formatToParts(d).map(p => [p.type, p.value]));
return { datum: `${t.year}-${t.month}-${t.day}`, tag: WT[t.weekday], min: +t.hour * 60 + +t.minute };
}
const zu = datum => FEIERTAGE.includes(datum) || (datum >= URLAUB[0] && datum <= URLAUB[1]);
function pxBerechnen(d = new Date()) {
const j = pxJetzt(d);
if (zu(j.datum) && j.datum >= URLAUB[0] && j.datum <= URLAUB[1]) return { k: '', t: 'Praxisurlaub bis 1. Januar · Vertretung siehe unten', heute: j.tag };
const heute = zu(j.datum) ? [] : (SPRECHZEITEN[j.tag] || []);
const jetztOffen = heute.find(([a, b]) => j.min >= a && j.min < b);
if (jetztOffen) {
const rest = jetztOffen[1] - j.min;
return rest <= 45 ? { k: 'bald', t: `Geöffnet · schließt in ${rest} Min.`, heute: j.tag } : { k: 'offen', t: `Jetzt geöffnet · bis ${uhrText(jetztOffen[1])}`, heute: j.tag };
}
const spaeter = heute.find(([a]) => a > j.min);
if (spaeter) return { k: '', t: `Geschlossen · öffnet heute um ${uhrText(spaeter[0])}`, heute: j.tag };
for (let n = 1; n <= 10; n++) {
const x = pxJetzt(new Date(d.getTime() + n * 864e5));
if (!zu(x.datum) && SPRECHZEITEN[x.tag]) return { k: '', t: `Geschlossen · öffnet ${n === 1 ? 'morgen' : TAGNAME[x.tag]} um ${uhrText(SPRECHZEITEN[x.tag][0][0])}`, heute: j.tag };
}
return { k: '', t: 'Geschlossen', heute: j.tag };
}
function pxStatus(d) {
const r = pxBerechnen(d);
pxStatusEl.classList.toggle('offen', r.k === 'offen'); pxStatusEl.classList.toggle('bald', r.k === 'bald');
$$('[data-px-zeiten] tr').forEach(tr => tr.classList.toggle('heute', +tr.dataset.tag === r.heute));
if (pxText.textContent === r.t) return;
const alt = pxText, neu = document.createElement('span');
neu.textContent = r.t; neu.dataset.pxStatusText = '';
if (reduziert() || !alt.textContent.trim()) { alt.textContent = r.t; return; }
alt.removeAttribute('data-px-status-text'); alt.after(neu);
const k = 'cubic-bezier(0.2, 0, 0.38, 0.9)';
alt.animate([{ transform: 'none', opacity: 1 }, { transform: 'translateY(-100%)', opacity: 0 }], { duration: 200, easing: k, fill: 'forwards' }).finished.then(() => alt.remove());
neu.animate([{ transform: 'translateY(100%)', opacity: 0 }, { transform: 'none', opacity: 1 }], { duration: 200, easing: k });
pxText = neu;
}
setInterval(() => { if (welt === 'praxis' && !html.classList.contains('vorfuehrung')) pxStatus(); }, 30000);
// Anfahrt: Reiter mit Pfeiltasten, Höhe gleitet, Inhalt blendet 8 px ein
const pxReiter = $$('[data-px-reiter] [role="tab"]'), pxFenster = $('[data-px-fenster]');
function pxWaehle(i, fokus) {
const neu = $('#' + pxReiter[i].getAttribute('aria-controls'));
if (!neu.hidden) return;
const h0 = pxFenster.offsetHeight;
pxReiter.forEach((r, k) => { r.setAttribute('aria-selected', String(k === i)); r.tabIndex = k === i ? 0 : -1; $('#' + r.getAttribute('aria-controls')).hidden = k !== i; });
if (fokus) pxReiter[i].focus();
if (reduziert()) return;
const h1 = pxFenster.offsetHeight;
neu.classList.remove('ein'); void neu.offsetWidth; neu.classList.add('ein');
pxFenster.animate([{ height: h0 + 'px' }, { height: h1 + 'px' }], { duration: 250, easing: 'cubic-bezier(0.2, 0, 0.38, 0.9)' });
}
pxReiter.forEach((r, i) => {
r.addEventListener('click', () => { stopVorfuehrung(); pxWaehle(i); });
r.addEventListener('keydown', e => {
const n = pxReiter.length; let z = null;
if (e.key === 'ArrowRight') z = (i + 1) % n; if (e.key === 'ArrowLeft') z = (i - 1 + n) % n;
if (e.key === 'Home') z = 0; if (e.key === 'End') z = n - 1;
if (z !== null) { e.preventDefault(); stopVorfuehrung(); pxWaehle(z, true); }
});
});
/* ---------- Studio-Bühne: Ortszeit, Mail-Roll, Wortmarke ---------- */
const buStudios = $$('.bu-studio').map(el => ({ el,
zeit: new Intl.DateTimeFormat('de-DE', { timeZone: el.dataset.buTz, hour: '2-digit', minute: '2-digit', second: '2-digit' }),
zone: new Intl.DateTimeFormat('de-DE', { timeZone: el.dataset.buTz, timeZoneName: 'short' }) }));
function buUhren() {
const d = new Date();
buStudios.forEach(o => {
const [hh, mm, ss] = o.zeit.format(d).split(':');
$('[data-bu-uhr]', o.el).innerHTML = `${hh}<span class="bu-sek">:</span>${mm}`;
$('[data-bu-uhr]', o.el).setAttribute('datetime', d.toISOString());
$('[data-bu-zone]', o.el).textContent = o.zone.formatToParts(d).find(p => p.type === 'timeZoneName').value;
if (+ss % 2) $('.bu-sek', o.el).classList.add('aus');
});
}
setInterval(() => { if (welt === 'buehne') buUhren(); }, 1000);
// Mail-Adresse in Zeichen zerlegen: jedes rollt 400 ms, 12 ms versetzt, die Kopie darunter ist orange
const buMail = $('[data-bu-mail]');
buMail.innerHTML = [...buMail.textContent].map((z, i) => `<span class="z" aria-hidden="true"><span data-z="${z}" style="--i:${i}">${z}</span></span>`).join('');
// Wortmarke auf volle Breite setzen und beim Erscheinen Buchstabe für Buchstabe heben
const buMarke = $('[data-bu-marke]');
buMarke.innerHTML = [...buMarke.textContent].map((z, i) => `<span style="--i:${i}">${z}</span>`).join('');
function buFit() {
if (welt !== 'buehne') return;
buMarke.style.fontSize = '100px';
const w = buMarke.scrollWidth, ziel = buMarke.parentElement.clientWidth;
buMarke.style.fontSize = (100 * ziel / w) + 'px';
}
addEventListener('resize', buFit);
if (document.fonts) document.fonts.ready.then(buFit);
let buIo = null;
function buBeobachten() {
if (!('IntersectionObserver' in window)) { buMarke.classList.remove('warten'); return; }
if (buIo) return;
buIo = new IntersectionObserver(es => es.forEach(e => { if (e.isIntersecting) buMarke.classList.remove('warten'); }), { threshold: 0.4 });
buIo.observe(buMarke);
}
/* ---------- Gastgeber: Rezeption-Status, E-Mail kopieren, Saisonbrief mit Prüfung nach dem Verlassen des Felds ---------- */
const gg = $('[data-gg]'), ggStatusEl = $('[data-gg-status]'), ggKopieren = $('[data-gg-kopieren]');
const ggForm = $('[data-gg-form]'), ggFeld = $('#gg-mail-feld'), ggFehler = $('[data-gg-fehler]'), ggBrief = $('[data-gg-brief]');
const REZEPTION = [7 * 60, 21 * 60];
let ggText = '';
function ggStatus(d = new Date()) {
const j = pxJetzt(d), offen = j.min >= REZEPTION[0] && j.min < REZEPTION[1], rest = REZEPTION[1] - j.min;
const text = !offen ? 'Rezeption ab 7 Uhr wieder da · Schlüsselkasten am Eingang' : rest <= 60 ? `Rezeption besetzt, noch ${rest} Min.` : 'Rezeption besetzt bis 21 Uhr';
ggStatusEl.classList.toggle('offen', offen);
if (text === ggText) return;
const box = $('.gg-st', ggStatusEl), alt = box.firstElementChild;
if (!ggText || reduziert()) { alt.textContent = text; ggText = text; return; }
ggText = text;
const neu = document.createElement('span'); neu.textContent = text; neu.className = 'rein';
alt.classList.add('raus'); alt.removeAttribute('data-gg-st'); box.append(neu);
setTimeout(() => alt.remove(), 220);
}
setInterval(() => { if (welt === 'gastgeber' && !html.classList.contains('vorfuehrung')) ggStatus(); }, 30000);
let ggUhr = 0;
async function ggKopiere(echt = true) {
try { if (echt) await navigator.clipboard.writeText(ggKopieren.dataset.text); } catch (e) { ansage.textContent = 'Kopieren nicht möglich, bitte die Adresse markieren.'; return; }
ggKopieren.classList.add('fertig'); ansage.textContent = 'E-Mail-Adresse kopiert';
clearTimeout(ggUhr); ggUhr = setTimeout(() => ggKopieren.classList.remove('fertig'), 1600);
}
ggKopieren.addEventListener('click', () => { stopVorfuehrung(); ggKopiere(); });
const ggGueltig = v => /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(v.trim());
let ggBeruehrt = false;
function ggPruefen(zeigen) {
const v = ggFeld.value, ok = ggGueltig(v);
const meldung = ok ? '' : v.trim() ? 'Bitte prüfen Sie die Adresse, zum Beispiel name@beispiel.de.' : 'Bitte geben Sie Ihre E-Mail-Adresse ein.';
if (zeigen || ggBeruehrt) { ggFehler.textContent = meldung; ggFeld.setAttribute('aria-invalid', String(!ok)); }
return ok;
}
ggFeld.addEventListener('blur', () => { if (ggFeld.value.trim()) { ggBeruehrt = true; ggPruefen(); } });
ggFeld.addEventListener('input', () => { if (ggBeruehrt) ggPruefen(); });
ggForm.addEventListener('submit', e => {
e.preventDefault(); ggBeruehrt = true;
if (!ggPruefen(true)) { if (!html.classList.contains('vorfuehrung')) ggFeld.focus(); return; }
const danke = document.createElement('p');
danke.className = 'gg-danke ein'; danke.tabIndex = -1; danke.dataset.ggDanke = '';
danke.textContent = `Fast geschafft: Bitte bestätigen Sie die Anmeldung in der Mail an ${ggFeld.value.trim()}.`;
ggForm.hidden = true; ggForm.after(danke);
if (!html.classList.contains('vorfuehrung')) danke.focus();
});
function ggZuruecksetzen() {
$$('[data-gg-danke]').forEach(d => d.remove()); ggForm.hidden = false; ggForm.reset();
ggBeruehrt = false; ggFehler.textContent = ''; ggFeld.removeAttribute('aria-invalid'); ggKopieren.classList.remove('fertig');
}
const briefKnoepfe = $$('[data-gg-brief-wahl]');
function ggBriefSetzen(mit) {
gg.classList.toggle('gg-ohne-brief', !mit); ggBrief.inert = !mit;
briefKnoepfe.forEach(b => b.setAttribute('aria-pressed', String((b.dataset.ggBriefWahl === 'mit') === mit)));
werteEl.textContent = WERTE_WELT.gastgeber + (mit ? ' · Saisonbrief mit Double-Opt-in' : ' · ohne Saisonbrief');
}
briefKnoepfe.forEach(b => b.addEventListener('click', () => { stopVorfuehrung(); ggBriefSetzen(b.dataset.ggBriefWahl === 'mit'); }));
/* ---------- Vorführung der Varianten ---------- */
function rundeWelt() {
if (welt === 'gastgeber') {
ggZuruecksetzen(); ggBriefSetzen(true); ggStatus(new Date('2026-11-05T13:10:00Z'));
zeiger.style.transition = 'none'; zeigerZu(ggStatusEl, .5, 1.8); zeiger.offsetWidth; zeiger.style.transition = '';
// gedachte Uhrzeiten: 14.10 Uhr, 20.20 Uhr, 22.30 Uhr
spaeter(() => ggStatus(new Date('2026-11-05T19:20:00Z')), 1300);
spaeter(() => ggStatus(new Date('2026-11-05T21:30:00Z')), 3000);
spaeter(() => zeigerZu(ggKopieren), 4200);
spaeter(() => { klick(); ggKopiere(false); }, 4950);
spaeter(() => zeigerZu(ggFeld, .2, .5), 6300);
const adresse = 'jana.ross@beispiel.de';
spaeter(() => { klick(); }, 7000);
[...adresse].forEach((z, i) => spaeter(() => { ggFeld.value = adresse.slice(0, i + 1); }, 7200 + i * 55));
spaeter(() => zeigerZu($('button', ggForm)), 8600);
spaeter(() => { klick(); ggForm.requestSubmit(); }, 9350);
spaeter(() => ggStatus(), 11500);
spaeter(rundeWelt, 13000);
return;
}
if (welt === 'praxis') {
pxWaehle(0); pxStatus();
zeiger.style.transition = 'none'; zeigerZu(pxStatusEl, .5, 1.6); zeiger.offsetWidth; zeiger.style.transition = '';
// gedachte Uhrzeiten: Donnerstag 11.20 Uhr, 18.25 Uhr, Samstag
spaeter(() => pxStatus(new Date('2026-11-05T10:20:00Z')), 700);
spaeter(() => pxStatus(new Date('2026-11-05T17:25:00Z')), 2600);
spaeter(() => pxStatus(new Date('2026-11-07T10:00:00Z')), 4500);
spaeter(() => zeigerZu(pxReiter[1]), 5600);
spaeter(() => { klick(); pxWaehle(1); }, 6350);
spaeter(() => zeigerZu(pxReiter[2]), 7700);
spaeter(() => { klick(); pxWaehle(2); }, 8450);
spaeter(() => zeigerZu($('.px-tel'), .4, .6), 9800);
spaeter(() => { pxStatus(); }, 10600);
spaeter(rundeWelt, 12000);
return;
}
// Bühne: Wortmarke erscheint, Zeiger rollt die Mail-Adresse, dann ein Anliegen
buMarke.classList.add('warten'); buFit();
zeiger.style.transition = 'none'; zeigerZu(buMail, .1, 2.2); zeiger.offsetWidth; zeiger.style.transition = '';
spaeter(() => buMarke.classList.remove('warten'), 300);
spaeter(() => zeigerZu(buMail, .5, .6), 1700);
spaeter(() => buMail.classList.add('rollt'), 2300);
spaeter(() => { buMail.classList.remove('rollt'); zeigerZu($('.bu-anliegen a'), .55, .5); }, 4400);
spaeter(() => $('.bu-anliegen a').classList.add('hv'), 5000);
spaeter(() => { $('.bu-anliegen a').classList.remove('hv'); zeigerZu($('.bu-anliegen li:nth-child(3) a'), .55, .5); }, 6600);
spaeter(rundeWelt, 8600);
}
const ausUrl = new URLSearchParams(location.search).get('v');
setzeWelt(WELTEN.includes(ausUrl) ? ausUrl : WELTEN[0], false);
})();
</script>
</body>
</html>