/* fest.v6.css - Besucherseite Herbstvolksfest. Eigenstaendig, laedt NICHT styles.css:
   die Seite muss in einer ueberlasteten Funkzelle laden, nicht huebsch aussehen.
   Tokens 1:1 aus css/styles.css uebernommen, damit die Marke stimmt.
   Cache-Bruch laeuft ueber den Dateinamen (v1, v2, ...), topcharge.tech kennt kein ?v=.

   Aenderungen gegenueber v2, alle aus dem Designaudit vom 2026-08-27:
   - Bruehnenformat im Hochformat 4/3 statt 1/1, weil der Startzoom jetzt den ganzen
     Plan zeigt und ein quadratischer Ausschnitt dabei 142 px leeren Rand erzeugte.
   - Vollbildknopf sitzt im Bedienstreifen unter dem Plan, nicht mehr auf dem Plan:
     er verdeckte dort die Kopfzeile des Aufstellplans.
   - Buehnenfarbe --paper statt --paper-2, damit der Rand um den freigestellten Plan
     nicht als Loch gelesen wird. */
:root{
  --paper:oklch(0.966 0.007 236);--paper-2:oklch(0.945 0.009 236);--paper-3:oklch(0.922 0.011 238);
  --ink:oklch(0.255 0.055 262);--ink-2:oklch(0.415 0.046 260);--ink-3:oklch(0.485 0.036 258);
  --rule:oklch(0.865 0.012 240);--rule-2:oklch(0.775 0.017 244);
  --green:oklch(0.795 0.185 129);--green-deep:oklch(0.485 0.148 129);
  --dark:oklch(0.235 0.055 262);--dark-2:oklch(0.295 0.05 262);
  --on-dark:oklch(0.932 0.012 236);--on-dark-2:oklch(0.775 0.021 238);
  --rot:oklch(0.47 0.19 26);
  --s-4:.25rem;--s-8:.5rem;--s-12:.75rem;--s-16:1rem;--s-24:1.5rem;--s-32:2rem;--s-48:3rem;
  --font-body:'Familjen Grotesk','Segoe UI',system-ui,sans-serif;
  --font-mono:'Spline Sans Mono',ui-monospace,'Cascadia Code','Consolas',monospace;
  --rand:clamp(1rem,.55rem + 2.2vw,2rem);
  --breit:46rem;
}
/* Abgeleitete Werte. Die Tokens oben bleiben unveraendert, diese hier entstehen aus
   ihnen und decken die Faelle ab, in denen der Token-Wert die WCAG-Schwelle knapp
   reisst: --green-deep auf --paper misst 4.49:1 (noetig 4.5:1), der alte Fokusring
   2.81:1 und Feldrahmen aus --rule-2 1.85:1 (noetig je 3:1). Gemessen, nicht geschaetzt. */
:root{
  --green-text:color-mix(in oklch,var(--green-deep) 86%,var(--ink));   /* 5.09:1 auf paper */
  --fokus:oklch(.58 .16 250);                                          /* 3.89:1 auf paper, 3.91:1 auf dark */
  --kante:color-mix(in oklch,var(--rule-2) 70%,var(--ink));            /* 3.30:1 auf paper */
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--paper-3);color:var(--ink);font-family:var(--font-body);font-size:1.02rem;line-height:1.55;-webkit-font-smoothing:antialiased}
img{max-width:100%;height:auto;display:block}
h1,h2,h3{margin:0;font-weight:700;line-height:1.1;text-wrap:balance}
p{margin:0}
a{color:inherit}
:focus-visible{outline:2px solid var(--fokus);outline-offset:3px}
.skip{position:absolute;left:var(--s-8);top:-60px;z-index:50;background:var(--ink);color:var(--on-dark);padding:var(--s-8) var(--s-16);font-family:var(--font-mono);font-weight:600;font-size:.85rem;border-radius:2px}
.skip:focus{top:var(--s-8)}
.klein{font-size:.82rem;color:var(--ink-3);line-height:1.5}
.marke{font-family:var(--font-mono);font-size:.78rem;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--green-text)}

