/* ══════════════════════════════════════════════════════════════════
   OPEN GÄRTCHEN — Design System
   Eine Quelle für Farben, Schrift und Bausteine. Alle Seiten laden
   diese Datei; seitenspezifisches Layout bleibt in der Seite selbst.
   Gerendert nachschlagen: styleguide.html
   Dokumentiert in: agentic/design/DESIGN.md
   ══════════════════════════════════════════════════════════════════ */

:root{
  /* ── Marken-Farben ──────────────────────────────────────────────
     Verbindlich. Stammen vom Flyer-Artwork und stehen so schon
     gedruckt bzw. verschickt — nicht ohne Not ändern. */
  --lens-blue:#2050d8;   /* blaues Brillenglas, Anaglyph-Blau */
  --red:#ff3a1c;         /* rotes Brillenglas, Anaglyph-Rot */
  --cream:#ece9f6;       /* Brillengestell-Highlight, Textfarbe */
  --ink:#141419;         /* Haar-Schwarz, Grundfläche */

  /* ── Erweiterte Artwork-Farben ──────────────────────────────────
     Direkt aus dem Bild gemessen (7×7-Mittelung gegen das Filmkorn).
     Für Flächen und Akzente, die es vorher nicht als Token gab. */
  --sky:#0e72d0;         /* Himmel-Blau, Bildfläche */
  --skin:#f19d9e;        /* Haut-Lachsrosa */
  --amber:#f89d5c;       /* Seifenblasen-Bernstein */
  --deep:#042c41;        /* Schatten-Marine, tiefster Blauton */

  /* ── Linien und Füllungen ───────────────────────────────────────
     Drei Linien- und zwei Füllstufen ersetzen die frühere Leiter aus
     sieben zufälligen Alpha-Werten. Mehr Stufen braucht es nicht. */
  --line-faint:rgba(236,233,246,.14);   /* Tabellen-Trenner */
  --line:rgba(236,233,246,.25);         /* Feld- und Kartenrand */
  --line-strong:rgba(236,233,246,.35);  /* Ghost-Button, aktive Kante */
  --fill-faint:rgba(236,233,246,.04);   /* Zeilen-Hover */
  --fill:rgba(236,233,246,.07);         /* Feld-Hintergrund */

  /* ── Schriftfamilien: drei Rollen, keine Ausnahmen ───────────── */
  --font-display:'Archivo Black',sans-serif;  /* Aussagen, Zahlen, Buttons */
  --font-body:'Space Mono',monospace;         /* Lesetext, Eingaben, Daten */
  --font-micro:'DotGothic16',monospace;       /* Labels, Kleinkram */

  /* ── Schriftgrößen ──────────────────────────────────────────────
     Vorher gab es vier Größen für dieselbe Label-Rolle. Jetzt zwei. */
  --fs-hero:clamp(2.65rem,11vw,6rem);         /* Flyer-Headline */
  --fs-display-lg:clamp(1.8rem,6vw,3rem);     /* Seiten-Headline */
  --fs-display-md:clamp(1.3rem,4.6vw,1.9rem); /* Line-up, Listen */
  --fs-display-sm:1.5rem;                     /* Dialog-Headline */
  --fs-stat:2.2rem;                           /* Kennzahl */
  --fs-body:clamp(.85rem,2.6vw,1rem);         /* Lesetext */
  --fs-body-sm:.9rem;                         /* Tabelle, Hinweise */
  --fs-input:1rem;                            /* Eingaben — siehe unten */
  --fs-eyebrow:.8rem;                         /* Übertitel, Abschnitts-Label */
  --fs-micro:.72rem;                          /* Feld-Label, Spaltenkopf */
  --fs-jp:clamp(.85rem,3vw,1.1rem);           /* japanische Zeile */

  /* ── Laufweite: zwei Stufen für Labels, eine für Buttons ─────── */
  --track-eyebrow:.4em;
  --track-label:.28em;
  --track-wide:.2em;
  --track-button:.14em;

  /* ── Radien ─────────────────────────────────────────────────── */
  --r-sm:10px;
  --r-md:12px;
  --r-lg:18px;
  --r-pill:999px;

  /* ── Anaglyph-Versatz (3D-Brillen-Effekt) ───────────────────── */
  --ana-sm:3px;
  --ana-md:4px;
  --ana-lg:6px;

  /* ── Maße ───────────────────────────────────────────────────── */
  --pad-page:clamp(20px,5vw,56px);
  --tap:48px;         /* Finger-Ziel für Buttons und Auswahl */
  --tap-dense:44px;   /* Finger-Ziel in dichten Listen und Tabellen */
  --scrim:4,10,30;    /* Basis für alle Verlaufs-Abdunklungen */

  /* Höhe der Radio-Leiste am unteren Rand, ohne Safe-Area. Alles, was über
     ihr schwebt, rechnet mit --radio-clear und nicht mit --radio-h — sonst
     schiebt sich der Home-Indicator zwischen Leiste und Launcher. */
  --radio-h:64px;
  --radio-clear:calc(var(--radio-h) + env(safe-area-inset-bottom));
}

*{margin:0;padding:0;box-sizing:border-box}
html,body{min-height:100%}

body{
  color:var(--cream);
  font-family:var(--font-body);
  -webkit-text-size-adjust:100%;
}

/* Sichtbarer Fokus auf allen Flächen. Rot hält auf Tinte 5,2:1 und
   sticht auch auf cremefarbenen Buttons heraus. */
:focus-visible{outline:3px solid var(--red);outline-offset:3px}

