/* ---------------------------------------------------------------------------
   Semesterauftakt – ein Erscheinungsbild für Einladung, Ticketkauf, Einlösen,
   Admin und Einlass. Die Farbwelt folgt dem Veranstaltungsplakat: sattes
   Kobaltblau als Nacht, warmes Elfenbein für Inhalt und Acid-Lime für die
   wenigen Stellen, die sofort ins Auge fallen sollen.

   Auf der Einladung liegt das gelieferte Discokugelmotiv hinter dem Satz. Ein
   blauer Verlauf lässt es nach unten in die ruhigen Shopflächen auslaufen.
   Formulare und Funktionsseiten bleiben ohne Foto, teilen aber dieselben
   Farben, harten Kanten und klaren Konturen. Fremde Marken bleiben unverändert.
   --------------------------------------------------------------------------- */

:root{
  /* Kobalt, Nachtblau, Elfenbein und das Limettengrün des Posters. */
  --bg:#080d7f;
  --bg-deep:#050853;
  --ink:#faf8ed;
  --mute:#b9c3f5;
  --line:#5968c7;
  --line-hard:#faf8ed;
  --panel:#0b1489;
  --panel-2:#121e96;

  /* Dunkle Fläche für das Datumsfeld; auf Limette steht immer Nachtblau. */
  --blatt:#0b1489;
  --auf-hell:#050853;

  --blau:#96a8ff;
  --limette:#cfef4c;

  /* Die Bärenkachel greift denselben Limettenton auf. */
  --signet:#cfef4c;

  /* Zustände – nur dort eingesetzt, wo eine Farbe eine Aussage trägt. Jeder
     Zustand steht zweimal: hell für Schrift und Strich auf dem blauen Grund
     (alle über 4,5:1), tief für die Stellen, an denen er selbst die Fläche
     ist und weiße Schrift trägt – am Einlass und auf dem Schild der
     Notaufnahme. Die tiefen Töne sind genau die, in denen die Zustände auf
     dem weißen Plakat standen. */
  --ok:#5fd08a;
  --warn:#e0b64a;
  --err:#ffa79b;
  --skip:#bdb5ff;

  --ok-flaeche:#1a7a44;
  --err-flaeche:#c0271b;
  --skip-flaeche:#3b32a8;

  --sans:"Helvetica Neue",Helvetica,Arial,"Liberation Sans",sans-serif;
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,"DejaVu Sans Mono",monospace;
  --wrap:44rem;
  --spalte:34rem;        /* die Spalte der Einladung */
  --luft:2rem;           /* der Rand links und rechts davon */
}

*{box-sizing:border-box}

/* Die Seite scrollt ausschließlich senkrecht. Kein weiches Scrollen, kein
   seitliches Wegrutschen, kein Gummiband nach links oder rechts: Überbreiten
   werden geklippt (clip, mit hidden als Rückfall für ältere Safari-Versionen)
   und was wirklich breit ist, scrollt in der eigenen Box statt in der Seite.

   Kein Gummiband nach oben und unten heißt zugleich: kein Neuladen durch
   Ziehen nach unten. Am oberen Rand steht die Seite einfach still, statt
   sich unter dem Finger aufzuziehen und beim Loslassen von vorn zu laden –
   ein halb ausgefülltes Bestellformular wäre sonst weg. `none` statt
   `contain`, damit auch das bloße Nachwippen ausbleibt. */
/* Der Grund hinter der Seite ist derselbe wie ihr eigener. Wo die Seite doch
   über ihren Rand hinausgezogen wird – ältere iOS-Fassungen kennen die Sperre
   von oben noch nicht –, malt das System in dem freigelegten Streifen den
   Grund der Wurzel; steht dort eine andere Farbe, reißt sie als fremder Balken
   auf. Hier ist es also dasselbe Kobaltblau, das auch als `theme-color` in der
   Leiste steht.

   `color-scheme:dark` sagt dem Browser nur, worauf er seine eigenen Teile
   stellen soll: Kästchen, Auswahlpunkte, Scrollleisten und der Grund, den er
   vor dem ersten Malen zeigt. Es ist keine zweite Fassung der Seite – die
   Seite hat genau eine, und `dark` ist hier fest gesetzt und nicht
   `light dark`: Es gibt nichts umzuschalten. */
html{-webkit-text-size-adjust:100%; height:100%;
  color-scheme:dark;
  background:var(--bg);
  scroll-behavior:auto;
  overflow-x:hidden; overflow-x:clip;
  overscroll-behavior:none}

/* Doppeltipp zoomt nicht. `manipulation` lässt Schieben und Aufziehen mit zwei
   Fingern zu und nimmt nur den Zoom auf den Doppeltipp – der trifft sonst jede
   zweite hastige Berührung an der Tür und verschiebt die Seite. Nebenbei fällt
   damit auch die alte Verzögerung von 300 ms vor jedem Tippen weg.
   Die Regel gilt allen Elementen: `touch-action` vererbt sich nicht, und
   maßgeblich ist das Element unter dem Finger. Stünde sie nur an Rumpf und
   Wurzel, zoomte der Doppeltipp auf jede Überschrift, jeden Verweis und jede
   Schaltfläche weiterhin – also überall dort, wo wirklich getippt wird. */
*{touch-action:manipulation}
/* Der Grund hinter der Seite. Ältere iOS-Fassungen lassen sie trotz der Sperre
   oben noch über den Rand ziehen; in dem freigelegten Streifen malt das System
   den Grund der Wurzel. Steht dort eine andere Farbe, reißt sie als fremder
   Balken auf – hier steht also dasselbe Kobaltblau, das auch als `theme-color` in
   der Leiste steht.

   Innerhalb der Seite sieht man davon nichts: Alles unterhalb des Kopfes deckt
   `.grund` ab. */
html{background:var(--bg)}
body{
  min-height:100%; margin:0; background:var(--bg); color:var(--ink);
  font:400 15px/1.65 var(--sans);
  font-synthesis-weight:none;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  display:flex; flex-direction:column;
  -webkit-user-select:none; user-select:none;
  overflow-x:clip; overscroll-behavior:none;
}
img,svg{max-width:100%}
/* Markieren ist abgeschaltet. Eingabefelder bleiben ausgenommen – ohne Auswahl
   ließe sich getippter Text nicht mehr korrigieren. */
input,textarea{-webkit-user-select:text; user-select:text}

/* --- Typografie ---------------------------------------------------------- */

h1{font:400 clamp(24px,4.4vw,30px)/1.2 var(--sans); letter-spacing:-.018em;
  margin:0 0 .5em; text-wrap:balance}
h2{font:400 18px/1.35 var(--sans); letter-spacing:-.01em; margin:2.25em 0 .7em}
h3{font:400 15px/1.5 var(--sans); color:var(--mute); margin:1.75em 0 .5em}
p{margin:0 0 1em}
.sub{color:var(--mute); margin:0 0 2rem}
a{color:inherit; text-decoration:underline; text-decoration-thickness:1px;
  text-underline-offset:.22em; text-decoration-color:var(--line)}
a:hover{text-decoration-color:var(--limette)}
:focus-visible{outline:2px solid var(--limette); outline-offset:3px}
strong{font-weight:600}
code,.mono,pre{font-family:var(--mono)}
code,.mono{font-size:.9em}
/* Text, der die Bedeutung einer rein gezeichneten Beschriftung für
   Vorlesesoftware erhält, ohne neben der Grafik ein zweites Mal sichtbar zu
   werden. */
.nur-vorleser{position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0}
p code,li code,td code{background:var(--panel-2); padding:1px 5px}
pre{font-size:13px; line-height:1.7; overflow-x:auto; overscroll-behavior-x:contain;
  background:var(--panel-2); padding:14px; margin:0 0 1em}
pre.mono{margin:0}
.muted{color:var(--mute)}
.small{font-size:13px}
.right{text-align:right}
hr{border:0; border-top:1px solid var(--line); margin:2rem 0}

/* --- Gerüst: Kopf, Inhalt, Fuß ------------------------------------------- */

/* `.grund` fasst Inhalt und Fuß zusammen, liegt über die ganze Breite und
   wächst bis zum unteren Rand, auch wenn die Seite kurz ist. Es trägt den
   Grund der Seite, damit er an dieser Fläche hängt und nicht am Rumpf. */
.grund{background:var(--bg); flex:1;
  display:flex; flex-direction:column}

body.einladung .grund{
  background-color:var(--bg);
  background-image:
    linear-gradient(180deg,rgba(8,13,127,.14) 0,rgba(8,13,127,.36) 27rem,var(--bg) 58rem),
    url('/zeichen/bg.webp');
  background-repeat:no-repeat;
  background-position:center top,center -7rem;
  background-size:100% 62rem,max(100%,62rem) auto;
}

