/* Alpinity Dashboard — produktneutrale Grundlage.
 *
 * Diese Datei wird von mehreren Dashboards benutzt (Voice, Chat, …). Sie enthält deshalb
 * ausschliesslich Allgemeines: Tokens, Typografie, Layout, Karten, Buttons, Formulare,
 * Tabellen, Zustände. Produktspezifisches gehört in eine eigene Datei daneben
 * (z. B. voice.css) — und Klassennamen tragen hier nie einen Produktnamen.
 *
 * Alle Werte stammen aus DESIGN.md, also aus der Messung an alpinity.ai. Was dort nicht
 * gemessen war, steht unten unter „Hergeleitet" und ist als solches markiert.
 *
 * Zwei Regeln, die man beim Erweitern nicht brechen darf:
 *
 *   1. DIE LICHTKANTE. Buttons, Karten und Eingabefelder haben ausschliesslich einen
 *      `border-top` in einem helleren Ton, alle anderen Seiten 0. Das simuliert Licht von
 *      oben und ist das häufigste Detail der Marke. Ein gleichmässiger vierseitiger Rahmen
 *      sieht sofort falsch aus.
 *   2. KEIN GRÜN. Die grünen Werte im Framer-Markup sind wirkungslose Fallbacks aus altem
 *      Branding. Für „erfolgreich/erledigt" gibt es Petrol oder zurückhaltendes Weiss.
 *
 * Kein heller Modus. Die Marke ist schwarz.
 */

@import url('/fonts/fonts.css');

:root {
  /* --- Farben (gemessen) ------------------------------------------------- */
  --bg:            #000000;   /* die Seite ist wirklich schwarz, nicht dunkelgrau */
  --surface:       #141414;   /* Karten */
  --surface-2:     #1e1e1e;   /* Eingabefelder, erhöhte Flächen */
  --border:        #1e1e1e;   /* Kartenkante, 2px */
  --border-2:      #262626;   /* Eingabefelder, Trenner */
  --text:          #ffffff;   /* nur Überschriften und Buttons */
  --text-2:        #a5a5a5;   /* Fliesstext */
  /* Achtung beim Verwenden: rgba(255,255,255,.4) auf Schwarz sind 3.66:1 und damit
     UNTER der Lesbarkeitsschwelle (AA verlangt 4.5:1). Nur fuer Beilaeufiges — alles,
     was eine Anweisung traegt, bekommt --text-2 (8.6:1). */
  --text-3:        rgba(255, 255, 255, 0.4);
  --accent:        #0e6f95;   /* Petrol, einzige tragende Akzentfarbe */
  --accent-light:  #4db4cf;   /* Lichtkanten, Fokus */
  --accent-pale:   #8ed0e0;   /* Eyebrow-Labels */
  --accent-mid:    #0a5776;
  --accent-deep:   #073a56;   /* Schein unter dem Primärbutton */
  /* Zustaende: bewusst OHNE eigene Farbe. Die Marke traegt genau einen Akzent;
     ein Zustand wird ueber FORM unterschieden (gefuellt vs. Ring), nicht ueber
     einen erfundenen Erfolgston. Semantische Namen, damit beide Dashboards
     dasselbe meinen und eine Aenderung zentral wirkt. */
  --state-on: var(--accent-light);
  --state-off: var(--text-2);
  --state-alert: #ffffff;
  --nav-bg:        rgba(20, 20, 20, 0.7);

  /* --- Hergeleitet -------------------------------------------------------
     Die Website kennt keinen Fehlerzustand — ein Dashboard braucht einen. Ein einziger
     gedämpfter Rotton, bewusst entsättigt, damit er neben dem Petrol nicht schreit.
     Erfolg und Hinweis kommen ohne neue Farbe aus: Petrol bzw. Weiss. */
  --danger:        #e0574c;
  --danger-soft:   rgba(224, 87, 76, 0.1);
  --accent-soft:   rgba(14, 111, 149, 0.18);
  --white-soft:    rgba(255, 255, 255, 0.07);

  /* --- Die drei erlaubten Schatten (gemessen) ---------------------------- */
  --shadow-accent: 0 20px 35px 0 var(--accent-deep);          /* Primärbutton */
  --shadow-light:  0 8px 24px 0 rgba(38, 38, 38, 0.5);        /* heller Button */
  --shadow-card:   0 20px 35px 0 #262626;                     /* neutrale Karte */

  /* --- Radien je Element (gemessen) -------------------------------------- */
  --r-card:   20px;
  --r-card-l: 24px;
  --r-btn:    14px;
  --r-input:  12px;
  --r-badge:  10px;
  --r-pill:   600px;

  /* --- Abstandsskala (gemessen) ------------------------------------------ */
  --s-1: 6px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 24px;
  --s-6: 32px; --s-7: 40px; --s-8: 48px; --s-9: 64px; --s-10: 112px;

  /* --- Schriften ---------------------------------------------------------
     Poppins trägt alles, Inter nur die Eyebrow-Labels. „Inter Display" ist die Fassung,
     die die Website über Framer benutzt; sie liegt NICHT bei Google Fonts und lässt sich
     darum nicht mitliefern. Bei 14px mit weiter Sperrung ist der Unterschied zur normalen
     Inter nicht wahrnehmbar — sie steht trotzdem zuerst im Stapel, damit ein System, das
     sie hat, sie nimmt.
     Geist Mono ist eine bewusste Abweichung von DESIGN.md und ausschliesslich für
     maschinelle Werte reserviert: Wiederherstellungscodes, Kennungen, Zeitstempel. In einer
     Proportionalschrift fluchten Spalten nicht und Codeblöcke sind schlechter abzutippen. */
  --font:      'Poppins', 'Helvetica Neue', Arial, sans-serif;
  --font-label:'Inter Display', 'Inter', 'Helvetica Neue', Arial, sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --content: 1200px;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text-2);
  font: 400 16px/1.5 var(--font);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ==========================================================================
   Typografie
   ==========================================================================
   Die Website beginnt bei 96px; fürs Dashboard sind die Grössen etwa halbiert.
   Verhältnisse und Laufweite bleiben — die enge negative Laufweite ist die Signatur
   der Marke, ohne sie sieht der Nachbau sofort fremd aus. Kein Heading über Gewicht 500. */

h1, h2, h3, h4 { margin: 0; font-family: var(--font); color: var(--text); }
h1 { font-size: 44px; font-weight: 500; line-height: 1.15; letter-spacing: -0.05em; }
h2 { font-size: 30px; font-weight: 400; line-height: 1.2;  letter-spacing: -0.05em; }
h3 { font-size: 22px; font-weight: 400; line-height: 1.3;  letter-spacing: -0.04em; }
h4 { font-size: 18px; font-weight: 400; line-height: 1.3;  letter-spacing: -0.04em; }