/* Randabstand, der Notch und Home-Indicator respektiert. */
.safe-pad{
  padding-top:max(var(--pad-page),env(safe-area-inset-top));
  padding-right:max(var(--pad-page),env(safe-area-inset-right));
  padding-bottom:max(var(--pad-page),env(safe-area-inset-bottom));
  padding-left:max(var(--pad-page),env(safe-area-inset-left));
}

/* ══ FLÄCHEN ═══════════════════════════════════════════════════════
   Zwei Modi, und die Wahl ist inhaltlich: Gäste sehen den Flyer,
   Betrieb sieht die Konsole. Nie mischen.
   ══════════════════════════════════════════════════════════════════ */

/* Flyer — Artwork randlos, Korn darüber, Laufband unten. */
.surface-flyer{
  background:var(--sky);   /* Fallback, bis das Bild geladen ist */
  overflow-x:hidden;
}

/* Konsole — ruhige Fläche für Betriebsansichten. Kein Korn, kein Bild. */
.surface-console{
  background:var(--ink);
  min-height:100dvh;
}

/* ── Artwork-Ebene ──────────────────────────────────────────────── */
.bg{position:fixed;inset:0;z-index:0}
.bg img{width:100%;height:100%;object-fit:cover}

/* Abdunklung. Pflicht, sobald Text mit Funktion über dem Artwork
   liegt: Creme auf dem Himmel schafft nur 4,0:1, auf der Haut 1,7:1.
   Oben ein schmaler Streifen für den Übertitel, unten eine Rampe für
   Datum, Line-up und Button. Die Bildmitte — Gesicht und Brille —
   bleibt unberührt. */
.bg::before{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(to bottom,
    rgba(var(--scrim),.5) 0%,
    rgba(var(--scrim),0) 24%);
}
.bg::after{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(to bottom,
    rgba(var(--scrim),0) 34%,
    rgba(var(--scrim),.5) 52%,
    rgba(var(--scrim),.78) 74%,
    rgba(var(--scrim),.9) 100%);
}

/* ── Filmkorn ───────────────────────────────────────────────────── */
.grain{
  position:fixed;
  inset:-50%;
  width:200%;
  height:200%;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity:.13;
  mix-blend-mode:overlay;
  pointer-events:none;
  z-index:5;
  animation:grain .7s steps(4) infinite;
}
@keyframes grain{
  0%{transform:translate(0,0)}
  25%{transform:translate(-1.5%,1%)}
  50%{transform:translate(1%,-1.5%)}
  75%{transform:translate(-1%,1.5%)}
  100%{transform:translate(1.5%,-1%)}
}

/* ══ SCHRIFT-ROLLEN ════════════════════════════════════════════════ */

.hero{
  font-family:var(--font-display);
  font-size:var(--fs-hero);
  line-height:.95;
  text-transform:uppercase;
}
.headline{
  font-family:var(--font-display);
  font-size:var(--fs-display-lg);
  line-height:.95;
  text-transform:uppercase;
}
.title{
  font-family:var(--font-display);
  font-size:var(--fs-display-sm);
  line-height:1;
  text-transform:uppercase;
}

/* Übertitel und Abschnitts-Label — die weite, dramatische Laufweite. */
.eyebrow{
  font-family:var(--font-micro);
  font-size:var(--fs-eyebrow);
  letter-spacing:var(--track-eyebrow);
  text-transform:uppercase;
}

/* Kleinteilige Labels — Feldnamen, Spaltenköpfe, Kennzahl-Beschriftung. */
.micro{
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
}

.body-text{
  font-size:var(--fs-body);
  line-height:1.9;
  letter-spacing:.08em;
}

/* Japanische Zeile — reine Dekoration, darf blass bleiben. */
.jp{
  font-family:var(--font-micro);
  font-size:var(--fs-jp);
  letter-spacing:var(--track-wide);
}

/* Abgeblendeter Text. Nur für Dekoratives oder für Text, der über
   einer ruhigen Fläche noch AA erreicht — nie für Fehlermeldungen,
   Bedienelemente oder Werte. */
.dim{opacity:.75}

/* ── Anaglyph ───────────────────────────────────────────────────────
   Der 3D-Brillen-Effekt: Rot nach links, Blau nach rechts. Nur für
   Display-Schrift ab etwa 1,5rem — bei Lesetext wird er zu Matsch. */
.anaglyph{
  --ana:var(--ana-sm);
  text-shadow:calc(-1 * var(--ana)) 0 var(--red),var(--ana) 0 var(--lens-blue);
}
.anaglyph--pulse{animation:anaglyph-pulse 3.5s ease-in-out infinite}
@keyframes anaglyph-pulse{
  0%,100%{text-shadow:calc(-1 * var(--ana-md)) 0 var(--red),var(--ana-md) 0 var(--lens-blue)}
  50%{text-shadow:calc(-1 * var(--ana-lg)) 0 var(--red),var(--ana-lg) 0 var(--lens-blue)}
}

/* ══ BUTTONS ═══════════════════════════════════════════════════════
   Ein Baustein, vier Varianten. Der Versatz läuft über --ana, damit
   Ruhe- und Hover-Zustand nicht auseinanderlaufen können.
   ══════════════════════════════════════════════════════════════════ */

.btn{
  --ana:var(--ana-md);
  --ana-hover:var(--ana-lg);
  display:inline-block;
  font-family:var(--font-display);
  font-size:.85rem;
  letter-spacing:var(--track-button);
  text-transform:uppercase;
  color:var(--ink);
  background:var(--cream);
  border:none;
  padding:13px 30px;
  border-radius:var(--r-pill);
  cursor:pointer;
  text-decoration:none;
  box-shadow:var(--ana) var(--ana) 0 var(--red),
             calc(-1 * var(--ana)) calc(-1 * var(--ana)) 0 var(--lens-blue);
  transition:transform .15s,box-shadow .15s;
}
.btn:disabled{opacity:.55;cursor:progress;transform:none}