/* Kopf. Die Eckdaten stehen oben, weil genau danach zuerst gefragt wird. */
.kopf{background:var(--paper);padding:var(--s-24) var(--rand) var(--s-32);border-bottom:2px solid var(--ink)}
.kopf h1{font-size:clamp(1.9rem,1.3rem + 2.9vw,3rem);letter-spacing:-.02em;margin:var(--s-12) 0 var(--s-12);max-width:16ch}
.lead{font-size:clamp(1.02rem,.98rem + .35vw,1.16rem);color:var(--ink-2);max-width:52ch}
.eckdaten{display:flex;flex-wrap:wrap;gap:var(--s-8) var(--s-32);margin:var(--s-24) 0 0;padding-top:var(--s-16);border-top:1px solid var(--rule)}
.eckdaten dt{font-family:var(--font-mono);font-size:.7rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3)}
.eckdaten dd{margin:2px 0 0;font-family:var(--font-mono);font-size:1.32rem;font-weight:600;font-variant-numeric:tabular-nums}
.eckdaten .u{color:var(--green-text);font-size:.86rem;font-weight:600}

/* Abschnitte */
main{max-width:var(--breit);margin:0 auto}
.block{background:var(--paper);padding:var(--s-32) var(--rand)}
.block + .block{border-top:1px solid var(--rule)}
.block h2{font-size:clamp(1.35rem,1.15rem + .9vw,1.75rem);letter-spacing:-.01em}
.hinweis{margin-top:var(--s-8);color:var(--ink-3);font-size:.9rem;max-width:56ch}
.fliess{margin-top:var(--s-12);color:var(--ink-2);max-width:66ch}

/* Hilfe. Einziger dunkler Block der Seite: abends im Gedraenge muss die Nummer
   ohne Suchen ins Auge fallen, und der Kontrast traegt bei niedriger Helligkeit. */
.hilfe{background:var(--dark);color:var(--on-dark);padding:var(--s-32) var(--rand);text-align:center}
.hilfe h2{font-size:clamp(1.3rem,1.1rem + .9vw,1.6rem)}
.hilfe p{color:var(--on-dark-2);margin-top:var(--s-8)}
.ruf{display:block;margin:var(--s-16) auto 0;max-width:22rem;padding:var(--s-16) var(--s-24);background:var(--green);color:var(--dark);text-decoration:none;border-radius:3px;font-family:var(--font-mono);font-size:clamp(1.1rem,.95rem + .8vw,1.45rem);font-weight:600;font-variant-numeric:tabular-nums;min-height:56px;display:grid;place-items:center}
.zeiten{font-size:.86rem;margin-top:var(--s-12)}

/* Ausleihe. Vier echte Schritte, deshalb Ziffern: sie sind die Reihenfolge selbst.
   Ueberschrift und Text stehen beide in Spalte 2, sonst schiebt die automatische
   Platzierung den Absatz in die 2rem schmale Ziffernspalte (ein Wort je Zeile). */
.schritte{list-style:none;counter-reset:s;margin:var(--s-24) 0 0;padding:0}
.schritte li{counter-increment:s;display:grid;grid-template-columns:2rem 1fr;gap:var(--s-4) var(--s-16);padding:var(--s-16) 0;border-top:1px solid var(--rule)}
.schritte li::before{content:counter(s);grid-column:1;grid-row:1;font-family:var(--font-mono);font-size:1.1rem;font-weight:600;color:var(--green-text);line-height:1.3}
.schritte h3,.schritte p{grid-column:2}
.schritte h3{font-size:1.02rem}
.schritte p{color:var(--ink-2);margin-top:2px;max-width:54ch}
.preis-zeile{margin-top:var(--s-24);padding:var(--s-16);background:var(--paper-2);border-top:2px solid var(--green);color:var(--ink-2);max-width:60ch}
.preis-zeile strong{font-family:var(--font-mono);font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}