p { margin: 0 0 var(--s-4); }
a { color: var(--accent-pale); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Jede Sektion beginnt mit einem gesperrten Versal-Label, darunter erst die Überschrift.
   Ohne dieses Element verliert die Seite ihren Rhythmus. */
.eyebrow {
  margin: 0 0 var(--s-3);
  font-family: var(--font-label);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent-pale);
}

.lead {
  max-width: 720px;
  font-size: 19px;
  line-height: 1.4;
  letter-spacing: -0.02em;
  color: var(--text);
}
.muted { color: var(--text-2); }
.quiet { color: var(--text-3); }
.small { font-size: 14px; line-height: 1.5; }
.mono  { font-family: var(--font-mono); font-size: 13px; }

/* ==========================================================================
   Freischwebende Navigation
   ==========================================================================
   Keine Kopfleiste, sondern ein schwebender Balken über dem Inhalt — mit
   Hintergrundunschärfe und einer feinen Unterkante.

   Der Balken ist auf JEDER Breite `fixed`. Bis 2026-08-20 wurde er unter 900px
   in den Fluss zurückgesetzt, weil er dort auf drei Zeilen wuchs und den Inhalt
   verdeckte. Die Ursache war aber nicht das Schweben, sondern dass die ganze
   Navigation in den Balken sollte: auf schmalen Geräten übernimmt jetzt das
   Schubfach, und übrig bleiben Marke, Produktumschalter und Menüknopf — eine
   Zeile, immer.

   --nav-space ist der Platz, den `main` oben freihalten muss. Er steht als
   Variable da, weil er an drei Stellen gebraucht wird (main, scroll-padding-top,
   Schubfach) und sonst dreimal getrennt falsch würde. */

:root { --nav-space: 120px; }

/* Ohne das rutscht ein Sprungziel (#inhalt, Fundstellen im Editor) unter den
   schwebenden Balken — der Browser scrollt bis zur Oberkante des Ziels und die
   Leiste liegt darüber. */
html { scroll-padding-top: calc(var(--nav-space) - var(--s-5)); }

.topbar {
  position: fixed;
  top: var(--s-5);
  left: 50%;
  transform: translateX(-50%);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--s-4);
  width: calc(100% - var(--s-8));
  max-width: var(--content);
  padding: var(--s-3) var(--s-5);
  background: var(--nav-bg);
  border: 0;
  border-bottom: 1px solid var(--border);
  border-radius: var(--r-card);
  flex-wrap: nowrap;
}

/* Die Hintergrundunschärfe liegt auf einem PSEUDO-ELEMENT, nicht auf `.topbar` selbst.
   Ein Element mit `backdrop-filter` wird zum Bezugsrahmen für `position: fixed` in
   seinem Inneren — mit der Unschärfe auf der Leiste war das Vollbildmenü darin nur so
   hoch wie die Leiste (60px) und die Seite schien hindurch. Ein Pseudo-Element hat
   keine Nachfahren und kann für niemanden Bezugsrahmen werden; die Optik bleibt
   dieselbe. Wer die Unschärfe hierher zurückholt, holt den Fehler mit. */
.topbar::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
/* Ohne Unschärfe wäre die Leiste halb durchsichtig und der Text darunter läge im Weg. */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .topbar { background: var(--surface); }
}

.brand {
  display: flex; align-items: center; gap: var(--s-3);
  flex-shrink: 1; min-width: 0;
  color: inherit; text-decoration: none;
}
.brand:hover { text-decoration: none; }
/* Das Logo ist eine App-Icon-Kachel mit eingebranntem Verlauf, kein freigestelltes
   Zeichen — deshalb als Kachel mit eigenem Radius, nicht auf eine Fläche gesetzt. */
.brand img { width: 36px; height: 36px; border-radius: var(--r-input); display: block; flex: none; }
.brand-text {
  font-size: 15px; letter-spacing: -0.03em; color: var(--text); line-height: 1.3;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.brand-text span {
  display: block;
  font-family: var(--font-label);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Produktumschalter
   --------------------------------------------------------------------------
   Eine segmentierte Pille, das aktive Segment gefüllt. Vorher standen hier zwei
   nackte Textlinks in einem `nav`, für das es gar kein CSS gab — sie lasen sich
   auf dem Telefon als ein Wort: „TelefonassistentChat-Assistent".

   `white-space: nowrap` ist hier nicht Kosmetik: bricht ein Segment um, wächst
   der Balken auf zwei Zeilen und schiebt den Inhalt darunter weg. */
.pswitch {
  display: flex;
  flex: none;
  gap: 2px;
  padding: 3px;
  background: var(--bg);
  border: 0;
  border-top: 1px solid var(--border-2);
  border-radius: var(--r-input);
}
.pseg {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border-radius: 9px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.3px;
  color: var(--text-2);
  text-decoration: none;
  white-space: nowrap;
}
.pseg:hover { text-decoration: none; color: var(--text); background: var(--surface-2); }
.pseg svg { width: 18px; height: 18px; flex: none; display: block; }
.pseg.ist-aktiv {
  background: var(--accent);
  border-top: 1px solid var(--accent-light);
  color: var(--text);
}
.pseg.ist-aktiv:hover { background: var(--accent); }
.pseg:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; }

.nav { display: flex; gap: var(--s-1); flex-wrap: wrap; max-width: 100%; min-width: 0; }
.nav a {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.3px;
  color: var(--text);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-pill);
  text-decoration: none;
  white-space: nowrap;
}
.nav a:hover { background: var(--surface-2); text-decoration: none; }
.nav a[aria-current='page'] { background: var(--accent); border-top: 1px solid var(--accent-light); }
.nav .count {
  display: inline-block;
  font-family: var(--font-label);
  font-size: 12px;
  font-weight: 500;
  margin-left: var(--s-2);
  padding: 1px 7px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent-pale);
}
.nav a[aria-current='page'] .count { background: rgba(0, 0, 0, 0.3); color: #fff; }

.topbar-end { margin-left: auto; display: flex; align-items: center; gap: var(--s-3); flex: none; }
/* Die Adresse darf schrumpfen und abschneiden — sie ist Beiwerk. Der Name nicht.
   Der vollständige Wert steht im title-Attribut, damit nichts verloren geht. */
.whoami {
  font-family: var(--font-label);
  font-size: 13px;
  color: var(--text-2);
  text-align: right;
  line-height: 1.4;
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.whoami strong {
  display: block; color: var(--text); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Schubfach: Vollbildmenü für schmale Geräte
   --------------------------------------------------------------------------
   Bewusst ein `<details>` und kein per JavaScript umgeschalteter Kasten: so
   öffnet das Menü auch ohne Skript. app.js ergänzt nur Rollsperre, Escape,
   Fokusfalle und das Schliessen beim Antippen daneben.

   Der Knopf liegt IM Balken und muss über der Fläche bleiben, sonst lässt sich
   das geöffnete Menü nicht wieder schliessen — daher der eigene Stapelkontext. */
/* Sitzt IM Fluss der Kopfzeile, ganz rechts. Dass die Vollbildfläche darin trotzdem
   den Bildschirm bekommt und nicht die Leiste, liegt an `.topbar::before` — die
   Begründung steht dort. */
.menue {
  position: relative;
  z-index: 45;
  display: none;
  flex: none;
  margin-left: auto;
}
.menue-knopf {
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;      /* 44px ist die kleinste gut treffbare Fläche */
  border-radius: var(--r-input);
  background: var(--surface-2);
  border-top: 1px solid var(--border-2);
  color: var(--text);
  cursor: pointer;
  list-style: none;
}
.menue-knopf::-webkit-details-marker { display: none; }
.menue-knopf::marker { content: ''; }
.menue-knopf svg { width: 20px; height: 20px; display: block; }
.menue-knopf:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; }
/* Zwei Symbole übereinander, es zeigt sich immer nur eines. */
.menue .menue-zu { display: none; }
.menue[open] .menue-auf { display: none; }
.menue[open] .menue-zu { display: block; }

.menue-panel {
  position: fixed;
  inset: 0;
  z-index: 1;
  background: rgba(0, 0, 0, 0.94);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  overflow-y: auto;
  /* Verhindert, dass das Weiterrollen am Ende der Liste die Seite darunter mitnimmt. */
  overscroll-behavior: contain;
}
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .menue-panel { background: #000; }
}
.menue-inhalt {
  max-width: 560px;
  margin: 0 auto;
  padding:
    calc(var(--s-10) + env(safe-area-inset-top))
    max(var(--s-5), env(safe-area-inset-right))
    calc(var(--s-8) + env(safe-area-inset-bottom))
    max(var(--s-5), env(safe-area-inset-left));
}
.menue-inhalt .eyebrow { margin-top: var(--s-6); }
.menue-inhalt .eyebrow:first-child { margin-top: 0; }

.menue-nav { display: flex; flex-direction: column; }
.menue-nav a {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  /* Grosse Ziele: das hier wird mit dem Daumen bedient, nicht mit einer Maus. */
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--border);
  font-size: 20px;
  font-weight: 400;
  letter-spacing: -0.03em;
  color: var(--text);
  text-decoration: none;
}
.menue-nav a:hover { text-decoration: none; color: var(--accent-pale); }
.menue-nav a[aria-current='page'] { color: var(--accent-pale); }
.menue-nav .count {
  margin-left: auto;
  font-family: var(--font-label);
  font-size: 12px;
  padding: 2px 9px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent-pale);
}

