/* Design-System der App, uebertragen auf das Betreiber-Dashboard (R102).
 *
 * Quelle jeder Zahl ist dieselbe wie fuer die Landing-Repliken:
 *   Farben/Skalen  frontend/src/platform/theme.ts   (lightColors, darkColors, radius, weight)
 *   Komponenten    frontend/src/platform/styles.ts  (panel, badge, primaryButton)
 *   Schriften      frontend/assets/fonts/*.ttf      (dieselben Binaries wie die App)
 *
 * Warum eine eigene Datei und kein Import von apps/landing: Die Landing baut mit Astro und
 * Tailwind, das Dashboard ist ein Thymeleaf-Server ohne Build-Schritt. Ein geteiltes Artefakt
 * haette eine Build-Kopplung zwischen zwei Dingen erzeugt, die sonst nichts verbindet. Die Tokens
 * sind Zahlen, die sich selten aendern; wandert eine, wandert sie hier mit.
 */

@font-face {
  font-family: 'HankenGrotesk';
  src: url('/fonts/HankenGrotesk.ttf') format('truetype');
  /* Ohne Range klemmt WebKit die Achse auf 400 und faked Bold. Dieselbe Zeile steht aus
     demselben Grund in app-ui.css der Landing. */
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: 'GeistMono';
  src: url('/fonts/GeistMono.ttf') format('truetype');
  font-weight: 100 900;
  font-display: swap;
}

:root {
  --bg: #f2f6f8;
  --surface: #ffffff;
  --border: #e1e7eb;
  --border-sub: #cfd8dd;
  --text-high: #0f1b20;
  --text-body: #41525a;
  --text-muted: #71858f;
  --text-faint: #9aaab2;
  --accent: #176d7a;
  --accent-strong: #125862;
  --accent-surface: #e8f4f5;
  --on-accent: #ffffff;
  --input-bg: #f7fafb;
  --input-border: #cfd8dd;
  --danger: #c33a31;
  --warn-bg: #f6ead3;
  --warn-text: #9a6a0e;
  --ok-bg: #e3f2ea;
  --ok-text: #1e7a4e;
  --err-bg: #f9e6e3;
  --err-text: #9e2c25;
  --note-bg: #eef3f5;
  --badge-muted-bg: #eef3f5;
  --badge-muted-text: #71858f;
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-field: 12px;
  --radius-pill: 999px;
  --w-medium: 400;
  --w-bold: 500;
  --w-heavy: 600;
}

/* Die App traegt einen Dunkelmodus, also traegt ihn auch dieses Werkzeug. Werte aus darkColors.
 *
 * Zwei Bloecke mit denselben Werten, und das ist Absicht. Der erste folgt der Systemeinstellung,
 * solange niemand von Hand gewaehlt hat. Der zweite gewinnt, sobald data-theme am <html> steht --
 * das setzt der Umschalter im Kopf. CSS kann einen Variablensatz nicht wiederverwenden, ohne ihn
 * an einen Selektor zu binden, deshalb steht er zweimal da. Wer eine Farbe aendert, aendert beide.
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #101214;
    --surface: #17191c;
    --border: #26292d;
    --border-sub: #33373c;
    --text-high: #eceef0;
    --text-body: #b0b5b9;
    --text-muted: #888d92;
    --text-faint: #5c6166;
    --accent: #7aacb8;
    --accent-strong: #629ca9;
    --accent-surface: #1a2529;
    --on-accent: #0a1418;
    --input-bg: #131518;
    --input-border: #33373c;
    --danger: #f06a5e;
    --warn-bg: #2c2310;
    --warn-text: #e0a73c;
    --ok-bg: #10261b;
    --ok-text: #4fbb86;
    --err-bg: #311613;
    --err-text: #f79a91;
    --note-bg: #1a1d20;
    --badge-muted-bg: #232629;
    --badge-muted-text: #888d92;
  }
}

:root[data-theme='dark'] {
    --bg: #101214;
    --surface: #17191c;
    --border: #26292d;
    --border-sub: #33373c;
    --text-high: #eceef0;
    --text-body: #b0b5b9;
    --text-muted: #888d92;
    --text-faint: #5c6166;
    --accent: #7aacb8;
    --accent-strong: #629ca9;
    --accent-surface: #1a2529;
    --on-accent: #0a1418;
    --input-bg: #131518;
    --input-border: #33373c;
    --danger: #f06a5e;
    --warn-bg: #2c2310;
    --warn-text: #e0a73c;
    --ok-bg: #10261b;
    --ok-text: #4fbb86;
    --err-bg: #311613;
    --err-text: #f79a91;
    --note-bg: #1a1d20;
    --badge-muted-bg: #232629;
    --badge-muted-text: #888d92;
  }

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 0 0 48px;
  background: var(--bg);
  color: var(--text-body);
  font-family: 'HankenGrotesk', system-ui, sans-serif;
  font-size: 15px;
  line-height: 22px;
  -webkit-font-smoothing: antialiased;
}

/* Zahlen, Zeitpunkte und Kennungen in der Monospace der App, mit gleichen Ziffernbreiten. */
.mono, td.num, .id {
  font-family: 'GeistMono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
}