/* Stoerfaelle */
.faelle{margin:var(--s-24) 0 0}
.faelle > div{padding:var(--s-16) 0;border-top:1px solid var(--rule)}
.faelle dt{font-weight:700}
.faelle dd{margin:var(--s-4) 0 0;color:var(--ink-2);max-width:64ch}

/* Formular */
.fb{margin-top:var(--s-24)}
.hp{position:absolute;left:-9999px;opacity:0}
.bewertung{margin:0;padding:0;border:0}
.bewertung legend{font-family:var(--font-mono);font-size:.72rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);padding:0}
.opt-reihe{display:flex;flex-wrap:wrap;gap:var(--s-8);margin-top:var(--s-8)}
.opt-reihe label{display:flex;align-items:center;gap:var(--s-8);min-height:48px;padding:0 var(--s-16);border:1px solid var(--kante);border-radius:999px;cursor:pointer;background:var(--paper)}
.opt-reihe input{accent-color:var(--green-text);width:1.1rem;height:1.1rem;margin:0}
.opt-reihe label:has(input:checked){background:var(--paper-2);border-color:var(--green-text);box-shadow:inset 0 0 0 1px var(--green-text);font-weight:700}
.feld{margin-top:var(--s-16);display:grid;gap:var(--s-8)}
.feld label{font-family:var(--font-mono);font-size:.72rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3)}
.opt{color:var(--ink-3);text-transform:none;letter-spacing:0;font-size:.76rem}
.fb textarea,.fb input[type=text]{width:100%;padding:var(--s-12);border:1px solid var(--kante);border-radius:2px;background:var(--paper);color:var(--ink);font:400 1rem/1.5 var(--font-body);min-height:48px}
.fb textarea{resize:vertical}
.fb-fuss{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-16);margin-top:var(--s-24)}
.knopf{min-height:48px;padding:0 var(--s-32);border:1px solid var(--green-text);border-radius:3px;background:var(--green);color:var(--dark);font:700 1rem/1 var(--font-body);cursor:pointer}
.knopf[aria-disabled=true]{opacity:.6;cursor:progress}
.fb-status{font-size:.92rem;color:var(--ink-2)}
.fb-status[data-state=success]{color:var(--green-text);font-weight:700}
.fb-status[data-state=error]{color:var(--rot)}
.fb .klein{margin-top:var(--s-16)}

/* Fuss */
.fuss{max-width:var(--breit);margin:0 auto;padding:var(--s-32) var(--rand) var(--s-48);color:var(--ink-2);font-size:.92rem;display:grid;gap:var(--s-4)}
.fuss .marke{margin-bottom:var(--s-8)}

/* ====================== Lageplan ======================
   Buehne = fester Ausschnitt, alles darin bewegt sich nur per transform.
   Bedienung und Statuszeile liegen UNTER der Buehne, nicht darauf: gemessen deckte
   die alte Anordnung auf einem 360er Handy 23 Prozent des Plans ab und die Leiste
   sass genau auf Marker 10.
   Hochformat bekommt einen hoeheren Ausschnitt als der Plan selbst (4/3 statt
   6749/3931), damit nach dem Hineinzoomen genug Hoehe zum Lesen bleibt. Frueher war
   das 1/1 zusammen mit einem fuellenden Startzoom; gemessen bei 390 px Breite waren
   dabei nur 58 Prozent der Planbreite sichtbar und fuenf der elf Marker lagen
   ausserhalb, ohne dass etwas darauf hinwies. Seit v5 zeigt der Startzoom den ganzen
   Plan, und 1/1 haette dabei 142 px leeren Rand erzeugt. */