/* Hover nur, wo es einen Zeiger gibt — sonst klebt der Zustand auf
   dem Touchscreen am Button fest. */
@media(hover:hover){
  .btn:hover{
    transform:translateY(-2px);
    box-shadow:var(--ana-hover) var(--ana-hover) 0 var(--red),
               calc(-1 * var(--ana-hover)) calc(-1 * var(--ana-hover)) 0 var(--lens-blue);
  }
  .btn:disabled:hover{
    transform:none;
    box-shadow:var(--ana) var(--ana) 0 var(--red),
               calc(-1 * var(--ana)) calc(-1 * var(--ana)) 0 var(--lens-blue);
  }
}

/* Groß — die eine tragende Aktion einer Seite. Höchstens einmal. */
.btn--lg{
  --ana:5px;
  --ana-hover:7px;
  padding:16px 44px;
  font-size:1rem;
}
@media(hover:hover){
  .btn--lg:hover{transform:translateY(-3px)}
}

/* Ghost — gleichrangige Werkzeug-Aktionen, etwa in der Konsolen-Leiste. */
.btn--ghost{
  background:transparent;
  color:var(--cream);
  border:2px solid var(--line-strong);
  box-shadow:none;
}
@media(hover:hover){
  .btn--ghost:hover{border-color:var(--cream);box-shadow:none}
}

/* Flach — im Dialog, wo der Anaglyph-Schatten mit dem Rahmen kollidiert. */
.btn--flat{box-shadow:none}
@media(hover:hover){
  .btn--flat:hover{box-shadow:none;transform:none}
}

/* Leise — Abbrechen und Schließen. Absichtlich Lesetext-Schrift:
   soll nicht so laut rufen wie die Bestätigung daneben. */
.btn--quiet{
  background:none;
  color:var(--cream);
  border:2px solid var(--line-strong);
  box-shadow:none;
  font-family:var(--font-body);
  font-size:.85rem;
  letter-spacing:0;
  text-transform:none;
  padding:13px 20px;
}
@media(hover:hover){
  .btn--quiet:hover{border-color:var(--cream);box-shadow:none;transform:none}
}

/* ══ FORMULARE ═════════════════════════════════════════════════════ */

.field{margin-bottom:16px}
.field > label{
  display:block;
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  opacity:.75;
  margin-bottom:8px;
}
.field input,.field textarea,.field select{
  width:100%;
  padding:13px 15px;
  background:var(--fill);
  border:2px solid var(--line);
  border-radius:var(--r-sm);
  color:var(--cream);
  font-family:var(--font-body);
  /* 1rem ist Absicht: unter 16px zoomt iOS beim Fokus ins Feld. */
  font-size:var(--fs-input);
}
.field textarea{resize:vertical;min-height:74px}
.field input:focus,.field textarea:focus,.field select:focus{
  outline:none;
  border-color:var(--cream);
}
.field input:focus-visible,.field textarea:focus-visible,.field select:focus-visible{
  outline:3px solid var(--red);
  outline-offset:3px;
}
.field select option{background:var(--ink)}
.field ::placeholder{color:var(--cream);opacity:.55}

/* Optional-Vermerk im Label. */
.opt{opacity:.6}

/* ── Auswahl-Gruppe ─────────────────────────────────────────────── */
.choice{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.choice input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.choice label{
  display:flex;
  align-items:center;
  justify-content:center;
  text-align:center;
  padding:12px 4px;
  border:2px solid var(--line);
  border-radius:var(--r-sm);
  font-size:.8rem;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.06em;
  cursor:pointer;
  transition:background .15s,border-color .15s,color .15s;
}
.choice input:checked + label{
  background:var(--cream);
  border-color:var(--cream);
  color:var(--ink);
}
.choice input:focus-visible + label{outline:3px solid var(--red);outline-offset:3px}

/* Honeypot gegen Bots — für Menschen unsichtbar, aber nicht per
   display:none, sonst füllen manche Bots ihn gar nicht erst aus. */
.hp{
  position:absolute;
  width:1px;height:1px;
  padding:0;margin:-1px;
  overflow:hidden;
  clip-path:inset(50%);
  white-space:nowrap;
  border:0;
}

/* ══ KENNZAHLEN ════════════════════════════════════════════════════ */

.stats{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(140px,1fr));
  gap:14px;
}
.stat{
  border:2px solid var(--line);
  border-radius:var(--r-md);
  padding:16px 18px;
}
/* Genau eine Kennzahl pro Ansicht darf die wichtigste sein. */
.stat--hero{border-color:var(--cream)}
.stat b{
  display:block;
  font-family:var(--font-display);
  font-size:var(--fs-stat);
  line-height:1.1;
}
.stat span{
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  opacity:.75;
}

/* ══ TABELLE ═══════════════════════════════════════════════════════ */

.table-wrap{overflow-x:auto}
.table-wrap table{width:100%;border-collapse:collapse;min-width:640px}
.table-wrap th,.table-wrap td{
  text-align:left;
  padding:12px 14px;
  border-bottom:1px solid var(--line-faint);
  font-size:var(--fs-body-sm);
  vertical-align:top;
}
.table-wrap th{
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  opacity:.75;
}
@media(hover:hover){
  .table-wrap tr:hover td{background:var(--fill-faint)}
}
.cell-name{font-weight:700}
.cell-note{opacity:.75;font-size:.82rem;max-width:280px;white-space:pre-wrap}