.menue-produkte { display: flex; flex-direction: column; gap: var(--s-2); }
.menue-produkt {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4);
  border-radius: var(--r-input);
  background: var(--surface);
  border-top: 1px solid var(--border-2);
  color: var(--text);
  font-size: 16px;
  text-decoration: none;
}
.menue-produkt:hover { text-decoration: none; background: var(--surface-2); }
.menue-produkt svg { width: 20px; height: 20px; flex: none; }
.menue-produkt.ist-aktiv { background: var(--accent-soft); border-top-color: var(--accent-mid); }
/* Ein nicht gebuchtes Produkt verschwindet nicht, es wird zurückgenommen — und führt
   auf die Upsell-Seite. Ein weggelassener Menüpunkt verkauft nichts. */
.menue-produkt.ist-gesperrt { color: var(--text-2); }
.menue-produkt em {
  margin-left: auto;
  font-style: normal;
  font-family: var(--font-label);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
  white-space: nowrap;
}

.lang-switch { display: flex; gap: var(--s-2); }
.lang-seg {
  flex: 1;
  padding: var(--s-3);
  border: 0;
  border-top: 1px solid var(--border-2);
  border-radius: var(--r-input);
  background: var(--surface);
  color: var(--text-2);
  font: 500 15px/1.4 var(--font);
  letter-spacing: 0.06em;
  cursor: pointer;
}
.lang-seg.ist-aktiv { background: var(--accent); border-top-color: var(--accent-light); color: var(--text); }
.lang-seg:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; }

/* Mandanten-Schnellwahl im Menue (nur Team-Konten). Gleiche Bausprache wie die
   Sprachwahl, aber untereinander: Mandantennamen sind zu lang fuer Segmente. */
.mandant-wahl { display: flex; flex-direction: column; gap: var(--s-2); }
.mandant-seg {
  padding: var(--s-3);
  border: 0;
  border-top: 1px solid var(--border-2);
  border-radius: var(--r-input);
  background: var(--surface);
  color: var(--text-2);
  font: 500 15px/1.4 var(--font);
  text-align: left;
  cursor: pointer;
}
.mandant-seg.ist-aktiv { background: var(--accent); border-top-color: var(--accent-light); color: var(--text); }
.mandant-seg:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; }

.menue-konto {
  margin-top: var(--s-6);
  padding-top: var(--s-5);
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
/* Im Schubfach ist Platz — hier darf die Adresse links stehen und umbrechen,
   statt wie im Balken abgeschnitten zu werden. */
.menue-konto .whoami {
  max-width: 100%;
  text-align: left;
  font-size: 15px;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Rollsperre, solange das Schubfach offen ist. Wird von app.js gesetzt; ohne
   Skript rollt die Seite hinter der Fläche mit, was verkraftbar ist. */
body.menue-offen { overflow: hidden; }

/* --------------------------------------------------------------------------
   Bereichsnavigation
   --------------------------------------------------------------------------
   Die Bereiche des Produkts (und auf Assistentenseiten darunter die Bereiche
   DIESES Assistenten). Sie stehen als Pillenreihen im Inhalt, nicht in der
   Kopfzeile: dort brauchten die neun Punkte 1054 Pixel und bekamen 423, worauf
   der Balken auf zwei bis vier Zeilen wuchs und der Seitenanfang darunter
   verschwand.

   Als erstes Element IN `main` und nicht davor — so bleibt der obere Abstand von
   `main` unverändert, und wenn die Reihe auf schmalen Geräten entfällt (dort
   führt das Schubfach), steht kein leerer Kasten herum. */
.subnav-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin-bottom: var(--s-6);
}
.subnav {
  display: flex;
  gap: var(--s-2);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: var(--s-2);
}
.subnav::-webkit-scrollbar { display: none; }
.subnav a {
  flex: none;
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r-pill);
  background: var(--surface);
  border: 0;
  border-top: 1px solid var(--border-2);
  color: var(--text-2);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.3px;
  text-decoration: none;
  white-space: nowrap;
}
.subnav a:hover { text-decoration: none; color: var(--text); }
.subnav a[aria-current='page'] {
  background: var(--surface-2);
  border-top-color: var(--accent-light);
  color: var(--text);
}
.subnav .count {
  display: inline-block;
  font-family: var(--font-label);
  font-size: 11px;
  margin-left: var(--s-2);
  padding: 1px 7px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent-pale);
}
/* Die zweite Reihe (Bereiche eines Assistenten) tritt gegenüber der ersten zurück:
   zwei gleich laute Pillenreihen übereinander lesen sich als eine verunglückte. */