.k{margin:var(--s-24) 0 0;display:grid;gap:10px}
.k-rahmen{display:grid;grid-template-rows:auto auto}
.k-buehne{position:relative;overflow:hidden;aspect-ratio:6749/3931;background:var(--paper);border:1px solid var(--rule);border-radius:3px 3px 0 0;touch-action:pan-y;cursor:grab;-webkit-user-select:none;user-select:none;contain:paint}
.k-buehne:active{cursor:grabbing}
@media (max-width:560px) and (orientation:portrait){.k-buehne{aspect-ratio:4/3}}
.k-flaeche{position:absolute;top:0;left:0;width:100%;aspect-ratio:6749/3931;transform-origin:0 0;will-change:transform}
.k-flaeche picture{display:block;pointer-events:none}
.k-bild{display:block;width:100%;height:auto}
.k-sanft .k-flaeche{transition:transform .3s cubic-bezier(.2,.7,.3,1)}
@media (prefers-reduced-motion:reduce){.k-sanft .k-flaeche{transition:none}}
/* Hotspots: 44x44 Trefferflaeche, Gegenskalierung haelt sie bildschirmgross. */
.k-punkte{position:absolute;inset:0;--inv:1}
.k-punkt{position:absolute;width:44px;height:44px;margin:0;padding:0;border:0;background:none;display:grid;place-items:center;border-radius:999px;cursor:pointer;transform:translate(-50%,-50%) scale(var(--inv))}
.k-punkt::after,.k-nr{border-radius:999px;background:var(--dark);color:var(--on-dark);font:600 11px/21px var(--font-mono);text-align:center}
.k-punkt::after{content:attr(data-nr);width:21px;height:21px;box-shadow:0 0 0 2px var(--paper)}
/* Gemeinsamer Marker fuer mehrere Stationen am selben Fleck (data-gruppe am <li>).
   Die Plakette traegt alle Nummern und wird dafuer breiter, die Trefferflaeche waechst mit. */
.k-punkt[data-mehr]{width:64px}
.k-punkt[data-mehr]::after{width:auto;min-width:21px;padding:0 6px}
.k-punkt[aria-pressed=true]{z-index:2}
.k-punkt[aria-pressed=true]::after{background:var(--green);color:var(--dark);box-shadow:0 0 0 3px var(--green-deep),0 0 0 6px var(--paper)}
/* Noch nicht bestaetigte Standorte (data-offen am <li>, vom JavaScript an den Marker
   durchgereicht): hohle Plakette statt gefuellter, damit niemand zu einem Pin laeuft,
   an dem noch nichts steht. Ausgewaehlt sehen sie aus wie alle anderen, sonst waere
   die Auswahl nicht erkennbar - deshalb das :not(), das haelt die Regel unabhaengig
   von der Reihenfolge im Stylesheet. */
.k-punkt[data-offen]:not([aria-pressed=true])::after,
.k-liste li[data-offen]:not(.k-an) .k-nr{background:var(--paper);color:var(--ink-2);box-shadow:inset 0 0 0 1.5px var(--ink-2),0 0 0 2px var(--paper)}
.k-liste li[data-offen] .k-ort{color:var(--ink-3)}
/* Bedienstreifen unter der Karte. Auf dem Plan liegt nichts mehr: der Vollbildknopf
   sass frueher oben rechts und verdeckte dort die Kopfzeile des Aufstellplans
   ("Willkommen auf dem Volksfestplatz!" samt Hinweiszeile), gemessen 87 x 44 px.
   Breit steht alles in einer Zeile: Text links, Vollbild und Zoom rechts.
   Schmal bekommt der Text eine eigene Zeile und die Bedienung die darunter,
   Vollbild links, Zoom rechts. Der Umbruch ist an eine Medienabfrage gebunden und
   nicht dem freien Umbruch der Flexbox ueberlassen: der ergab je nach Textlaenge
   mal zwei, mal drei Zeilen, und der Streifen sprang beim Auswaehlen einer Station
   in der Hoehe. Gemessen bei 390 px: 107 px hoch statt der jetzigen 96. */