/* Zeilen-Aktion. Volle Deckkraft ist Pflicht: Rot auf Tinte hält
   5,2:1, dasselbe Rot auf 55 % nur 2,2:1. */
.row-action{
  background:none;
  border:none;
  color:var(--red);
  cursor:pointer;
  font-family:var(--font-body);
  font-size:1.1rem;
  line-height:1;
  padding:4px 8px;
  border-radius:var(--r-sm);
}
@media(hover:hover){
  .row-action:hover{background:var(--fill)}
}

/* ══ STATUS-CHIPS ══════════════════════════════════════════════════
   Die Zusage-Farben sind festgelegt: Creme heißt zugesagt, Blau heißt
   vielleicht, Rot heißt abgesagt. Rot trägt Tinte, nicht Creme —
   Creme auf Rot erreicht nur 2,95:1 und ist damit unter AA.
   ══════════════════════════════════════════════════════════════════ */

.tag{
  display:inline-block;
  padding:3px 12px;
  border-radius:var(--r-pill);
  font-size:var(--fs-micro);
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.1em;
  white-space:nowrap;
}
.tag--yes{background:var(--cream);color:var(--ink)}
.tag--maybe{background:var(--lens-blue);color:var(--cream)}
.tag--no{background:var(--red);color:var(--ink)}

/* ══ DIALOG ════════════════════════════════════════════════════════ */

dialog.sheet{
  border:none;
  padding:8px;
  background:transparent;
  max-width:min(440px,calc(100vw - 32px));
  max-height:calc(100dvh - 32px);
  width:100%;
  color:var(--cream);
  overflow-y:auto;
  overscroll-behavior:contain;
}
dialog.sheet::backdrop{background:rgba(10,10,30,.72);backdrop-filter:blur(6px)}
.sheet-inner{
  background:var(--ink);
  border:2px solid var(--cream);
  border-radius:var(--r-lg);
  padding:clamp(22px,5vw,32px);
  box-shadow:var(--ana-lg) var(--ana-lg) 0 var(--red),
             calc(-1 * var(--ana-lg)) calc(-1 * var(--ana-lg)) 0 var(--lens-blue);
}
.sheet .hint{
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  opacity:.75;
  margin:8px 0 22px;
}
.sheet-actions{display:flex;gap:10px;align-items:center;margin-top:22px}
.sheet-actions .btn--flat{flex:1}
/* Fehlermeldungen sind funktional: volle Deckkraft, Rot auf Tinte
   erreicht 5,2:1. */
.sheet-msg{margin-top:14px;font-size:var(--fs-body-sm);min-height:1.2em;color:var(--red)}

/* Bestätigung nach dem Absenden. */
.done{text-align:center;padding:14px 0 4px}
.done .big{
  font-family:var(--font-display);
  font-size:2.6rem;
  line-height:1;
  text-transform:uppercase;
}
.done p{margin-top:14px;font-size:var(--fs-body-sm);opacity:.85;line-height:1.7}
.done-address{
  max-width:30rem;
  margin:18px auto 0;
  padding:13px 16px 14px;
  border:2px solid var(--cream);
  background:var(--deep);
  color:var(--cream);
  box-shadow:4px 4px 0 var(--red),-4px -4px 0 var(--lens-blue);
}
.done-address span{
  display:block;
  margin-bottom:4px;
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
}
.done-address strong{
  display:block;
  font-family:var(--font-body);
  font-size:clamp(1rem,4vw,1.2rem);
  line-height:1.35;
}

/* ══ PARTY-CHAT ════════════════════════════════════════════════════
   Der Launcher ist ein Ausschnitt des echten Artworks. Das Panel
   spricht dieselbe harte Vierfarb-Sprache wie der RSVP-Dialog.
   ══════════════════════════════════════════════════════════════════ */
.chat-launcher{
  position:fixed;
  right:max(18px,env(safe-area-inset-right));
  bottom:calc(var(--radio-clear) + 16px);
  z-index:7;
  width:72px;
  height:72px;
  padding:0;
  border:3px solid var(--cream);
  border-radius:50%;
  background:var(--ink);
  color:var(--cream);
  box-shadow:5px 5px 0 var(--red),-5px -5px 0 var(--lens-blue);
  cursor:pointer;
  transition:transform .16s cubic-bezier(.22,1,.36,1),box-shadow .16s cubic-bezier(.22,1,.36,1);
}
.chat-launcher img,.chat-avatar img{
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:53% 45%;
}
.chat-launcher img{display:block;border-radius:50%}
.chat-launcher span{
  position:absolute;
  right:56px;
  bottom:2px;
  padding:5px 9px;
  border:2px solid var(--cream);
  background:var(--ink);
  color:var(--cream);
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  letter-spacing:.08em;
  white-space:nowrap;
}
@media(hover:hover){
  .chat-launcher:hover{
    transform:translateY(-3px);
    box-shadow:7px 7px 0 var(--red),-7px -7px 0 var(--lens-blue);
  }
}
.chat-launcher:active{transform:translateY(2px);box-shadow:3px 3px 0 var(--red),-3px -3px 0 var(--lens-blue)}