main{width:100%; max-width:var(--wrap); margin:0 auto; padding:2.5rem 1.5rem 4rem; flex:1}

footer{width:100%; max-width:var(--wrap); margin:0 auto;
  padding:2rem 1.5rem 3rem; font-size:13px; color:var(--mute)}
footer .recht{display:flex; gap:1.5rem; margin:0}
footer .recht a{text-decoration:none}
footer .recht a:hover{text-decoration:underline}

/* --- Seite für sich -------------------------------------------------------
   Impressum und Datenschutzerklärung stehen allein: keine Rechtsspalte im
   Fuß, kein Verweis fort von hier. Im Fuß steht eine einzige Schaltfläche,
   unten links, und sie führt zurück zum Anfang.

   Die Angaben sind zum Mitnehmen da – Anschrift, Adresse, Registernummer.
   Deshalb ist auf dieser Fläche das Markieren wieder erlaubt, das sonst
   überall aus ist. */
body.allein main{padding-top:3.5rem}
body.allein footer{padding-bottom:3.5rem}

/* Die erste Zwischenüberschrift einer Seite, dicht unter der Hauptüberschrift:
   Der Abstand, den ein `h2` sonst über sich zieht, trennt zwei Zeilen, die
   zusammengehören – die Seite hieße sonst „Hilfe“ und begänne erst weit
   darunter. So steht die Hilfeseite da (src/routes/hilfe.js). */
h2.erste{margin-top:1.25rem}

.anbieter{-webkit-user-select:text; user-select:text}
.anbieter p{margin:0 0 1.75rem}
.anbieter p:last-child{margin-bottom:0}

/* --- Pflichtinformationen (Datenschutz) -----------------------------------
   Die Erklärung besteht aus Listen: Zwecke, Rechtsgrundlagen, Empfänger,
   Rechte. Sie stehen in derselben Spalte wie jeder andere Text, nur eingerückt
   und mit einer Stufe unter der Zwischenüberschrift für die berechtigten
   Interessen. Aufzählungen gibt es sonst nirgends im Fließtext – deshalb
   hängt die Regel an dieser Seite und nicht an `li`.

   Sie heißt `erklaerung` und nicht `pflicht`: Unter `pflicht` stehen weiter
   unten die Pflichtangaben des Besuchers im letzten Kaufschritt.

   Wie im Impressum und im Vertragstext ist hier das Markieren wieder erlaubt,
   das sonst überall aus ist – die Angaben sind zum Mitnehmen da. */
.erklaerung{-webkit-user-select:text; user-select:text}
.erklaerung h5{font:400 13px/1.5 var(--sans); color:var(--mute);
  margin:1.5em 0 .5em}
.erklaerung ul{margin:0 0 1em; padding-left:1.2em}
.erklaerung li{margin:0 0 .4em}
.erklaerung li:last-child{margin-bottom:0}

/* --- Vertragstext und Beilagen --------------------------------------------
   Das Dokument, das an den Links über der Schaltfläche hängt: der
   Vertragstext, dahinter die weiteren Bedingungen, und der Hinweis zu
   Lärm/Gesundheitsgefahren. Beides ist zum Lesen und zum Mitnehmen da –
   deshalb ist hier, wie im Impressum, das Markieren wieder erlaubt.

   Aufzählungen gibt es sonst nirgends im Fließtext; die Regel hängt deshalb an
   diesem Dokument und nicht an `li`. */
.vertrag{-webkit-user-select:text; user-select:text}
.vertrag ul{margin:0 0 1em; padding-left:1.2em}
.vertrag li{margin:0 0 .4em}
.vertrag li:last-child{margin-bottom:0}
.vertrag ul ul{margin:.4em 0 0}

/* Eine Beilage, wie sie gesetzt wurde: das PDF im Betrachter des Browsers, im
   Seitenverhältnis von A4. Zeigt der Browser kein PDF an – auf dem Telefon ist
   das die Regel –, steht im selben Rahmen der Ersatz: bei der Hausordnung ein
   Satz mit dem Weg zur Datei, beim Lärmhinweis dasselbe Blatt als SVG. */
.blatt{display:block; width:100%; aspect-ratio:1/1.414; margin:1.5rem 0 .5rem;
  border:1px solid var(--line); background:var(--panel)}
.blatt img{width:100%; height:100%; object-fit:contain}
.blatt p{padding:1rem; margin:0}

/* --- Einladung ------------------------------------------------------------
   Eine linksbündige Spalte, aber die Bänder darum laufen über die ganze
   Breite. Deshalb ist `main` hier randlos und in voller Breite, und jeder
   Abschnitt trägt seinen Satzspiegel selbst (`.satz`). Das spart die
   100vw-Rechnerei, die sonst um die Breite der Scrollleiste danebenliegt –
   und genau das hatte den Schriftzug an die Kante geschoben. */

body.einladung main{max-width:none; padding:0}
body.einladung footer{max-width:var(--spalte); padding:2.5rem var(--luft) 4rem}

.satz{max-width:var(--spalte); margin:0 auto; padding:0 var(--luft)}

.aufmacher{padding:2.25rem 0 1.5rem}

/* Der weiße Bär aus der Originaldatei wird als Maske nachtblau auf die
   Limettenkachel gesetzt. Ohne Maskenunterstützung bleibt ein dunkler,
   kontrastreicher Rückfall über den Filter sichtbar. */
.signet{display:flex; align-items:center; gap:1.4rem; margin:0 0 1.1rem}
.signet>span{display:block; background:var(--signet); padding:.85rem 1.25rem}
.signet .fell{display:block}
.signet .fell img{display:block; height:60px; width:auto; filter:brightness(.2)}

/* Neben der Kachel das Zeichen der Fachschaftsinitiative: gleich hoch wie der
   Bär, damit die beiden als ein Paar stehen und nicht als Zeichen und
   Fußnote. In der Datei ist es Petrol – gezeigt wird es weiß wie die Schrift
   daneben, über dieselbe Rechnung wie bei der Wortmarke des Hauses. Die Datei
   selbst bleibt unangetastet (siehe assets/README.md). */
.signet .fsi{display:block; height:60px; width:auto; filter:brightness(0) invert(1)}