.subnav-zweite a { font-size: 13px; padding: 6px var(--s-3); background: transparent; }
.subnav-zweite a[aria-current='page'] { background: var(--surface); }

/* ==========================================================================
   Grundgerüst
   ========================================================================== */

main {
  max-width: var(--content);
  margin: 0 auto;
  /* Oben Platz für die schwebende Navigation — siehe --nav-space. */
  padding: var(--nav-space) var(--s-7) var(--s-10);
}
.page-head { margin-bottom: var(--s-9); }
.page-head h1 { margin-bottom: var(--s-4); }

.stack  { display: flex; flex-direction: column; gap: var(--s-5); }
.row    { display: flex; gap: var(--s-3); flex-wrap: wrap; align-items: center; }
.row-end { margin-left: auto; }
.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--s-5); }
.grid-4 { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--s-4); }

/* Flex- und Grid-Kinder haben von sich aus eine Mindestbreite in Höhe ihres Inhalts.
   Genau das macht eine lange E-Mail-Adresse zum Layoutproblem. */
.topbar > *, .card, .tile, .stack > *, .grid-2 > *, .grid-4 > * { min-width: 0; }

/* ==========================================================================
   Karten
   ==========================================================================
   #141414 auf #000, Lichtkante oben in 2px, Radius 20px, KEIN Schatten.
   Die Hierarchie entsteht über den minimalen Helligkeitsunterschied, nicht über Farbe. */

.card {
  background: var(--surface);
  border: 0;
  border-top: 2px solid var(--border);
  border-radius: var(--r-card);
  padding: var(--s-5);
}
.card > h2, .card > h3 { margin-bottom: var(--s-2); }
.card-head { display: flex; align-items: baseline; gap: var(--s-3); margin-bottom: var(--s-4); flex-wrap: wrap; }
.card-head p { margin: 0; }
.card-foot { margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid var(--border-2); }

/* Hervorgehobene Karte: kein anderer Rahmen, sondern ein Verlauf von unten. */
.card-accent {
  border-radius: var(--r-card-l);
  background: linear-gradient(0deg, var(--surface) 0%, var(--accent-deep) 45%, var(--accent-mid) 65%, var(--accent) 85%);
}

.tile {
  background: var(--surface);
  border: 0;
  border-top: 2px solid var(--border);
  border-radius: var(--r-card);
  padding: var(--s-5);
}
.tile .k {
  font-family: var(--font-label);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
  margin-bottom: var(--s-3);
}
.tile .v {
  font-family: var(--font);
  font-size: 40px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.05em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.tile .u { font-size: 14px; color: var(--text-3); margin-top: var(--s-2); }
.tile.accent .v { color: var(--accent-pale); }

/* Farbe liegt als Licht hinter dem Inhalt, nie als Fläche darauf. Das ist der Trick,
   mit dem die Seite trotz Schwarz nicht tot wirkt. */
.glow {
  position: absolute;
  inset: auto 0 0 0;
  height: 340px;
  border-radius: var(--r-card-l);
  background: linear-gradient(180deg, rgba(84, 84, 84, 0) 0%, var(--accent) 100%);
  opacity: 0.5;
  filter: blur(60px);
  pointer-events: none;
  z-index: 0;
}

/* ==========================================================================
   Buttons
   ==========================================================================
   Primär = Petrol mit Lichtkante und tiefem Schein.
   Sekundär = WEISS mit schwarzem Text. Nicht dunkelgrau — das ist der hohe Kontrast,
   den die Website oben rechts einsetzt.
   Leise = die zurückgenommene Variante für alles, was nicht die Haupthandlung ist. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  font-family: var(--font);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: -0.3px;
  padding: var(--s-4) 18px;
  border: 0;
  border-radius: var(--r-btn);
  background: var(--surface-2);
  border-top: 1px solid var(--border-2);
  color: var(--text);
  cursor: pointer;
  text-decoration: none;
}
.btn:hover { text-decoration: none; filter: brightness(1.15); }
.btn:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; }
.btn[disabled], .btn[aria-disabled='true'] { opacity: 0.45; cursor: not-allowed; filter: none; }

.btn-primary {
  background: var(--accent);
  border-top: 1px solid var(--accent-light);
  box-shadow: var(--shadow-accent);
}
.btn-secondary {
  background: #ffffff;
  color: #000000;
  border-top: 1px solid var(--text-2);
  box-shadow: var(--shadow-light);
}
/* Auf einer Karte (#141414) verschwindet ein durchsichtiger Knopf vollständig — er las
   sich als schwebende Beschriftung, nicht als Schaltfläche. Deshalb die erhöhte Fläche. */
.btn-quiet {
  background: var(--surface-2);
  border-top: 1px solid var(--border-2);
  color: var(--text-2);
}
.btn-quiet:hover { color: var(--text); background: var(--surface-2); }
.btn-danger {
  background: transparent;
  border-top: 1px solid rgba(224, 87, 76, 0.5);
  color: var(--danger);
}
.btn-sm { padding: var(--s-2) var(--s-3); font-size: 14px; border-radius: var(--r-input); }
.btn-block { width: 100%; }

/* ==========================================================================
   Formulare
   ========================================================================== */

/* Bewusst NICHT das nackte `label`: als Container um ein Optionsfeld gelegt
   (der natürliche Weg für eine grosse Klickfläche) würde sonst auch der
   Erklärtext zwangsversalisiert — "CLAUDE-SONNET-5 / SCHNELL UND GÜNSTIG".
   Befund des Chat-Dashboards, dort zuerst aufgetreten. */
.label, .field > label {
  display: block;
  font-family: var(--font-label);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
  margin-bottom: var(--s-2);
}
.field { margin-bottom: var(--s-5); }
.field .help { font-size: 14px; color: var(--text-2); margin-top: var(--s-2); line-height: 1.5; }

input[type='text'], input[type='email'], input[type='password'], input[type='file'], textarea, select {
  width: 100%;
  font: 400 16px/1.4 var(--font);
  color: var(--text);
  background: var(--surface-2);
  border: 0;
  border-top: 2px solid var(--border-2);
  border-radius: var(--r-input);
  padding: 14px;
}
textarea { line-height: 1.55; resize: vertical; min-height: 120px; }
input:focus, textarea:focus, select:focus {
  outline: none;
  border: 1px solid var(--accent-light);
  border-top: 1px solid var(--accent-light);
}
input::placeholder, textarea::placeholder { color: var(--text-3); }
input[readonly], textarea[readonly] { color: var(--text-2); background: #101010; }

select {
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-2) 50%),
    linear-gradient(135deg, var(--text-2) 50%, transparent 50%);
  background-position: calc(100% - 20px) calc(50% + 2px), calc(100% - 15px) calc(50% + 2px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 42px;
}

.code-input {
  font-family: var(--font-mono);
  font-size: 28px;
  letter-spacing: 0.4em;
  text-align: center;
  padding: 18px 14px;
}

.counter { font-family: var(--font-mono); font-size: 12px; color: var(--text-3); }
.counter.over { color: var(--text); }

/* ==========================================================================
   Zustände: Fehler, Hinweis, Erfolg, leer
   ==========================================================================
   Eine Meldung besteht aus zwei Teilen: was passiert ist, und was jetzt zu tun ist.
   Der zweite Teil steht in .what-now und ist der Grund, warum die Meldung existiert. */

.notice {
  border: 0;
  border-top: 2px solid var(--border-2);
  border-radius: var(--r-card);
  background: var(--surface);
  padding: var(--s-4) var(--s-5);
  margin-bottom: var(--s-5);
  font-size: 15px;
  line-height: 1.55;
  color: var(--text-2);
}
.notice strong { display: block; color: var(--text); font-weight: 500; margin-bottom: var(--s-1); }
.notice .what-now { display: block; margin-top: var(--s-3); color: var(--text-2); font-size: 14px; }
.notice ul { margin: var(--s-3) 0 0; padding-left: 20px; }
.notice li { margin-bottom: var(--s-2); }

.notice-error { border-top-color: var(--danger); background: var(--danger-soft); }
.notice-error strong { color: var(--danger); }
/* Erfolg und Hinweis kommen ohne neue Farbe aus — Petrol trägt beides. */
.notice-ok    { border-top-color: var(--accent-light); background: var(--accent-soft); }
.notice-info  { border-top-color: var(--accent); background: var(--accent-soft); }
.notice-warn  { border-top-color: var(--text-2); background: var(--white-soft); }

.empty {
  text-align: center;
  padding: var(--s-9) var(--s-4);
  color: var(--text-2);
  font-size: 15px;
}

/* ==========================================================================
   Marken
   ==========================================================================
   Offen = Petrol, weil es Aufmerksamkeit braucht. Erledigt = zurückgenommenes Weiss,
   weil es keine mehr braucht. Kein Grün. */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  font-family: var(--font-label);
  font-size: 12px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: var(--r-badge);
  background: var(--surface-2);
  color: var(--text-2);
  white-space: nowrap;
}
.badge-open   { background: var(--accent-soft); color: var(--accent-pale); }
.badge-done   { background: var(--surface-2); color: var(--text-2); }
.badge-off    { background: var(--surface-2); color: var(--text-2); }
/* `ok` und `warn` heissen NICHT grün und gelb — die Marke trägt einen Akzent, und
   ein Zustand wird über Helligkeit unterschieden, nicht über eine erfundene
   Ampelfarbe. Beide wurden von den Ansichten schon benutzt, bevor es sie gab:
   `badge-ok`/`badge-warn` entstanden in JS-Variablen (`['badge-ok', 'Prompt']`)
   und fielen deshalb keiner Suche nach `class="…"` auf. */
