/* ROKI — öffentlicher Service-Assistent (Widget unten rechts).
 *
 * Design-Vertrag: ausschließlich `--rok-*`-Tokens, keine Literal-Farben und
 * keine freien Radien. ROKAMAT ist kubisch — es gibt nur `--rok-radius-0/1/2`
 * (0 / 2px / 4px). Runde Pillen wären markenfremd; der Radius-Guard erzwingt das.
 *
 * Z-Index-Nachbarschaft (gemessen in index.css): Suchoverlay, PDF-Overlay und
 * Mobil-Drawer liegen auf 1100. ROKI bleibt bewusst darunter — wer die Suche
 * oder ein PDF öffnet, soll den Assistenten nicht darüber liegen haben.
 *
 * ── Die Aufzieh-Animation ──────────────────────────────────────────────────
 * Der Balken IST der Kopf des Fensters, er wird nicht ersetzt. Beim Öffnen
 * laufen zwei Bewegungen NACHEINANDER:
 *   1. Breite: von der gemessenen Balkenbreite (`--roki-bar-w`, kommt als
 *      Inline-Variable aus der Komponente) auf die Fensterbreite.
 *   2. Höhe:   der Rumpf darunter zieht auf — mit `transition-delay`, damit er
 *      erst startet, wenn die Breite steht.
 * Der Container ist unten rechts verankert, also wächst er nach OBEN.
 * `--roki-bar-h` ist bewusst fest: aus ihr wird die Zielhöhe des Rumpfes
 * berechnet, und eine `auto`-Höhe ließe sich nicht überblenden.
 */

.roki {
  --roki-bar-h: 46px;
  --roki-w: min(420px, calc(100vw - 32px));
  --roki-h: min(880px, calc(100dvh - 48px));

  position: fixed;
  right: var(--rok-space-5);
  bottom: var(--rok-space-5);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  /* `max-content` als Ausgangswert, NICHT `auto`: der Balken innen hat
     `width: 100%`, und zusammen mit einem `auto`-Container ist das zirkulär —
     der Browser loest es auf, indem er den Container streckt. Das Ergebnis war
     ein Balken ueber die volle Fensterbreite, den die Messung dann auch noch
     eingefroren hat. `max-content` bindet die Breite an den Inhalt. */
  width: var(--roki-bar-w, max-content);
  max-width: calc(100vw - 32px);
  border: var(--rok-border-w) solid var(--rok-accent);
  background: var(--rok-bg);
  box-shadow: var(--rok-shadow-lg);
  /* Waehrend der Aufzieh-Animation (Quadrat -> Fensterbreite) darf die
     Beschriftung nicht kurz links ueberstehen — der Container blendet sie sauber
     auf. Der Schatten liegt AUSSERHALB der Box und wird davon nicht beschnitten. */
  overflow: hidden;
  transition: width 220ms var(--rok-ease);
}

.roki.is-open {
  width: var(--roki-w);
  border-color: var(--rok-border-strong);
}

/* Der Balken: geschlossen der Auslöser, geöffnet der Kopf — in beiden
   Zuständen identisch. `--rok-text-on-orange` ist das Token für Schrift auf
   orangem Grund und trägt dort 7,28:1 Kontrast. */
.roki-bar {
  display: flex;
  align-items: center;
  gap: var(--rok-space-2);
  width: 100%;
  min-height: var(--roki-bar-h);
  padding: 0 var(--rok-space-4);
  border: 0;
  border-radius: var(--rok-radius-0);
  background: var(--rok-accent);
  color: var(--rok-text-on-orange);
  font-family: var(--rok-font-body);
  font-size: var(--rok-fs-sm);
  font-weight: var(--rok-fw-medium);
  line-height: 1;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}

.roki-bar:focus-visible { outline: 3px solid var(--rok-fg); outline-offset: -3px; }

.roki-bar-icon { display: block; flex-shrink: 0; }
/* Geschlossen richtet sich die Breite nach der Beschriftung — dort darf sie
   niemals kuerzen. Erst im geoeffneten Zustand ist die Breite fest, und nur
   dort ist eine Ellipse ueberhaupt sinnvoll (sehr lange Uebersetzung, schmales
   Fenster). */
.roki-bar-label { flex: 0 0 auto; }
.roki.is-open .roki-bar-label { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }

/* Chevron: zeigt nach oben, solange zu (》öffnet nach oben《), und dreht beim
   Öffnen auf „nach unten" = zuklappen. `margin-left:auto` schiebt ihn erst an
   den rechten Rand, wenn der Balken die volle Breite hat. */
.roki-bar-caret {
  margin-left: auto;
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-135deg) translate(-2px, -2px);
  transition: transform 220ms var(--rok-ease);
}
.roki.is-open .roki-bar-caret { transform: rotate(45deg) translate(-2px, -2px); }

/* ── Geschlossen = kompaktes Marken-Quadrat, nur der Sparkle ─────────────────
 * „Minimieren" fuehrt hierher zurueck (der Balken/das Fenster klappt zu) — der
 * kleine Launcher bleibt sichtbar und laesst sich beliebig oft verlustfrei
 * wieder aufziehen. Das ist NICHT das „Ausblenden": der bleibt als separater,
 * gesetzlicher Opt-Out (Widerspruch Art. 21) unten im Fenster.
 * Quadrat = Kantenlaenge --roki-bar-h; on-brand (kubisch, radius-0). */
.roki:not(.is-open) { width: var(--roki-bar-h); }
.roki:not(.is-open) .roki-bar { justify-content: center; padding: 0; }
/* Beschriftung nur VISUELL verstecken, nicht aus dem A11y-Baum nehmen: der
 * Balken-Button behaelt so seinen zugaenglichen Namen „ROKI Service-Assistent"
 * (Screenreader + Sprachsteuerung, WCAG 2.5.3). `display:none` wuerde ihn
 * namenlos machen, weil der Sparkle `aria-hidden` ist. */
.roki:not(.is-open) .roki-bar-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* Chevron ist reine Deko (aria-hidden) — geschlossen ganz weg. */
.roki:not(.is-open) .roki-bar-caret { display: none; }

/* Der Rumpf. Geschlossen Höhe 0 — er belegt keinen Platz und ist für Maus wie
   Tastatur unerreichbar (`visibility: hidden` nimmt ihn aus der Tab-Reihenfolge,
   `height: 0` allein täte das nicht). */
.roki-shell {
  display: flex;
  flex-direction: column;
  /* `width: 0` ist im geschlossenen Zustand NICHT kosmetisch: der Container ist
     `max-content` breit, und dessen intrinsische Breite richtet sich nach dem
     BREITESTEN Kind. Der Rumpf enthaelt Eingabefeld und Fliesstext — er trieb
     den geschlossenen Balken damit auf gut die doppelte Breite, obwohl er null
     hoch und unsichtbar war. Auf 0 gesetzt zaehlt nur noch der Balken. */
  width: 0;
  height: 0;
  overflow: hidden;
  visibility: hidden;
  transition:
    height 260ms var(--rok-ease) 200ms,
    visibility 0s linear 460ms;
}

.roki.is-open .roki-shell {
  width: 100%;
  height: calc(var(--roki-h) - var(--roki-bar-h));
  visibility: visible;
  transition:
    height 260ms var(--rok-ease) 200ms,
    visibility 0s linear 200ms;
}

.roki-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--rok-space-4);
  display: flex;
  flex-direction: column;
  gap: var(--rok-space-3);
  font-size: var(--rok-fs-sm);
  line-height: 1.55;
}

.roki-intro { margin: 0; color: var(--rok-fg-muted); }

.roki-msg { margin: 0; }
.roki-msg--user {
  align-self: flex-end;
  max-width: 85%;
  padding: var(--rok-space-2) var(--rok-space-3);
  border-radius: var(--rok-radius-0);
  background: var(--rok-gray-100);
}
.roki-msg--bot { align-self: flex-start; max-width: 100%; }
.roki-msg--bot p { margin: 0; }

.roki-actions { display: flex; flex-wrap: wrap; gap: var(--rok-space-2); margin-top: var(--rok-space-3); }

.roki-action {
  display: inline-block;
  padding: var(--rok-space-2) var(--rok-space-3);
  border: var(--rok-border-w) solid var(--rok-border-strong);
  border-radius: var(--rok-radius-0);
  background: var(--rok-bg);
  color: var(--rok-fg);
  font-size: var(--rok-fs-xs);
  font-weight: var(--rok-fw-medium);
  text-decoration: none;
  cursor: pointer;
}
.roki-action:hover { background: var(--rok-gray-100); }
.roki-action:focus-visible { outline: 2px solid var(--rok-fg); outline-offset: 2px; }