@supports (mask-image:url(#a)) or (-webkit-mask-image:url(#a)){
  .signet .fell{
    background:var(--bg-deep);
    -webkit-mask:url(/zeichen/charite-baer.svg) no-repeat center/contain;
    mask:url(/zeichen/charite-baer.svg) no-repeat center/contain;
  }
  /* Das Bild trägt nur noch Maß und Alternativtext; gezeigt wird die Maske. */
  .signet .fell img{opacity:0}
}

/* Der Kopf der Einladung ist eine feste Vektorzeichnung in der weichen
   Retro-Displayform des Posters. Die Buchstaben sind Pfade: keine externe
   Schrift, kein Rasterbild und keine abweichende Darstellung je Gerät.
   Ein tiefer Kobaltversatz gibt ihnen dieselbe gedruckte Körperlichkeit wie
   der Vorlage; zwei Limettenfunken binden sie an die übrige Palette. */
.titel{margin:0 0 1.1rem; line-height:0; color:var(--ink)}
.titel .poster-titel{display:block; width:100%; height:auto; margin:0;
  overflow:visible}
.titel .poster-schatten{fill:var(--bg-deep)}
.titel .poster-flaeche{fill:currentColor}
.titel .poster-funke{fill:var(--limette)}

/* Datum und Anlass stehen nebeneinander: links das Blatt mit der Uhrzeit,
   rechts Semester und Vorlesungswoche – die Zeilen, die sagen, wann im
   Semester der Abend liegt. Sie sitzen auf der Höhe der Tageszahl, damit
   Blatt und Text eine Linie halten. Wird die Spalte schmal, rutschen sie
   untereinander. Die Musik steht darunter in eigener Zeile. */
.termin-satz{display:flex; flex-wrap:wrap; align-items:center;
  gap:1rem 1.5rem; margin:0 0 1.1rem}

/* Das Datumsblatt und die Uhrzeit gehören zusammen und stehen deshalb in
   einem Block: das Blatt, darunter mittig die Zeit. Der Block ist so breit
   wie das Blatt, dann sitzt die Zeile von selbst unter der Tageszahl. */
.datumsblock{flex:none; width:6.2rem}

/* Datumsblock wie auf dem Plakat: Kobaltblau in einem kräftigen
   Limettenrahmen; zugleich der Griff zum Kalendereintrag. */
.kalenderblatt{margin:0; flex:none}
.kalenderblatt a{display:block; width:100%; text-align:center;
  text-decoration:none; border:3px solid var(--limette); color:var(--ink)}
.kalenderblatt a:hover{box-shadow:4px 4px 0 var(--limette)}
.kalenderblatt .monat{display:block; padding:.2rem 0 .25rem; font-size:12px;
  font-weight:500; color:var(--limette); border-bottom:1px solid var(--limette)}
/* Alle drei Zeilen bleiben hell auf Kobalt; der Monat greift Limette auf.
   Das Blatt trägt das Datum, und das Datum ist die Auskunft, wegen der man
   auf die Seite kommt: Die Zahl steht deshalb halbfett, Monat und Wochentag
   eine Spur kräftiger als der Text daneben. Fett wäre zu viel – dann stünde
   es lauter da als der Name des Abends darüber. */
.kalenderblatt .zahl{display:block; background:var(--blatt); color:var(--ink);
  font:600 38px/1 var(--sans); letter-spacing:-.045em;
  font-variant-numeric:lining-nums; padding:.18em 0 .06em}
.kalenderblatt .wochentag{display:block; background:var(--blatt); color:var(--ink);
  font-size:12px; font-weight:500; padding:0 0 .35rem}

/* Neben dem Blatt: das Semester, darunter die Vorlesungswoche. Reicht der
   Platz nicht, rücken die Zeilen ganz unter das Blatt. */
.termin-angaben{flex:1 1 13rem; min-width:0}
.termin-angaben p{margin:0; color:var(--mute); font-size:15px; line-height:1.4;
  letter-spacing:-.012em}
.termin-angaben .semester{color:var(--limette); font-weight:700}
.termin-angaben .anlass{font-size:13px; margin-top:.15rem}
.einlasszeit{margin:.4rem 0 0; font-size:13px; text-align:center}

/* Die Uhr bis zum Einlass: eine kleine Nebenauskunft, keine Schlagzeile. Sie
   läuft als eine Zeile mit, die Zahl fett, das Wort dahinter klein und grau –
   in der Größe kostet sie kaum Höhe, und das Datumsblatt bleibt das, was von
   oben ins Auge fällt. */
.uhr{display:flex; flex-wrap:wrap; gap:.15rem .9rem; margin:0 0 1.1rem;
  align-items:baseline}
.uhr[hidden]{display:none}
.uhr span{display:flex; align-items:baseline; gap:.25rem}
.uhr b{font:600 17px/1.2 var(--sans); letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.uhr small{font-size:12px; line-height:1.2; color:var(--mute)}

/* Musikrichtungen: eigene Zeile über die ganze Spalte, fett gesetzt, kein
   Genre bricht in sich um. */
.genres{margin:0 0 .35rem; color:var(--limette); font-weight:700; font-size:15px; line-height:1.5;
  text-wrap:balance}
.genres span{white-space:nowrap}

/* Ort: die Wortmarke des Hauses, darunter der Ausrichter. Die Wortmarke ist
   zugleich der Kartenlink; die Anschrift steht nicht darunter, sondern
   beschriftet ihn. Der Link umschließt nur das Bild, damit die Klickfläche
   nicht über die Zeile hinauswächst; beim Zeigen hebt ihn ein Limettenstrich
   unter der Marke.

   Die Wortmarke ist in der Datei schwarz. Statt sie auf eine weiße Kachel zu
   stellen, steht sie jetzt selbst hell auf dem Kobalt: `brightness(0)` zieht
   die Zeichnung schwarz, `invert(1)` dreht sie ins Helle – der leere Teil der
   Datei ist durchsichtig und bleibt es. Die Datei geht unverändert raus, hell
   ist nur das Bild auf dem Schirm (siehe assets/README.md). */
.saal{padding:1rem 0 2.25rem}
/* Der Abstand zur Zeile darunter ist der einer Beischrift, nicht der zweier
   Blöcke: Marke und Ausrichter gehören zusammen. */
.ort{margin:0 0 .8rem}
.ort a{display:block; width:66%; max-width:257px;
  padding:0 0 .5rem; border-bottom:2px solid transparent}
.ort a:hover,.ort a:focus-visible{border-bottom-color:var(--limette)}
.mark{display:block; width:100%; height:auto; filter:brightness(0) invert(1)}

/* Der Ausrichter, ausgeschrieben unter der Wortmarke des Hauses: kleine ruhige
   Zeile, damit sie die Marke begleitet und nicht mit ihr um Aufmerksamkeit
   streitet. Signete stehen hier keine mehr – das der Fachschaftsinitiative
   ist nach oben zum Bären gezogen, das des Vereins ist weg. */
.ausrichter{margin:0; font-size:13px; line-height:1.4; color:var(--mute)}

/* Der Kauf steht auf derselben Seite. Ein eigenes Band in tiefem Nachtblau
   setzt ihn von der Einladung ab, ohne eine zweite Seite zu brauchen. Nach
   unten hält das Band keinen Abstand: Die Campus-Szene beginnt unmittelbar an
   seiner Kante. */
.kauf{background:var(--bg-deep); border-top:1px solid var(--limette);
  border-bottom:1px solid var(--limette); padding:2rem 0 2.25rem; margin:0}
.kauf>.satz>h2:first-child{margin-top:0}
.kauf .card{border:0; background:none; padding:0; margin:0 0 1.35rem}

/* Die Überschrift des Kaufs ist das Zeichen selbst: ISO 7001 PI PF 010, das
   Piktogramm für Tickets. Anders als die Zeichen am Fuß der Seite steht es
   frei – keine Kontur, keine Kachel: In dieser Größe sähe ein gerahmtes
   Zeichen aus wie eine Schaltfläche und wollte angeklickt werden. Hier ist es
   Überschrift und nicht Verweis; das Wort trägt der Alternativtext.

   Das weiße Feld unter der Zeichnung bringt die Originaldatei selbst mit –
   und genau dieses Feld soll nicht dastehen. Zwei Schritte nehmen es weg:
   `invert(1)` dreht die Datei um, die schwarze Zeichnung wird weiß und das
   weiße Feld schwarz; `mix-blend-mode:screen` legt das Ergebnis so auf den
   Grund, dass Schwarz darin aufgeht und nur das Weiße stehen bleibt. Übrig
   ist das Piktogramm, weiß auf dem Band – ohne Kasten. Die Datei bleibt
   unangetastet (siehe assets/README.md). */
.kauf-titel{margin:0 0 1.1rem; line-height:0}
.kauf-titel .pf010{display:block; width:96px; height:96px;
  filter:invert(1); mix-blend-mode:screen}

/* --- Die Daten des Besuchers --------------------------------------------
   Das Formular ist eine Spalte, aber was zusammengehört, steht in einer Zeile:
   Vorname und Familienname, Straße und weitere Adresszeile, Postleitzahl und
   Ort. Die Hälften sind gleich breit – außer bei der Postleitzahl, die kurz
   ist und keine halbe Zeile braucht. Wird die Spalte schmal, rutschen die
   Paare von selbst untereinander. */
/* Die Grundbreite ist knapp gewählt (8rem): Auf einem Telefon von 320 px
   bleiben die beiden Hälften damit noch nebeneinander, statt bei der ersten
   Verengung umzubrechen – und ein Feld, das schmaler ist als sein Inhalt,
   schiebt seinen Text ohnehin mit. */
.paar{display:flex; gap:1rem; flex-wrap:wrap}
/* Bricht eine Beschriftung auf zwei Zeilen um, während die daneben einzeilig
   bleibt, stünden die Felder versetzt. Die Hälften sind gleich hoch, und was
   in ihnen steht, hängt unten – damit stehen die Felder auf einer Linie. */
.paar>div{flex:1 1 8rem; min-width:0;
  display:flex; flex-direction:column; justify-content:flex-end}
.paar.plz>div:first-child{flex:0 1 7rem}
.paar label{margin-top:1.25rem}

/* Die Adressen gehören zusammen: die eigene, die private daneben und die der
   Charité – oder der Buchungscode an deren Stelle. Untereinander gelesen wären
   es drei weitere Fragen zur Person; ein wenig Luft darunter und das Wort
   darüber machen eine daraus, so wie es die Anschrift weiter unten schon tut.
   Das Wort steht in der Farbe des Textes und etwas kräftiger als eine
   Beschriftung – es ist die Überschrift des Blocks und kein Feldname. */
.kauf fieldset.mails{margin-top:.6rem; margin-bottom:1.8rem}
/* Die erste Adresse rückt näher an das Wort heran: Der übliche Abstand einer
   Beschriftung ließe die Überschrift allein stehen. Blendet das Skript die
   Blöcke darunter aus, bleibt genau diese eine Zeile stehen – der Block
   schrumpft auf sie zusammen, statt auseinanderzufallen. */
.kauf fieldset.mails>label:first-of-type{margin-top:0}

/* Der zweite Teil einer Beschriftung – „für den Ticketversand“. Er steht in
   derselben Zeile und derselben Größe, nur heller: Der Feldname ist die
   Frage, der Zusatz die Erläuterung dazu. Ist er nicht an der Reihe, nimmt
   ihn das Skript mit `hidden` weg. */
.zusatz{color:var(--mute)}
.zusatz[hidden]{display:none}

/* Der Teil für Charité-Leute: Die Überschrift links, das Wort „optional“
   rechts auf derselben Linie. Es ist kein zweiter Titel, sondern die Auskunft
   darüber, ob dieser Teil einen etwas angeht – also steht es kleiner als die
   Überschrift und in derselben stillen Farbe, an der Kante, wo der Blick die
   Zeile ohnehin verlässt. Bricht die Überschrift auf einem schmalen Schirm
   um, rutscht das Wort mit; ein Umbruch in ihm selbst wäre keiner. */
#studium>h3{display:flex; align-items:baseline; justify-content:space-between;
  gap:1rem; flex-wrap:wrap}
#studium>h3 .optional{font-size:13px; color:var(--mute); white-space:nowrap}

/* Der Haken steht hier ausnahmsweise oben, nicht vor der Schaltfläche: Er ist
   die erste Frage dieses Teils und entscheidet über die beiden darunter. Der
   übliche Abstand eines Hakens gehört zu einem, der einen Block abschließt –
   dieser eröffnet ihn und rückt näher an die Überschrift. */
.haken.haken-oben{margin:.35rem 0 0}
/* Nimmt der Haken die Fragen weg, bleibt die Karte auf Überschrift und Haken
   stehen – ohne den Abstand, den die erste Beschriftung sonst mitbrächte. */
#studienfragen[hidden]{display:none}

/* Der Hinweis zur Verwendung steht am Fuß des Adressblocks – einmal, unter
   beiden Feldern, denn er gilt für beide zusammen. Der Haken für den
   Newsletter stand hier einmal daneben; er steht jetzt ganz unten, vor der
   Schaltfläche (siehe `.haken`). */
.mail-verwendung{margin:.65rem 0 0}
button.hinweis-verwendung{border:0; padding:0; background:transparent;
  color:var(--mute); font-size:13px; text-decoration:underline;
  text-decoration-thickness:1px; text-underline-offset:.22em;
  text-decoration-color:var(--line)}
button.hinweis-verwendung:hover{border:0; background:transparent; color:var(--ink);
  text-decoration-color:var(--limette)}

/* Die Anschrift ist ein Block für sich. Untereinander gelesen sähen Straße,
   Adresszeile, Postleitzahl und Ort aus wie vier weitere Fragen zur Person;
   ein wenig Luft davor und das Wort darüber machen aus ihnen eine Adresse. Das
   Wort steht in der Farbe des Textes und etwas kräftiger als eine Beschriftung
   – so liest es sich als Überschrift des Blocks und nicht als Feldname. */
.kauf fieldset.anschrift{margin-top:2.25rem}
.kauf fieldset.anschrift>legend{color:var(--ink); font-weight:600}
/* Die erste Reihe rückt näher an das Wort heran: Der übliche Abstand einer
   Beschriftung zum Feld darüber ließe die Überschrift allein stehen. */
.kauf fieldset.anschrift>.paar:first-of-type label{margin-top:.55rem}

/* Das freiwillige zweite Adressfeld bleibt hinter einem kleinen nativen
   Disclosure. Mit einem zurückgegebenen Wert ist <details open> und die
   Eingabe dadurch sofort sichtbar. */
.adresszusatz{margin-top:1rem}
.adresszusatz summary{display:block; list-style:none; width:max-content; max-width:100%;
  color:var(--mute); font-size:13px; cursor:pointer; text-decoration:underline;
  text-decoration-thickness:1px; text-underline-offset:.22em;
  text-decoration-color:var(--line)}
.adresszusatz summary::-webkit-details-marker{display:none}
.adresszusatz-symbol::before{content:"+"; display:inline-block; width:1.1em;
  text-decoration:none}
.adresszusatz[open] .adresszusatz-symbol::before{content:"−"}
.adresszusatz summary:hover{color:var(--ink); text-decoration-color:var(--limette)}
.adresszusatz[open] summary{margin-bottom:.2rem}
.adresszusatz input{margin-top:.65rem}

/* Ein Rahmen ohne Rahmen: `fieldset` hält Frage und Antworten für
   Vorlesekräfte zusammen, gezeichnet wird nichts davon. */
.kauf fieldset{border:0; padding:0; margin:1.75rem 0 0; min-width:0}
.kauf legend{padding:0; font-size:13px; color:var(--mute); line-height:1.5}
.kauf legend + .small{margin-top:.25rem}

/* --- Zahlungsmethoden ----------------------------------------------------
   Drei Zeilen zum Ankreuzen, jede mit dem Wort, den Marken und einem Satz
   dazu. Die Marken stehen rechts am Rand: Erkannt wird die Zeile am Bild,
   gelesen wird sie am Wort – und wer sie vorgelesen bekommt, hört das Wort,
   weil das Bild seinen Namen im `alt` trägt.
   ------------------------------------------------------------------------ */

.zahlarten{border:0; padding:0; margin:1.25rem 0 0; min-width:0}
.zahlarten>legend{padding:0; font-size:13px; color:var(--mute); line-height:1.5}

.zahlart{display:grid; grid-template-columns:auto 1fr auto; align-items:center;
  gap:.2rem .9rem; margin:.75rem 0 0; padding:.85rem 1rem;
  border:1px solid var(--line); font-size:15px; color:var(--ink); cursor:pointer}
.zahlart:hover{border-color:var(--blau)}
/* Die gewählte Zeile bekommt die Kontur – dieselbe Linie wie ein Feld, nur
   umlaufend. Farbe braucht es dafür nicht: Der Punkt im Kästchen ist blau,
   und zwei blaue Zeichen für dieselbe Aussage wären eines zu viel. */
.zahlart:has(input:checked){border-color:var(--line-hard)}
/* Der Punkt sitzt in seiner eigenen Spalte; der Abstand kommt vom Raster. */
.zahlart input[type=radio]{margin:0}
.zahlart .erlaeuterung{grid-column:2 / 4; font-size:13px; color:var(--mute); line-height:1.5}

/* Die Marken der Zahlungsmethoden, unverändert wie geliefert. Jede Datei
   bringt ihre eigene Schutzzone mit – die Visa-Wortmarke steht in weniger als
   einem Drittel ihrer Fläche, das Mastercard-Zeichen füllt zwei Drittel.
   Deshalb sind die Höhen hier verschieden: Erst so erscheinen die Marken
   nebeneinander gleich groß.

   Für Apple Pay und Google Pay steht hier nichts mehr: Der Shop zeigt als
   Kartenmarken nur noch Visa und Mastercard (siehe src/zahlarten.js). */
.marken{display:inline-flex; flex-wrap:wrap; align-items:center; gap:.35rem;
  justify-self:end}
.marken img{display:block; width:auto}
.marken .visa{height:42px}
.marken .mc{height:28px}
.marken .sepa{height:22px}
/* In einer laufenden Zeile und über den Kartenfeldern stehen sie kleiner –
   dort begleiten sie das Wort, statt die Zeile zu tragen. */
.marken.klein .visa{height:30px}
.marken.klein .mc{height:19px}
.marken.klein .sepa{height:18px}

/* Die Schaltfläche unter der Auswahl braucht Luft: Ein `fieldset` bringt
   selbst keine mit, und ohne sie klebte sie an der letzten Zeile. */
fieldset.zahlarten + p{margin-top:1.5rem}

/* Wohin überwiesen werden soll: eine Tabelle aus Begriff und Angabe, die
   Angaben in der Schreibmaschinenschrift – sie werden abgetippt. */
table.anweisung{margin:1rem 0 0}
table.anweisung th{width:11rem}

@media (max-width:420px){
  .zahlart{grid-template-columns:auto 1fr; gap:.35rem .7rem}
  .zahlart .marken{grid-column:2; justify-self:start}
  .zahlart .erlaeuterung{grid-column:2 / 3}
  table.anweisung th{width:auto}
}

/* Was das Skript ausblendet, ist weg – auch dann, wenn eine Regel darüber
   dem Element ein `display` gibt. */
[hidden]{display:none !important}

/* Das Auskunftszeichen ist in der Datei schwarz auf durchsichtigem Grund und
   steht hier hell auf dem Kobalt – dieselbe Rechnung wie bei der Wortmarke. Die
   Kachel darunter ist weg; geblieben ist die Fläche von 46 px, damit ein
   Finger sie trifft. Sie ist jetzt durchsichtig, und weil das Zeichen keinen
   Rand mehr hat, darf es darin größer stehen. Beim Zeigen kommt der Limetten-
   Strich darunter – derselbe wie unter der Wortmarke. */
.zeichen{display:flex; align-items:center; gap:1rem; margin:0}
.zeichen a{display:flex; align-items:center; justify-content:center;
  width:46px; height:46px; color:var(--ink); text-decoration:none;
  border-bottom:2px solid transparent}
.zeichen a:hover,.zeichen a:focus-visible{border-bottom-color:var(--limette)}
.zeichen img{display:block; filter:brightness(0) invert(1)}
.zeichen .iso0435{width:28px; height:28px}

/* Steht das Wort dabei, ist die Fläche nicht mehr quadratisch: Sie wächst
   nach links um den Text, bleibt aber 46 px hoch. Der Limettenstrich beim
   Zeigen läuft dann unter beidem durch – Wort und Zeichen sind eine Marke,
   nicht zwei Ziele. */
.zeichen a:has(.wort){width:auto; padding:0 .1rem; gap:.5rem}
.zeichen .wort{font-size:15px; color:var(--ink)}

/* Das Auskunftszeichen der Einladung sitzt oben rechts in der Spalte: Es
   fluchtet mit deren rechtem Rand und nicht mit der Kante des Schirms. Der
   Kasten darum ist nur der Satzspiegel und selbst ohne Höhe – das Zeichen
   hängt darin und nimmt dem Satz keinen Platz. Links darunter beginnt der
   Bär auf seiner Kachel. */
.satz.ecke{position:relative; height:0}
.satz.ecke .zeichen{position:absolute; top:var(--luft); right:var(--luft); z-index:2}

/* --- Flächen ------------------------------------------------------------- */

.card{background:var(--panel); border:1px solid var(--line); padding:1.5rem; margin:0 0 1.25rem}
.card>h2:first-child,.card>form>h2:first-child{margin-top:0}
.grid{display:grid; gap:1.25rem}
@media(min-width:720px){
  .grid.cols-2{grid-template-columns:1fr 1fr}
  .grid.cols-3{grid-template-columns:repeat(3,1fr)}
}

/* --- Formulare ----------------------------------------------------------- */

label{display:block; font-size:13px; color:var(--mute); margin:1.25rem 0 .3rem}
input,select,textarea{width:100%; padding:10px 12px; background:var(--bg-deep); color:var(--ink);
  border:1px solid var(--line-hard); border-radius:0; font:400 16px/1.4 var(--sans);
  appearance:none}
/* Ein Feld unter 16px lässt iOS Safari beim Antippen in die Seite zoomen, und
   erst dieser Zoom macht sie seitlich schiebbar. Also nirgends kleiner – auch
   nicht, wenn eine Klasse sonst verkleinert: .small und .mono treffen ein Feld
   mit höherer Spezifität als die Regel darüber und müssen einzeln zurück. */
input,select,textarea,
input.small,select.small,textarea.small,
input.mono,select.mono,textarea.mono{font-size:16px}
select{background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
  linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 16px) center,calc(100% - 11px) center;
  background-size:5px 5px; background-repeat:no-repeat; padding-right:34px}