/* --- Kopfzeile ------------------------------------------------------------ */
header {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 14px 24px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
header h1 {
  margin: 0;
  color: var(--text-high);
  font-size: 17px;
  font-weight: var(--w-heavy);
}
/* Der Mark statt einer Wortmarke, und daneben sagt die Ueberschrift, wo man ist. Der frueher
   danebenstehende Chip "Betreiber" sagte dasselbe ein zweites Mal. */
header .brand { height: 30px; width: auto; display: block; }
header h1 + nav { margin-left: auto; }
nav { display: flex; gap: 4px; margin-left: auto; }

/* Suchfeld ueber einer Liste. Schmaler als ein Formularfeld, es steht in einer Kopfzeile. */
.filter {
  min-height: 34px;
  padding: 6px 12px;
  border: 1px solid var(--input-border);
  border-radius: var(--radius-pill);
  background: var(--input-bg);
  color: var(--text-body);
  font-family: inherit;
  font-size: 13px;
}
.panel__head .filter { margin-left: auto; }
.panel__head .filter + .panel__hint { margin-left: 0; }
nav a {
  padding: 7px 14px;
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  font-size: 14px;
  font-weight: var(--w-bold);
  text-decoration: none;
}
nav a:hover { background: var(--note-bg); color: var(--text-body); }
nav a.active { background: var(--accent-surface); color: var(--accent); }

main { max-width: 1200px; margin: 0 auto; padding: 24px; }

/* --- Meldungen (styles.ts noteCard) --------------------------------------- */
.notice {
  padding: 12px 16px;
  margin-bottom: 20px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--ok-text);
  border-radius: var(--radius-md);
  background: var(--ok-bg);
  color: var(--ok-text);
  font-weight: var(--w-bold);
}
.notice.error {
  border-left-color: var(--err-text);
  background: var(--err-bg);
  color: var(--err-text);
}

/* --- Kennzahlen ----------------------------------------------------------- */
.stats { display: flex; gap: 12px; margin-bottom: 20px; flex-wrap: wrap; }
.stat {
  flex: 1 1 160px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.stat .value {
  display: block;
  color: var(--text-high);
  font-family: 'GeistMono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 26px;
  font-weight: var(--w-heavy);
  line-height: 32px;
}
.stat .label { color: var(--text-muted); font-size: 13px; }
/* Als Knopf gebaut, damit Tastatur und Vorlesesoftware ihn finden. Deshalb muss hier zuruecknehmen,
   was der Browser einem Knopf sonst mitgibt. */
.stat--klick {
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.stat--klick:hover { border-color: var(--accent); }

/* Der verschickte Text auf der Lauf-Seite. Zeilenumbrueche bleiben, wie sie getippt wurden. */
.sent-text { margin: 12px 0; }
.sent-text p { margin: 8px 0 0; }

/* --- Panel und Tabelle (styles.ts panel) ---------------------------------- */
.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.panel__head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
}
.panel__title { color: var(--text-high); font-size: 16px; font-weight: var(--w-heavy); }
.panel__hint { margin-left: auto; color: var(--text-muted); font-size: 13px; }
.panel__scroll { overflow-x: auto; }

table { width: 100%; border-collapse: collapse; }
th {
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 12px;
  font-weight: var(--w-bold);
  text-align: left;
  white-space: nowrap;
}
td {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--note-bg); }

.primary { color: var(--text-high); font-weight: var(--w-bold); }
.sub { color: var(--text-muted); font-size: 13px; }
.empty { padding: 32px 16px; color: var(--text-muted); text-align: center; }