.roki-sources { margin: var(--rok-space-3) 0 0; padding: 0; list-style: none; }
.roki-sources-label {
  margin: var(--rok-space-3) 0 var(--rok-space-1);
  font-size: var(--rok-fs-xs);
  font-weight: var(--rok-fw-medium);
  color: var(--rok-fg-muted);
}
.roki-sources li { margin: 0 0 var(--rok-space-1); font-size: var(--rok-fs-xs); }
.roki-sources a { color: var(--rok-fg-muted); }

/* Transparenzhinweis (kein Einwilligungs-Kasten). Bewusst ruhig gehalten: er
   steht dauerhaft oben im Fenster und soll informieren, nicht alarmieren. */
.roki-notice {
  margin: 0;
  padding: var(--rok-space-3);
  border-left: var(--rok-border-accent-w) solid var(--rok-accent);
  background: var(--rok-gray-50);
}
.roki-notice p {
  margin: 0;
  font-size: var(--rok-fs-xs);
  line-height: 1.5;
  color: var(--rok-fg-muted);
}

.roki-error { margin: 0; color: var(--rok-danger); }

.roki-foot {
  border-top: var(--rok-border-w) solid var(--rok-border);
  padding: var(--rok-space-3) var(--rok-space-4) var(--rok-space-4);
}

.roki-form { display: flex; gap: var(--rok-space-2); }

.roki-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--rok-space-2) var(--rok-space-3);
  border: var(--rok-border-w) solid var(--rok-border-strong);
  border-radius: var(--rok-radius-0);
  background: var(--rok-bg);
  color: var(--rok-fg);
  font: inherit;
  font-size: var(--rok-fs-sm);
}
.roki-input:focus-visible { outline: 2px solid var(--rok-fg); outline-offset: 1px; }

.roki-send {
  padding: var(--rok-space-2) var(--rok-space-4);
  border: var(--rok-border-w) solid var(--rok-fg);
  border-radius: var(--rok-radius-0);
  background: var(--rok-fg);
  color: var(--rok-bg);
  font-size: var(--rok-fs-sm);
  font-weight: var(--rok-fw-medium);
  cursor: pointer;
}
.roki-send:disabled { opacity: 0.45; cursor: default; }

.roki-disclaimer {
  margin: var(--rok-space-2) 0 0;
  font-size: var(--rok-fs-xs);
  line-height: 1.4;
  color: var(--rok-fg-muted);
}

/* Der Honeypot muss für Bots im DOM stehen, aber für Menschen und
   Screenreader unerreichbar sein — daher nicht `display:none` (das füllen
   manche Bots trotzdem nicht), sondern aus dem Viewport geschoben. */
.roki-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

@media (max-width: 520px) {
  .roki {
    right: var(--rok-space-2);
    bottom: var(--rok-space-2);
    /* Auf dem Telefon nimmt das geöffnete Fenster die volle Breite und fast
       die volle Höhe — ein 420px-Fenster neben 8px Rand gäbe es dort nicht. */
    --roki-w: calc(100vw - 16px);
    --roki-h: calc(100dvh - 16px);
  }
}

/* Widerruf der Einwilligung — bewusst unauffaellig, aber jederzeit erreichbar
   (Art. 7 Abs. 3 DS-GVO verlangt, dass der Widerruf so einfach ist wie die
   Erteilung, nicht dass er gleich prominent ist). */
.roki-revoke {
  margin-top: var(--rok-space-2);
  padding: 0;
  border: 0;
  background: none;
  color: var(--rok-fg-muted);
  font-family: var(--rok-font-body);
  font-size: var(--rok-fs-xs);
  text-decoration: underline;
  cursor: pointer;
}
.roki-revoke:hover { color: var(--rok-fg); }
.roki-revoke:focus-visible { outline: 2px solid var(--rok-fg); outline-offset: 2px; }

/* Schreibmarke des Schreibmaschinen-Effekts. Blinkt nur, solange getippt wird;
   danach entfernt die Komponente das Element wieder. */
.roki-caret {
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-left: 2px;
  vertical-align: text-bottom;
  background: var(--rok-fg-muted);
  animation: roki-blink 1s steps(2, start) infinite;
}

@keyframes roki-blink {
  to { visibility: hidden; }
}

@media (prefers-reduced-motion: reduce) {
  .roki,
  .roki-shell,
  .roki-bar-caret { transition: none; }
  .roki-caret { animation: none; }
}