input:hover,select:hover,textarea:hover{border-color:var(--blau)}
input:focus-visible,select:focus-visible,textarea:focus-visible{outline-offset:2px}

/* Ein Feld, dessen Domain feststeht: „@charite.de“ steht neben der Eingabe als
   Text und nicht als zweites Feld – zu bearbeiten ist daran nichts. Der Rahmen
   liegt um beides und trägt, was sonst das Feld selbst trägt: Kontur, Fläche,
   die Farbe der Beanstandung. Das Feld darin ist randlos und nimmt den Platz,
   der übrig bleibt; die Linie davor sagt, wo das Getippte aufhört.

   Der Fokusring liegt am Rahmen und nicht am Feld darin – ein Ring um ein
   randloses Feld mitten in einem Rahmen sähe aus wie ein zweites Feld. Er
   kommt damit auch beim Klicken; das ist die kleinere Abweichung.

   Tippt jemand eine ganze Adresse, nimmt das Skript die Domain mit `hidden`
   weg (siehe src/ticketformular.js und src/routes/hilfe.js) – sie stünde sonst
   ein zweites Mal da. */
.mailfeld{display:flex; align-items:stretch;
  background:var(--bg-deep); border:1px solid var(--line-hard)}
.mailfeld:hover{border-color:var(--blau)}
.mailfeld:focus-within{outline:2px solid var(--limette); outline-offset:2px}
.mailfeld:has(input[aria-invalid=true]){border-color:var(--err)}
.mailfeld input{flex:1 1 auto; width:auto; min-width:0; border:0; background:none}
.mailfeld input:focus-visible{outline:none}
.mailfeld-domain{flex:none; display:flex; align-items:center; padding:0 12px;
  border-left:1px solid var(--line); color:var(--mute);
  font:400 16px/1.4 var(--sans); white-space:nowrap}