.k-fuss{display:flex;flex-wrap:wrap;align-items:center;gap:6px var(--s-8);padding:6px 8px;background:var(--paper-2);border:1px solid var(--rule);border-top:0;border-radius:0 0 3px 3px}
.k-status{flex:1 1 auto;min-width:0;margin:0;padding:0 4px;color:var(--ink-2);font:400 12.5px/1.35 var(--font-body)}
.k-weit{order:2}
.k-zoom{order:3;display:flex;gap:6px;flex:none}
@media (max-width:560px){
  .k-status{flex:1 1 100%}
  .k-zoom{margin-left:auto}
}
.k-btn{min-width:44px;min-height:44px;padding:0 14px;border:1px solid var(--kante);border-radius:999px;background:oklch(.966 .007 236/.94);color:var(--ink);cursor:pointer;font:400 13px/1 var(--font-body)}
.k-zoom .k-btn{padding:0;font-size:17px;background:var(--paper)}
/* Standortliste */
.k-liste{list-style:none;margin:0;padding:0;border:1px solid var(--rule);border-radius:3px;overflow:hidden}
.k-liste li + li{border-top:1px solid var(--rule)}
.k-eintrag{display:grid;grid-template-columns:26px 1fr auto;align-items:baseline;gap:4px 10px;width:100%;min-height:48px;padding:10px 12px;border:0;border-radius:0;text-align:left;background:var(--paper);color:var(--ink);cursor:pointer;font:400 14.5px/1.35 var(--font-body)}
.k-btn:hover,.k-eintrag:hover,.k-an .k-eintrag{background:var(--paper-3)}
.k-an .k-nr{background:var(--green-text)}
.k-stand{color:var(--ink-3);font:600 11.5px/1 var(--font-mono);white-space:nowrap}
.k figcaption{color:var(--ink-3);font-size:.8rem}
/* Vollbild ueber das native <dialog>: Fokusfalle und Escape ohne eigenen Code. */
.k-dialog{width:100dvw;max-width:none;height:100dvh;max-height:none;margin:0;padding:0;border:0;background:var(--paper)}
.k-dialog::backdrop{background:rgb(0 0 0/.68)}
.k-rahmen.k-voll{height:100dvh;grid-template-rows:1fr auto}
.k-voll .k-buehne{aspect-ratio:auto;width:100%;height:100%;border:0;border-radius:0;touch-action:none}
.k-voll .k-fuss{border:0;border-top:1px solid var(--rule);border-radius:0;padding-bottom:max(6px,env(safe-area-inset-bottom))}
.k-buehne:focus-visible,.k-punkt:focus-visible,.k-btn:focus-visible{outline:2px solid var(--fokus);outline-offset:3px}
/* Der Listenrahmen kappt mit overflow:hidden alles, was ueber einen Eintrag
   hinausragt. Ein aussen liegender Ring blieb dort bis auf einen einzigen Strich
   unsichtbar, und der Strich sass an der Kante zum naechsten Eintrag, zeigte also
   auf die falsche Zeile. Deshalb liegt der Ring hier innen. */
.k-eintrag:focus-visible{outline:2px solid var(--fokus);outline-offset:-3px}

/* ---------------- Eigener Standort und Wegfuehrung ----------------
   Der Standortpunkt ist bewusst BLAU. Gruen gehoert auf dieser Karte den
   Stationen; ein zweites Gruen fuer "ich" waere genau die Unterscheidung, die
   im Gedraenge bei halber Bildschirmhelligkeit als Erstes verlorengeht.
   Die Zeichenebene liegt IN .k-flaeche und wird deshalb mitverschoben und
   mitskaliert. Ihr viewBox traegt die Pixelmasse des Plans: mit 0 0 100 100
   waere der Genauigkeitskreis zur Ellipse gezogen worden, weil das Bild nicht
   quadratisch ist. */
.k-ueber{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible}
/* Der Genauigkeitskreis hat eine echte Groesse in Metern und waechst deshalb
   MIT dem Zoom - darin liegt seine ganze Aussage. Die Route dagegen bleibt per
   non-scaling-stroke bildschirmfest, sonst waere sie herausgezoomt ein Haar und
   hineingezoomt ein Balken. */