/* --- Badges (styles.ts badge) --------------------------------------------- */
.badge {
  display: inline-block;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  background: var(--accent-surface);
  color: var(--accent);
  font-size: 13px;
  font-weight: var(--w-heavy);
  white-space: nowrap;
}
.badge--ok { background: var(--ok-bg); color: var(--ok-text); }
.badge--warn { background: var(--warn-bg); color: var(--warn-text); }

/* Ein Hinweis, der erklaert, warum etwas fehlt. Dieselbe Farbe wie das Etikett, auf das er sich
   bezieht, aber ohne Flaeche -- er meldet keinen Erfolg und keinen Fehler. */
.sub--warn { color: var(--warn-text); }
.badge--err { background: var(--err-bg); color: var(--err-text); }
.badge--muted { background: var(--badge-muted-bg); color: var(--badge-muted-text); }

/* --- Formulare (styles.ts input / primaryButton) -------------------------- */
/* Umrandet, damit "sperren" als Knopf zu erkennen ist und nicht als Textlink. Es oeffnet nur das
   Formular, der gefaehrliche Knopf steckt darin und ist rot. */
details > summary {
  display: inline-block;
  padding: 6px 12px;
  border: 1px solid var(--border-sub);
  border-radius: var(--radius-pill);
  color: var(--accent);
  font-size: 13px;
  font-weight: var(--w-bold);
  cursor: pointer;
  list-style: none;
}
details > summary::-webkit-details-marker { display: none; }
details > summary:hover { background: var(--accent-surface); }
details[open] > summary { color: var(--text-muted); }

form.row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
/* Wo neben dem Bedienelement ein erklaerender Satz steht, sollen beide auf einer Mittellinie
   liegen. Ohne das haengt der zweizeilige Satz oben und das Auswahlfeld darunter wie verrutscht. */
form.row--center { align-items: center; }
input[type=text], input[type=password], input[type=email] {
  min-height: 40px;
  padding: 8px 12px;
  border: 1px solid var(--input-border);
  border-radius: var(--radius-field);
  background: var(--input-bg);
  color: var(--text-body);
  font-family: inherit;
  font-size: 14px;
}
input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-surface);
}
input::placeholder { color: var(--text-faint); }

button {
  min-height: 40px;
  padding: 8px 18px;
  border: none;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--on-accent);
  font-family: inherit;
  font-size: 14px;
  font-weight: var(--w-heavy);
  cursor: pointer;
}
button:hover { background: var(--accent-strong); }
button.danger { background: var(--danger); }
button.danger:hover { filter: brightness(0.92); }

@media (max-width: 700px) {
  header { flex-wrap: wrap; gap: 12px; padding: 12px 16px; }
  nav { margin-left: 0; width: 100%; }
  main { padding: 16px; }
}

/* --- Umschalter Hell/Dunkel ----------------------------------------------- */
.theme-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  min-height: 0;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
.theme-toggle:hover { background: var(--note-bg); color: var(--text-body); }
.theme-toggle svg { width: 18px; height: 18px; }
/* Sonne im Dunkeln, Mond im Hellen -- gezeigt wird, wohin der Klick fuehrt. */
.theme-toggle .sun { display: none; }
:root[data-theme='dark'] .theme-toggle .sun { display: block; }
:root[data-theme='dark'] .theme-toggle .moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .theme-toggle .sun { display: block; }
  :root:not([data-theme='light']) .theme-toggle .moon { display: none; }
}

/* --- Versand (R101) -------------------------------------------------------- */
.panel__body { display: flex; flex-direction: column; gap: 10px; padding: 16px; }
.panel__body > label { color: var(--text-muted); font-size: 12px; font-weight: var(--w-bold); }
.panel__head .button-link,
.panel__head button { margin-left: auto; }

.button-link {
  padding: 8px 18px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--on-accent);
  font-size: 14px;
  font-weight: var(--w-heavy);
  text-decoration: none;
}
.button-link:hover { background: var(--accent-strong); }
/* Zurueckhaltende Zweitaktion neben einer Ueberschrift: derselbe Umriss, keine Farbflaeche.
   "Formular leeren" soll nicht wie der Hauptknopf aussehen, sonst trifft man ihn versehentlich. */
.button-link--quiet {
  padding: 6px 14px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: var(--w-bold);
}
.button-link--quiet:hover { background: var(--note-bg); color: var(--text-body); }

textarea, select {
  padding: 8px 12px;
  border: 1px solid var(--input-border);
  border-radius: var(--radius-field);
  background: var(--input-bg);
  color: var(--text-body);
  font-family: inherit;
  font-size: 14px;
}
textarea { min-height: 200px; resize: vertical; }
select { min-height: 40px; }
textarea:focus, select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-surface);
}