dialog.chat-widget{
  position:fixed;
  inset:auto max(18px,env(safe-area-inset-right)) calc(var(--radio-clear) + 20px) auto;
  z-index:8;
  width:min(390px,calc(100vw - 32px));
  height:min(600px,calc(100dvh - var(--radio-h) - 56px));
  max-width:none;
  max-height:none;
  margin:0;
  padding:0;
  border:2px solid var(--cream);
  border-radius:var(--r-md);
  background:var(--ink);
  color:var(--cream);
  box-shadow:var(--ana-lg) var(--ana-lg) 0 var(--red),
             calc(-1 * var(--ana-lg)) calc(-1 * var(--ana-lg)) 0 var(--lens-blue);
  overflow:hidden;
}
.chat-widget[open]{display:flex;flex-direction:column}
.chat-header{
  display:grid;
  grid-template-columns:48px minmax(0,1fr) var(--tap-dense);
  gap:12px;
  align-items:center;
  padding:14px;
  border-bottom:2px solid var(--cream);
  background:var(--deep);
}
.chat-avatar{
  width:48px;
  height:48px;
  overflow:hidden;
  border:2px solid var(--cream);
  border-radius:50%;
}
.chat-header h2{
  font-family:var(--font-display);
  font-size:1.05rem;
  line-height:1.15;
}
.chat-header p{
  margin-top:4px;
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  line-height:1.4;
  opacity:.82;
}
.chat-close{
  width:var(--tap-dense);
  height:var(--tap-dense);
  border:2px solid transparent;
  border-radius:var(--r-sm);
  background:transparent;
  color:var(--cream);
  font-family:var(--font-body);
  font-size:1.6rem;
  line-height:1;
  cursor:pointer;
}
@media(hover:hover){.chat-close:hover{border-color:var(--cream);background:var(--fill)}}
.chat-close:active{background:var(--cream);color:var(--ink)}

.chat-messages{
  flex:1;
  display:flex;
  flex-direction:column;
  gap:14px;
  min-height:0;
  padding:18px 16px;
  overflow-y:auto;
  overscroll-behavior:contain;
  scrollbar-color:var(--lens-blue) var(--ink);
}
.chat-message{
  width:fit-content;
  max-width:88%;
  padding:12px 14px;
  border:2px solid var(--cream);
  border-radius:4px;
  font-family:var(--font-body);
  font-size:1rem;
  line-height:1.55;
  overflow-wrap:anywhere;
  white-space:pre-wrap;
}
.chat-message--bot{
  align-self:flex-start;
  background:var(--cream);
  color:var(--ink);
  box-shadow:4px 4px 0 var(--red);
}
.chat-message--user{
  align-self:flex-end;
  background:var(--lens-blue);
  color:var(--cream);
  box-shadow:4px 4px 0 var(--red);
}
.chat-form{padding:12px 14px 10px;border-top:2px solid var(--line)}
.chat-compose{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px}
.chat-compose input{
  min-width:0;
  min-height:var(--tap);
  border:2px solid var(--line-strong);
  border-radius:var(--r-sm);
  background:var(--fill);
  color:var(--cream);
  padding:11px 13px;
  font:inherit;
  font-size:var(--fs-input);
}
.chat-compose input::placeholder{color:rgba(236,233,246,.78)}
.chat-send{
  min-width:72px;
  min-height:var(--tap);
  padding:10px 14px;
  border:2px solid var(--cream);
  border-radius:var(--r-pill);
  background:var(--cream);
  color:var(--ink);
  font-family:var(--font-display);
  font-size:.85rem;
  cursor:pointer;
}
.chat-send:disabled{opacity:.62;cursor:progress}
@media(hover:hover){.chat-send:not(:disabled):hover{background:var(--red);border-color:var(--red)}}
.chat-send:not(:disabled):active{transform:translateY(2px)}
.chat-error{
  min-height:1.25em;
  margin-top:7px;
  color:var(--red);
  font-size:.8rem;
  line-height:1.4;
}

.visually-hidden{
  position:absolute;
  width:1px;
  height:1px;
  padding:0;
  margin:-1px;
  overflow:hidden;
  clip-path:inset(50%);
  white-space:nowrap;
  border:0;
}

/* ══ LAUFBAND ══════════════════════════════════════════════════════
   Nur der laufende Streifen, ohne eigene Position. Früher klebte er selbst
   am Seitenfuß; diesen Platz hat jetzt die Radio-Leiste, und sie nimmt das
   Laufband als Baustein auf. Der Text steht immer zweimal im Markup — so
   bleibt er lesbar, wenn die Bewegung abgeschaltet ist.
   ══════════════════════════════════════════════════════════════════ */

.marquee{
  white-space:nowrap;
  overflow:hidden;
  font-family:var(--font-micro);
  font-size:var(--fs-eyebrow);
  letter-spacing:.25em;
}
.marquee span{display:inline-block;animation:marquee 20s linear infinite}
@keyframes marquee{from{transform:translateX(0)}to{transform:translateX(-100%)}}

/* ══ GÄRTCHEN FM ═══════════════════════════════════════════════════
   Die Leiste am unteren Rand und das Deck, das aus ihr aufklappt. Sie
   dreht die Fläche um: der Flyer ist dunkel, das Radio ist creme. Deshalb
   trägt hier alles Funktionale --ink. Rot bleibt Akzent und sitzt nur auf
   --ink — auf Creme hält es 2,98:1 und ist damit unter AA.
   ══════════════════════════════════════════════════════════════════ */

.radio{
  position:fixed;
  inset:auto 0 0 0;
  z-index:6;
  display:flex;
  align-items:center;
  gap:12px;
  min-height:var(--radio-h);
  padding:8px max(14px,env(safe-area-inset-right))
          max(8px,env(safe-area-inset-bottom)) max(14px,env(safe-area-inset-left));
  background:var(--cream);
  color:var(--ink);
  border-top:2px solid var(--ink);
  box-shadow:0 -10px 30px rgba(var(--scrim),.45);
}

/* Kassetten-Knopf: öffnet das Deck. Umriss statt Fläche, damit die drei
   gefüllten Transport-Knöpfe rechts die lauteren bleiben. */