.badge-ok     { background: var(--accent-soft); color: var(--accent-pale); }
.badge-warn   { background: var(--white-soft); color: var(--text); }
/* Der einzige laute Zustand: weiss auf schwarz, wie der Haupt-CTA der Website. */
.badge-urgent { background: #ffffff; color: #000000; }

/* ==========================================================================
   Tabellen
   ========================================================================== */

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 15px; }
th {
  text-align: left;
  font-family: var(--font-label);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
  padding: 0 var(--s-4) var(--s-3) 0;
  border-bottom: 1px solid var(--border-2);
  white-space: nowrap;
}
td {
  padding: var(--s-4) var(--s-4) var(--s-4) 0;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
  color: var(--text-2);
  /* E-Mail-Adressen und Kennungen haben keine Trennstellen — ohne das reissen sie
     die Tabelle auf und die Seite scrollt seitwärts. `break-word`, nicht `anywhere`:
     die Begründung steht weiter unten bei der zweiten Fassung dieser Regel. */
  overflow-wrap: break-word;
}
td strong { color: var(--text); font-weight: 500; }
tr:last-child td { border-bottom: none; }
td:last-child, th:last-child { padding-right: 0; }
td time, td .when {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-2);
  white-space: nowrap;
}

/* Anteilsbalken in Tabellen (Kriterien, Themen). */
.meter { background: var(--bg); border-radius: var(--r-pill); height: 8px; overflow: hidden; }
.meter i { display: block; height: 100%; background: var(--accent); }

/* ==========================================================================
   Filter, Blättern, Aufklappbares
   ========================================================================== */

.filters { display: flex; gap: var(--s-2); margin-bottom: var(--s-5); flex-wrap: wrap; align-items: center; }
.filters a {
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.3px;
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r-pill);
  background: var(--surface);
  border: 0;
  border-top: 1px solid var(--border-2);
  color: var(--text-2);
  text-decoration: none;
}
.filters a:hover { text-decoration: none; color: var(--text); }
.filters a[aria-current='true'] {
  background: var(--accent);
  border-top: 1px solid var(--accent-light);
  color: var(--text);
}

.pager { display: flex; gap: var(--s-3); align-items: center; margin-top: var(--s-5); font-size: 14px; color: var(--text-2); }

details.disclose { border-top: 1px solid var(--border-2); padding-top: var(--s-3); margin-top: var(--s-3); }
details.disclose summary { cursor: pointer; font-size: 14px; color: var(--accent-pale); }
details.disclose pre {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.6;
  color: var(--text-2);
  background: var(--bg);
  border: 0;
  border-top: 1px solid var(--border-2);
  border-radius: var(--r-input);
  padding: var(--s-3);
  margin-top: var(--s-3);
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 340px;
  overflow: auto;
}

/* ==========================================================================
   Gesperrter, aber sichtbarer Block
   ==========================================================================
   Für Inhalte, die der Kunde sehen soll, aber nicht ändern darf. */

.locked-block {
  border: 0;
  border-top: 2px solid var(--accent-mid);
  border-radius: var(--r-card);
  background: var(--accent-soft);
  padding: var(--s-5);
}
.locked-block .locked-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-label);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-pale);
  margin-bottom: var(--s-3);
}
.locked-block pre {
  margin: 0;
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.6;
  color: var(--text-2);
  white-space: pre-wrap;
  word-break: break-word;
}

/* ==========================================================================
   Seiten vor der Anmeldung
   ==========================================================================
   Farbe als Licht hinter dem Inhalt, nicht als Fläche darauf. */

.auth-page {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: var(--s-5);
  position: relative;
  overflow: hidden;
}
.auth-glow {
  position: absolute;
  left: 50%;
  bottom: -22%;
  width: min(1000px, 120%);
  height: 760px;
  transform: translateX(-50%);
  border-radius: var(--r-card-l);
  background: linear-gradient(180deg, rgba(84, 84, 84, 0) 0%, var(--accent) 100%);
  opacity: 0.75;
  filter: blur(70px);
  pointer-events: none;
}
.auth-card {
  position: relative;
  width: 100%;
  max-width: 460px;
  background: var(--surface);
  border: 0;
  border-top: 2px solid var(--border);
  border-radius: var(--r-card);
  padding: var(--s-6);
}
.auth-card-wide { max-width: 620px; }
.auth-card h1 { font-size: 34px; margin-bottom: var(--s-3); }
.auth-card .lead { font-size: 17px; margin-bottom: var(--s-5); }
.auth-brand { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-6); }
.auth-brand img { width: 44px; height: 44px; border-radius: var(--r-btn); }
.auth-foot { margin-top: var(--s-5); font-size: 13px; color: var(--text-2); line-height: 1.6; }