.k-genau{fill:oklch(.58 .16 250/.13);stroke:oklch(.58 .16 250/.34);stroke-width:1;vector-effect:non-scaling-stroke}
.k-route{fill:none;stroke:var(--fokus);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;
  vector-effect:non-scaling-stroke;stroke-dasharray:1 7;animation:k-lauf 1.1s linear infinite}
@keyframes k-lauf{to{stroke-dashoffset:-8}}
@media (prefers-reduced-motion:reduce){.k-route{animation:none;stroke-dasharray:none;opacity:.9}}

/* Der Punkt bleibt bildschirmgross wie die Stationsmarker: er zeigt eine
   Position, keine Flaeche. Wie sicher sie ist, sagt der Kreis darunter. */
.k-ich{position:absolute;width:44px;height:44px;display:grid;place-items:center;pointer-events:none;
  transform:translate(-50%,-50%) scale(var(--inv));z-index:3}
.k-ich::after{content:'';width:16px;height:16px;border-radius:999px;background:var(--fokus);
  box-shadow:0 0 0 3px var(--paper),0 0 0 4px oklch(.58 .16 250/.5)}
/* Nur waehrend der Suche pulst der Punkt. Sobald eine Position steht, hoert das
   auf: ein dauerhaft pulsender Punkt liest sich als "noch nicht fertig" und
   kostet auf einem Platz, auf dem die Karte minutenlang offen liegt, Akku. */
.k-ich[data-suche]::after{animation:k-puls 1.4s ease-out infinite}
@keyframes k-puls{0%{box-shadow:0 0 0 3px var(--paper),0 0 0 4px oklch(.58 .16 250/.5)}
  70%{box-shadow:0 0 0 3px var(--paper),0 0 0 15px oklch(.58 .16 250/0)}
  100%{box-shadow:0 0 0 3px var(--paper),0 0 0 4px oklch(.58 .16 250/0)}}
@media (prefers-reduced-motion:reduce){.k-ich[data-suche]::after{animation:none}}

/* Der Standortknopf steht links vom Vollbildknopf. Eingeschaltet wird er
   gefuellt, damit ohne Text ablesbar ist, ob die Ortung laeuft - das
   entscheidet ueber den Akku. */
.k-ort-btn[aria-pressed=true]{background:var(--fokus);color:var(--paper);border-color:var(--fokus)}
.k-ort-btn[data-zustand=fehler]{border-color:var(--rot);color:var(--rot)}

/* Entfernung je Listeneintrag. Sie steht in einer eigenen Zeile unter dem
   Namen, damit auf 320 px nichts umbricht, und verschwindet ohne Standort. */
.k-weit-m{grid-column:2/-1;margin-top:2px;font:400 11.5px/1.2 var(--font-mono);color:var(--ink-3);
  font-variant-numeric:tabular-nums}
.k-weit-m:empty{display:none}
/* Die naechstgelegene Station wird hervorgehoben, aber nicht ausgewaehlt: wer
   eine andere antippt, soll seine Wahl behalten. */
.k-liste li.k-naechste .k-eintrag{background:var(--paper-2);box-shadow:inset 3px 0 0 var(--green-deep)}
.k-liste li.k-naechste .k-weit-m{color:var(--green-text);font-weight:600}

/* Der Kopf steht ausserhalb von <main> und laeuft deshalb ueber die volle Breite.
   Damit seine Zeilen trotzdem in derselben Spalte beginnen wie alles darunter,
   waechst hier das Polster mit dem Fenster.
   ACHTUNG: .hilfe darf diese Regel NICHT bekommen. Der Block liegt IN <main>, ist
   also schon auf --breit begrenzt; das Polster wuerde von der Spaltenbreite noch
   einmal abgezogen. Gemessen bei 1440 px: Inhalt 32 px statt 672 px, die
   Telefonnummer stand senkrecht und lief aus ihrer Flaeche heraus. */
@media (min-width:720px){
  .kopf{padding-left:max(var(--rand),calc(50vw - var(--breit)/2));padding-right:max(var(--rand),calc(50vw - var(--breit)/2))}
}