.radio-deck-toggle{
  flex:0 0 auto;
  display:grid;
  place-items:center;
  width:var(--tap-dense);
  height:var(--tap-dense);
  padding:0;
  border:2px solid var(--ink);
  border-radius:var(--r-sm);
  background:none;
  color:var(--ink);
  cursor:pointer;
  transition:background .15s,color .15s;
}
@media(hover:hover){
  .radio-deck-toggle:hover{background:var(--ink);color:var(--cream)}
}
.radio-deck-toggle[aria-expanded="true"]{background:var(--ink);color:var(--cream)}

/* Sendelampe. Aus ist ein stumpfer Punkt, an ist Rot mit Glimmen. */
.radio-led{
  flex:0 0 auto;
  display:flex;
  align-items:center;
  gap:8px;
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
}
.radio-led i{
  width:10px;
  height:10px;
  border-radius:50%;
  background:rgba(20,20,25,.4);
  transition:background .2s,box-shadow .2s;
}
.radio.is-playing .radio-led i{
  background:var(--red);
  box-shadow:0 0 8px var(--red);
  animation:radio-led 1s ease-in-out infinite;
}
@keyframes radio-led{50%{transform:scale(.7)}}

/* Das Laufband trägt die Ansage und ist zugleich die breite Klickfläche
   aufs Deck — auf dem Telefon der einzige bequem treffbare Weg dorthin. */
.radio .marquee{
  flex:1 1 auto;
  min-width:0;
  padding:0;
  border:none;
  background:none;
  color:inherit;
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  text-align:left;
  text-transform:uppercase;
  cursor:pointer;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 5%,#000 95%,transparent);
}

/* Aussteuerung. Reine Zierde, deshalb aria-hidden im Markup. */
.radio-eq{
  flex:0 0 auto;
  display:flex;
  align-items:flex-end;
  gap:3px;
  height:20px;
}
.radio-eq i{
  width:4px;
  height:100%;
  background:var(--ink);
  transform:scaleY(.18);
  transform-origin:bottom;
}
.radio.is-playing .radio-eq i{animation:radio-eq .68s ease-in-out infinite alternate}
.radio-eq i:nth-child(2){animation-delay:.14s;animation-duration:.56s}
.radio-eq i:nth-child(3){animation-delay:.05s;animation-duration:.8s}
.radio-eq i:nth-child(4){animation-delay:.22s;animation-duration:.62s}
@keyframes radio-eq{from{transform:scaleY(.15)}to{transform:scaleY(1)}}

.radio-controls{flex:0 0 auto;display:flex;align-items:center;gap:8px}
.radio-btn{
  display:grid;
  place-items:center;
  width:var(--tap-dense);
  height:var(--tap-dense);
  padding:0;
  border:2px solid var(--ink);
  border-radius:var(--r-md);
  background:var(--ink);
  color:var(--cream);
  cursor:pointer;
  box-shadow:var(--ana-sm) var(--ana-sm) 0 var(--red),
             calc(-1 * var(--ana-sm)) calc(-1 * var(--ana-sm)) 0 var(--lens-blue);
  transition:transform .12s,box-shadow .12s;
}
.radio-btn:active{
  transform:translate(2px,2px);
  box-shadow:1px 1px 0 var(--red),-1px -1px 0 var(--lens-blue);
}
.radio-btn svg{width:16px;height:16px;fill:currentColor}
.radio-btn--play{
  width:var(--tap);
  height:var(--tap);
  border-radius:50%;
}
.radio-btn--play svg{width:19px;height:19px}
.radio-btn:disabled{opacity:.4;cursor:not-allowed;transform:none}

/* ── Kassetten-Deck ─────────────────────────────────────────────────
   Klappt links über der Leiste auf. Geschlossen ist es visibility:hidden
   und damit auch aus der Tab-Reihenfolge — nur Deckkraft zu nullen würde
   die Titelliste unsichtbar, aber weiter anspringbar lassen. */
.tape-deck{
  position:fixed;
  left:max(14px,env(safe-area-inset-left));
  bottom:calc(var(--radio-clear) + 14px);
  z-index:7;
  width:min(360px,calc(100vw - 28px));
  max-height:calc(100dvh - var(--radio-h) - 40px);
  overflow-y:auto;
  overscroll-behavior:contain;
  padding:16px;
  background:var(--ink);
  color:var(--cream);
  border:2px solid var(--cream);
  border-radius:var(--r-lg);
  box-shadow:var(--ana-lg) var(--ana-lg) 0 var(--red),
             calc(-1 * var(--ana-lg)) calc(-1 * var(--ana-lg)) 0 var(--lens-blue);
  visibility:hidden;
  opacity:0;
  transform:translateY(14px);
  transition:opacity .2s,transform .24s cubic-bezier(.22,1,.36,1),visibility 0s linear .24s;
}
.tape-deck.is-open{
  visibility:visible;
  opacity:1;
  transform:none;
  transition:opacity .2s,transform .24s cubic-bezier(.22,1,.36,1),visibility 0s;
}

.tape-head{display:flex;align-items:center;gap:10px;margin-bottom:14px}
.tape-side{
  margin-left:auto;
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  opacity:.8;
}
.tape-close{
  width:var(--tap-dense);
  height:var(--tap-dense);
  border:2px solid transparent;
  border-radius:var(--r-sm);
  background:none;
  color:var(--cream);
  font-family:var(--font-body);
  font-size:1.5rem;
  line-height:1;
  cursor:pointer;
}
@media(hover:hover){.tape-close:hover{border-color:var(--cream);background:var(--fill)}}
.tape-close:active{background:var(--cream);color:var(--ink)}