/* Sprachwahl vor der Anmeldung: zwei stille Links unter der Karte. Die aktive
   Sprache ist Text, kein Link — es gibt nichts zu tun, also nichts Klickbares. */
.sprachwahl {
  margin-top: var(--s-4);
  display: flex; justify-content: center; gap: var(--s-4);
  font-size: 13px; letter-spacing: 0.08em;
}
.sprachwahl a { color: var(--text-3); text-decoration: none; }
.sprachwahl a:hover { color: var(--text); text-decoration: underline; }
.sprachwahl [aria-current] { color: var(--text); font-weight: 600; }

/* ==========================================================================
   Maschinelle Werte
   ========================================================================== */

.codes {
  display: grid;
  /* Die Spalte muss breiter sein als ein vollständiger Code, sonst laufen die Codes
     über ihre Spalte hinaus und verschmelzen optisch — beim Abtippen fatal. */
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: var(--s-2);
  font-family: var(--font-mono);
  font-size: 14px;
  background: var(--bg);
  border: 0;
  border-top: 2px solid var(--border-2);
  border-radius: var(--r-input);
  padding: var(--s-4);
  margin-bottom: var(--s-4);
  color: var(--text);
}
.codes span { padding: var(--s-1) 4px; letter-spacing: 0.06em; white-space: nowrap; }

.qr {
  background: #ffffff;
  border-radius: var(--r-input);
  padding: var(--s-4);
  width: fit-content;
  line-height: 0;
}
.qr svg { width: 208px; height: 208px; display: block; }

.secret {
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 0.12em;
  background: var(--bg);
  border: 0;
  border-top: 1px solid var(--border-2);
  border-radius: var(--r-input);
  padding: var(--s-3);
  word-break: break-all;
  color: var(--text);
}

/* ==========================================================================
   Balkenreihe
   ==========================================================================
   Bewusst als CSS-Balken statt als Diagrammbibliothek: kein Bundler, kein Skript,
   und die Marke verträgt eine ruhige Reihe besser als ein buntes Diagramm. */

.bars { display: flex; align-items: flex-end; gap: var(--s-1); height: 120px; margin-top: var(--s-4); overflow-x: auto; }
.bars .bar { flex: 1 0 14px; display: flex; flex-direction: column; justify-content: flex-end; gap: var(--s-1); text-align: center; min-width: 0; }
.bars .bar i {
  display: block;
  background: linear-gradient(180deg, var(--accent) 0%, var(--accent-deep) 100%);
  border-top: 1px solid var(--accent-light);
  border-radius: var(--s-1) var(--s-1) 3px 3px;
  min-height: 3px;
}
.bars .bar em { font-family: var(--font-mono); font-size: 11px; color: var(--text-2); font-style: normal; }

/* --------------------------------------------------------------------------
   Diagramme (views/charts.js)
   --------------------------------------------------------------------------
   Ein Akzent, unterschieden durch FORM. Die Segmente eines gestapelten Balkens
   tragen dasselbe Petrol in anderer Helligkeit; ab dem zweiten kommt eine
   Schraffur dazu, damit die Unterscheidung auch bei Farbenblindheit und im
   Ausdruck traegt. Kein zweiter Farbton, keine erfundene Erfolgsfarbe. */

.chart { margin-top: var(--s-4); }

.sparkline { display: block; width: 100%; height: auto; }

.chart-axis {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-2);
  margin-top: var(--s-2);
}

/* Die Tabelle unter jedem Diagramm. Zugeklappt unauffaellig, aufgeklappt eine
   gewoehnliche Tabelle -- sie ist der barrierefreie Zugang zu denselben Zahlen. */
.chart-data { margin-top: var(--s-3); }
.chart-data > summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--text-2);
  padding: var(--s-2) 0;
}
.chart-data > summary:hover { color: var(--text); }
.chart-data > summary:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; }
.chart-table { font-size: 13px; }
.chart-table td { font-variant-numeric: tabular-nums; }

.bars .bar-stack .bar-col {
  display: flex;
  flex-direction: column-reverse;
  border-radius: var(--s-1) var(--s-1) 3px 3px;
  overflow: hidden;
}
/* Im Stapel bekommt NUR das oberste Segment die Lichtkante -- eine Kante je
   Segment liesse den Balken gestreift wirken statt geschichtet. */
.bars .bar-stack .bar-col i { border-top: 0; border-radius: 0; }
.bars .bar-stack .bar-col i:last-child { border-top: 1px solid var(--accent-light); }

.seg-hatch {
  background-image: repeating-linear-gradient(
    45deg, rgba(0, 0, 0, 0.28) 0 3px, rgba(0, 0, 0, 0) 3px 6px);
}

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  list-style: none;
  margin: var(--s-3) 0 0;
  padding: 0;
  font-size: 13px;
  color: var(--text-2);
}
.chart-legend li { display: flex; align-items: center; gap: var(--s-2); }
.chart-legend .swatch {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  border-top: 1px solid var(--accent-light);
  flex: none;
}

/* Hervorgehobene Zeile in einer Tabelle: der Abbruchgrund, der ein technischer
   Fehler ist. Kein Rot als Flaeche -- eine Kante links reicht, und sie stoert
   die Tabelle nicht. */
tr.zeile-alarm td, tr.zeile-alarm th {
  background: var(--danger-soft);
  box-shadow: inset 3px 0 0 var(--danger);
}

/* --------------------------------------------------------------------------
   Anrufaufnahme
   --------------------------------------------------------------------------
   Der native Abspieler bleibt als Rueckfall stehen (ohne JavaScript ist er das
   Einzige, was da ist); mit JavaScript uebernimmt die eigene Bedienung. */
.audio-player { width: 100%; margin-top: var(--s-3); }

.player {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin-top: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: var(--surface-2);
  border-top: 1px solid var(--border-2);
  border-radius: var(--r-card);
}

.player-toggle {
  flex: none;
  width: 44px; height: 44px;      /* 44px ist die kleinste gut treffbare Flaeche */
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.player-toggle:hover { background: var(--accent-light); }
.player-toggle:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; }
/* Zwei Symbole uebereinander, es zeigt sich immer nur eines. */
.player-toggle .pause { display: none; }
.player-toggle.laeuft .play { display: none; }
.player-toggle.laeuft .pause { display: block; }