.mailfeld-domain[hidden]{display:none}

/* Ein Feld, dessen Inhalt schon beim Tippen beanstandet wurde. Die Kontur
   trägt die Aussage, die daneben in Worten steht (siehe .feldmeldung) –
   `:invalid` allein wird hier bewusst nicht gefärbt: Ein Pflichtfeld ist
   ungültig, bevor es überhaupt jemand angesehen hat. */
input[aria-invalid=true]{border-color:var(--err)}
input[aria-invalid=true]:hover{border-color:var(--err)}

/* Die Rückmeldung unter einem Feld: eine Zeile, klein, in der Farbe ihrer
   Aussage. Rot beanstandet und hält das Absenden auf, Gelb weist nur hin,
   Grün bestätigt – die Adresse an der Charité ist erkannt. Ohne Text steht
   der Absatz auf `hidden` und nimmt keinen Platz ein. */
.feldmeldung{margin:.4rem 0 0; font-size:13px; line-height:1.45; color:var(--err)}
.feldmeldung.hinweis{color:var(--warn)}
.feldmeldung.ok{color:var(--ok)}
input[type=number]{max-width:110px; font-family:var(--mono)}
/* Kalender und Bedienung kommen vom Browser/OS. Der allgemeine Form-Reset
   darf den nativen Datepicker nicht in ein gewöhnliches Textfeld verwandeln. */
input[type=date]{appearance:auto; -webkit-appearance:auto; color-scheme:dark}
/* Kästchen und Punkte zeichnet der Browser selbst. Die Regel weiter oben nimmt
   jedem Feld sein Aussehen – hier bliebe davon ein leeres Rechteck, das auch
   angekreuzt leer aussieht. Also alles zurück auf Original, nur die Farbe des
   Hakens ist unsere. */
input[type=radio],input[type=checkbox]{appearance:auto; -webkit-appearance:auto;
  width:auto; height:auto; padding:0; border:0; background:none;
  margin:0 9px 0 0; accent-color:var(--limette)}

button,.btn{display:inline-block; padding:11px 22px; border:1px solid var(--limette);
  border-radius:0; background:var(--limette); color:var(--auf-hell);
  font:400 15px/1.35 var(--sans); letter-spacing:-.006em;
  cursor:pointer; text-decoration:none; text-align:center}
/* Auf den hellen Flächen – Limette im Ruhezustand, Elfenbein beim Zeigen –
   steht die Beschriftung dunkel. */
button:hover,.btn:hover{background:var(--ink); border-color:var(--ink); color:var(--auf-hell)}
button.secondary,.btn.secondary{background:transparent; color:var(--ink); border-color:var(--line-hard)}
button.secondary:hover,.btn.secondary:hover{background:var(--limette); color:var(--auf-hell); border-color:var(--limette)}
/* Die Schaltfläche, die etwas wegnimmt, ist eine Fläche und trägt deshalb den
   tiefen Ton mit weißer Schrift; beim Zeigen kehrt sie sich um. */