/* Die Kassette selbst — cremefarbene Karte auf dunklem Deck. */
.cassette{
  background:var(--cream);
  color:var(--ink);
  border:2px solid var(--ink);
  border-radius:var(--r-md);
  padding:10px;
}
.cassette-label{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:10px;
  padding:7px 11px;
  margin-bottom:10px;
  background:#fff;
  border:2px solid var(--ink);
  border-radius:var(--r-sm);
}
/* Läuft-gerade: Funktionstext, deshalb --ink und nicht Rot. */
.cassette-artist{
  min-width:0;
  font-family:var(--font-display);
  font-size:.95rem;
  line-height:1.2;
  text-transform:uppercase;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.cassette-mix{
  flex:0 0 auto;
  font-family:var(--font-micro);
  font-size:.58rem;
  letter-spacing:.14em;
  line-height:1.6;
  text-align:right;
  text-transform:uppercase;
  opacity:.75;
}
.cassette-window{
  display:flex;
  align-items:center;
  gap:12px;
  height:78px;
  padding:0 14px;
  background:var(--ink);
  border-radius:var(--r-sm);
}
.reel{
  flex:0 0 auto;
  width:52px;
  height:52px;
  border-radius:50%;
  border:3px solid var(--cream);
  background:
    radial-gradient(circle,var(--cream) 0 24%,#b9b5c6 25% 33%,transparent 34%),
    repeating-conic-gradient(var(--cream) 0 16deg,var(--deep) 16deg 60deg);
  animation:reel 2.4s linear infinite;
  animation-play-state:paused;
}
.tape-deck.is-playing .reel{animation-play-state:running}
@keyframes reel{to{transform:rotate(360deg)}}
.tape-line{flex:1;height:6px;border-radius:3px;background:var(--deep)}

.tape-counter{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap:10px;
  margin-top:14px;
}
/* Rot auf --ink hält 5,2:1. */
.tape-time{
  font-family:var(--font-micro);
  font-size:1.6rem;
  letter-spacing:.08em;
  color:var(--red);
}
.tape-meta{
  font-family:var(--font-micro);
  font-size:var(--fs-micro);
  letter-spacing:var(--track-label);
  text-transform:uppercase;
  opacity:.8;
}

.tape-list{list-style:none;display:flex;flex-direction:column;gap:4px;margin-top:12px}
.tape-list button{
  display:flex;
  align-items:baseline;
  gap:10px;
  width:100%;
  min-height:var(--tap-dense);
  padding:8px 10px;
  text-align:left;
  background:none;
  border:2px solid transparent;
  border-radius:var(--r-sm);
  color:inherit;
  font-family:var(--font-body);
  font-size:.76rem;
  letter-spacing:.1em;
  text-transform:uppercase;
  cursor:pointer;
}
@media(hover:hover){.tape-list button:hover{border-color:var(--line-strong)}}
.tape-list .num{flex:0 0 22px;opacity:.75}
.tape-list .t-artist{font-weight:700}
.tape-list .t-title{opacity:.75;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tape-list li[aria-current="true"] button{
  border-color:var(--red);
  background:rgba(255,58,28,.16);
}

/* Störungsmeldung, wenn eine Spur nicht lädt. Rot auf --ink, volle Deckkraft. */
.radio-error{
  margin-top:10px;
  color:var(--red);
  font-size:.76rem;
  line-height:1.5;
}
.radio-error:empty{display:none}

/* Auf dem Telefon fällt zuerst die Zierde: Aussteuerung weg, Lampe ohne
   Wort. Die drei Transport-Knöpfe und das Laufband bleiben unangetastet —
   sie sind das, wofür die Leiste da ist. */
@media(max-width:640px),(max-width:960px) and (max-height:520px){
  :root{--radio-h:58px}
  .radio{gap:10px;padding-left:max(10px,env(safe-area-inset-left));padding-right:max(10px,env(safe-area-inset-right))}
  .radio-eq{display:none}
  .radio-led span{display:none}
  .radio .marquee{font-size:.66rem;letter-spacing:.16em}
  .radio-controls{gap:6px}
  .tape-deck{
    left:max(10px,env(safe-area-inset-left));
    right:max(10px,env(safe-area-inset-right));
    width:auto;
  }
}
@media(max-width:380px){
  .radio{gap:8px}
  .radio .marquee{font-size:.62rem;letter-spacing:.12em}
}

/* ══ HILFSKLASSEN ══════════════════════════════════════════════════ */

.hidden{display:none}
.msg{margin-top:16px;font-size:var(--fs-body-sm);color:var(--red);min-height:1.2em}
.empty{padding:40px 0;opacity:.75;font-size:var(--fs-body-sm)}
.toolbar{display:flex;gap:12px;flex-wrap:wrap;align-items:center}

/* ══ FINGER-ZIELE ══════════════════════════════════════════════════ */
@media(pointer:coarse){
  .btn,.choice label{min-height:var(--tap)}
  .row-action{min-width:var(--tap-dense);min-height:var(--tap-dense)}
  .chat-close{min-width:var(--tap);min-height:var(--tap)}
  .radio-btn,.radio-deck-toggle,.tape-close,.tape-list button{
    min-width:var(--tap-dense);
    min-height:var(--tap-dense);
  }
  .radio-btn--play{min-width:var(--tap);min-height:var(--tap)}
}

/* ══ KONSOLE AUF KLEINEN SCHIRMEN ══════════════════════════════════
   Eine sechsspaltige Tabelle lässt sich auf einem Telefon nicht
   sinnvoll seitwärts schieben. Unter 700px wird jede Zeile zu einer
   Karte; die Spaltenköpfe wandern über `data-label` in die Zellen.
   Jede Tabelle braucht dafür `data-label` an jedem `td`.
   ══════════════════════════════════════════════════════════════════ */
@media(max-width:700px){
  .stats{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .stat{padding:14px}
  .stat b{font-size:1.85rem}

  .toolbar{display:grid;grid-template-columns:1fr;gap:10px}
  .toolbar .btn{width:100%}

  .table-wrap{overflow:visible}
  .table-wrap table{min-width:0}
  .table-wrap table,.table-wrap tbody,.table-wrap tr,.table-wrap td{
    display:block;
    width:100%;
  }
  /* Kopfzeile bleibt für Screenreader erhalten, verschwindet aber
     optisch — die Karte trägt ihre Labels selbst. */
  .table-wrap thead{
    position:absolute;
    width:1px;height:1px;
    padding:0;margin:-1px;
    overflow:hidden;
    clip-path:inset(50%);
    white-space:nowrap;
    border:0;
  }
  .table-wrap tbody{display:grid;gap:14px}
  .table-wrap tr{
    border:2px solid var(--line);
    border-radius:var(--r-md);
    padding:8px 14px;
  }
  .table-wrap td{
    display:grid;
    grid-template-columns:minmax(92px,34%) minmax(0,1fr);
    gap:12px;
    align-items:start;
    padding:10px 0;
    overflow-wrap:anywhere;
  }
  .table-wrap td::before{
    content:attr(data-label);
    font-family:var(--font-micro);
    font-size:.68rem;
    letter-spacing:.16em;
    text-transform:uppercase;
    opacity:.75;
  }
  /* Letzte Spalte ist die Zeilen-Aktion: kein Label, rechts ausgerichtet. */
  .table-wrap td:last-child{display:flex;justify-content:flex-end;border-bottom:0}
  .table-wrap td:last-child::before{content:none}
  .row-action{min-width:var(--tap-dense);min-height:var(--tap-dense);font-size:1.4rem}
  .cell-note{max-width:none}
}
@media(max-width:360px){
  .stats{grid-template-columns:1fr}
  .table-wrap td{grid-template-columns:1fr;gap:5px}
}

/* ══ ENGE UND FLACHE VIEWPORTS ═════════════════════════════════════ */
@media(max-width:380px){
  dialog.sheet{max-width:calc(100vw - 20px);max-height:calc(100dvh - 20px)}
  .sheet-inner{padding:20px 16px}
  /* Drei Chips passen unter 380px nicht mehr nebeneinander. */
  .choice{grid-template-columns:repeat(2,minmax(0,1fr))}
  .choice label:last-of-type{grid-column:1 / -1}
  .sheet-actions{flex-direction:column;align-items:stretch}
  .sheet-actions .btn{width:100%}
}
@media(max-width:640px),(max-width:960px) and (max-height:520px){
  .chat-launcher{
    position:static;
    display:grid;
    grid-template-columns:44px minmax(0,1fr) 44px;
    align-items:center;
    gap:10px;
    width:100%;
    max-width:none;
    height:auto;
    min-height:56px;
    margin:16px 0 0;
    padding:4px;
    border-width:2px;
    border-radius:var(--r-pill);
    box-shadow:4px 4px 0 var(--red),-4px -4px 0 var(--lens-blue);
  }
  .chat-launcher img{
    flex:0 0 44px;
    width:44px;
    height:44px;
  }
  .chat-launcher span{
    position:static;
    display:block;
    justify-self:center;
    padding:0;
    border:0;
    background:transparent;
    font-size:.72rem;
    line-height:1.25;
    letter-spacing:.08em;
    text-align:center;
    white-space:normal;
  }
  .chat-launcher::after{
    content:"";
    width:44px;
    height:44px;
  }
  .chat-launcher:active{
    box-shadow:2px 2px 0 var(--red),-2px -2px 0 var(--lens-blue);
  }
  dialog.chat-widget{
    inset:auto 8px max(64px,calc(52px + env(safe-area-inset-bottom))) 8px;
    width:auto;
    height:min(620px,calc(100dvh - 78px));
    border-radius:var(--r-sm) var(--r-sm) 0 0;
  }
  .chat-header{grid-template-columns:44px minmax(0,1fr) var(--tap);padding:12px}
  .chat-avatar{width:44px;height:44px}
  .chat-messages{padding:16px 12px}
  .chat-form{padding:10px 10px max(10px,env(safe-area-inset-bottom))}
}
@media(max-height:620px){
  dialog.sheet{max-height:calc(100dvh - 16px)}
  .sheet-inner{padding-top:18px;padding-bottom:18px}
  .sheet .hint{margin-bottom:14px}
  .field{margin-bottom:12px}
  .field textarea{min-height:56px}
  .sheet-actions{margin-top:14px}
}

/* ══ BEWEGUNG ══════════════════════════════════════════════════════
   Korn, Anaglyph-Puls, Laufband, Spulen, Aussteuerung und Sendelampe
   laufen endlos. Wer Bewegung reduziert haben will, bekommt die Seite
   still — das Laufband bleibt lesbar, weil der Text sowieso doppelt im
   Markup steht, und die Spulen bleiben stehen, wo sie stehen. Ohne die
   Ruhestellungen unten würden die Endbilder der Animationen hängen
   bleiben: die Aussteuerung voll ausgeschlagen, das Laufband halb aus
   dem Bild.
   ══════════════════════════════════════════════════════════════════ */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
  .marquee span{transform:none}
  .radio-eq i{transform:scaleY(.18)}
  .radio-led i{transform:none}
  .reel{animation:none !important}
}