.player-seek {
  flex: 1 1 auto;
  min-width: 0;
  accent-color: var(--accent-light);
}
.player-time {
  flex: none;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 480px) {
  /* Auf schmalen Geraeten steht die Zeit unter der Schiene statt daneben --
     nebeneinander bleiben fuer die Schiene sonst keine 100px. */
  .player { flex-wrap: wrap; }
  .player-seek { flex-basis: 100%; order: 3; }
}

/* --------------------------------------------------------------------------
   Konnektor-Kacheln
   --------------------------------------------------------------------------
   Ein nicht gebuchter Konnektor wird ZURUECKGENOMMEN, nicht eingefaerbt: die
   Marke traegt einen Akzent, und ein Zustand wird ueber Form unterschieden.
   Deshalb nur weniger Deckkraft und ein blasserer Rand -- keine zweite Farbe.
   Die Deckkraft bleibt bei 0.65 und nicht darunter: bei 0.5 faellt der
   Fliesstext unter die Lesbarkeitsschwelle, und eine Kachel, die man nicht
   lesen kann, kann man auch nicht anfragen. */
.card.ist-gedaempft { opacity: 0.65; }
.card.ist-gedaempft:hover,
.card.ist-gedaempft:focus-within { opacity: 1; }

/* Ankreuzfeld mit Beschriftung und Erklaerung darunter. */
.field-check {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
}
.field-check input { margin-top: 4px; flex: none; }
.field-check > span { display: flex; flex-direction: column; gap: 2px; }
.field-check strong { font-weight: 500; }

/* ==========================================================================
   Fusszeile
   ========================================================================== */

.foot {
  max-width: var(--content);
  margin: 0 auto;
  padding: var(--s-6) var(--s-7) var(--s-8);
  border-top: 1px solid var(--border);
  font-size: 13px;
  color: var(--text-2);
  display: flex;
  gap: var(--s-5);
  flex-wrap: wrap;
}

/* ==========================================================================
   Zugänglichkeit
   ========================================================================== */

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 30;
  background: var(--accent); color: #fff; padding: var(--s-3) 18px;
  border-radius: 0 0 var(--r-btn) 0;
}
.skip-link:focus { left: 0; }

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

/* --------------------------------------------------------------------------
   Sichere Bereiche (Notch, Dynamic Island, Homebalken)
   --------------------------------------------------------------------------
   Gehoert zu `viewport-fit=cover` im Kopf der Seite. Ohne BEIDES zusammen liegt
   die Kopfzeile auf dem iPhone unter der Dynamic Island und der Fusszeilentext
   unter dem Homebalken. `max()` statt `+`: auf Geraeten ohne Notch ist der Wert
   0, und dann soll der gewohnte Abstand gelten, nicht gar keiner.

   Links und rechts gilt dasselbe im Querformat — dort schiebt die Insel den
   Inhalt zur Seite, und ohne diese Zeilen klebt die Leiste am Rand des Auges. */

.topbar {
  top: max(var(--s-5), env(safe-area-inset-top));
  padding-left: max(var(--s-5), env(safe-area-inset-left));
  padding-right: max(var(--s-5), env(safe-area-inset-right));
}
main {
  padding-left: max(var(--s-7), env(safe-area-inset-left));
  padding-right: max(var(--s-7), env(safe-area-inset-right));
}
.foot { padding-bottom: max(var(--s-8), env(safe-area-inset-bottom)); }

/* ==========================================================================
   Schmale Geräte
   ==========================================================================
   Unterhalb von 900px passen Bereichsnavigation und Konto-Block nicht mehr neben
   die Marke. Sie wandern ins Schubfach; im Balken bleiben Marke,
   Produktumschalter und Menüknopf — eine Zeile, immer.

   Der Balken bleibt dabei `fixed`. Die frühere Fassung setzte ihn hier in den
   Fluss zurück; damit hing der Abstand zur Statusleiste an einem `margin-top`,
   das im Standalone-Modus (schwarz-durchscheinende Statusleiste) unter der
   iPhone-Uhr landete. Genau das war der Befund „der Protokoll-Titel klebt hinter
   der Uhr". */

@media (max-width: 900px) {
  :root { --nav-space: calc(84px + env(safe-area-inset-top)); }

  .topbar {
    top: max(var(--s-3), env(safe-area-inset-top));
    width: auto;
    left: max(var(--s-3), env(safe-area-inset-left));
    right: max(var(--s-3), env(safe-area-inset-right));
    transform: none;
    max-width: none;
    gap: var(--s-3);
    padding: var(--s-2) max(var(--s-3), env(safe-area-inset-right))
             var(--s-2) max(var(--s-3), env(safe-area-inset-left));
  }
  .brand img { width: 32px; height: 32px; }
  .brand-text { font-size: 14px; }

  /* Diese beiden leben ab hier im Schubfach. */
  .nav, .topbar-end { display: none; }
  .menue { display: block; }
  /* Ohne Umschalter (Mandant mit einem Produkt) trägt die Marke die Breite. */
  .pswitch { margin-left: auto; }

  main { padding: var(--nav-space) var(--s-4) var(--s-9); }
  main {
    padding-left: max(var(--s-4), env(safe-area-inset-left));
    padding-right: max(var(--s-4), env(safe-area-inset-right));
  }

  /* Die Pillen BRECHEN UM statt seitwärts zu rollen (Julians Vorgabe vom 21.08.2026).
     Ein waagerechter Roller versteckt seine hinteren Punkte: „Konnekt…" am rechten
     Rand sieht aus wie ein Anzeigefehler, und niemand wischt in einer Leiste, die wie
     eine Leiste aussieht. Umbrechend sind alle Punkte auf einen Blick da — bei neun
     Punkten sind das zwei bis drei Zeilen, deshalb hier kleiner und enger. */
  .subnav {
    flex-wrap: wrap;
    overflow-x: visible;
    padding-bottom: 0;
  }
  .subnav a { font-size: 12.5px; padding: 5px var(--s-3); }
  .subnav-zweite a { font-size: 12px; padding: 4px 10px; }
}

/* Auf Telefonbreite muss es noch enger sein, sonst wird aus der umbrechenden Reihe
   ein Block. Gemessen bei 390px (Reihe 358px breit): die neun Punkte des
   Telefonprodukts brauchten mit 12,5px und 12px Polsterung zusammen 937px und damit
   VIER Zeilen. Mit den Werten hier sind es rund 830px — drei Zeilen, wie
   vorgegeben. Wer die Polsterung wieder aufmacht, bekommt die vierte Zeile zurück. */
@media (max-width: 480px) {
  .subnav { gap: 6px; }
  .subnav a { font-size: 12px; padding: 4px 9px; }
  .subnav .count { margin-left: 5px; padding: 1px 5px; font-size: 10px; }
  .foot { padding: var(--s-5) var(--s-4) max(var(--s-6), env(safe-area-inset-bottom)); }
}