/* Die Art der Nachricht steht ausgeschrieben da und nicht als knappes Etikett. Sie entscheidet
   ueber den Empfaengerkreis und ueber die Pflichtangaben, das soll man beim Waehlen lesen. */
.kinds { display: flex; flex-direction: column; gap: 10px; border: 0; padding: 0; margin: 0; }
.kinds legend { color: var(--text-muted); font-size: 12px; font-weight: var(--w-bold); padding: 0; }
.kinds label { display: flex; gap: 10px; align-items: flex-start; font-size: 13px; line-height: 19px; }
.kinds input { margin-top: 3px; }

.picks { list-style: none; margin: 0; padding: 0; max-height: 320px; overflow-y: auto; }
.picks li { border-top: 1px solid var(--border); }
.picks li:first-child { border-top: 0; }
/* Eine Zeile bleibt eine Zeile. Vorher brach sie um, sobald Name und Firmenname zusammen breit
   genug waren -- dann stand das Etikett bei einem Eintrag darunter und bei seinem Nachbarn nicht,
   und die Liste sah kaputt aus. Jetzt kuerzt stattdessen der Text, und zwar von rechts nach links:
   erst der Firmenname, dann die Adresse, der Name zuletzt. */
.picks label {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 8px;
  padding: 8px 2px;
  cursor: pointer;
}
.picks label > input { flex: none; }
.picks label > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.picks label > .primary { flex-shrink: 1; }
.picks label > .mono { flex-shrink: 2; }
.picks label > .sub:not(.mono) { flex-shrink: 3; }
.picks__tags { display: flex; gap: 6px; margin-left: auto; flex: none; overflow: visible; }

/* Der Schalter fuer die Interessenten. Wie eine Zeile aus .kinds, denn er ist dieselbe Art
   Entscheidung: einer, der erklaert werden muss, und keiner zum schnellen Durchklicken. */
.pick-all {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  font-size: 13px;
  line-height: 19px;
}
.pick-all input { margin-top: 3px; }
.pick-all input:disabled + span { color: var(--text-faint); }
.pick-all .sub { display: block; margin-top: 4px; }

/* Zwei Spalten erst, wenn beide nebeneinander etwas taugen. Darunter steht die Vorschau unter dem
   Formular, statt auf 300 px zusammengedrueckt zu werden. */
.compose { display: grid; gap: 16px; }
.compose__form { display: flex; flex-direction: column; gap: 16px; }
.compose__preview iframe {
  width: 100%;
  height: 620px;
  border: 0;
  background: #ffffff;
}
@media (min-width: 1100px) {
  .compose { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
  .compose__preview { position: sticky; top: 16px; }
}

/* Blaetterer, dem PaginationFooter der App nachempfunden: "Pro Seite", die Spanne, zwei Pfeile.
   Die Pfeile sind bewusst unauffaellig -- sie sind Navigation und keine Aktion. */
.pager {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border-top: 1px solid var(--border);
}
.pager .sub:last-of-type { margin-left: auto; }
.pager select { min-height: 32px; padding: 4px 8px; font-size: 13px; }
.pager button {
  min-height: 32px;
  min-width: 32px;
  padding: 0 10px;
  border: 1px solid var(--border-sub);
  background: transparent;
  color: var(--text-body);
  font-size: 15px;
}
.pager button:hover:not(:disabled) { background: var(--note-bg); }
.pager button:disabled { color: var(--text-faint); cursor: default; }

/* --- Oeffentliche Abmeldeseite -------------------------------------------- */
body.plain { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 24px; }
.plain__card {
  width: 100%;
  max-width: 460px;
  padding: 28px 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
}
.plain__card h1 { margin: 0 0 20px; color: var(--text-high); font-size: 20px; }
.brand--card { height: 36px; margin-bottom: 20px; }
.plain__card p { margin: 0 0 12px; }
.plain__card form { margin: 16px 0; }
.plain__card label { display: block; margin-bottom: 6px; color: var(--text-muted); font-size: 14px; }
.plain__card input[type=email] { width: 100%; margin-bottom: 12px; }

/* Der Honigtopf. Nicht `display:none` -- manche Skripte ueberspringen, was so ausgezeichnet ist.
   Aus dem Bild geschoben faellt er nur denen auf, die das Formular gar nicht ansehen. */
.honigtopf {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
