Mega-Footer mit Sitemap und Utility-Leiste
Mega-Footer mit Sitemap-Spalten, CTA-Streifen und Utility-Leiste (Status, Theme, Sprache, Cookies), der unter 640 px Containerbreite zum Akkordeon wird.
Ein großer Footer in drei Ebenen. Oben ein optionaler CTA-Streifen (Testen, Beratung). In der Mitte mehrere betitelte Spalten mit je 5 bis 8 Links in kleiner, ruhiger Schrift, etwa Produkt, Lösungen, Ressourcen, Unternehmen. Unten eine Utility-Leiste mit Logo, Copyright, Rechtlichem, Cookie-Einstellungen, Theme-Auswahl, Sprachwahl und Statusanzeige. Studios ersetzen die Produktspalten durch Menü, Social, externe Projekte (Shop, Schrift, Podcast), Adresse und Newsletter.
Wer bis ans Ende scrollt, sucht oft etwas Bestimmtes. Der Footer fängt diese Nutzer auf und zeigt die ganze Struktur der Seite auf einen Blick. Die Utility-Leiste zeigt Sorgfalt: Theme, Status und Cookies sind dort, wo man sie erwartet.
Wann einsetzen
Produkt- und SaaS-Seiten, Agenturen und Studios mit vielen Bereichen, Institutionen.
Wann nicht
Kleine One-Pager. Seiten, auf denen die Spalten nur die Hauptnavigation wiederholen würden.
Varianten
- Produktspalten mit Utility-Leiste und Theme-Auswahl (Vercel)
- Sechs Spalten mit eigener Spalte für Rechtliches (Linear)
- Studio-Footer mit Spalte „Extern“ für Shop und eigene Projekte (Locomotive)
- Akkordeon-Spalten auf Mobil
Umsetzung
Spalten als CSS Grid mit repeat(auto-fit, minmax(10rem, 1fr)) und 32 bis 64 px Abstand. Links in <ul>, Spaltentitel als h2 oder h3. Jede Spalte steckt in <details>/<summary>: Unter einer Container-Query (z. B. 640 px) wird sie zum Akkordeon, darüber setzt ein kleines Skript open und blockiert das Zuklappen. Mit dem name-Attribut ist das Akkordeon exklusiv. Utility-Leiste als Flex mit space-between und flex-wrap. Theme-Auswahl als Radiogruppe in einem <fieldset>, Cookie-Einstellungen als Popover. Den Status per Fetch von der Statusseite holen und als Badge mit Punkt und Text zeigen, nie nur über Farbe. Gleiche Linktexte nie zu verschiedenen Zielen führen lassen.
Robust umsetzen
Telefon. Spalten als Akkordeon oder zweispaltig. Kopfzeilen mindestens 44 px hoch. Die Utility-Leiste steht untereinander.
Ohne Bewegung. Der Footer selbst ist statisch. Kleine Bewegungen wie Statuspuls, Theme-Pille und Akkordeon-Höhe abschalten.
Barrierefrei. <footer> als Landmark contentinfo, die Sitemap in <nav aria-label="Fußzeile">. Zwischen eng gesetzten Links mindestens 24 px Trefferfläche (WCAG 2.2). Theme-Auswahl als echte Radiogruppe mit Legende, Icons mit Textalternative. Status nie nur über Farbe zeigen. <details>/<summary> ist nativ per Tastatur bedienbar.
Code
<!DOCTYPE html>
<!--
Mega-Footer mit Sitemap und Utility-Leiste
Fundus · Footer · https://cecodesign.de/lab/fundus/footer/mega-footer-sitemap/
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>Mega-Footer mit Sitemap und Utility-Leiste · 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: 'Instrument Sans'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/instrument-sans:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 400 700; 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; }
@font-face { font-family: 'Instrument Serif'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/instrument-serif@latest/latin-400-italic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
/* Farben des Footers als registrierte Eigenschaften: der Theme-Wechsel blendet weich über */
@property --f-grund { syntax: '<color>'; inherits: true; initial-value: #131312; }
@property --f-text { syntax: '<color>'; inherits: true; initial-value: #f1efe9; }
@property --f-leise { syntax: '<color>'; inherits: true; initial-value: rgba(241, 239, 233, .56); }
@property --f-linie { syntax: '<color>'; inherits: true; initial-value: rgba(241, 239, 233, .12); }
@property --f-flaeche{ syntax: '<color>'; inherits: true; initial-value: rgba(241, 239, 233, .06); }
@property --f-ok { syntax: '<color>'; inherits: true; initial-value: #4fd18b; }
:root {
--papier: #e6e2d9; --tinte: #161615; --leise: rgba(22, 22, 21, .68); --linie: rgba(22, 22, 21, .14);
--kurve: cubic-bezier(0.16, 1, 0.3, 1); /* expo.out */
--ui: 150ms; /* Hover, Fokus */
--thema: 400ms; /* Farbwechsel des Footers */
}
* { box-sizing: border-box; margin: 0; }
html { background: var(--papier); color: var(--tinte); font-family: 'Instrument Sans', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
body { min-height: 100svh; padding: clamp(12px, 2vw, 24px); display: flex; flex-direction: column; gap: clamp(10px, 1.4vw, 16px); }
.mono { font: 500 11px/1.3 'Geist Mono', ui-monospace, monospace; letter-spacing: .14em; text-transform: uppercase; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
a { color: inherit; }
button, input, select { font: inherit; color: inherit; }
/* Seitenende über dem Footer (nur Desktop/Telefon, nicht in der Vorschau) */
.seitenende { display: flex; justify-content: space-between; align-items: end; gap: 24px; padding: clamp(20px, 4vh, 48px) clamp(8px, 2vw, 24px) clamp(8px, 1.6vh, 16px); }
.seitenende p:first-child { font-size: clamp(22px, 2.6vw, 34px); letter-spacing: -.03em; line-height: 1.1; max-width: 22ch; }
.seitenende em { font-family: 'Instrument Serif', serif; font-weight: 400; }
/* Bedienelemente der Demo */
.bedien { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 10px 24px; padding-inline: clamp(4px, 1vw, 12px); color: var(--leise); }
.wahl { display: flex; gap: 2px; padding: 3px; border: 1px solid var(--linie); border-radius: 999px; }
.wahl button { border: 0; background: none; padding: 7px 12px; border-radius: 999px; cursor: pointer; color: var(--leise); transition: background-color var(--ui) linear, color var(--ui) linear; }
.wahl button[aria-pressed="true"] { background: var(--tinte); color: var(--papier); }
.wahl button:focus-visible { outline: 2px solid var(--tinte); outline-offset: 2px; }
.werte { text-transform: none; letter-spacing: .02em; }
/* ---------- Der Footer ---------- */
.buehne { display: flex; flex-direction: column; }
.fuss {
container: fuss / inline-size;
--f-grund: #131312; --f-text: #f1efe9; --f-leise: rgba(241, 239, 233, .56); --f-linie: rgba(241, 239, 233, .12); --f-flaeche: rgba(241, 239, 233, .06); --f-ok: #4fd18b;
background: var(--f-grund); color: var(--f-text);
border-radius: clamp(14px, 1.6vw, 22px);
padding: clamp(24px, 4vw, 56px) clamp(20px, 4vw, 56px) clamp(18px, 2.4vw, 28px);
transition: --f-grund var(--thema) var(--kurve), --f-text var(--thema) var(--kurve), --f-leise var(--thema) var(--kurve), --f-linie var(--thema) var(--kurve), --f-flaeche var(--thema) var(--kurve), --f-ok var(--thema) var(--kurve);
interpolate-size: allow-keywords;
}
.fuss[hidden] { display: none !important; }
.fuss[data-thema="hell"] { --f-grund: #faf9f5; --f-text: #161615; --f-leise: rgba(22, 22, 21, .66); --f-linie: rgba(22, 22, 21, .12); --f-flaeche: rgba(22, 22, 21, .05); --f-ok: #13804a; }
@media (prefers-color-scheme: light) {
.fuss[data-thema="system"] { --f-grund: #faf9f5; --f-text: #161615; --f-leise: rgba(22, 22, 21, .66); --f-linie: rgba(22, 22, 21, .12); --f-flaeche: rgba(22, 22, 21, .05); --f-ok: #13804a; }
}
.fuss .mono { color: var(--f-leise); }
/* 1 · CTA-Streifen */
.cta { display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 24px 48px; padding-bottom: clamp(28px, 3.4vw, 44px); border-bottom: 1px solid var(--f-linie); }
.cta-titel { font-size: clamp(30px, 4.2vw, 58px); font-weight: 500; letter-spacing: -.04em; line-height: .98; }
.cta-titel em { font-family: 'Instrument Serif', serif; font-weight: 400; letter-spacing: -.02em; }
.cta-text { margin-top: 14px; font-size: 15px; line-height: 1.5; color: var(--f-leise); max-width: 46ch; }
.knoepfe { display: flex; flex-wrap: wrap; gap: 10px; }
.knopf { display: inline-flex; align-items: center; gap: 8px; height: 44px; padding: 0 20px; border-radius: 999px; border: 1px solid var(--f-linie); font-size: 14px; font-weight: 500; text-decoration: none; white-space: nowrap; transition: background-color var(--ui) linear, border-color var(--ui) linear; }
.knopf.voll { background: var(--f-text); color: var(--f-grund); border-color: transparent; }
.knopf:hover, .knopf.gezeigt { border-color: var(--f-leise); }
.knopf.voll:hover, .knopf.voll.gezeigt { background: color-mix(in srgb, var(--f-text) 86%, var(--f-grund)); }
/* Studio: Shop-Karte statt Knöpfen */
.shop { display: grid; grid-template-columns: 112px auto; gap: 16px; align-items: center; padding: 10px 22px 10px 10px; border: 1px solid var(--f-linie); border-radius: 14px; text-decoration: none; transition: border-color var(--ui) linear, background-color var(--ui) linear; }
.shop img { width: 112px; aspect-ratio: 3 / 2; object-fit: cover; border-radius: 8px; display: block; }
.shop strong { display: block; font-size: 15px; font-weight: 500; letter-spacing: -.01em; margin: 6px 0 2px; }
.shop span:last-child { font-size: 13px; color: var(--f-leise); }
.shop:hover, .shop.gezeigt { border-color: var(--f-leise); background: var(--f-flaeche); }
.mail { display: inline-block; margin-top: 14px; font: 500 13px/1.4 'Geist Mono', monospace; letter-spacing: .02em; color: var(--f-leise); text-decoration: none; border-bottom: 1px solid var(--f-linie); }
/* 2 · Sitemap: Spalten per auto-fit */
.karte { display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: 32px 48px; padding-block: clamp(28px, 3.6vw, 48px); --schmal: 0; }
.spalte summary { list-style: none; cursor: default; }
.spalte summary::-webkit-details-marker { display: none; }
.spalte h2 { font: 500 11px/1.3 'Geist Mono', ui-monospace, monospace; letter-spacing: .14em; text-transform: uppercase; color: var(--f-leise); margin-bottom: 10px; }
.spalte summary .plus { display: none; }
.spalte ul { list-style: none; padding: 0; }
.spalte li a, .spalte li button {
display: inline-flex; align-items: center; gap: 7px; min-height: 28px;
font-size: 14px; line-height: 2; text-decoration: none; color: var(--f-text); opacity: .8;
text-decoration-line: underline; text-decoration-color: transparent; text-underline-offset: 4px; text-decoration-thickness: 1px;
transition: opacity var(--ui) linear, text-decoration-color var(--ui) linear;
}
.spalte li a:hover, .spalte li a.gezeigt, .spalte li a:focus-visible { opacity: 1; text-decoration-color: currentColor; }
.spalte li a:focus-visible, .leiste a:focus-visible, .leiste button:focus-visible, .knopf:focus-visible, .shop:focus-visible, .spalte summary:focus-visible { outline: 2px solid var(--f-text); outline-offset: 3px; border-radius: 4px; }
.marke { font: 500 9.5px/1 'Geist Mono', monospace; letter-spacing: .1em; text-transform: uppercase; padding: 3px 6px 2px; border-radius: 999px; border: 1px solid var(--f-linie); color: color-mix(in srgb, var(--f-text) 80%, transparent); } /* sitzt im Link mit opacity .8: wirksam .64, nicht .45 */
.raus { width: 9px; height: 9px; opacity: .55; }
.notiz { display: block; font-size: 12.5px; line-height: 1.5; color: var(--f-leise); margin: 4px 0 12px; max-width: 26ch; }
.brief { display: flex; gap: 6px; max-width: 280px; }
.brief input { flex: 1; min-width: 0; height: 40px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--f-linie); background: var(--f-flaeche); font-size: 13.5px; }
.brief input::placeholder { color: var(--f-leise); }
.brief input:focus-visible { outline: 2px solid var(--f-text); outline-offset: 2px; }
.brief button { height: 40px; width: 40px; flex: none; border-radius: 50%; border: 0; background: var(--f-text); color: var(--f-grund); cursor: pointer; display: grid; place-items: center; }
.brief-ok { font-size: 12.5px; color: var(--f-ok); margin-top: 8px; min-height: 1.5em; }
/* 3 · Utility-Leiste */
.leiste { border-top: 1px solid var(--f-linie); padding-top: 18px; display: grid; gap: 14px; }
.leiste-oben, .leiste-unten { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 12px 24px; }
.logo { display: inline-flex; align-items: center; gap: 10px; font-size: 16px; font-weight: 600; letter-spacing: -.02em; text-decoration: none; }
.logo svg { width: 22px; height: 22px; }
.werkzeuge { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.status { display: inline-flex; align-items: center; gap: 9px; height: 34px; padding: 0 14px 0 12px; border-radius: 999px; border: 1px solid var(--f-linie); font-size: 13px; text-decoration: none; transition: border-color var(--ui) linear; }
.status:hover, .status.gezeigt { border-color: var(--f-leise); }
.punkt { position: relative; width: 8px; height: 8px; border-radius: 50%; background: var(--f-ok); }
.punkt::after { content: ''; position: absolute; inset: 0; border-radius: 50%; background: var(--f-ok); animation: puls 2.4s var(--kurve) infinite; }
@keyframes puls { from { scale: 1; opacity: .7; } to { scale: 2.8; opacity: 0; } }
.thema { position: relative; display: flex; border: 1px solid var(--f-linie); border-radius: 999px; padding: 2px; }
.thema legend { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.thema label { position: relative; z-index: 1; width: 32px; height: 28px; display: grid; place-items: center; cursor: pointer; color: var(--f-leise); transition: color var(--ui) linear; border-radius: 999px; }
.thema label:has(:checked) { color: var(--f-text); }
.thema label:has(:focus-visible) { outline: 2px solid var(--f-text); outline-offset: 1px; }
.thema input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.thema svg { width: 15px; height: 15px; }
.pille { position: absolute; left: 2px; top: 2px; width: 32px; height: 28px; border-radius: 999px; background: var(--f-flaeche); box-shadow: inset 0 0 0 1px var(--f-linie); transition: translate .6s var(--kurve); }
.thema:has([value="hell"]:checked) .pille { translate: 32px 0; }
.thema:has([value="dunkel"]:checked) .pille { translate: 64px 0; }
.sprache { position: relative; display: inline-flex; align-items: center; height: 34px; border: 1px solid var(--f-linie); border-radius: 999px; }
.sprache svg { position: absolute; left: 11px; width: 14px; height: 14px; color: var(--f-leise); pointer-events: none; }
.sprache select { appearance: none; height: 100%; padding: 0 30px 0 32px; border: 0; border-radius: 999px; background: transparent; font-size: 13px; cursor: pointer; }
.sprache select option { color: #161615; }
.sprache select:focus-visible { outline: 2px solid var(--f-text); outline-offset: 2px; }
.sprache::after { content: ''; position: absolute; right: 13px; top: 13px; width: 5px; height: 5px; border-right: 1.5px solid var(--f-leise); border-bottom: 1.5px solid var(--f-leise); rotate: 45deg; pointer-events: none; }
.leiste-unten { font-size: 12.5px; color: var(--f-leise); }
.rechtlich { display: flex; flex-wrap: wrap; gap: 0 18px; list-style: none; padding: 0; }
.rechtlich a, .rechtlich button { display: inline-flex; align-items: center; min-height: 28px; text-decoration: none; background: none; border: 0; padding: 0; cursor: pointer; color: var(--f-leise); transition: color var(--ui) linear; font-size: 12.5px; }
.rechtlich a:hover, .rechtlich button:hover, .rechtlich .gezeigt { color: var(--f-text); }
.uhr { font-variant-numeric: tabular-nums; }
/* Cookie-Einstellungen als Popover */
.kekse { position: fixed; inset: auto auto 20px 20px; margin: 0; width: min(340px, calc(100vw - 40px)); padding: 20px; border: 1px solid var(--f-linie); border-radius: 16px; background: var(--f-grund); color: var(--f-text); box-shadow: 0 24px 60px rgba(0, 0, 0, .28); }
.kekse p { font-size: 13.5px; line-height: 1.5; color: var(--f-leise); margin: 8px 0 14px; }
.kekse label { display: flex; justify-content: space-between; align-items: center; min-height: 36px; font-size: 14px; border-top: 1px solid var(--f-linie); }
.kekse input { accent-color: var(--f-text); width: 18px; height: 18px; }
.kekse .knopf { margin-top: 14px; height: 38px; cursor: pointer; }
/* Mobil (Container unter 640 px): Spalten werden zu einem Akkordeon */
@container fuss (max-width: 640px) {
.cta { grid-template-columns: 1fr; }
.cta-titel { font-size: 34px; }
.karte { display: block; padding-block: 8px 20px; --schmal: 1; }
.spalte { border-bottom: 1px solid var(--f-linie); }
.spalte summary { cursor: pointer; display: flex; justify-content: space-between; align-items: center; min-height: 56px; }
.spalte h2 { font: 500 16px/1.2 'Instrument Sans', sans-serif; letter-spacing: -.01em; text-transform: none; color: var(--f-text); margin: 0; }
.spalte summary .plus { display: block; position: relative; width: 14px; height: 14px; }
.plus::before, .plus::after { content: ''; position: absolute; left: 0; top: 6.25px; width: 14px; height: 1.5px; background: currentColor; transition: rotate .6s var(--kurve); }
.plus::after { rotate: 90deg; }
details[open] .plus::after { rotate: 0deg; }
.spalte details::details-content { block-size: 0; overflow: hidden; transition: block-size .6s var(--kurve), content-visibility .6s allow-discrete; }
.spalte details[open]::details-content { block-size: auto; }
.spalte ul { padding-bottom: 14px; }
.spalte li a { font-size: 15px; min-height: 36px; }
.leiste { border-top: 0; padding-top: 4px; }
.leiste-oben { flex-direction: column; align-items: flex-start; }
.leiste-unten { flex-direction: column-reverse; align-items: flex-start; gap: 6px; }
.brief { max-width: none; }
}
/* Variante „Mobil“: derselbe Footer in einem 390-px-Rahmen */
.buehne[data-ansicht="mobil"] .fuss { width: 100%; max-width: 390px; margin-inline: auto; padding: 28px 20px 22px; }
/* Gedachter Zeiger für die Vorführung */
.zeiger { position: fixed; left: 0; top: 0; z-index: 20; width: 20px; height: 20px; pointer-events: none; display: none; transition: transform .7s var(--kurve); }
.zeiger path { transition: scale .15s var(--kurve); transform-origin: 3px 2px; }
.zeiger.drueckt path { scale: .82; }
.vorfuehrung .zeiger { display: block; }
/* Vorschau 960 × 720: nur Bedienleiste und Footer */
.vorschau body { height: 100svh; overflow: hidden; padding: 12px; gap: 10px; }
.vorschau .seitenende { display: none; }
.vorschau .buehne { flex: 1; min-height: 0; justify-content: flex-end; }
.vorschau .buehne:not([data-ansicht="mobil"]) .fuss { flex: 1; display: flex; flex-direction: column; padding: 36px 36px 22px; }
.vorschau .buehne:not([data-ansicht="mobil"]) .leiste { margin-top: auto; }
.vorschau .buehne:not([data-ansicht="mobil"]) .cta-titel { font-size: 46px; }
.vorschau .buehne[data-ansicht="mobil"] .cta-text { display: none; }
.vorschau .buehne[data-ansicht="mobil"] { justify-content: flex-start; }
.vorschau .buehne[data-ansicht="mobil"] .fuss { max-height: 100%; overflow: auto; scrollbar-width: none; padding: 26px 20px 20px; }
/* Touch: kein Hover-Unterstrich, größere Trefferflächen in der Leiste */
@media (hover: none) {
.spalte li a:hover { opacity: .8; text-decoration-color: transparent; }
.status, .sprache { height: 40px; }
.thema label { width: 40px; height: 34px; }
.pille { width: 40px; height: 34px; }
.thema:has([value="hell"]:checked) .pille { translate: 40px 0; }
.thema:has([value="dunkel"]:checked) .pille { translate: 80px 0; }
.wahl button { padding: 10px 14px; }
}
@media (max-width: 560px) {
.seitenende { flex-direction: column; align-items: flex-start; padding-top: 48px; }
.werte { display: none; }
}
/* Reduzierte Bewegung: kein Pulsieren, kein Gleiten, Farbwechsel und Akkordeon sofort */
.reduziert .fuss, .reduziert .pille, .reduziert .zeiger, .reduziert .plus::before, .reduziert .plus::after { transition: none !important; }
.reduziert .spalte details::details-content { transition: none !important; }
.reduziert .punkt::after { animation: none; }
@media (forced-colors: active) {
button, [role=button], [role=tab], [role=switch] { border: 1px solid ButtonText !important; }
}
</style>
</head>
<body>
<section class="seitenende" aria-label="Seitenende">
<p>Ende der Seite. <em>Und hier</em> fängt der Footer dich auf.</p>
<p class="mono" style="color: var(--leise)">Fundus · Footer · 13</p>
</section>
<div class="bedien">
<div class="wahl" role="group" aria-label="Variante" data-wahl>
<button class="mono" type="button" data-variante="produkt" aria-pressed="true">Produkt</button>
<button class="mono" type="button" data-variante="studio" aria-pressed="false">Studio</button>
<button class="mono" type="button" data-variante="mobil" aria-pressed="false">Mobil</button>
</div>
<p class="mono werte" data-werte aria-live="polite"></p>
</div>
<div class="buehne" data-buehne data-ansicht="produkt">
<!-- Variante 1: Produktseite (erfundene Software für Architekturbüros) -->
<footer class="fuss" data-fuss="produkt" data-thema="dunkel">
<div class="cta">
<div>
<p class="cta-titel">Weniger Verwaltung. <em>Mehr Entwurf.</em></p>
<p class="cta-text">Zeiten, Honorare und Planlisten an einem Ort. 14 Tage kostenlos testen, ohne Kreditkarte.</p>
</div>
<div class="knoepfe">
<a class="knopf voll" href="#testen">Kostenlos testen</a>
<a class="knopf" href="#beratung">Beratung buchen</a>
</div>
</div>
<nav class="karte" aria-label="Fußzeile">
<div class="spalte"><details open><summary><h2>Produkt</h2><span class="plus" aria-hidden="true"></span></summary>
<ul>
<li><a href="#uebersicht">Übersicht</a></li>
<li><a href="#zeiten">Zeiterfassung</a></li>
<li><a href="#hoai">Honorar nach HOAI</a></li>
<li><a href="#planlisten">Planlisten</a></li>
<li><a href="#maengel">Mängelmanagement <span class="marke">Neu</span></a></li>
<li><a href="#preise">Preise</a></li>
<li><a href="#neuerungen">Neuerungen</a></li>
</ul></details></div>
<div class="spalte"><details open><summary><h2>Lösungen</h2><span class="plus" aria-hidden="true"></span></summary>
<ul>
<li><a href="#architektur">Architekturbüros</a></li>
<li><a href="#ingenieure">Ingenieurbüros</a></li>
<li><a href="#innen">Innenarchitektur</a></li>
<li><a href="#landschaft">Landschaftsarchitektur</a></li>
<li><a href="#steuerung">Projektsteuerung</a></li>
</ul></details></div>
<div class="spalte"><details open><summary><h2>Ressourcen</h2><span class="plus" aria-hidden="true"></span></summary>
<ul>
<li><a href="#handbuch">Handbuch</a></li>
<li><a href="#vorlagen">Vorlagen und Muster</a></li>
<li><a href="#rechner">HOAI-Rechner</a></li>
<li><a href="#webinare">Webinare</a></li>
<li><a href="#api">Schnittstellen (API) <svg class="raus" viewBox="0 0 10 10" aria-hidden="true"><path d="M2 8 8 2M3.5 2H8v4.5" fill="none" stroke="currentColor" stroke-width="1.3"/></svg></a></li>
<li><a href="#forum">Anwenderforum <svg class="raus" viewBox="0 0 10 10" aria-hidden="true"><path d="M2 8 8 2M3.5 2H8v4.5" fill="none" stroke="currentColor" stroke-width="1.3"/></svg></a></li>
</ul></details></div>
<div class="spalte"><details open><summary><h2>Unternehmen</h2><span class="plus" aria-hidden="true"></span></summary>
<ul>
<li><a href="#ueber">Über uns</a></li>
<li><a href="#karriere">Karriere <span class="marke">3 offen</span></a></li>
<li><a href="#presse">Presse</a></li>
<li><a href="#partner">Partnerprogramm</a></li>
<li><a href="#kontakt">Kontakt</a></li>
</ul></details></div>
</nav>
<div class="leiste">
<div class="leiste-oben">
<a class="logo" href="#start" aria-label="Planwerk, zur Startseite">
<svg viewBox="0 0 22 22" aria-hidden="true"><rect x="1" y="1" width="20" height="20" rx="5" fill="currentColor"/><path d="M6 15.5V6.5h5.2a2.9 2.9 0 0 1 0 5.8H6M13.5 15.5h2.5" fill="none" stroke="var(--f-grund)" stroke-width="1.8" stroke-linecap="round"/></svg>
Planwerk
</a>
<div class="werkzeuge">
<a class="status" href="#status"><span class="punkt" aria-hidden="true"></span>Alle Systeme laufen</a>
<fieldset class="thema">
<legend>Farbschema</legend>
<span class="pille" aria-hidden="true"></span>
<label title="System"><input type="radio" name="thema-produkt" value="system"><svg viewBox="0 0 16 16" aria-hidden="true"><rect x="1.5" y="2.5" width="13" height="9" rx="1.5" fill="none" stroke="currentColor" stroke-width="1.3"/><path d="M5.5 14h5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg><span class="sr">System</span></label>
<label title="Hell"><input type="radio" name="thema-produkt" value="hell"><svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="3" fill="none" stroke="currentColor" stroke-width="1.3"/><path d="M8 1v1.6M8 13.4V15M1 8h1.6M13.4 8H15M3 3l1.1 1.1M11.9 11.9 13 13M3 13l1.1-1.1M11.9 4.1 13 3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg><span class="sr">Hell</span></label>
<label title="Dunkel"><input type="radio" name="thema-produkt" value="dunkel" checked><svg viewBox="0 0 16 16" aria-hidden="true"><path d="M13.5 9.6A5.8 5.8 0 0 1 6.4 2.5a5.8 5.8 0 1 0 7.1 7.1Z" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/></svg><span class="sr">Dunkel</span></label>
</fieldset>
<label class="sprache"><span class="sr">Sprache</span><svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="6.3" fill="none" stroke="currentColor" stroke-width="1.2"/><path d="M1.7 8h12.6M8 1.7c-3.4 3.6-3.4 9 0 12.6M8 1.7c3.4 3.6 3.4 9 0 12.6" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>
<select><option>Deutsch</option><option lang="en">English</option></select></label>
</div>
</div>
<div class="leiste-unten">
<p>© 2026 Planwerk GmbH, Leipzig</p>
<ul class="rechtlich">
<li><a href="#impressum">Impressum</a></li>
<li><a href="#datenschutz">Datenschutz</a></li>
<li><a href="#agb">AGB</a></li>
<li><a href="#av">AV-Vertrag</a></li>
<li><a href="#barrierefreiheit">Barrierefreiheit</a></li>
<li><button type="button" popovertarget="kekse-produkt">Cookie-Einstellungen</button></li>
</ul>
</div>
</div>
<div class="kekse" id="kekse-produkt" popover>
<p class="mono">Cookie-Einstellungen</p>
<p>Notwendige Cookies halten dich angemeldet. Statistik setzen wir nur mit deiner Zustimmung.</p>
<label>Notwendig <input type="checkbox" checked disabled></label>
<label>Statistik <input type="checkbox"></label>
<button class="knopf voll" type="button" popovertarget="kekse-produkt" popovertargetaction="hide">Speichern</button>
</div>
</footer>
<!-- Variante 2: Studio-Footer mit Spalte „Extern“ (erfundenes Gestaltungsatelier) -->
<footer class="fuss" data-fuss="studio" data-thema="dunkel" hidden>
<div class="cta">
<div>
<p class="cta-titel">Neues Projekt?<br><em>Schreib uns.</em></p>
<a class="mail" href="#mail">post@atelier-kranich.de</a>
</div>
<a class="shop" href="#shop">
<img src="bilder/magazin-doppelseite.jpg" alt="" width="112" height="75">
<span><span class="mono">Neu im Shop</span><strong>Heft 04 · Die Ruhe der Dinge</strong><span>64 Seiten, Risodruck · 18 €</span></span>
</a>
</div>
<nav class="karte" aria-label="Fußzeile">
<div class="spalte"><details open><summary><h2>Menü</h2><span class="plus" aria-hidden="true"></span></summary>
<ul>
<li><a href="#arbeiten">Arbeiten</a></li>
<li><a href="#atelier">Atelier</a></li>
<li><a href="#haltung">Haltung</a></li>
<li><a href="#journal">Journal</a></li>
<li><a href="#kontakt-s">Kontakt</a></li>
</ul></details></div>
<div class="spalte"><details open><summary><h2>Social</h2><span class="plus" aria-hidden="true"></span></summary>
<ul>
<li><a href="#instagram">Instagram <svg class="raus" viewBox="0 0 10 10" aria-hidden="true"><path d="M2 8 8 2M3.5 2H8v4.5" fill="none" stroke="currentColor" stroke-width="1.3"/></svg></a></li>
<li><a href="#linkedin">LinkedIn <svg class="raus" viewBox="0 0 10 10" aria-hidden="true"><path d="M2 8 8 2M3.5 2H8v4.5" fill="none" stroke="currentColor" stroke-width="1.3"/></svg></a></li>
<li><a href="#behance">Behance <svg class="raus" viewBox="0 0 10 10" aria-hidden="true"><path d="M2 8 8 2M3.5 2H8v4.5" fill="none" stroke="currentColor" stroke-width="1.3"/></svg></a></li>
<li><a href="#arena">Are.na <svg class="raus" viewBox="0 0 10 10" aria-hidden="true"><path d="M2 8 8 2M3.5 2H8v4.5" fill="none" stroke="currentColor" stroke-width="1.3"/></svg></a></li>
</ul></details></div>
<div class="spalte"><details open><summary><h2>Extern</h2><span class="plus" aria-hidden="true"></span></summary>
<ul>
<li><a href="#shop2">Shop <span class="marke">Drucke</span></a></li>
<li><a href="#schrift">Kranich Grotesk <span class="marke">Schrift</span></a></li>
<li><a href="#reise">Atelierreise 2027</a></li>
<li><a href="#podcast">Podcast „Zwischenraum“</a></li>
</ul></details></div>
<div class="spalte"><details open><summary><h2>Post</h2><span class="plus" aria-hidden="true"></span></summary>
<span class="notiz">Viermal im Jahr: neue Arbeiten, Drucke und Termine.</span>
<form class="brief" data-brief>
<label class="sr" for="brief-mail">E-Mail-Adresse</label>
<input id="brief-mail" type="email" placeholder="deine@adresse.de" autocomplete="email">
<button type="submit" aria-label="Abonnieren"><svg viewBox="0 0 14 14" width="14" height="14" aria-hidden="true"><path d="M2 7h10M8 3l4 4-4 4" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
</form>
<p class="brief-ok" data-brief-ok aria-live="polite"></p>
</details></div>
</nav>
<div class="leiste">
<div class="leiste-oben">
<a class="logo" href="#start-s" aria-label="Atelier Kranich, zur Startseite">
<svg viewBox="0 0 22 22" aria-hidden="true"><circle cx="11" cy="11" r="9.5" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M5 15.5 15.5 5M11 15.5h4.5V11" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
Atelier Kranich
</a>
<div class="werkzeuge">
<a class="status" href="#anfrage"><span class="punkt" aria-hidden="true"></span>Frei für Projekte ab Januar</a>
<fieldset class="thema">
<legend>Farbschema</legend>
<span class="pille" aria-hidden="true"></span>
<label title="System"><input type="radio" name="thema-studio" value="system"><svg viewBox="0 0 16 16" aria-hidden="true"><rect x="1.5" y="2.5" width="13" height="9" rx="1.5" fill="none" stroke="currentColor" stroke-width="1.3"/><path d="M5.5 14h5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg><span class="sr">System</span></label>
<label title="Hell"><input type="radio" name="thema-studio" value="hell"><svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="3" fill="none" stroke="currentColor" stroke-width="1.3"/><path d="M8 1v1.6M8 13.4V15M1 8h1.6M13.4 8H15M3 3l1.1 1.1M11.9 11.9 13 13M3 13l1.1-1.1M11.9 4.1 13 3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg><span class="sr">Hell</span></label>
<label title="Dunkel"><input type="radio" name="thema-studio" value="dunkel" checked><svg viewBox="0 0 16 16" aria-hidden="true"><path d="M13.5 9.6A5.8 5.8 0 0 1 6.4 2.5a5.8 5.8 0 1 0 7.1 7.1Z" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/></svg><span class="sr">Dunkel</span></label>
</fieldset>
<label class="sprache"><span class="sr">Sprache</span><svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="6.3" fill="none" stroke="currentColor" stroke-width="1.2"/><path d="M1.7 8h12.6M8 1.7c-3.4 3.6-3.4 9 0 12.6M8 1.7c3.4 3.6 3.4 9 0 12.6" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>
<select><option>Deutsch</option><option lang="en">English</option></select></label>
</div>
</div>
<div class="leiste-unten">
<p>Ehrenfeldgürtel 88, 50823 Köln · <a href="#karte">Karte</a> · <span class="uhr" data-uhr>Köln</span></p>
<ul class="rechtlich">
<li><a href="#impressum-s">Impressum</a></li>
<li><a href="#datenschutz-s">Datenschutz</a></li>
<li><button type="button" popovertarget="kekse-studio">Cookies</button></li>
<li><span>© 2026</span></li>
</ul>
</div>
</div>
<div class="kekse" id="kekse-studio" popover>
<p class="mono">Cookies</p>
<p>Wir messen nur anonym, wie oft Seiten aufgerufen werden. Und nur, wenn du zustimmst.</p>
<label>Notwendig <input type="checkbox" checked disabled></label>
<label>Statistik <input type="checkbox"></label>
<button class="knopf voll" type="button" popovertarget="kekse-studio" popovertargetaction="hide">Speichern</button>
</div>
</footer>
</div>
<svg class="zeiger" data-zeiger viewBox="0 0 20 20" aria-hidden="true"><path d="M3 2 17 10.2l-6.3 1.4-3 5.9Z" fill="#161615" stroke="#faf9f5" stroke-width="1.3" stroke-linejoin="round"/></svg>
<script>
(() => {
const html = document.documentElement;
const reduziert = () => html.classList.contains('reduziert');
const buehne = document.querySelector('[data-buehne]');
const fuesse = { produkt: document.querySelector('[data-fuss="produkt"]'), studio: document.querySelector('[data-fuss="studio"]') };
const knoepfe = [...document.querySelectorAll('[data-wahl] button')];
const werteZeile = document.querySelector('[data-werte]');
const zeiger = document.querySelector('[data-zeiger]');
const KURVE = 'cubic-bezier(0.16, 1, 0.3, 1)';
let variante = 'produkt', thema = 'dunkel';
const aktiverFuss = () => variante === 'studio' ? fuesse.studio : fuesse.produkt;
/* Akkordeon nur, wenn der Container schmal ist (Quelle der Wahrheit: --schmal aus der Container-Query) */
function akkordeon(fuss) {
const karte = fuss.querySelector('.karte');
const schmal = getComputedStyle(karte).getPropertyValue('--schmal').trim() === '1';
if (fuss.dataset.schmal === String(schmal)) return;
fuss.dataset.schmal = String(schmal);
fuss.querySelectorAll('.spalte details').forEach(d => {
const s = d.querySelector('summary');
if (schmal) { d.open = false; d.name = 'fuss-' + fuss.dataset.fuss; s.removeAttribute('tabindex'); }
else { d.removeAttribute('name'); d.open = true; s.tabIndex = -1; }
});
}
Object.values(fuesse).forEach(f => {
f.querySelectorAll('.spalte summary').forEach(s => s.addEventListener('click', e => { if (f.dataset.schmal !== 'true') e.preventDefault(); }));
new ResizeObserver(() => akkordeon(f)).observe(f);
});
function werteZeigen() {
werteZeile.textContent = variante === 'mobil'
? 'Container ≤ 640 px · details/summary, exklusiv · 600 ms expo.out'
: 'auto-fit minmax(10rem, 1fr) · Spaltenabstand 48 px · Link 14/28 px';
}
function varianteSetzen(v, still) {
if (v === variante && !still) return;
variante = v;
knoepfe.forEach(k => k.setAttribute('aria-pressed', String(k.dataset.variante === v)));
buehne.dataset.ansicht = v;
fuesse.produkt.hidden = v === 'studio';
fuesse.studio.hidden = v !== 'studio';
const f = aktiverFuss();
akkordeon(f);
werteZeigen();
if (!still) f.animate(reduziert()
? [{ opacity: 0 }, { opacity: 1 }]
: [{ opacity: 0, transform: 'translateY(18px)' }, { opacity: 1, transform: 'none' }],
{ duration: reduziert() ? 150 : 900, easing: KURVE });
}
knoepfe.forEach(k => k.addEventListener('click', () => varianteSetzen(k.dataset.variante)));
function themaSetzen(t) {
thema = t;
Object.values(fuesse).forEach(f => {
f.dataset.thema = t;
const r = f.querySelector(`.thema input[value="${t}"]`); if (r) r.checked = true;
});
}
document.querySelectorAll('.thema input').forEach(r => r.addEventListener('change', () => themaSetzen(r.value)));
document.querySelectorAll('.sprache select').forEach(s => s.addEventListener('change', () => document.querySelectorAll('.sprache select').forEach(o => o.selectedIndex = s.selectedIndex)));
document.querySelectorAll('.fuss a').forEach(a => a.addEventListener('click', e => e.preventDefault()));
const brief = document.querySelector('[data-brief]');
brief.addEventListener('submit', e => { e.preventDefault(); document.querySelector('[data-brief-ok]').textContent = 'Danke. Bitte bestätige die Mail in deinem Postfach.'; });
const uhr = document.querySelector('[data-uhr]');
const fmt = new Intl.DateTimeFormat('de-DE', { timeZone: 'Europe/Berlin', hour: '2-digit', minute: '2-digit' });
const tick = () => { uhr.textContent = 'Köln ' + fmt.format(new Date()); };
tick(); setInterval(tick, 30000);
/* Vorführung: ein gedachter Zeiger zeigt Links, schaltet Theme, Variante und Akkordeon */
const finde = (text, wurzel = aktiverFuss()) => [...wurzel.querySelectorAll('a, summary, .shop, .status')].find(el => el.textContent.trim().startsWith(text));
const radio = w => aktiverFuss().querySelector(`.thema input[value="${w}"]`);
const knopf = v => knoepfe.find(k => k.dataset.variante === v);
let gezeigt = null;
function zeige(el) {
if (!el) return;
if (gezeigt) gezeigt.classList.remove('gezeigt');
const ziel = el.closest('label') || el;
const r = ziel.getBoundingClientRect();
const x = r.left + Math.min(r.width * 0.5, 44), y = r.top + r.height * 0.55;
zeiger.style.transform = `translate(${x - 3}px, ${y - 2}px)`;
if (el.matches('a, .shop, .status')) { el.classList.add('gezeigt'); gezeigt = el; }
}
function klick(el) {
if (!el) return;
zeiger.classList.add('drueckt');
setTimeout(() => zeiger.classList.remove('drueckt'), 160);
el.click();
}
const ablauf = [
[500, () => zeige(finde('Zeiterfassung'))],
[800, () => zeige(finde('Honorar nach HOAI'))],
[800, () => zeige(finde('Mängelmanagement'))],
[800, () => zeige(finde('HOAI-Rechner'))],
[800, () => zeige(finde('Karriere'))],
[1000, () => zeige(finde('Alle Systeme'))],
[1000, () => zeige(radio('hell'))],
[650, () => klick(radio('hell'))],
[1500, () => zeige(knopf('studio'))],
[650, () => klick(knopf('studio'))],
[1100, () => zeige(finde('Kranich Grotesk'))],
[800, () => zeige(finde('Atelierreise'))],
[900, () => zeige(finde('Neu im Shop'))],
[1200, () => zeige(radio('dunkel'))],
[650, () => klick(radio('dunkel'))],
[1500, () => zeige(knopf('mobil'))],
[650, () => klick(knopf('mobil'))],
[1200, () => zeige(finde('Produkt'))],
[650, () => klick(finde('Produkt'))],
[1600, () => zeige(finde('Lösungen'))],
[650, () => klick(finde('Lösungen'))],
[2000, () => zeige(knopf('produkt'))],
[650, () => klick(knopf('produkt'))],
[1200, () => {}]
];
let uhrwerk = null, schritt = 0;
function laufen() {
const [warte, tu] = ablauf[schritt];
uhrwerk = setTimeout(() => {
tu();
schritt = (schritt + 1) % ablauf.length;
laufen();
}, warte);
}
function grundzustand() {
if (gezeigt) { gezeigt.classList.remove('gezeigt'); gezeigt = null; }
themaSetzen('dunkel');
varianteSetzen('produkt', true);
document.querySelectorAll('.kekse').forEach(p => { try { p.hidePopover(); } catch (e) {} });
}
function neustart() { pause(); html.classList.remove('vorfuehrung'); grundzustand(); schritt = 0; }
function vorfuehren() {
pause();
grundzustand();
schritt = 0;
html.classList.add('vorfuehrung');
zeiger.style.transition = 'none';
zeiger.style.transform = `translate(${innerWidth * 0.62}px, ${innerHeight * 0.4}px)`;
zeiger.getBoundingClientRect();
zeiger.style.transition = '';
laufen();
}
function pause() { clearTimeout(uhrwerk); uhrwerk = null; }
function weiter() { if (!uhrwerk && html.classList.contains('vorfuehrung')) laufen(); }
varianteSetzen('produkt', true);
})();
</script>
</body>
</html>