button.danger,.btn.danger{background:var(--err-flaeche); border-color:var(--err-flaeche); color:#fff}
button.danger:hover,.btn.danger:hover{background:var(--err); border-color:var(--err);
  color:var(--auf-hell)}
button.danger.secondary{background:transparent; color:var(--err); border-color:var(--err)}
button.danger.secondary:hover{background:var(--err); color:var(--auf-hell)}
button.small,.btn.small{padding:6px 12px; font-size:13px}
button:disabled{opacity:.35; cursor:not-allowed}
button:disabled:hover{opacity:.35; background:var(--limette); border-color:var(--limette); color:var(--auf-hell)}

/* Eine Schaltfläche direkt hinter einem Feld oder einer Karte braucht Luft
   nach oben – der Absatz, in dem sie steht, bringt selbst keine mit. */
input + p > button, input + p > .btn,
select + p > button, select + p > .btn,
textarea + p > button, textarea + p > .btn,
.mailfeld + p > button, .mailfeld + p > .btn,
.card + p > button, .card + p > .btn{margin-top:1.25rem}

/* Eingebettete Kartenzahlung. Das eigentliche Feld zeichnet Stripe in einem
   eigenen sicheren iframe; hier stehen nur Platz und Status.
   Der Abstand nach oben gehört der Preiszeile darüber: Ohne Stripe steht hier
   statt des Feldes ein Hinweis, und `.notice` bringt keinen oberen Rand mit –
   der Abstand wäre sonst genau dann weg, wenn nicht bezahlt werden kann. */
.checkout{padding-top:.4rem !important}
/* Der Block bekommt sein Wort: „Kartendaten“, in der Farbe des Textes und
   etwas kräftiger als eine Beschriftung – dieselbe Überschrift wie über der
   Anschrift, denn es ist derselbe Fall. Marken stehen nicht daneben: Welche
   Karten angenommen werden, zeigt Stripe im Feld für die Kartennummer selbst.
   Den Abstand nach oben setzt die Preiszeile darüber, deshalb bringt der
   Block selbst keinen mit. */
.kauf fieldset.kartendaten{margin:0}
.kartendaten>legend{color:var(--ink); font-weight:600}
#payment-element{min-height:11rem; margin:.55rem 0 0}
#zahlungsfehler{margin:1rem 0}
.checkout>#zahlungspflichtig{width:100%; margin-top:.5rem}

/* Der Betrag: eine Zahl, mehr steht nicht da. Sie steht eine Spur kräftiger
   als der Text daneben und sonst nichts – nicht als Überschrift und nicht als
   Schlagzeile: Wer bis hierher gescrollt hat, sucht die Zahl nicht, er hat
   sie schon gefunden. Groß gesetzt sähe der Preis nach Angebot aus, und
   daneben steht ohnehin die Zeile, die sagt, wofür er gilt.
   Die Ziffern stehen in gleicher Breite – so springt der Betrag nicht, wenn
   das Skript ihn nach einem Preiswechsel austauscht. */
.betrag{margin:0; font:600 clamp(16px,2.2vw,18px)/1.3 var(--sans);
  letter-spacing:-.01em; font-variant-numeric:tabular-nums lining-nums;
  color:var(--ink)}

/* Zahl und Abend stehen nebeneinander auf einer Grundlinie. Die Zeile daneben
   nimmt den Rest der Breite und bricht in sich um; wird die Spalte zu schmal,
   rutscht sie ganz unter die Zahl. */
.preiszeile{display:flex; align-items:baseline; flex-wrap:wrap;
  gap:.35rem 1.1rem; margin:0 0 1.35rem}
.anlasszeile{margin:0; flex:1 1 17rem; color:var(--mute); font-size:13px;
  line-height:1.4; text-wrap:balance}
/* In dieser Zeile steht der Preis in der Gestalt, die er früher oben auf einer
   eigenen Karte hatte (siehe `.preis` weiter unten). Den unteren Rand setzt
   hier die Zeile, nicht der Absatz; die Ziffern stehen in gleicher Breite,
   damit der Betrag nicht springt, wenn das Skript ihn nach einem Preiswechsel
   austauscht. */
.preiszeile .preis{margin:0; font-variant-numeric:tabular-nums lining-nums}
/* Tag und Uhrzeit sind eine Angabe und werden nicht auseinandergerissen. */
.anlasszeile time{white-space:nowrap}

/* Ein Haken mit seinem Wort in einer Zeile, unmittelbar vor der Schaltfläche.
   Beschriftungen stehen sonst über dem Feld – ein Kästchen ist aber schmaler
   als sein Wort und gehört daneben. Das Wort ist hier keine Frage, sondern
   die Antwort selbst, und steht deshalb in der Farbe des Textes. Die ganze
   Zeile ist anklickbar. */
.haken{margin:1.75rem 0 1rem}
.haken label{display:flex; align-items:baseline; gap:.6rem; margin:0;
  font-size:15px; color:var(--ink); cursor:pointer}
.haken input[type=checkbox]{margin:0; flex:none; align-self:center}

/* Der Nachtrag unter der Schaltfläche: der Weg zu den Bedingungen, nicht
   deren Inhalt. Ausgeschrieben standen sie hier einmal und füllten einen
   Bildschirm mit Text, den vor dem Kauf niemand liest. */
.nachtrag{margin:1rem 0}

/* Nach erfolgreicher Bestätigung gibt es bewusst kein Seitengerüst und keine
   zweite Information: nur den Eingang der Bestellung in der Bildschirmmitte. */
body.bestellung-eingegangen{min-height:100vh; min-height:100dvh;
  display:grid; place-items:center; padding:2rem; background:var(--bg-deep)}
body.bestellung-eingegangen main{width:auto; max-width:none; margin:0; padding:0}
body.bestellung-eingegangen h1{margin:0; text-align:center}

/* --- Tabellen ------------------------------------------------------------ */

table{width:100%; max-width:100%; border-collapse:collapse; font-size:14px}
th,td{text-align:left; padding:10px 12px 10px 0; border-bottom:1px solid var(--line);
  vertical-align:top; overflow-wrap:break-word}
/* Ticketcodes und Beträge brechen um, statt die Tabelle breitzudrücken. */
td.mono,td .mono,td.num,th.num{overflow-wrap:anywhere}
th{font-weight:400; font-size:12px; color:var(--mute)}
td.num,th.num{text-align:right; padding-right:0; font-variant-numeric:tabular-nums}
td:last-child,th:last-child{padding-right:0}

/* --- Marken und Hinweise ------------------------------------------------- */

.tag{display:inline-block; padding:2px 7px; border:1px solid var(--line-hard);
  border-radius:0; font-size:11px; line-height:1.55; color:var(--ink)}
.tag.skip{color:var(--skip); border-color:currentColor}
.tag.free{color:var(--ok); border-color:currentColor}
.tag.used{color:var(--err); border-color:currentColor}
.tag.warn{color:var(--warn); border-color:currentColor}

.notice{background:var(--panel); border:1px solid var(--line);
  border-left:4px solid var(--mute); padding:12px 16px; margin:0 0 1.25rem}
.notice.err{border-left-color:var(--err)}
.notice.ok{border-left-color:var(--ok)}
.notice.warn{border-left-color:var(--warn)}
.notice strong{display:block; margin-bottom:2px}
.notice p:last-child{margin-bottom:0}

/* --- Preis und Pflichtangaben -------------------------------------------- */

/* Der Preis steht nur noch an einer Stelle: unten in der Kaufkarte, gleich
   über der Zahlung (siehe `.preiszeile`). Die Größe ist die der früheren
   Preiskarte – eine Spur größer als der Text daneben und weit entfernt von
   einer Schlagzeile. */
.preis{font-size:18px; margin:0 0 .5rem}
.preis .tag{margin-left:.5rem; vertical-align:2px}
/* Der reguläre Preis, durchgestrichen vor dem Frühbucherpreis. */
.preis .statt{color:var(--mute); font-size:15px; margin-right:.35rem;
  text-decoration-thickness:1px}

.pflicht{margin:0}
.pflicht dt{font-size:13px; color:var(--mute); margin:1.25rem 0 .25rem}
.pflicht dt:first-of-type{margin-top:0}
.pflicht dd{margin:0}

/* --- Preisaufstellung ---------------------------------------------------- */

.sum{list-style:none; padding:0; margin:0; font-size:14px}
.sum li{display:flex; justify-content:space-between; gap:14px; padding:9px 0;
  border-bottom:1px solid var(--line); font-variant-numeric:tabular-nums}
.sum li.discount{color:var(--ok)}
.sum li.total{border-bottom:0; border-top:1px solid var(--line-hard);
  font-weight:600; font-size:17px; padding-top:12px}

/* --- Pegelbalken --------------------------------------------------------- */

.bar{position:relative; height:8px; border:1px solid var(--line-hard); background:var(--panel);
  overflow:hidden; margin:10px 0 8px}
.bar>span{display:block; height:100%; background:var(--limette)}

/* --- Zahlen und Codes ---------------------------------------------------- */

.big{font:400 clamp(32px,6vw,44px)/1.1 var(--sans); letter-spacing:-.02em;
  font-variant-numeric:tabular-nums; margin:.12em 0}
/* Ein Betrag ist länger als eine Anzahl: „1.234,00 €“ in der Größe einer
   zweistelligen Zahl spränge aus seiner Kachel. */
.big.geld{font-size:clamp(24px,3.6vw,32px)}
.codebox{font:400 clamp(18px,4vw,24px)/1.4 var(--mono); letter-spacing:.1em;
  background:var(--limette); color:var(--auf-hell); border:1px solid var(--line-hard);
  padding:14px; word-break:break-all}

/* Der Buchungslink auf der Bestellseite. Er will kopiert und verschickt
   werden, also steht er ganz da und darf umbrechen, wo er muss. Ohne Farbe:
   Er meldet nichts, er ist eine Adresse – der Rahmen genügt, um sie vom
   Fließtext zu lösen. */
.linkbox{font-family:var(--mono); font-size:14px; line-height:1.6;
  border:1px solid var(--line); padding:12px; word-break:break-all}

/* --- Portal --------------------------------------------------------------
   Die Zeile über den Zahlen: wann sie gemessen wurden und ob die Leitung
   steht. Das Wort „live“ ist eine Zusage – steht die Leitung nicht, muss es
   auch anders dastehen, sonst liest jemand alte Zahlen für neue. */

.portal-stand{color:var(--mute); font-size:13px; margin:0 0 1.25rem}
.portal-stand time{font-variant-numeric:tabular-nums}
/* Der Punkt davor: grün, solange die Zahlen nachrücken. */
.portal-live::before,.portal-tot::before{content:""; display:inline-block;
  width:7px; height:7px; margin-right:.4rem; vertical-align:1px; border-radius:50%}
.portal-live{color:var(--ok)}
.portal-live::before{background:currentColor}
.portal-tot{color:var(--warn)}
.portal-tot::before{background:currentColor}

/* --- Einlasskontrolle ----------------------------------------------------
   Am Einlass zählt Erkennbarkeit auf einen Blick – hier trägt die Farbe die
   Aussage und darf deshalb die ganze Fläche füllen. */

.result{padding:2rem 1.5rem; margin:0 0 1.25rem; border:1px solid transparent; color:#fff}
.scan-ok{background:var(--ok-flaeche)}
.scan-err{background:var(--err-flaeche)}
.scan-skip{background:var(--skip-flaeche)}
.result .muted,.result .tag{color:inherit; opacity:.85; border-color:currentColor}
.result .tag{background:transparent}

/* Bleibt eine Tabelle zu breit, scrollt sie in sich selbst und nicht die Seite. */

@media (max-width:640px){
  table{display:block; overflow-x:auto; overscroll-behavior-x:contain}
}

@media (max-width:420px){
  :root{--luft:1.25rem}
  .aufmacher{padding:1.75rem 0 1.25rem}
  .signet{gap:1.1rem}
  .signet .fell img,.signet .fsi{height:52px}
  /* Die Kachel zählt ihre Polsterung nach innen: auf dem schmalen Schirm
     bekommt sie ein Stück mehr Breite, damit die Marke darin nicht schrumpft. */
  .ort a{width:76%}
}

/* --- Campus-Szene ---------------------------------------------------------
   Der Fries unter der Einladung, gezeichnet in src/klinik.js: Bettenhochhaus,
   Tanzfläche, Hörsaal, Notaufnahme. Er steht in der Spalte des Inhalts und
   hängt ohne jeden Abstand am Kaufband darüber – der Abstand dafür fehlt auf
   beiden Seiten: hier `margin:0`, dort keiner nach unten.

   Farbe trägt hier eine Aussage wie sonst nur am Einlass: Fensterlicht, Rot am
   Schild, Blau auf dem Wagen, das Licht von der Kugel. Alles andere bleibt
   Haarlinie. Der Takt: 0,48 Sekunden je Schlag, rund 125 in der Minute –
   darauf gehen Membranen, Beine, Herz und Bett. Wer keine Bewegung will,
   bekommt dasselbe Bild im Stillstand.
   -------------------------------------------------------------------------- */

/* Auf dem kobaltblauen Grund ist der Fries eine Nachtansicht: Die Zeichnung
   steht elfenbeinfarben (`--ink`), die Flächen darin tragen den Grund. Zwei Töne mussten dafür
   die Seite wechseln – ein unbeleuchtetes Fenster ist jetzt dunkler als die
   Wand, nicht heller, und das Blaulicht leuchtet, statt zu versacken. */
.klinik-band{
  --k-licht:#cfef4c;     /* erleuchtetes Fenster */
  --k-dunkel:#03064f;    /* dunkles Fenster      */
  --k-blau:#96a8ff;      /* Blaulicht            */
  --k-pink:#f0ecff;      /* Licht von der Kugel  */
  --k-cyan:#8ea2ff;      /* Licht von der Kugel  */
  width:100%; margin:0; line-height:0;
}
.klinik{display:block; width:100%; height:auto}

/* Grundformen */
.klinik .k-linie,.klinik .k-kontur,.klinik .k-treppe{fill:none; stroke:var(--ink); stroke-width:2}
.klinik .k-haar,.klinik .k-haar-pfad{fill:none; stroke:var(--ink); stroke-width:1; opacity:.45}
.klinik .k-flaeche,.klinik .k-pult{fill:var(--bg); stroke:var(--ink); stroke-width:2}
.klinik .k-glas,.klinik .k-leinwand{fill:var(--panel-2); stroke:var(--ink); stroke-width:1.5}
.klinik .k-linie-fuell{fill:var(--ink); stroke:none}
.klinik .k-boden{stroke:var(--ink); stroke-width:2}
.klinik .k-beutel{fill:var(--panel-2); stroke:var(--ink); stroke-width:1.5}

/* Bettenhochhaus: Fensterraster, ein paar Betten darin, gläserner Aufzug */
.klinik .k-fenster{fill:var(--k-dunkel); stroke:none}
.klinik .k-fenster.hell{fill:var(--k-licht)}
.klinik .k-fenster.flimmert{animation-name:k-flimmern; animation-iteration-count:infinite;
  animation-timing-function:steps(1,end)}
.klinik .k-fenster.disco{fill:var(--k-pink); animation:k-disco .96s steps(1,end) infinite}
.klinik .k-fenster.disco.b{fill:var(--k-cyan); animation-delay:-.48s}
.klinik .k-bett{fill:var(--ink); opacity:.5}
.klinik .k-beacon{fill:var(--err); animation:k-beacon 2.6s ease-in-out infinite}
.klinik .k-aufzug{animation:k-aufzug 15s ease-in-out infinite}

@keyframes k-flimmern{0%,88%{opacity:1}89%,90%{opacity:.2}91%,93%{opacity:1}94%,97%{opacity:.2}
  98%,100%{opacity:1}}
@keyframes k-disco{0%,49%{opacity:1}50%,100%{opacity:.25}}
@keyframes k-beacon{0%,42%{opacity:1}50%,100%{opacity:.12}}
@keyframes k-aufzug{0%,7%{transform:translateY(0)}45%,57%{transform:translateY(-256px)}
  95%,100%{transform:translateY(0)}}

/* Fahrradständer */
.klinik .k-felge,.klinik .k-rahmen{fill:none; stroke:var(--ink); stroke-width:2.5;
  stroke-linecap:round; stroke-linejoin:round}

/* Hörsaal: Leinwand, Plattenteller, Pulte */
.klinik .k-herz{fill:var(--err); transform-box:fill-box; transform-origin:center;
  animation:k-herz .48s ease-in-out infinite}
.klinik .k-platte{fill:var(--ink); stroke:none}
.klinik .k-platte-punkt{fill:var(--bg); stroke:none}
.klinik .k-kegel{fill:var(--k-licht); opacity:.22; stroke:none}
.klinik .k-becher{fill:var(--bg); stroke:var(--ink); stroke-width:1.5}
.klinik .k-buch{stroke:var(--ink); stroke-width:1}
.klinik .k-buch.rot{fill:var(--err)}
.klinik .k-buch.cyan{fill:var(--k-cyan)}
.klinik .k-buch.gelb{fill:var(--k-licht)}

@keyframes k-herz{0%,100%{transform:scale(1)}22%{transform:scale(1.18)}44%{transform:scale(1)}}

/* Discokugel */
.klinik .k-kugel-grund{fill:#c8d0ff; stroke:none}
.klinik .k-kugel-rand{fill:none; stroke:var(--ink); stroke-width:2}
.klinik .k-kachel{fill:#8795e8; stroke:var(--bg); stroke-width:1}
.klinik .k-kachel.hell{fill:#f0efff}
.klinik .k-kachel.pink{fill:var(--k-pink)}
.klinik .k-kachel.cyan{fill:var(--k-cyan)}
.klinik .k-kacheln{animation:k-kacheln 2.6s linear infinite}
.klinik .k-strahl{opacity:.11}
.klinik .k-strahl.pink{fill:var(--k-pink)}
.klinik .k-strahl.cyan{fill:var(--k-cyan)}
.klinik .k-glanz path{fill:var(--k-pink); animation:k-glanz 1.9s steps(1,end) infinite}
.klinik .k-glanz path.b{fill:var(--k-cyan); animation-delay:-.95s}

@keyframes k-kacheln{to{transform:translateX(-11px)}}
@keyframes k-glanz{0%,40%{opacity:.9}41%,100%{opacity:0}}

/* Boxentürme */
.klinik .k-membran{fill:var(--panel-2); stroke:var(--ink); stroke-width:2;
  transform-box:fill-box; transform-origin:center;
  animation:k-membran .48s ease-in-out infinite}
.klinik .k-membran.b{animation-duration:.96s}

@keyframes k-membran{0%,100%{transform:scale(1)}50%{transform:scale(1.16)}}

/* Wimpelkette */
.klinik .k-schnur{fill:none; stroke:var(--ink); stroke-width:1.5}
.klinik .k-kette{animation:k-kette 6.5s ease-in-out infinite}
.klinik .k-wimpel{stroke:none}
.klinik .k-wimpel.pink{fill:var(--k-pink)}
.klinik .k-wimpel.cyan{fill:var(--k-cyan)}
.klinik .k-wimpel.gelb{fill:var(--k-licht)}
.klinik .k-wimpel.rot{fill:var(--err)}
.klinik .k-wimpel.gruen{fill:var(--ok)}

@keyframes k-kette{0%,100%{transform:translateY(0)}50%{transform:translateY(4px)}}

/* Die Menge. Figuren sind Strich und Punkt: Kreis gefüllt, Pfade gestrichen. */
.klinik .k-tanz,.klinik .k-steht,.klinik .k-figur,.klinik .k-einlass g{stroke:var(--ink);
  stroke-width:3.2; stroke-linecap:round; stroke-linejoin:round}
.klinik .k-tanz circle,.klinik .k-steht circle,.klinik .k-figur circle,
.klinik .k-einlass circle{fill:var(--ink); stroke:none}
.klinik .k-tanz path,.klinik .k-steht path,.klinik .k-figur path,
.klinik .k-einlass path{fill:none}
.klinik .k-tanz .k-kittel{fill:var(--bg)}
.klinik .k-tanz{animation-name:k-tanz; animation-timing-function:ease-in-out;
  animation-iteration-count:infinite}
.klinik .k-tanz .k-arme{animation:k-arme .96s ease-in-out infinite}
.klinik .k-steht{animation-name:k-steht; animation-timing-function:ease-in-out;
  animation-iteration-count:infinite}
.klinik .k-kordel{fill:none; stroke:var(--err); stroke-width:3.5; stroke-linecap:round}

/* Das Skelett aus dem Präpkurs */
.klinik .k-skelett{stroke-width:2}
.klinik .k-skelett .k-schaedel,.klinik .k-skelett .k-becken{fill:var(--bg)}
.klinik .k-skelett .k-auge{fill:var(--ink); stroke:none}

@keyframes k-tanz{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
@keyframes k-arme{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
@keyframes k-steht{0%,100%{transform:translateX(0)}50%{transform:translateX(2px)}}

/* Bettenrennen: einmal quer durchs Bild, mit Schlagloch */
.klinik .k-rennen{animation:k-rennen 17s linear infinite}
.klinik .k-huepf{animation:k-huepf .48s ease-in-out infinite}

@keyframes k-rennen{from{transform:translateX(-120px)}to{transform:translateX(1330px)}}
@keyframes k-huepf{0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)}}

/* Was durch die Luft geht: Hüte, Flieger, Handschuhballons, Konfetti */
.klinik .k-hut{transform-box:fill-box; transform-origin:center;
  animation:k-hut 1.4s linear infinite}
.klinik .k-hut-kopf,.klinik .k-hut-deckel{fill:var(--ink); stroke:none}
.klinik .k-hut-quaste{fill:none; stroke:var(--ink); stroke-width:2}
.klinik .k-handschuh{fill:var(--panel-2); stroke:var(--ink); stroke-width:1.8}
.klinik .k-ballon.b .k-handschuh{fill:#e7dcf3}
.klinik .k-ballon.c .k-handschuh{fill:#dceef3}
.klinik .k-ballon{animation-name:k-ballon; animation-timing-function:linear;
  animation-iteration-count:infinite}
.klinik .k-ballon-wiegt{animation:k-wiegt 4.2s ease-in-out infinite}
.klinik .k-konfetti{stroke:none; transform-box:fill-box; transform-origin:center;
  animation-name:k-konfetti; animation-timing-function:linear;
  animation-iteration-count:infinite}
.klinik .k-konfetti.pink{fill:var(--k-pink)}
.klinik .k-konfetti.cyan{fill:var(--k-cyan)}
.klinik .k-konfetti.gelb{fill:var(--k-licht)}
.klinik .k-konfetti.rot{fill:var(--err)}
.klinik .k-konfetti.gruen{fill:var(--ok)}

@keyframes k-hut{to{transform:rotate(360deg)}}
@keyframes k-ballon{from{transform:translateY(0)}to{transform:translateY(-600px)}}
@keyframes k-wiegt{0%,100%{transform:translateX(-9px) rotate(-7deg)}
  50%{transform:translateX(9px) rotate(7deg)}}
@keyframes k-konfetti{
  from{transform:translateY(0) rotate(0deg)}
  to{transform:translateY(560px) rotate(540deg)}}

/* Notaufnahme: Schild, Schiebetür, Rettungswagen, Trage */
.klinik text{paint-order:stroke}
/* Das Schild der Notaufnahme trägt weiße Schrift und ist deshalb Fläche:
   der tiefe Rotton, nicht der helle für Schrift auf dem Grund. */
.klinik .k-schild{fill:var(--err-flaeche); stroke:none}
.klinik .k-schild-schrift{font:400 27px/1 var(--sans); letter-spacing:-.01em; fill:#fff;
  text-anchor:middle}
.klinik .k-tuer-loch{fill:var(--ink); opacity:.9}
.klinik .k-tuer-l{animation:k-tuer-l 12s ease-in-out infinite}
.klinik .k-tuer-r{animation:k-tuer-r 12s ease-in-out infinite}
.klinik .k-trage{animation:k-trage 12s ease-in-out infinite}
.klinik .k-signal{fill:var(--bg); stroke:none}
.klinik .k-signal.hell{fill:var(--err)}
.klinik .k-blaulicht{fill:var(--k-blau); stroke:var(--ink); stroke-width:1.5;
  animation:k-blink 1.1s steps(1,end) infinite}
.klinik .k-blaulicht.b{animation-delay:-.55s}
.klinik .k-schein{fill:var(--k-blau); stroke:none; opacity:0;
  animation:k-schein 1.1s steps(1,end) infinite}
.klinik .k-schein.b{animation-delay:-.55s}

@keyframes k-blink{0%,49%{opacity:1}50%,100%{opacity:.2}}
@keyframes k-schein{0%,49%{opacity:.2}50%,100%{opacity:0}}
@keyframes k-tuer-l{0%,36%{transform:translateX(0)}46%,70%{transform:translateX(-38px)}
  80%,100%{transform:translateX(0)}}
@keyframes k-tuer-r{0%,36%{transform:translateX(0)}46%,70%{transform:translateX(38px)}
  80%,100%{transform:translateX(0)}}
@keyframes k-trage{0%,10%{transform:translateX(0); opacity:0}
  18%{transform:translateX(10px); opacity:1}
  60%{transform:translateX(84px); opacity:1}
  70%{transform:translateX(104px); opacity:0}
  100%{transform:translateX(104px); opacity:0}}

/* Der Puls unter allem: eine Ableitung, die endlos durchläuft */
.klinik .k-puls{fill:none; stroke:var(--ok); stroke-width:2.5; stroke-linecap:round;
  stroke-linejoin:round; animation:k-ekg 3.4s linear infinite}
@keyframes k-ekg{to{transform:translateX(-150px)}}

@media (prefers-reduced-motion:reduce){
  .klinik *{animation:none !important}
}