@media (max-width: 720px) {
  body { font-size: 14px; }
  h1 { font-size: 32px; }
  h2 { font-size: 24px; }
  h3 { font-size: 20px; }
  .lead { font-size: 16px; }
  .eyebrow { font-size: 12px; }
  .tile .v { font-size: 32px; }
  .auth-card { padding: var(--s-5); }
  .auth-card h1 { font-size: 28px; }
  .menue-nav a { font-size: 18px; }
}

/* Ab hier wird der Umschalter zu zwei Symbolen. Die Beschriftung steht weiterhin
   im aria-label und im title — sichtbar verschwindet nur das Wort, nicht die
   Bedeutung. */
@media (max-width: 560px) {
  .pseg-text { display: none; }
  .pseg { padding: var(--s-2); }
  .brand-text span { display: none; }
}

/* Auf sehr schmalen Geräten (iPhone SE, 320px) reicht der Platz für den
   Mandantennamen neben Umschalter und Knopf nicht mehr. Das Logo allein ist
   eindeutig genug — es führt weiterhin zur Übersicht. */
@media (max-width: 380px) {
  .brand-text { display: none; }
}

/* --------------------------------------------------------------------------
   Tabellen auf schmalen Geraeten
   --------------------------------------------------------------------------
   Eine sechsspaltige Tabelle zerfaellt auf einem Telefon: entweder schiebt sie
   die ganze Seite zur Seite, oder die Spalten quetschen sich auf je zwei
   Zeichen. Beides ist unbrauchbar.

   Deshalb werden Tabellen mit `data-karten` unter 700px zu gestapelten Karten:
   jede Zeile wird eine Karte, jede Zelle bekommt ihre Spaltenueberschrift als
   Beschriftung davor (aus dem `data-label`-Attribut, das die Ansicht setzt).
   Tabellen OHNE dieses Attribut scrollen weiterhin in ihrem eigenen Container --
   das ist fuer wenige, kurze Spalten die bessere Wahl.
   
   Der Kopf verschwindet dabei visuell, bleibt aber fuer Bildschirmleser stehen:
   `display:none` wuerde die Zuordnung Kopf-zu-Zelle mitnehmen. */

.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Lange Werte (E-Mail, Kennungen) brechen, statt die Spalte zu sprengen.
 *
 * `break-word` und NICHT `anywhere`, und der Unterschied ist genau der Fehler, den
 * das hier vorher verursacht hat: `anywhere` zaehlt auch bei der Berechnung der
 * Mindestbreite mit. Eine Spalte darf dann beliebig schmal werden, und die
 * Tabellenverteilung nutzt das aus — auf der Agent-Seite standen deshalb
 * „Aufbewahr/ung", „Aenderunge/n" und „Offenlegun/g" mitten im Wort getrennt,
 * obwohl daneben Platz frei war.
 *
 * `break-word` laesst die Mindestbreite beim laengsten Wort und bricht ein Wort nur,
 * wenn es allein nicht in die Zeile passt. Lange Adressen und Kennungen brechen also
 * weiterhin — gewoehnliche Beschriftungen nicht mehr. */
td, th { overflow-wrap: break-word; }

@media (max-width: 700px) {
  table[data-karten] thead {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  table[data-karten],
  table[data-karten] tbody,
  table[data-karten] tr,
  table[data-karten] td,
  table[data-karten] th { display: block; width: auto; }

  table[data-karten] tbody tr {
    background: var(--surface);
    border-top: 2px solid var(--border);
    border-radius: var(--r-card);
    padding: var(--s-4);
    margin-bottom: var(--s-3);
  }
  table[data-karten] tbody td,
  table[data-karten] tbody th {
    border: 0;
    padding: var(--s-1) 0;
    text-align: left;
    display: flex;
    justify-content: space-between;
    gap: var(--s-3);
  }
  /* Die Zeilenueberschrift wird in der Kartenansicht zum TITEL der Karte. Ohne die
     Ruecknahmen erbt sie die Gestaltung der Spaltenkoepfe: gesperrte Versalien und
     `white-space: nowrap`. Ein Klientenname stand dann als
     „ANNA KATHARINA MUSTERMANN-S" da und war am Kartenrand abgeschnitten. */
  table[data-karten] tbody th {
    display: block;
    font-family: var(--font);
    font-size: 17px;
    font-weight: 500;
    letter-spacing: -0.02em;
    text-transform: none;
    white-space: normal;
    color: var(--text);
    padding-bottom: var(--s-3);
  }
  table[data-karten] tbody th[data-label]::before { display: none; }
  table[data-karten] tbody td[data-label]::before {
    content: attr(data-label);
    color: var(--text-2);
    font-family: var(--font-label);
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    flex: none;
  }
  /* Eine leere Zelle braucht keine Zeile -- sonst steht die Karte voller
     Beschriftungen ohne Werte. */
  table[data-karten] tbody td:empty { display: none; }

  /* Zellen mit mehrzeiligem Inhalt (der Wert vorher/nachher im Protokoll, ein
     aufklappbarer Volltext) koennen nicht als "Beschriftung links, Wert rechts"
     nebeneinander stehen: fuer den Wert blieben zwei Zentimeter. Sie stapeln
     stattdessen, die Beschriftung darueber. */
  table[data-karten] tbody td.zelle-block {
    display: block;
    padding-top: var(--s-3);
  }
  table[data-karten] tbody td.zelle-block[data-label]::before {
    display: block;
    margin-bottom: var(--s-2);
  }
  /* Zwischen zwei Karten braucht es eine sichtbare Trennung, sobald eine davon
     mehrere Zeilen hoch ist. */
  table[data-karten] tbody tr + tr { margin-top: var(--s-3); }
}

/* Zelle mit Anteilsbalken (Kriterien, Themen, Verteilungen). */
.meter-cell { width: 38%; min-width: 120px; }
.meter-cell + td, td.nowrap { white-space: nowrap; }
.meter-row { display: flex; align-items: center; gap: var(--s-3); flex-wrap: nowrap; }
.meter-row .meter { flex: 1; }

/* Der Benutzerblock in der Kopfzeile führt zu den Zugangsdaten. */
a.whoami { text-decoration: none; display: block; }
a.whoami:hover { text-decoration: none; }
a.whoami:hover strong { color: var(--accent-pale); }

/* ---------------------------------------------------------------------------
   Zustandspunkt
   ---------------------------------------------------------------------------
   Unterscheidet ueber die Form: gefuellt mit Hof = an, hohler Ring = aus.
   Ein Punkt in Petrol allein liest sich wie Navigation -- deshalb der Hof.
   Faellt Farbe weg (Schwarzweissdruck, Farbsehschwaeche), traegt die Form
   die Aussage immer noch. Aus demselben Grund steht neben dem Punkt Text.
   --------------------------------------------------------------------------- */
.dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  vertical-align: middle;
  margin-right: var(--s-2);
  flex: none;
}
.dot-on {
  background: var(--state-on);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--state-on) 22%, transparent);
}
.dot-off {
  background: transparent;
  border: 1.5px solid var(--state-off);
}
.dot-alert {
  background: var(--state-alert);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.18);
}
