/* ============================================================================
   ZENITH UI — Central Design System
   ----------------------------------------------------------------------------
   Single source of truth for all shared component styles of the Sales Agent app.
   In the prototype (07-Prototyp) these rules were copy-pasted into a <style>
   block on every page, with small per-page divergences. They are consolidated
   here into ONE canonical definition per component.

   How styling works in this app:
   - Layout & spacing: Tailwind utility classes in the HTML (config in
     assets/js/tailwind.config.js).
   - Component "skins" (cards, badges, chips, inputs, the AI pane, ...): the
     custom classes in THIS file.

   Color values are declared once as CSS custom properties in :root and reused
   via var(). The same palette is mirrored in tailwind.config.js so the Tailwind
   utility classes (bg-bg-main, text-txt-primary, ...) resolve to identical
   colors. Keep the two in sync when changing a token.

   NOTE: Several components had 2–3 diverging definitions across pages
   (.chip, .dash-card, .status-badge, .text-badge, .input-contrast:focus).
   They were converged to the values below. See docs/ANALYSE.md for the full
   convergence list.
   ============================================================================ */

/* ----------------------------------------------------------------------------
   1. DESIGN TOKENS
   ---------------------------------------------------------------------------- */
:root {
  /* Surfaces */
  --bg-main: #F4F4F5;       /* app background */
  --bg-card: #FFFFFF;       /* cards, panels */
  /* Hover MUSS sich vom Seitengrund unterscheiden. Vorher war dieser Wert
     identisch mit --bg-main: weisse Listenzeilen nahmen beim Ueberfahren
     exakt die Farbe des Hintergrunds an und verschwanden optisch. */
  --bg-hover: #FAFAFA;      /* row / item hover */
  --bg-input: #FFFFFF;

  /* Text */
  --txt-primary: #09090B;   /* near-black, headlines & primary text */
  --txt-secondary: #52525B; /* body text */
  --txt-tertiary: #71717A;  /* muted labels, captions */

  /* Borders */
  --border-light: #E4E4E7;
  --border-strong: #D4D4D8;

  /* Accent (monochrome) */
  --accent: #09090B;
  --accent-hover: #27272A;

  /* CTA (coral-orange) */
  --cta: #E86D4C;
  --cta-hover: #E25D3B;
  --cta-active: #D85535;
  --cta-border: #D65A39;
  --cta-light: #FEF0EC;

  /* Status */
  --status-error: #DC2626;
  --status-warning: #D97706;
  --status-success: #059669;
  --status-info: #2563EB;

  /* Elevation */
  /* Card shadows: previously carried a 1px ring (`0 0 0 1px …`) that read as
     a visible border on every card. Removed to match the Live-Prototyp where
     cards float on the page surface without a drawn frame. Hover gains a
     softer lift instead of a thicker ring. */
  --shadow-card: 0 1px 2px rgba(9, 9, 11, 0.04);
  --shadow-card-hover: 0 10px 24px -4px rgba(9, 9, 11, 0.08), 0 4px 10px -2px rgba(9, 9, 11, 0.04);
  /* Input ring stays — it's the only "border" inputs have. But softer than card,
     so it reads as a thin underline rather than a frame. */
  /* Eingabefeld-Kante — nur fuer Felder auf WEISSEM Grund (.boxed).
     Auf grauem Grund traegt die weisse Flaeche allein, siehe design.md. */
  --shadow-input: 0 0 0 1px #D4D4D8;
  --shadow-input-focus: 0 0 0 1px #E86D4C, 0 0 0 4px rgba(232, 109, 76, 0.15);
  --shadow-btn: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(9, 9, 11, 0.05);
  --shadow-btn-hover: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 2px 4px rgba(9, 9, 11, 0.1);
  --shadow-ai-pane: -1px 0 0 #E4E4E7, -16px 0 48px rgba(9, 9, 11, 0.08);

  /* Motion */
  --ease-zenith: cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* ----------------------------------------------------------------------------
   2. KEYFRAMES
   Declared globally so both Tailwind animation utilities (animate-fade-in,
   animate-slide-up) and the raw `animation:` references below (accordion, tabs)
   resolve correctly.
   ---------------------------------------------------------------------------- */
@keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } }
@keyframes slideUp { 0% { transform: translateY(6px); opacity: 0; } 100% { transform: translateY(0); opacity: 1; } }
@keyframes slideDown { 0% { transform: translateY(-6px); opacity: 0; } 100% { transform: translateY(0); opacity: 1; } }

/* ----------------------------------------------------------------------------
   3. BASE TYPOGRAPHY & RESET
   ---------------------------------------------------------------------------- */
body {
  background-color: var(--bg-main);
  color: var(--txt-primary);
  font-family: 'Inter', sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow: hidden; /* app shell scrolls inside <main>, not the document */
  font-feature-settings: "tnum", "cv02", "cv03", "cv04", "cv11";
  letter-spacing: -0.015em;
}

h1, h2, h3, h4, .font-serif {
  letter-spacing: -0.035em;
  color: var(--txt-primary);
  font-weight: 600;
}

/* Playfair Display (serif) is used for headlines/greetings, often in italic. */
.font-serif { font-family: 'Playfair Display', serif; font-weight: 500; }

/* ----------------------------------------------------------------------------
   4. CARDS
   .dash-card        → static surface
   .dash-card.hoverable → opt-in hover lift (add the modifier where wanted)
   .group\/kpi       → compact KPI tile variant
   ---------------------------------------------------------------------------- */
.dash-card {
  background: var(--bg-card);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
  transition: all 0.2s var(--ease-zenith);
  position: relative;
}
.dash-card.hoverable:hover {
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-2px);
  border-color: var(--border-strong);
}
/* `.dash-card.flat` — listen-wrapper variant. Drops the 1px ring-shadow that
   the default `.dash-card` carries, so vertically-stacked rows read as a sheet
   of records rather than a card-with-frame. Used on the Kunden/Angebote/...
   list outer divs to match the Live-Prototyp look (no border rundum). */
.dash-card.flat {
  box-shadow: none;
  background: transparent;
}

.group\/kpi {
  background: var(--bg-card) !important;
  border: 1px solid var(--border-light) !important;
  box-shadow: 0 1px 2px rgba(9, 9, 11, 0.02) !important;
  border-radius: 8px !important;
  transition: all 0.2s var(--ease-zenith) !important;
}
.group\/kpi:hover {
  border-color: var(--border-strong) !important;
  box-shadow: 0 6px 12px rgba(9, 9, 11, 0.04) !important;
  transform: translateY(-1px);
}

/* ----------------------------------------------------------------------------
   5. BUTTONS
   .bg-future   → primary CTA (coral, tactile shadow stack)
   .btn-secondary → neutral outlined button
   .btn-hover   → press-down micro-interaction (add to any clickable)
   .text-future → CTA-colored text
   ---------------------------------------------------------------------------- */
.bg-future {
  background: var(--cta);
  color: #fff;
  box-shadow: var(--shadow-btn), 0 0 0 1px var(--cta-border);
  border: none;
  transition: all 0.2s ease;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
}
.bg-future:hover { background: var(--cta-hover); box-shadow: var(--shadow-btn-hover), 0 0 0 1px #C24A2A; }
.bg-future:active { background: var(--cta-active); box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1), 0 0 0 1px #C24A2A; transform: translateY(0); }

.btn-secondary {
  background: var(--bg-card);
  color: var(--txt-primary);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-btn);
  transition: all 0.2s ease;
}
.btn-secondary:hover { border-color: var(--txt-primary); box-shadow: var(--shadow-btn-hover); }
.btn-secondary:active { box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.05); }

.btn-hover { transition: transform 0.1s ease; }
.btn-hover:active { transform: scale(0.97); }

.text-future { color: var(--cta); -webkit-background-clip: unset; -webkit-text-fill-color: unset; }

/* ----------------------------------------------------------------------------
   6. INPUTS
   Canonical focus = CTA ring (matches the modal inputs in components.js).
   ---------------------------------------------------------------------------- */
/* Eingabefeld auf grauem Grund: die weisse Flaeche grenzt sich selbst ab,
   eine gezeichnete Kante daneben wirkt starr. Steht das Feld auf weissem
   Grund (Karte, Dialog), braucht es zusaetzlich .boxed. */
.input-contrast {
  background: var(--bg-input);
  border: none;
  border-radius: 8px;
  color: var(--txt-primary);
  font-size: 13px;
  font-weight: 500;
  transition: all 0.2s ease;
}
.input-contrast:focus,
.input-contrast:focus-visible { outline: none; box-shadow: var(--shadow-input-focus); border-color: transparent; }
.input-contrast::placeholder { color: var(--txt-tertiary); font-weight: 400; }

/* Auf weissem Grund braucht das Feld eine Kante, sonst verschwindet es. */
/* Beanstandetes Feld: rote Kante statt nur einer Meldung daneben. */
.input-contrast.fehlt,
.input-contrast.boxed.fehlt { box-shadow: 0 0 0 1px var(--status-error); }

.input-contrast.boxed { box-shadow: var(--shadow-input); }
.input-contrast.boxed:focus,
.input-contrast.boxed:focus-visible { box-shadow: var(--shadow-input-focus); }

.input-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: var(--txt-secondary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 6px;
}

/* ----------------------------------------------------------------------------
   7. BADGES
   .status-badge → solid pill with tinted background + inset colored border
   .text-badge   → lighter inline label (feeds, lists)
   .ai-badge     → AI-suggested marker (coral)
   .medium-badge → channel marker (web/print/newsletter/social)
   ---------------------------------------------------------------------------- */
.status-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: 5px;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  background: var(--bg-card);
}
.status-badge.success { color: var(--status-success); box-shadow: inset 0 0 0 1px rgba(5, 150, 105, 0.3); background: rgba(5, 150, 105, 0.05); }
.status-badge.warning { color: var(--status-warning); box-shadow: inset 0 0 0 1px rgba(217, 119, 6, 0.3); background: rgba(217, 119, 6, 0.05); }
.status-badge.error   { color: var(--status-error);   box-shadow: inset 0 0 0 1px rgba(220, 38, 38, 0.3);  background: rgba(220, 38, 38, 0.05); }
.status-badge.info    { color: var(--status-info);    box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.3);  background: rgba(37, 99, 235, 0.05); }
.status-badge.neutral { color: var(--txt-secondary);  box-shadow: inset 0 0 0 1px var(--border-strong);     background: var(--bg-main); }

/* Lead — Hausfarbe, weil hier jemand ran muss.
   -------------------------------------------------------------------------
   Vorher lief der Lead auf `info` (blau). Blau ist im ganzen System die
   Farbe für „zur Kenntnis": „Später", „Geplant", „Versendet". Ein Lead ist
   das Gegenteil — eine offene Aufgabe, an der noch niemand war.

   Eigene Variante statt Umfärben von `info`: Sonst würde jede geplante
   Aufgabe und jedes versendete Angebot mitwandern und dieselbe Dringlichkeit
   behaupten.

   Bewusst getönt und nicht gefüllt: Die volle Hausfarbe gehört der
   Hauptaktion („Jetzt anrufen"). Stünden zwanzig Leads in einer Liste in
   Vollfarbe, ginge genau der Knopf unter, der etwas bewirkt. */
.status-badge.lead    { color: var(--cta); box-shadow: inset 0 0 0 1px rgba(232, 109, 76, 0.3); background: rgba(232, 109, 76, 0.06); }

.text-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: 5px;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
}
.text-badge.success { background: #ECFDF5; color: var(--status-success); border: 1px solid rgba(5, 150, 105, 0.15); }
.text-badge.warning { background: #FFFBEB; color: var(--status-warning); border: 1px solid rgba(217, 119, 6, 0.15); }
.text-badge.error   { background: #FEF2F2; color: var(--status-error);   border: 1px solid rgba(220, 38, 38, 0.15); }
.text-badge.info    { background: #EFF6FF; color: var(--status-info);    border: 1px solid rgba(37, 99, 235, 0.15); }
.text-badge.neutral { background: #F4F4F5; color: var(--txt-secondary);  border: 1px solid rgba(82, 82, 91, 0.15); }
.text-badge.lead    { background: #FEF0EC; color: var(--cta);            border: 1px solid rgba(232, 109, 76, 0.18); }

.ai-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: 5px;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  background: var(--cta-light); color: var(--cta);
  box-shadow: inset 0 0 0 1px rgba(232, 109, 76, 0.2);
}

.medium-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 10px; border-radius: 6px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
}
.medium-badge.web        { background: #EFF6FF; color: var(--status-info); }
.medium-badge.print      { background: #FEF3C7; color: #92400E; }
.medium-badge.newsletter { background: #DBEAFE; color: var(--status-info); }
.medium-badge.social     { background: #F3E8FF; color: #6B21A8; }

/* ----------------------------------------------------------------------------
   8. FILTER CHIPS
   ---------------------------------------------------------------------------- */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; padding: 6px 14px; border-radius: 99px;
  background: var(--bg-card); border: none;
  box-shadow: 0 1px 2px rgba(9, 9, 11, 0.02);
  color: var(--txt-secondary); font-weight: 500; white-space: nowrap;
  cursor: pointer; transition: all 0.15s var(--ease-zenith);
  box-shadow: 0 1px 2px rgba(9, 9, 11, 0.02);
}
/* Ohne Rand traegt der Schatten die Rueckmeldung. Bewusst ohne Anheben:
   eine Filterzeile mit mehreren Chips wirkt sonst unruhig. */
.chip:hover { color: var(--txt-primary); box-shadow: 0 2px 8px rgba(9, 9, 11, 0.07); }
.chip.active { background: var(--accent); color: #fff; box-shadow: 0 1px 2px rgba(9, 9, 11, 0.06); }

/* Auf weissem Grund (Dialog, Karte) faellt ein weisser Chip nicht auf.
   Dieselbe Loesung wie beim Symbolknopf: gefuellte Flaeche statt Rand. */
.chip.on-white { background: var(--bg-main); box-shadow: none; }
.chip.on-white:hover { background: var(--border-light); box-shadow: none; color: var(--txt-primary); }
.chip.on-white.active { background: var(--accent); color: #fff; }

/* Runder Symbolknopf.
   -------------------------------------------------------------------------
   Die Fuellung haengt vom Untergrund ab — dieselbe Regel wie bei Eingaben:

     auf GRAUEM Grund   weisse Flaeche, sie grenzt sich selbst ab
     auf WEISSEM Grund  graue Flaeche (--bg-main), sonst verschwindet er

   Ein weisser Knopf auf weisser Karte braucht sonst einen gezeichneten Rand,
   und der wirkt neben einer randlosen Umgebung wie ein Fremdkoerper. Die
   gefuellte Flaeche loest das ruhiger. */
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 99px; flex-shrink: 0;
  background: var(--bg-card);
  color: var(--txt-secondary);
  box-shadow: 0 1px 2px rgba(9, 9, 11, 0.04);
  cursor: pointer; transition: all 0.2s var(--ease-zenith);
}
.icon-btn:hover { color: var(--txt-primary); box-shadow: 0 2px 8px rgba(9, 9, 11, 0.08); }

/* Auf weisser Flaeche: gefuellt statt umrandet. */
.icon-btn.on-white { background: var(--bg-main); box-shadow: none; }
.icon-btn.on-white:hover { background: var(--border-light); box-shadow: none; }

/* Hauptaktion — nur eine pro Gruppe. */
.icon-btn.cta { background: var(--cta); color: #fff; box-shadow: var(--shadow-btn); }
.icon-btn.cta:hover { background: var(--cta-hover); color: #fff; }

/* Deaktiviert heisst blass, nicht grau.
   -------------------------------------------------------------------------
   Eine graue Fuellung ist eine eigene Farbe und faellt dort auf, wo der
   Untergrund nicht weiss ist — im Hero mit seinem warmen Verlauf sass so ein
   Knopf wie ein Fleck. Reduzierte Deckkraft nimmt dagegen genau das zurueck,
   was ohnehin da ist: Der Knopf behaelt seine Form und tritt zurueck. */
.icon-btn[disabled] {
  opacity: 0.45;
  box-shadow: none; cursor: not-allowed;
}
.icon-btn[disabled]:hover { box-shadow: none; color: var(--txt-secondary); }

/* Tastaturfokus in der Hausfarbe. Ohne diese Regel zeichnet der Browser
   seinen eigenen — bei Chrome ein blauer Ring, der in einer Oberflaeche ohne
   ein einziges Blau sofort auffaellt. */
.icon-btn:focus-visible {
  outline: 2px solid var(--cta);
  outline-offset: 2px;
}

/* Tagesziel — Griff an der Kante, Slide-over dahinter.
   -------------------------------------------------------------------------
   DREI TEILE
     .sa-tz-griff     dunkler Griff an der rechten Kante, immer sichtbar
     .sa-tz-vorhang   abgedunkelte, weichgezeichnete Flaeche darunter
     .sa-tz-panel     440px, volle Hoehe, faehrt von rechts herein

   DER GRIFF VERSCHWINDET NICHT, ER WANDERT MIT.
   Erst trat er beim Oeffnen ab — das war falsch: Der Griff IST der Schalter,
   und ein Schalter, der beim Betaetigen verschwindet, laesst einen suchen,
   wie man wieder zumacht. Jetzt faehrt er mit dem Panel nach links und legt
   sich an dessen Kante. Ein Element, zwei Zustaende, derselbe Weg zurueck.

   DAMIT ER DORT NICHT AUF WEISS KLEBT
   Das Panel traegt einen dunklen Rahmen: Aussen die Farbe der Seitenleiste,
   innen die weisse Flaeche mit eigener Rundung — ein Passepartout. Der
   schwarze Griff dockt an schwarzem Grund an, statt auf einer weissen Kante
   zu sitzen. */

/* Das Panel parkt geschlossen um seine volle Breite ausserhalb des Fensters.
   Ohne diese Klammer scrollt jede Seite waagrecht — und zwar nur deshalb. */
body { overflow-x: hidden; }

/* ---- Der Griff ----
   Schmal, weiss, vertikal beschriftet, darunter ein kleiner Fortschrittsring.

   WARUM KEINE BALKEN UND KEINE ZAHL
   Beides zwang den Griff in die Breite und verlangte, gelesen zu werden. Ein
   Element am Bildschirmrand wird aber nicht gelesen, es wird im Vorbeigehen
   gesehen — und dafuer reicht ein Ring. Die genaue Zahl steht drinnen, gross
   und in Ruhe. */
/* ---- Die Kante: ein Stapel aus Registern ----
   Der Fortschritt war lange der einzige Griff am rechten Rand und trug seine
   Position selbst. Mit dem zweiten — den Fehlermeldungen — geht das nicht
   mehr: Zwei unabhaengig positionierte Pillen am selben Rand stehen nie
   verlaesslich untereinander, und beim Andocken muesste jede fuer sich
   dasselbe rechnen.

   Also traegt die Kante die Position, und die Register haengen darin wie
   Reiter an einer Mappe. Faehrt ein Panel herein, wandert die ganze Kante
   mit: Der Reiter des offenen Panels ist dessen Schliessknopf, der andere
   bleibt daneben liegen und wechselt hinueber. Genau so verhaelt sich ein
   Registerstapel aus Papier.

   pointer-events: Die Luecke zwischen den Reitern gehoert der Seite. Ohne das
   faengt ein unsichtbarer Streifen am rechten Rand Klicks ab. */
.sa-kante {
  position: fixed;
  top: 50%;
  right: 0;
  z-index: 49;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  /* stretch, nicht flex-end: So sind beide Reiter so breit wie der breitere —
     sie sehen aus wie zwei Register einer Mappe und nicht wie zwei Knöpfe, die
     zufällig untereinander liegen. Die Breite gibt der Fortschritt vor; sein
     Ring ist das breiteste Element im Stapel. */
  align-items: stretch;
  /* Kein Abstand: Die Reiter stoßen aneinander wie an einer Mappe. Getrennt
     sahen sie aus wie zwei Knöpfe, die zufällig untereinander liegen. */
  gap: 0;
  pointer-events: none;
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.sa-kante > * { pointer-events: auto; }
/* 446 statt 440: Die Reiter ragen sechs Pixel über ihre eigene rechte Kante
   hinaus (siehe unten). Angedockt lägen diese sechs Pixel sonst ÜBER der
   Panelfläche — der graue Bugs-Reiter schob sich sichtbar auf das offene
   Panel. Sechs Pixel weiter links stößt er genau an dessen Kante. */
.sa-kante.angedockt { transform: translateY(-50%) translateX(-446px); }

/* ÜBERSTAND NACH RECHTS.
   Die Reiter ragen sechs Pixel über den Fensterrand hinaus. Sichtbar ist davon
   nichts (die rechte Seite ist ohnehin eckig, und `body` schneidet waagrecht
   ab) — aber beim Überfahren wandert der Reiter vier Pixel nach links, und
   ohne diesen Vorrat entstünde dabei rechts eine Lücke zwischen Reiter und
   Fensterkante. Sie war der Grund, warum der Knopf beim Hover „nicht breit
   genug" wirkte. */
.sa-kante > * { margin-right: -6px; padding-right: 14px; }

.sa-tz-griff {
  position: relative;
  padding: 18px 8px;
  display: flex; flex-direction: column; align-items: center; gap: 12px;

  background: var(--bg-card);
  border: none;
  border-radius: 14px 0 0 14px;
  /* Weiss auf hellem Grund traegt sich nicht selbst — der Schatten macht die
     Kante. Etwas kraeftiger als bei einer Karte, weil der Griff schwebt. */
  /* Eine einzige weiche Lage. Ein Ring zog eine sichtbare Linie um den Knopf,
     eine enge zweite Schattenlage tat dasselbe in Grau — beides liess ihn wie
     aufgeklebt wirken. Was bleibt, ist ein Hauch Tiefe nach links. */
  box-shadow: -4px 0 16px rgba(9, 9, 11, 0.06);
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;              /* die Fuellung bleibt im Knopf */
  /* Der Hover verschiebt, er verbreitert nicht mehr.
     `padding-right` war richtig, solange der Griff allein am Rand hing: Die
     Fläche blieb unter dem Zeiger stehen. In einem Stapel gleich breiter
     Register ginge das nicht — die Breite bestimmt jetzt das breiteste Kind,
     und ein wachsender Reiter zöge den anderen mit. Vier Pixel nach links sind
     wenig genug, dass der Zeiger auf der Fläche bleibt. */
  /* `background-color` und `color` gehören in die Liste.
     Ohne sie sprang der Reiter beim Wechsel hart von Weiß auf Grau — und weil
     genau in diesem Moment auch das Panel überblendet, sah es aus, als ruckle
     der Knopf. Die Bewegung war sauber; der Farbsprung daneben war es nicht. */
  transition:
    transform 0.24s var(--ease-zenith),
    box-shadow 0.24s var(--ease-zenith),
    background-color 0.22s ease,
    color 0.22s ease;
}
.sa-kante:not(.angedockt) .sa-tz-griff:hover,
.sa-kante:not(.angedockt) .sa-bug-griff:hover {
  transform: translateX(-4px);
  box-shadow: -6px 0 22px rgba(9, 9, 11, 0.10);
}
/* Der Fokusring gehoert NACH INNEN: Der Knopf sitzt buendig auf der
   Bildschirmkante, ein aeusserer Ring wuerde dort abgeschnitten und stuende
   als halbe Klammer am Rand. */
.sa-tz-griff:focus-visible {
  outline: none;
  box-shadow: -4px 0 16px rgba(9, 9, 11, 0.06), 0 0 0 2px var(--cta);
}

/* VORNE UND HINTEN.
   Ein Registerstapel hat immer einen Reiter vorne. Der trägt die weiße Fläche
   und den Schatten und liegt über dem anderen; der hintere steht etwas
   zurück — gedämpfte Fläche, kein eigener Schatten, blassere Schrift.

   Welcher vorne liegt, entscheidet das Skript: standardmäßig der Fortschritt,
   und der jeweils geöffnete, sobald sein Panel herausfährt. Ohne diesen Wechsel
   läge beim offenen Bug-Panel der Fortschritt über dem Reiter, der gerade die
   Sache führt — und das las sich falsch herum. */
.sa-kante > * { position: relative; z-index: 1; }
.sa-kante > .vorne { z-index: 2; }

.sa-kante > :not(.vorne) {
  background: #F2F2F3;
  box-shadow: none;
}
.sa-tz-wort, .sa-bug-griff i { transition: color 0.22s ease; }
.sa-kante > :not(.vorne) .sa-tz-wort { color: var(--txt-tertiary); }
.sa-kante > :not(.vorne) i { color: var(--txt-tertiary); }

/* Überfahren holt auch den hinteren Reiter nach vorn — optisch, nicht in der
   Stapelordnung. Er ist anklickbar, also muss er sich auch so anfühlen: Ein
   Element, das auf den Zeiger nicht reagiert, wirkt abgeschaltet. */
.sa-kante > :not(.vorne):hover {
  background: var(--bg-card);
  z-index: 3;
}
.sa-kante > :not(.vorne):hover .sa-tz-wort { color: var(--txt-primary); }
.sa-kante > :not(.vorne):hover i { color: var(--txt-secondary); }

/* Geoeffnet gehoeren die Register zum Panel — dessen Schatten traegt sie.
   Ein eigener daneben zoege eine Naht durch eine Flaeche, die keine hat. */
.sa-kante.angedockt .sa-tz-griff,
.sa-kante.angedockt .sa-bug-griff { box-shadow: none; }

/* ---- Die Fortschrittsanzeige ----
   Ein kleiner Ring unter dem Wort. Er greift auf, was das Werkzeug ohnehin
   spricht: runde Icon-Knoepfe in Akte und Tagesplan, der grosse Ring im
   Panel. Der Farbverlauf, der vorher den ganzen Knopf fuellte, war das
   einzige Element ohne Verwandtschaft im System — er sah fuer sich gut aus
   und gehoerte trotzdem nicht dazu.

   Klein genug, um am Rand nicht zu rufen. Gross genug, um im Vorbeigehen zu
   erkennen, ob da viel oder wenig steht. */
.sa-tz-ring-klein { width: 18px; height: 18px; flex-shrink: 0; }
.sa-tz-ring-klein svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.sa-tz-ring-klein .bahn { color: var(--border-light); }
.sa-tz-ring-klein .bogen {
  color: var(--cta);
  transition: stroke-dashoffset 1s var(--ease-zenith), color 0.4s ease;
}
.sa-tz-griff.geschafft .sa-tz-ring-klein .bogen { color: var(--status-success); }

/* Ein leiser Atem, wenn das Ziel steht — alle vier Sekunden einmal. Nur im
   erreichten Zustand: Vorher waere es Unruhe, nachher ist es der einzige
   Moment, in dem etwas gefeiert werden darf. */
@keyframes sa-tz-atem {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.09); }
}
.sa-tz-griff.geschafft .sa-tz-ring-klein { animation: sa-tz-atem 4s ease-in-out infinite; }

/* ---- Die Beschriftung ----
   Von unten nach oben gelesen, wie an einem Buchruecken im Regal. */
.sa-tz-wort {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--txt-primary);
  white-space: nowrap;
}

/* Die Y-Zentrierung sitzt jetzt an der Kante, nicht am Griff — der Impuls
   darf sie deshalb nicht mehr mitschreiben, sonst spraenge der Reiter beim
   Anlaufen der Animation um seine halbe Hoehe nach unten. */
@keyframes sa-tz-impuls {
  0%   { transform: translateX(0); }
  35%  { transform: translateX(-6px); }
  100% { transform: translateX(0); }
}
.sa-kante:not(.angedockt) .sa-tz-griff.impuls { animation: sa-tz-impuls 0.5s var(--ease-zenith); }

/* Ziel erreicht: einmal ein Schimmer von unten nach oben. Kein Konfetti,
   kein Ton — die Fuellung wechselt ohnehin schon auf Gruen. */
@keyframes sa-tz-schimmer {
  from { transform: translateY(110%); }
  to   { transform: translateY(-110%); }
}
.sa-tz-griff.schimmer::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(to top, transparent, rgba(5, 150, 105, 0.18), transparent);
  animation: sa-tz-schimmer 1.1s var(--ease-zenith);
  pointer-events: none;
}

/* ---- Vorhang ---- */
.sa-tz-vorhang {
  position: fixed; inset: 0; z-index: 47;
  background: rgba(9, 9, 11, 0.22);
  backdrop-filter: blur(3px);
  opacity: 0; pointer-events: none;
  transition: opacity 0.3s ease;
}
.sa-tz-vorhang.offen { opacity: 1; pointer-events: auto; }

/* ---- Panel: dunkler Rahmen aussen, weisse Flaeche innen ---- */
.sa-tz-panel {
  position: fixed; top: 0; right: 0; z-index: 48;
  width: 100%; max-width: 440px; height: 100%;
  background: var(--bg-card);
  /* KEINE gezeichnete Kante links: Sie lief genau dort, wo der Griff andockt,
     und stand als Strich mitten in der Fuge — der Griff liegt zwar darueber,
     aber ober- und unterhalb von ihm blieb sie sichtbar. Den Rand macht der
     Schatten, und zwar nur, solange das Panel offen ist.

     KEIN Schatten im geschlossenen Zustand. Das Panel parkt ausserhalb des
     Fensters, sein Schatten aber ragte 72px HEREIN — als grauer Streifen am
     rechten Rand jeder Seite. Ein Schatten an etwas Unsichtbarem ist kein
     Schatten, sondern ein Fehler. */
  transform: translateX(100%);
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1),
              box-shadow 0.3s ease;
}
.sa-tz-panel.offen {
  transform: translateX(0);
  /* EINE Lage, weit und weich. Eine zweite, harte Lage (-1px 0 0) sass als
     Strich genau in der Fuge, in der der Griff andockt — sie sah aus wie ein
     Rand am Knopf. Ein Slide-over braucht keine gezeichnete Kante: Der weite
     Schatten hebt es genug von der Seite ab. */
  box-shadow: -20px 0 40px rgba(9, 9, 11, 0.09);
}

/* Der dunkle Rahmen ist entfallen: Er war noetig, solange der Griff schwarz
   war und sonst auf weisser Kante geklebt haette. Jetzt sind beide weiss —
   der Griff wird zur Nase des Panels, nicht zu einem Fremdkoerper daran. */
.sa-tz-flaeche {
  width: 100%; height: 100%;
  display: flex; flex-direction: column;
  overflow: hidden;
}

.sa-tz-kopf {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 22px 24px 18px;
  flex-shrink: 0;
}

/* Luft. Der Tagesblick wird einmal am Tag gelesen, nicht ueberflogen. */
.sa-tz-inhalt { flex: 1; overflow-y: auto; padding: 0 24px 24px; }

/* ---- Der Ring: die eine grosse Zahl ---- */
.sa-tz-ringfeld {
  display: flex; align-items: center; gap: 20px;
  margin-bottom: 22px;
}
.sa-tz-ring { width: 96px; height: 96px; flex-shrink: 0; position: relative; }
.sa-tz-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.sa-tz-ring-bahn { color: var(--border-light); }
.sa-tz-ring-bogen {
  color: var(--cta);
  transition: stroke-dashoffset 1s var(--ease-zenith), color 0.4s ease;
}
.sa-tz-ringfeld.geschafft .sa-tz-ring-bogen { color: var(--status-success); }

.sa-tz-ring-kern {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.sa-tz-ring-zahl {
  font-size: 30px; font-weight: 700; line-height: 1;
  color: var(--txt-primary); font-variant-numeric: tabular-nums;
}
.sa-tz-ring-von { font-size: 11px; font-weight: 600; color: var(--txt-tertiary); margin-top: 3px; }
.sa-tz-ringfeld.geschafft .sa-tz-ring-zahl { color: var(--status-success); }

.sa-tz-gross {
  font-size: 20px; font-weight: 600; line-height: 1.2;
  color: var(--txt-primary); letter-spacing: -0.015em;
  margin-bottom: 5px;
}
.sa-tz-ringfeld.geschafft .sa-tz-gross { color: var(--status-success); }
.sa-tz-klein { font-size: 13px; color: var(--txt-secondary); line-height: 1.45; }

.sa-tz-serie {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 14px; margin-bottom: 24px;
  background: var(--bg-main);
  border-radius: 10px;
  font-size: 12.5px; color: var(--txt-secondary);
}
.sa-tz-serie i { color: var(--cta); }

/* ---- Der Tagesablauf ----
   Gebaut wie die Traffic-Kurve in Analytics: Achsenbeschriftung links,
   Gitterlinien dahinter, Flaeche mit auslaufendem Verlauf, Linie darueber.
   Dieselbe Sprache an beiden Orten — wer die eine kennt, liest die andere. */
.sa-tz-bogen { margin-bottom: 26px; }

.sa-tz-kurve { display: flex; gap: 8px; }

.sa-tz-achse {
  display: flex; flex-direction: column; justify-content: space-between;
  height: 96px; flex-shrink: 0;
  font-size: 10px; color: var(--txt-tertiary);
  font-variant-numeric: tabular-nums;
  text-align: right; min-width: 12px;
}

.sa-tz-kurvenfeld { position: relative; flex: 1; height: 96px; }

/* Die Spitzenpunkte der Kurve.
   Sie liegen NEBEN dem SVG, nicht darin: Das SVG wird waagrecht gestaucht
   (preserveAspectRatio="none"), und ein <circle> darin würde zum Oval. Als
   gewöhnliches Element mit fester Größe in Pixeln bleibt der Punkt rund,
   während seine Position prozentual mitwandert. */
.sa-tz-punkt {
  position: absolute;
  width: 8px; height: 8px;
  margin: -4px 0 0 -4px;          /* auf den Mittelpunkt setzen */
  border-radius: 50%;
  background: var(--bg-card);
  border: 2px solid var(--cta);
  box-sizing: border-box;
  pointer-events: none;
}

.sa-tz-gitter {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; justify-content: space-between;
  pointer-events: none;
}
.sa-tz-gitter div { width: 100%; height: 1px; background: var(--border-light); }

.sa-tz-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

.sa-tz-stunden {
  display: flex; justify-content: space-between;
  margin-top: 7px; padding-left: 20px;
  font-size: 10px; color: var(--txt-tertiary);
  font-variant-numeric: tabular-nums;
}

/* ---- Vier Kennzahlen als Kacheln ---- */
.sa-tz-kacheln {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;
  margin-bottom: 28px;
}
.sa-tz-kachel {
  display: flex; align-items: center; gap: 11px;
  padding: 13px 14px;
  background: var(--bg-main);
  border-radius: 11px;
}
.sa-tz-kachel-icon {
  width: 30px; height: 30px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-card); flex-shrink: 0;
  box-shadow: 0 1px 2px rgba(9, 9, 11, 0.05);
}
.sa-tz-kachel-zahl {
  font-size: 18px; font-weight: 700; line-height: 1.1;
  color: var(--txt-primary); font-variant-numeric: tabular-nums;
}
.sa-tz-kachel.leer .sa-tz-kachel-zahl { color: var(--txt-tertiary); font-weight: 600; }
.sa-tz-kachel-label {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--txt-tertiary);
}

/* ---- Verlauf ---- */
.sa-tz-ueberschrift {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.14em; color: var(--txt-tertiary);
  margin-bottom: 12px;
}
.sa-tz-zeile {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border-light);
}
.sa-tz-zeile:last-child { border-bottom: none; }
.sa-tz-uhr {
  font-size: 11px; color: var(--txt-tertiary);
  width: 34px; flex-shrink: 0; padding-top: 2px;
  font-variant-numeric: tabular-nums;
}

.sa-tz-fuss {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 15px; border-top: 1px solid var(--border-light);
  text-decoration: none; font-size: 13px; font-weight: 600;
  color: var(--txt-primary); transition: background 0.15s ease;
  flex-shrink: 0;
}
.sa-tz-fuss:hover { background: var(--bg-hover); }

/* Auf schmalen Schirmen fuellt das Panel die Breite — dann braucht der Griff
   keinen Andockplatz, weil links nichts mehr uebrig ist. */
@media (max-width: 520px) {
  .sa-kante.angedockt { transform: translateY(-50%) translateX(100%); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .sa-kante, .sa-tz-griff, .sa-bug-griff, .sa-tz-panel, .sa-bug-panel,
  .sa-tz-vorhang, .sa-tz-ring-klein .bogen,
  .sa-tz-ring-bogen { transition: none; }
  .sa-kante:not(.angedockt) .sa-tz-griff.impuls, .sa-tz-griff.schimmer::after,
  .sa-tz-griff.geschafft .sa-tz-ring-klein { animation: none; }
}

/* Fehlermeldungen — das zweite Register an der Kante.
   =========================================================================
   WARUM KEIN VORHANG
   Das Panel des Tagesziels dunkelt die Seite ab und zeichnet sie weich: Der
   Blick auf den eigenen Tag SOLL eine Unterbrechung sein. Hier ist es genau
   umgekehrt. Wer einen Fehler meldet, meldet ihn ueber das, was gerade auf
   dem Bildschirm steht — und muss davon einen Ausschnitt aufnehmen koennen.
   Ein Schleier daraeber machte jeden Screenshot unbrauchbar und jede
   Beschreibung schwerer, weil man nicht mehr nachsehen kann, was da eigentlich
   stand.

   Also: kein Vorhang, kein Weichzeichner, kein Klickfang. Die Seite bleibt
   bedienbar, waehrend das Panel offen steht. Es ist eine Randnotiz, keine
   Unterbrechung — und das ist bei diesem Werkzeug die richtige Rolle.

   WARUM DAS REGISTER SCHMALER IST
   Der Fortschritt ist der Hauptreiter; die Fehlermeldung haengt darunter wie
   ein Zweitreiter an einer Mappe. Gleich breit waeren es zwei gleichwertige
   Knoepfe, und das sind sie nicht. */
.sa-bug-griff {
  position: relative;
  padding: 14px 8px;
  display: flex; flex-direction: column; align-items: center; gap: 8px;

  background: var(--bg-card);
  border: none;
  /* Dieselbe Rundung wie oben: Zwei verschiedene Radien nebeneinander lesen
     sich als zwei verschiedene Bauteile. */
  border-radius: 14px 0 0 14px;
  box-shadow: -4px 0 16px rgba(9, 9, 11, 0.06);
  cursor: pointer;
  /* Farbwechsel gehört mit in die Liste — siehe .sa-tz-griff. */
  transition:
    transform 0.24s var(--ease-zenith),
    box-shadow 0.24s var(--ease-zenith),
    background-color 0.22s ease,
    color 0.22s ease;
}
/* Der Fokusring nach innen — der Reiter sitzt buendig auf der Bildschirmkante,
   ein aeusserer wuerde dort abgeschnitten. */
.sa-bug-griff:focus-visible {
  outline: none;
  box-shadow: -4px 0 16px rgba(9, 9, 11, 0.06), 0 0 0 2px var(--cta);
}
.sa-bug-griff i { font-size: 13px; color: var(--txt-tertiary); }

/* Die Zahl offener Meldungen. Kein Kreis mit Ziffer wie eine Benachrichtigung:
   Offene Fehler sind kein Posteingang, den man abarbeiten muss. Ein Punkt
   genuegt — es gibt welche oder nicht. */
.sa-bug-punkt {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--status-warning);
  flex-shrink: 0;
}
.sa-bug-griff:not(.hat-offene) .sa-bug-punkt { display: none; }

/* ---- Das Panel ---- */
.sa-bug-panel {
  position: fixed; top: 0; right: 0; z-index: 48;
  width: 100%; max-width: 440px; height: 100%;
  background: var(--bg-card);
  transform: translateX(100%);
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1),
              box-shadow 0.3s ease;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.sa-bug-panel.offen {
  transform: translateX(0);
  box-shadow: -20px 0 40px rgba(9, 9, 11, 0.09);
}
/* ÜBERBLENDEN STATT AUSFAHREN.
   -------------------------------------------------------------------------
   Steht schon ein Slide-over offen und man wechselt auf das andere Register,
   wäre ein zweites Einfahren von rechts falsch: Es gibt nichts einzufahren —
   die Fläche ist schon da, nur ihr Inhalt wechselt. Ein Panel, das dafür erst
   hinausfährt und ein anderes hereinschiebt, erzählt eine Bewegung, die nicht
   stattfindet.

   `.ueberblenden` schaltet die Bewegung für einen Wechsel ab: Das Panel sitzt
   sofort an seinem Platz und blendet nur ein bzw. aus. Die Klasse wird nach
   dem Übergang wieder entfernt, damit das nächste Öffnen aus dem Nichts wieder
   normal hereinfährt. */
.sa-tz-panel.ueberblenden,
.sa-bug-panel.ueberblenden {
  transform: translateX(0);
  opacity: 0;
  transition: opacity 0.22s ease;
}
.sa-tz-panel.ueberblenden.offen,
.sa-bug-panel.ueberblenden.offen { opacity: 1; }

/* Ausgeblendet, aber noch an seinem Platz: Es liegt unsichtbar über der Seite
   und würde jeden Klick abfangen, der eigentlich dem Inhalt gilt. */
.sa-tz-panel.ueberblenden:not(.offen),
.sa-bug-panel.ueberblenden:not(.offen) { pointer-events: none; }

/* Das hereinkommende liegt über dem gehenden — sonst blitzt für einen Moment
   der alte Inhalt durch den neuen. */
.sa-tz-panel.ueberblenden.offen,
.sa-bug-panel.ueberblenden.offen { z-index: 49; }

/* Waehrend der Aufnahme tritt das Panel kurz ab: Sonst fotografiert man es
   mit, und zwar genau ueber der Stelle, um die es meist geht. */
.sa-bug-panel.abgetreten {
  transform: translateX(100%);
  box-shadow: none;
  transition: transform 0.18s ease;
}
.sa-kante.aufnahme { opacity: 0; transition: opacity 0.18s ease; }

.sa-bug-kopf {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 22px 24px 16px;
  flex-shrink: 0;
}
.sa-bug-inhalt { flex: 1; overflow-y: auto; padding: 0 24px 24px; }

/* ---- Das Formular ---- */
.sa-bug-feld {
  width: 100%;
  min-height: 92px;
  padding: 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--bg-card);
  font-family: inherit; font-size: 13px; line-height: 1.5;
  color: var(--txt-primary);
  resize: vertical;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.sa-bug-feld::placeholder { color: var(--txt-tertiary); }
.sa-bug-feld:focus {
  outline: none;
  border-color: var(--cta);
  box-shadow: 0 0 0 3px rgba(232, 109, 76, 0.12);
}

/* Die Werkzeugleiste unter dem Feld — dieselbe Bauart wie unter dem
   Antwortfeld im Sales-Chat: Symbole links, die Handlung rechts. */
.sa-bug-leiste {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 10px;
}

/* Die Herkunft: Adresse und Fenstergroesse, klein und grau. Sie steht da,
   damit man sie SIEHT — nicht, damit man sie liest. Wer meldet, soll wissen,
   was mitgeht. */
.sa-bug-herkunft {
  margin-top: 12px;
  font-size: 11px; line-height: 1.5;
  color: var(--txt-tertiary);
  word-break: break-all;
}

/* ---- Vorschau der Bilder ---- */
.sa-bug-bilder { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.sa-bug-bild {
  position: relative;
  width: 72px; height: 54px;
  border-radius: 6px; overflow: hidden;
  border: 1px solid var(--border-light);
  background: var(--bg-main);
}
.sa-bug-bild img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sa-bug-bild button {
  position: absolute; top: 2px; right: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  border: none; cursor: pointer;
  background: rgba(9, 9, 11, 0.65); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; line-height: 1;
}
.sa-bug-bild.laeuft { opacity: 0.5; }

/* Das Formular sitzt in einem eigenen Kasten und ist damit sichtbar vom
   Gemeldeten getrennt. Vorher standen die Einträge direkt unter dem Eingabefeld
   und lasen sich wie dessen Fortsetzung. */
.sa-bug-formular {
  padding: 14px;
  background: var(--bg-main);
  border: 1px solid var(--border-light);
  border-radius: 12px;
  margin-bottom: 22px;
}
.sa-bug-formular .sa-bug-feld { background: var(--bg-card); }

/* Das Fristfeld sieht aus wie die Symbolknöpfe daneben und wächst erst auf,
   wenn ein Datum drinsteht. Ein leeres Datumsfeld in voller Breite nähme mehr
   Platz als der ganze Rest der Leiste — für eine Angabe, die meist ausbleibt. */
.sa-bug-frist-feld {
  display: inline-flex; align-items: center; gap: 6px;
  align-self: flex-start;
  height: 30px; padding: 0 10px;
  border: 1px solid var(--border-light);
  border-radius: 8px;
  background: var(--bg-card);
  color: var(--txt-tertiary);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.sa-bug-frist-feld:hover { border-color: var(--border-strong); color: var(--txt-secondary); }
.sa-bug-frist-feld:focus-within { border-color: var(--cta); color: var(--txt-primary); }
.sa-bug-frist-feld input {
  border: none; background: transparent; padding: 0;
  font-family: inherit; font-size: 12px; color: var(--txt-primary);
  width: 0; opacity: 0;
  transition: width 0.2s var(--ease-zenith), opacity 0.2s ease;
}
.sa-bug-frist-feld input { width: 104px; opacity: 1; }
.sa-bug-frist-feld:hover { color: var(--txt-primary); border-color: var(--border-strong); }

/* Das Wort daneben sagt, was der Klick tut. Ein nacktes Datumsfeld im Fuß
   eines Eintrags liest sich sonst wie eine Anzeige, nicht wie ein Feld. */
.sa-bug-frist-wort { font-size: 11px; font-weight: 600; }
.sa-bug-frist-feld:has(input:not([value=""])) .sa-bug-frist-wort { display: none; }
.sa-bug-frist-feld input::-webkit-calendar-picker-indicator { display: none; }

/* ---- Die Liste ----
   Jeder Eintrag ist zugeklappt: eine Zeile mit Zustand, Titel und Frist. Der
   Kopf IST der Schalter — ein Pfeil davor wäre ein zweites Ziel für dieselbe
   Handlung, und beim Beitragspanel hat genau der schon einmal mehr gestört als
   geholfen. */
.sa-bug-eintrag {
  border-top: 1px solid var(--border-light);
}
.sa-bug-eintrag:last-child { border-bottom: 1px solid var(--border-light); }

.sa-bug-kopfzeile {
  width: 100%;
  display: flex; align-items: center; gap: 9px;
  padding: 11px 2px;
  background: none; border: none; cursor: pointer;
  text-align: left;
  transition: background 0.15s ease;
}
.sa-bug-kopfzeile:hover { background: var(--bg-hover); }

.sa-bug-titel {
  flex: 1; min-width: 0;
  font-size: 13px; font-weight: 500; color: var(--txt-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Der Kopf bleibt auch aufgeklappt einzeilig. Umbrechend wiederholte er die
   ersten neun Wörter der Beschreibung, die zwei Zeilen tiefer noch einmal in
   voller Länge steht — und die Kopfzeile wechselte beim Aufklappen ihre Höhe,
   sodass der Text darunter wegsprang. */
.sa-bug-eintrag.offen .sa-bug-titel { font-weight: 600; }

.sa-bug-koerper {
  padding: 2px 2px 14px;
  display: flex; flex-direction: column; gap: 10px;
}
.sa-bug-fuss {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 11px; color: var(--txt-tertiary);
  word-break: break-all;
}

/* Die Frist: nur ein Datum mit Fähnchen. Rot erst, wenn sie verstrichen ist —
   und nur, solange die Sache offen ist. An einer behobenen Meldung wäre ein
   rotes Datum eine Anklage ohne Adressat. */
.sa-bug-frist {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 600;
  color: var(--txt-tertiary);
  flex-shrink: 0;
}
.sa-bug-frist.vorbei { color: var(--status-error); }

.sa-bug-zustand {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 999px;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  flex-shrink: 0;
  border: none;
}
button.sa-bug-zustand { cursor: pointer; }
.sa-bug-zustand.offen     { background: #FEF3E2; color: var(--status-warning); }
.sa-bug-zustand.in_arbeit { background: var(--cta-light); color: var(--cta); }
.sa-bug-zustand.behoben   { background: #E7F6EF; color: var(--status-success); }

.sa-bug-galerie { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.sa-bug-galerie a {
  width: 56px; height: 42px; border-radius: 5px; overflow: hidden;
  border: 1px solid var(--border-light); display: block;
}
.sa-bug-galerie img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---- Die Aufnahmeschicht ----
   Ein Rahmen wird aufgezogen; alles ausserhalb bleibt sichtbar, damit man
   sieht, was man markiert. Ein Schleier waere hier falsch: Er faerbte genau
   das ein, was gleich fotografiert wird. */
.sa-bug-aufnahme {
  position: fixed; inset: 0; z-index: 60;
  cursor: crosshair;
  background: rgba(9, 9, 11, 0.06);
}
.sa-bug-aufnahme-hinweis {
  position: absolute; top: 22px; left: 50%; transform: translateX(-50%);
  background: var(--txt-primary); color: #fff;
  padding: 9px 16px; border-radius: 999px;
  font-size: 12.5px; font-weight: 600;
  box-shadow: 0 12px 32px rgba(9, 9, 11, 0.3);
  display: flex; align-items: center; gap: 8px;
  white-space: nowrap;
}
.sa-bug-aufnahme-still { font-weight: 400; opacity: 0.7; }
.sa-bug-aufnahme-rahmen {
  position: absolute;
  border: 2px solid var(--cta);
  background: rgba(232, 109, 76, 0.08);
  box-shadow: 0 0 0 9999px rgba(9, 9, 11, 0.12);
  pointer-events: none;
}

/* Kennzahlenreihe im Tagesablauf — vier Kacheln, oder fünf, wenn an dem Tag
   Mails eingegangen sind. Die Zahl steht in --spalten; das Skript setzt sie.
   Auf schmalen Schirmen bleiben es zwei, egal wie viele es gibt. */
@media (min-width: 768px) {
  /* Der Klassenname steht doppelt, um die Spezifitaet zu erhoehen. Tailwinds
     `grid-cols-2` hat dieselbe Spezifitaet, und das Play-CDN schiebt seine
     Regeln zur Laufzeit HINTER diese Datei — bei Gleichstand gewinnt die
     spaetere, und die Reihe blieb zweispaltig. */
  .ta-zahlen.ta-zahlen { grid-template-columns: repeat(var(--spalten, 4), minmax(0, 1fr)); }
}

/* Der Fuß der Gesprächsliste — nur der Archivknopf, links.
   -------------------------------------------------------------------------
   Zuerst war es eine Leiste über die volle Breite mit Symbol, Wort und Zahl.
   Sie funktionierte, war aber zu laut für das, was sie ist: ein Weg, den man
   ein paarmal am Tag geht. Ein runder Symbolknopf sagt dasselbe leiser — und
   es ist derselbe Knopf wie oben neben den Filtern, also nichts Neues zu
   lernen.

   Das Wort ist entfallen: Der Knopf trägt sein Symbol (Archivkasten hin,
   Posteingang zurück) und einen Titel für den Zeiger. Wo eine Beschriftung
   nur wiederholt, was das Symbol schon sagt, ist sie Ballast.

   Ohne `on-white`: Der Fuß ist grau, und `on-white` füllt den Knopf mit genau
   dieser Graufläche — er verschwände darin. Weiß mit einem Hauch Schatten
   macht ihn als Knopf erkennbar. */
.sa-chat-fuss {
  display: flex; align-items: center;
  flex-shrink: 0;
  padding: 10px 14px;
  border-top: 1px solid var(--border-light);
  background: var(--bg-main);
}

/* Im Archiv kehrt sich der Knopf um — dunkel, wie ein aktiver Chip. */
.sa-chat-fuss [aria-pressed="true"] {
  background: var(--txt-primary);
  border-color: var(--txt-primary);
  color: #fff;
}
.sa-chat-fuss [aria-pressed="true"]:hover { background: #27272A; color: #fff; }

/* Die Zahl der archivierten Gespräche als kleiner Punkt am Knopf — nicht als
   Ziffer daneben. Sie beantwortet „liegt da überhaupt etwas", und dafür genügt
   ein Zeichen; die genaue Zahl steht drinnen in der Liste. */
.sa-chat-archiv-zahl {
  position: absolute; top: -2px; right: -2px;
  min-width: 15px; height: 15px; padding: 0 4px;
  border-radius: 999px;
  background: var(--txt-tertiary); color: #fff;
  font-size: 9px; font-weight: 700; line-height: 15px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.sa-chat-archiv-zahl:empty { display: none; }
.sa-chat-fuss [aria-pressed="true"] .sa-chat-archiv-zahl { display: none; }

/* Textbausteine — Schreibfeld, Werkzeugleiste, Platzhalter.
   =========================================================================
   Das Schreibfeld ist ein `contenteditable`, kein `<textarea>`: Fett, kursiv
   und Listen brauchen Auszeichnung, und die Produktplatzhalter sind echte
   Elemente, keine Zeichenfolgen. Es sieht trotzdem aus wie jedes andere
   Eingabefeld im System — wer hier schreibt, soll nicht merken, dass darunter
   etwas anderes liegt. */
.sa-tb-feld {
  width: 100%;
  min-height: 92px;
  padding: 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--bg-card);
  font-family: inherit; font-size: 13.5px; line-height: 1.6;
  color: var(--txt-primary);
  overflow-y: auto;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.sa-tb-feld.gross { min-height: 200px; max-height: 420px; }
.sa-tb-feld:focus {
  outline: none;
  border-color: var(--cta);
  box-shadow: 0 0 0 3px rgba(232, 109, 76, 0.12);
}

/* Der Hinweistext im leeren Feld.
   `:empty` genügt nicht: Sobald der Browser ein <br> einsetzt — und das tut er
   beim ersten Klick —, ist das Element nicht mehr leer. Die Klasse setzt das
   Skript, das auch weiß, dass ein einzelner Platzhalter kein leeres Feld ist. */
.sa-tb-feld.ist-leer::before {
  content: attr(data-leer);
  color: var(--txt-tertiary);
  pointer-events: none;
}

/* Innerhalb des Felds gelten wieder die Grundabstände — der CSS-Reset des
   Themes nimmt Absätzen und Listen sonst alles weg, und der Text klebt. */
.sa-tb-feld p { margin: 0 0 8px; }
.sa-tb-feld p:last-child { margin-bottom: 0; }
.sa-tb-feld ul, .sa-tb-feld ol { margin: 0 0 8px; padding-left: 20px; }
.sa-tb-feld ul { list-style: disc; }
.sa-tb-feld ol { list-style: decimal; }
.sa-tb-feld li { margin-bottom: 3px; }
.sa-tb-feld strong, .sa-tb-feld b { font-weight: 700; }
.sa-tb-feld em, .sa-tb-feld i { font-style: italic; }

.sa-tb-leiste {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
  padding: 6px;
  background: var(--bg-main);
  border: 1px solid var(--border-light);
  border-radius: 8px 8px 0 0;
  border-bottom: none;
  margin-bottom: -1px;
}
.sa-tb-leiste + .sa-tb-feld { border-radius: 0 0 8px 8px; }

/* Der Platzhalter im Text.
   Er sieht aus wie eine Marke, nicht wie Text: Man soll auf einen Blick sehen,
   dass an dieser Stelle beim Einfügen etwas anderes steht. Der Preis darin ist
   nur eine Vorschau — gespeichert wird die Produktnummer. */
.sa-tb-chip {
  display: inline-flex; align-items: center;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--cta-light);
  color: var(--cta);
  font-size: 12.5px; font-weight: 600;
  white-space: nowrap;
  vertical-align: baseline;
  user-select: all;   /* als Ganzes markieren, nicht buchstabenweise */
}
.sa-tb-chip.feld {
  background: var(--bg-main);
  color: var(--txt-secondary);
  border: 1px dashed var(--border-strong);
}

/* Die Bausteinliste im Blitzmenü des Sales-Chats. */
.sa-tb-eintrag {
  display: flex; flex-direction: column; gap: 2px;
  width: 100%; padding: 9px 12px;
  background: none; border: none; cursor: pointer;
  text-align: left;
  transition: background 0.15s ease;
}
.sa-tb-eintrag:hover { background: var(--bg-hover); }
.sa-tb-eintrag-titel { font-size: 13px; font-weight: 600; color: var(--txt-primary); }
.sa-tb-eintrag-text {
  font-size: 11.5px; color: var(--txt-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Die Einführungstour.
   =========================================================================
   Ein Begleiter, kein Vorhang. Das Fenster ist klein, sitzt neben dem Bereich,
   um den es geht, und springt von Station zu Station an eine andere Stelle.

   ABGEDUNKELT WIRD NUR, WAS GERADE NICHT ZÄHLT. Eine Fläche über allem sagt
   „nichts hier ist wichtig" — falsch, denn genau ein Bereich ist wichtig und
   soll sichtbar bleiben, während die Tour über ihn spricht. Deshalb vier
   Felder rundherum statt einer Fläche darüber.

   Warum nicht ein `clip-path` auf einer Fläche: `backdrop-filter` und
   beschnittene Flächen vertragen sich in Browsern schlecht. Vier schlichte
   Rechtecke funktionieren überall und lassen sich exakt setzen. */
.sa-tour-blende { position: fixed; inset: 0; z-index: 118; pointer-events: none; }

.sa-tour-feld {
  position: fixed;
  background: rgba(9, 9, 11, 0.42);
  backdrop-filter: blur(3px);
  pointer-events: auto;
  animation: sa-tour-auf 0.28s ease;
  /* Der Ausschnitt gleitet, wenn nachgemessen wird — etwa während ein Panel
     noch hereinfährt. Ein springender Schleier sähe nach Fehler aus. */
  transition: left 0.22s var(--ease-zenith), top 0.22s var(--ease-zenith),
              width 0.22s var(--ease-zenith), height 0.22s var(--ease-zenith);
}
@keyframes sa-tour-auf { from { opacity: 0; } to { opacity: 1; } }

/* Der Deckel über dem Ausschnitt: durchsichtig, aber im Weg.
   Der freigestellte Bereich soll GESEHEN, nicht bedient werden — ein Klick auf
   eine Kundenzeile mitten in der Führung risse den Benutzer aus ihr heraus,
   ohne dass er es wollte.

   Er trägt außerdem einen feinen Rahmen nach innen. Ohne den las sich der
   Ausschnitt auf hellen Seiten als weißer Kasten, der aus dem Nichts erschien;
   mit ihm liest er sich als das, was er ist — eine Markierung. Nach innen, weil
   ein äußerer Schatten auf die Blende fiele und dort ausfranste. */
.sa-tour-loch {
  position: fixed;
  pointer-events: auto;
  box-shadow: inset 0 0 0 1.5px rgba(232, 109, 76, 0.4);
  transition: left 0.22s var(--ease-zenith), top 0.22s var(--ease-zenith),
              width 0.22s var(--ease-zenith), height 0.22s var(--ease-zenith);
}

.sa-tour-fenster {
  position: fixed; z-index: 122;
  width: 340px; max-width: calc(100vw - 32px);
  background: var(--bg-card);
  border-radius: 16px;
  box-shadow: 0 20px 56px rgba(9, 9, 11, 0.28), 0 0 0 1px rgba(9, 9, 11, 0.05);
  overflow: hidden;
}

/* Der Sprung von Station zu Station: Position und Größe wechseln hart, das
   Fenster blendet dabei kurz auf. Eine Bewegung ÜBER den Bildschirm wäre hier
   falsch — zwischen zwei Stationen liegt oft ein Seitenwechsel, und was
   scheinbar gewandert ist, wäre in Wahrheit neu entstanden. */
.sa-tour-fenster.kommt { animation: sa-tour-herein 0.3s var(--ease-zenith); }
/* Innerhalb einer Station folgt das Fenster gleitend, wenn nachgemessen wird. */
.sa-tour-fenster.folgt {
  transition: left 0.22s var(--ease-zenith), top 0.22s var(--ease-zenith);
}
@keyframes sa-tour-herein {
  from { transform: translateY(8px) scale(0.985); opacity: 0; }
  to   { transform: translateY(0)   scale(1);     opacity: 1; }
}

.sa-tour-x { position: absolute; top: 12px; right: 12px; }

.sa-tour-inhalt { padding: 22px 22px 20px; }

.sa-tour-zaehler {
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--txt-tertiary);
  margin-bottom: 8px;
}

/* Serifenlos, Schnitt 500. Die Playfair steht im Haus für Seitentitel — eine
   Führungskarte ist kein Seitentitel, sondern eine Stimme daneben, und die
   spricht in derselben Schrift wie die Oberfläche, über die sie redet. */
.sa-tour-titel {
  font-family: inherit;
  font-size: 17px; font-weight: 500; font-style: normal;
  letter-spacing: -0.01em;
  color: var(--txt-primary); line-height: 1.3;
  margin-bottom: 12px; padding-right: 26px;
}

/* Großzügig gesetzt. Der Text steht in einem schmalen Fenster über einer
   abgedunkelten Seite; eng gesetzt läse ihn niemand zu Ende. */
.sa-tour-text {
  font-size: 13.5px; line-height: 1.75; color: var(--txt-secondary);
}
.sa-tour-text strong { color: var(--txt-primary); font-weight: 600; }

/* Der Nachsatz: eine Sache, die man erst beim zweiten Hinsehen bemerkt hätte.
   Kleiner und abgesetzt, damit er den Haupttext nicht verwässert. */
.sa-tour-klein {
  margin-top: 16px; padding-top: 16px;
  border-top: 1px solid var(--border-light);
  font-size: 12px; line-height: 1.7; color: var(--txt-tertiary);
}

.sa-tour-fuss {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 16px 12px 20px;
  border-top: 1px solid var(--border-light);
  background: #FAFAFA;
}

/* Die Punkte zeigen, wie weit es noch geht. Nicht anklickbar: Ein Sprung auf
   Station 6 hieße einen Seitenwechsel, den niemand bestellt hat — vorwärts
   geht es der Reihe nach. */
.sa-tour-punkte { display: flex; align-items: center; gap: 5px; }
.sa-tour-punkt {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--border-strong);
  transition: background 0.2s ease, width 0.2s var(--ease-zenith);
}
.sa-tour-punkt.vorbei { background: var(--txt-tertiary); }
.sa-tour-punkt.jetzt { background: var(--cta); width: 14px; border-radius: 999px; }

.sa-tour-weiter {
  padding: 8px 16px; border: none; border-radius: 8px;
  background: var(--cta); color: #fff;
  font-family: inherit; font-size: 12.5px; font-weight: 600;
  box-shadow: var(--shadow-btn); cursor: pointer;
  transition: background 0.15s ease;
}
.sa-tour-weiter:hover { background: var(--cta-hover); }

.sa-tour-still {
  padding: 8px 10px; border: none; background: none;
  font-family: inherit; font-size: 12.5px; font-weight: 500;
  color: var(--txt-tertiary); cursor: pointer;
  transition: color 0.15s ease;
}
.sa-tour-still:hover { color: var(--txt-primary); }
/* Unsichtbar, aber am Platz: Ohne den Platzhalter spränge „Weiter" beim ersten
   Schritt nach links und beim zweiten wieder zurück. */
.sa-tour-still.unsichtbar { visibility: hidden; }

/* Der erste Schritt.
   =========================================================================
   Ein Schimmer, der um die Karte läuft, die als Nächstes dran ist, wenn auf
   dem Tagesplan seit zwölf Sekunden nichts passiert. Er sagt nichts, er zeigt
   hin — welche Karte es trifft, entscheidet pages/tagesplan.js.

   UM DIE KARTE, NICHT UM DEN KNOPF. Der erste Entwurf umrandete den Knopf. Das
   war zu klein für das, was er sagen soll: Nicht „drück hier", sondern „hier
   geht es weiter". Der Blick soll erst den Bereich finden und dann den Knopf
   darin — die Karte trägt beides.

   ZWEI SCHICHTEN, WEIL EINE NICHT ÜBERALL LÄUFT
   Der umlaufende Farbverlauf braucht `@property`: Ohne registrierten Winkel
   lässt sich `conic-gradient(from …)` nicht animieren. Wo das fehlt, steht der
   Verlauf still und man sähe nur einen schiefen Rand. Deshalb liegt darunter
   ein atmender Schein, der ohne Voraussetzungen funktioniert und die Bewegung
   allein trägt. */
@property --sa-schimmer {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

.sa-erster-schritt {
  position: relative;
  animation: sa-schritt-atem 2.8s ease-in-out infinite;
}

/* Nur der Rand, nicht die Fläche: Der Verlauf wird auf einen 2 px breiten Saum
   maskiert (Fläche minus Innenfläche). Ohne die Maske läge er über Text und
   Icon des Knopfes. */
.sa-erster-schritt::before {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: inherit;
  padding: 2px;
  pointer-events: none;
  background: conic-gradient(from var(--sa-schimmer),
    rgba(232, 109, 76, 0) 0deg,
    rgba(232, 109, 76, 0) 190deg,
    rgba(232, 109, 76, 0.5) 285deg,
    var(--cta) 330deg,
    rgba(232, 109, 76, 0) 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  animation: sa-schritt-lauf 2.8s linear infinite;
}

@keyframes sa-schritt-lauf { to { --sa-schimmer: 360deg; } }

/* Der eigene Schatten der Karte läuft mit, sonst verschwände er im Takt des
   Atems und die Karte legte sich bei jedem Durchgang flach auf die Seite. */
@keyframes sa-schritt-atem {
  0%, 100% { box-shadow: var(--shadow-card), 0 0 0 0 rgba(232, 109, 76, 0.18); }
  50%      { box-shadow: var(--shadow-card), 0 0 18px 2px rgba(232, 109, 76, 0.26); }
}

/* Wer Bewegung abbestellt hat, bekommt trotzdem den Hinweis — nur still. */
@media (prefers-reduced-motion: reduce) {
  .sa-erster-schritt { animation: none; box-shadow: var(--shadow-card), 0 0 0 2px rgba(232, 109, 76, 0.35); }
  .sa-erster-schritt::before { display: none; }
}

/* Der Punkt am Fragezeichen: Es gibt Stationen, die dieser Benutzer noch nie
   gesehen hat. Dieselbe Form wie in der Seitenleiste — „hier wartet etwas". */
[data-tour-auf].hat-neues::after {
  content: '';
  position: absolute; top: 5px; right: 5px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--cta);
  box-shadow: 0 0 0 2px var(--bg-main);
}

@media (prefers-reduced-motion: reduce) {
  .sa-tour-feld, .sa-tour-fenster.kommt { animation: none; }
  .sa-tour-feld, .sa-tour-loch, .sa-tour-fenster.folgt { transition: none; }
}

/* Suche über alles — Spotlight-Fenster.
   -------------------------------------------------------------------------
   Es sitzt im oberen Drittel, nicht in der Mitte: Die Liste wächst nach unten,
   und ein mittig zentriertes Fenster spränge bei jedem Tastendruck, weil sich
   seine Höhe ändert. Oben verankert bleibt das Suchfeld stehen, wo es war. */
.sa-suche-schicht {
  position: fixed; inset: 0; z-index: 120;
  background: rgba(9, 9, 11, 0.28);
  backdrop-filter: blur(3px);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 12vh 16px 16px;
  animation: sa-suche-auf 0.16s ease;
}
@keyframes sa-suche-auf { from { opacity: 0; } to { opacity: 1; } }

.sa-suche-fenster {
  width: 100%; max-width: 560px;
  background: var(--bg-card);
  border-radius: 16px;
  box-shadow: 0 24px 64px rgba(9, 9, 11, 0.28);
  overflow: hidden;
  display: flex; flex-direction: column;
  max-height: 70vh;
}

.sa-suche-kopf {
  display: flex; align-items: center; gap: 11px;
  padding: 15px 16px;
  border-bottom: 1px solid var(--border-light);
  flex-shrink: 0;
}
.sa-suche-feld {
  flex: 1; min-width: 0;
  border: none; background: transparent; padding: 0;
  font-family: inherit; font-size: 15px; font-weight: 600;
  color: var(--txt-primary);
}
.sa-suche-feld::placeholder { color: var(--txt-tertiary); font-weight: 500; }
.sa-suche-feld:focus { outline: none; }
/* Das eigene Kreuz von type="search" sitzt an einer anderen Stelle als unseres
   und sieht in jedem Browser anders aus. Escape schließt ohnehin. */
.sa-suche-feld::-webkit-search-cancel-button { display: none; }

.sa-suche-kbd {
  font-size: 10px; font-weight: 600;
  padding: 3px 7px; border-radius: 5px;
  border: 1px solid var(--border-light);
  background: var(--bg-main); color: var(--txt-tertiary);
  flex-shrink: 0;
}

.sa-suche-liste { flex: 1; overflow-y: auto; padding-bottom: 8px; }

/* Ausgewählt heißt: Enter öffnet das hier. Dieselbe Fläche wie beim Überfahren
   mit der Maus — sonst gäbe es zwei Arten von „aktiv" nebeneinander. */
.sa-suche-zeile:hover,
.sa-suche-zeile.gewaehlt { background: var(--bg-hover); }
.sa-suche-zeile.gewaehlt { box-shadow: inset 2px 0 0 var(--cta); }

/* Sidebar-Platzhalter.
   -------------------------------------------------------------------------
   Die Sidebar baut ui/layout.js — aber erst, wenn die Skripte gelaufen sind.
   Bis dahin stand der Inhalt 260px zu weit links und sprang dann sichtbar an
   seinen Platz. Deshalb steht die leere Huelle schon im HTML, und ihre Masse
   stehen hier statt in Tailwind-Klassen: das CDN schreibt seine Regeln
   ebenfalls erst zur Laufzeit und waere zu spaet.

   Der eingeklappte Zustand kommt aus localStorage und wird von einem
   Inline-Skript im <head> an <html> gesetzt — vor dem ersten Frame. */
.sa-sidebar {
  width: 260px;
  flex-shrink: 0;
  background: var(--accent);
  color: #fff;
  position: relative;
  z-index: 30;
  border-right: 1px solid rgba(255, 255, 255, 0.05);
  display: none;
  flex-direction: column;
  transition: width 0.3s var(--ease-zenith);
  overflow-x: hidden;
}
@media (min-width: 1024px) { .sa-sidebar { display: flex; } }

html.sa-collapsed .sa-sidebar { width: 72px; }

/* Gespraechsliste im Sales-Chat — gleiche Ursache wie oben.
   Mit `w-full md:w-[340px]` ist die Spalte bildschirmbreit, bis Tailwind vom
   CDN geladen hat, und schrumpft dann sichtbar zusammen. Die Breite steht
   deshalb hier, wo sie mit dem ersten Frame gilt. */
.sa-chat-liste { width: 100%; flex-shrink: 0; }
@media (min-width: 768px)  { .sa-chat-liste { width: 340px; } }
@media (min-width: 1024px) { .sa-chat-liste { width: 380px; } }

/* ----------------------------------------------------------------------------
   9. LIST INTERACTIONS (CRM tables, tasks, leads)
   ---------------------------------------------------------------------------- */
/* Zeigefinger auf allem, was ein Kontextmenü trägt.
   ---------------------------------------------------------------------------
   Ein Rechtsklickmenü ist unsichtbar. Der einzige Hinweis darauf, dass eine
   Zeile mehr kann als dastehen, ist der Zeiger, der sich über ihr ändert. Er
   stand bisher nur dort, wo die Zeile ohnehin per Linksklick etwas öffnete —
   im Tagesplan zum Beispiel fehlte er, obwohl dort dasselbe Menü hängt.

   Die Auswahl läuft über die Datenattribute, nicht über Klassennamen: Ein
   Attribut wie data-tp-task ist genau das, woran der contextmenu-Handler die
   Zeile erkennt. Beides aus derselben Quelle zu speisen heißt, dass der Zeiger
   nicht auseinanderlaufen kann, wenn eine Liste dazukommt. */
[data-customer-id],
[data-conversation-id],
[data-tp-task],
[data-tp-kunde],
[data-ka-zeile],
[data-ka-merk] { cursor: pointer; }

.customer-row { transition: all 0.2s ease; }
.customer-row.row-selected { background-color: var(--cta-light) !important; border-bottom-color: rgba(232, 109, 76, 0.1) !important; }
.customer-row:hover .quick-actions { opacity: 1 !important; pointer-events: auto; }

.inactive-row { opacity: 0.6; background-color: #FAFAFA; }
.inactive-row:hover { opacity: 1; }

/* Square checkbox for selectable CRM list rows */
.crm-checkbox {
  width: 18px; height: 18px; border-radius: 4px; border: 2px solid var(--border-strong);
  display: flex; align-items: center; justify-content: center;
  color: transparent; background: #fff; cursor: pointer; flex-shrink: 0;
  transition: all 0.15s ease;
}
.crm-checkbox:hover { border-color: var(--txt-tertiary); }
.crm-checkbox.checked { background: var(--cta); border-color: var(--cta); color: #fff; }

/* Round checkbox for the day-plan task list */
/* Ankreuzfeld: Trefferflaeche 34px, sichtbarer Kreis 18px.
   -------------------------------------------------------------------------
   Rings um die Zeile liegt ein Klickbereich, der zur Kundenakte springt. Bei
   einem 18px grossen Ziel trifft man regelmaessig daneben und landet in der
   Akte, statt abzuhaken — es sah aus, als liesse sich nichts erledigen.

   Padding allein reichte nicht: Mit `box-sizing: border-box` (Tailwind-
   Voreinstellung) rechnet es in die 18px hinein, statt sie zu vergroessern.
   Deshalb traegt der Knopf die Flaeche und ein Pseudoelement den Kreis. */
.task-checkbox {
  width: 34px; height: 34px; margin: -8px;   /* negativer Rand: Layout bleibt */
  border: none; background: transparent;
  display: flex; align-items: center; justify-content: center;
  position: relative; cursor: pointer; flex-shrink: 0;
}
.task-checkbox::before {
  content: ''; position: absolute;
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--border-strong);
  transition: all 0.15s ease;
}
.task-checkbox i { position: relative; z-index: 1; color: transparent; }

.task-checkbox:hover::before { border-color: var(--txt-primary); box-shadow: 0 0 0 7px var(--bg-hover); }
.task-checkbox.checked::before { background: var(--accent); border-color: var(--accent); }
.task-checkbox.checked i { color: #fff; }

.task-row.checked-row .task-title { text-decoration: line-through; color: var(--txt-tertiary); }
.task-row.checked-row .task-desc { color: var(--txt-tertiary); }
.task-row.checked-row .ai-badge { opacity: 0.5; filter: grayscale(1); }

/* ----------------------------------------------------------------------------
   10. TABS (customer detail)
   ---------------------------------------------------------------------------- */
.nav-tab {
  color: var(--txt-secondary); font-weight: 500; font-size: 13px;
  padding: 12px 16px; border-bottom: 2px solid transparent;
  cursor: pointer; white-space: nowrap; transition: all 0.2s ease;
}
.nav-tab:hover { color: var(--txt-primary); border-bottom-color: var(--border-strong); }
.nav-tab.active { color: var(--txt-primary); font-weight: 600; border-bottom-color: var(--txt-primary); }
.tab-content { display: none; }
.tab-content.active { display: block; animation: fadeIn 0.3s ease-out forwards; }

/* ----------------------------------------------------------------------------
   11. ACCORDION / COLLAPSIBLE
   ---------------------------------------------------------------------------- */
.accordion-content { display: none; }
.accordion-content.expanded { display: block; animation: slideDown 0.3s var(--ease-zenith) forwards; }
.expand-icon { transition: transform 0.3s var(--ease-zenith); }
.is-expanded .expand-icon { transform: rotate(180deg); }

/* ----------------------------------------------------------------------------
   12. TIMELINE (activity feeds)
   ---------------------------------------------------------------------------- */
.timeline-dot { width: 9px; height: 9px; border-radius: 50%; border: 2px solid var(--txt-tertiary); background: #fff; position: relative; z-index: 10; }
.timeline-dot.filled  { background: var(--txt-primary);     border-color: var(--txt-primary); }
.timeline-dot.alert   { background: var(--status-warning);  border-color: var(--status-warning); }
.timeline-dot.success { background: var(--status-success);  border-color: var(--status-success); }

/* ----------------------------------------------------------------------------
   13. INBOX / CHAT LIST (SALES-Chat)
   ---------------------------------------------------------------------------- */
.convo-item { transition: all 0.15s ease; cursor: pointer; border-radius: 8px; margin: 4px 8px; padding: 12px 14px; border: 1px solid transparent; }
.convo-item:hover:not(.active) { background-color: #FAFAFA; border-color: var(--border-light); }
.convo-item.active { background-color: var(--cta-light); border-color: rgba(232, 109, 76, 0.2); position: relative; z-index: 10; }
.convo-item.unread .convo-title { font-weight: 700; color: var(--txt-primary); }
.convo-item.unread .convo-preview { font-weight: 600; color: var(--txt-primary); }

.email-bubble { border-radius: 12px; padding: 20px; transition: all 0.2s ease; }

.command-item { transition: all 0.1s ease; }
.command-item:hover { background-color: var(--bg-main); }

/* ----------------------------------------------------------------------------
   14. AI PANE (440px slide-over) + FAB
   The slide-over markup/logic lives in assets/js/ui/chat-panel.js.
   ---------------------------------------------------------------------------- */
.ai-bubble-in {
  background: transparent; border: none; box-shadow: none;
  padding: 4px 16px 12px 0; max-width: 95%;
  font-size: 14px; line-height: 1.6; color: var(--txt-primary);
}
.ai-bubble-out {
  background: var(--txt-primary); color: #fff; border: none;
  border-radius: 16px 16px 4px 16px; padding: 12px 18px; max-width: 85%; margin-left: auto;
  font-size: 14px; font-weight: 400; line-height: 1.5;
  box-shadow: 0 4px 12px rgba(9, 9, 11, 0.1);
}

#aiFab {
  background: var(--accent) !important;
  box-shadow: 0 4px 12px rgba(9, 9, 11, 0.2), 0 0 0 1px rgba(9, 9, 11, 0.1) !important;
  transition: all 0.25s var(--ease-zenith) !important;
}
#aiFab:hover {
  transform: scale(1.05) translateY(-2px) !important;
  background: var(--accent-hover) !important;
  box-shadow: 0 8px 24px rgba(9, 9, 11, 0.25), 0 0 0 1px rgba(9, 9, 11, 0.1) !important;
}

/* ----------------------------------------------------------------------------
   15. TABLES (offer detail) + PRICE BREAKDOWN
   ---------------------------------------------------------------------------- */
.offer-table { width: 100%; border-collapse: collapse; }
.offer-table th { background: var(--bg-main); padding: 12px; text-align: left; font-size: 11px; font-weight: 600; color: var(--txt-secondary); text-transform: uppercase; letter-spacing: 0.05em; border-bottom: 1px solid var(--border-light); }
.offer-table td { padding: 16px 12px; border-bottom: 1px solid var(--border-light); }
.offer-table tr:last-child td { border-bottom: none; }

.price-table { width: 100%; margin-top: 24px; }
.price-row { display: flex; justify-content: space-between; align-items: baseline; padding: 8px 0; font-size: 14px; }
.price-label { color: var(--txt-secondary); }
.price-value { font-family: ui-monospace, 'SFMono-Regular', 'Menlo', monospace; font-weight: 500; color: var(--txt-primary); }
.price-value.discount { color: var(--cta); }
.price-row.total { border-top: 2px solid var(--border-light); border-bottom: 2px solid var(--border-light); padding: 12px 0; font-weight: 700; font-size: 16px; }
.price-row.total .price-value { font-weight: 700; font-size: 16px; }

/* ----------------------------------------------------------------------------
   16. CHARTS (Analytics SVG)
   ---------------------------------------------------------------------------- */
.chart-hover-line { opacity: 0; transition: opacity 0.2s ease; pointer-events: none; }
.chart-hover-area:hover .chart-hover-line { opacity: 1; }
.chart-hover-area:hover ~ .chart-tooltip { opacity: 1; pointer-events: none; }
.sparkline { stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; }

/* ----------------------------------------------------------------------------
   17. SCROLLBARS
   ---------------------------------------------------------------------------- */
/* Der Platz für den Rollbalken bleibt reserviert, auch wenn keiner da ist.
   -------------------------------------------------------------------------
   Ohne diese Zeile verschiebt sich der zentrierte Inhalt um die halbe
   Balkenbreite, sobald eine Seite kürzer wird als der Bildschirm — in der
   Produktakte sprang beim Wechsel von „Übersicht" auf „Preise" alles um drei
   Pixel nach rechts. Das ist zu wenig, um es zu benennen, und genug, um
   unruhig zu wirken. `stable` hält den Streifen frei; sichtbar wird er nur,
   wenn es wirklich etwas zu rollen gibt. */
.custom-scroll { scrollbar-gutter: stable; }
.custom-scroll::-webkit-scrollbar { width: 5px; height: 5px; }
.custom-scroll::-webkit-scrollbar-track { background: transparent; }
.custom-scroll::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 10px; }
.custom-scroll::-webkit-scrollbar-thumb:hover { background: #A1A1AA; }

.dark-scroll::-webkit-scrollbar { width: 4px; height: 4px; }
.dark-scroll::-webkit-scrollbar-track { background: transparent; }
.dark-scroll::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.1); border-radius: 10px; }
.dark-scroll::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.2); }

.hide-scrollbar::-webkit-scrollbar { display: none; }
.hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }

/* ----------------------------------------------------------------------------
   18. COLLAPSIBLE SIDEBAR
   Sidebar markup is injected by assets/js/ui/layout.js. These rules drive the
   260px → 72px collapse animation and the collapsed-state visibility swaps.
   ---------------------------------------------------------------------------- */
#sidebar { transition: width 0.3s var(--ease-zenith); overflow-x: hidden; }
#sidebar.collapsed { width: 72px; }
#sidebar.collapsed .sidebar-text { display: none; }
#sidebar.collapsed .sidebar-section-title { text-align: center; padding: 0; margin-bottom: 8px; }
.title-collapsed { display: none; }
#sidebar.collapsed .title-expanded { display: none; }
#sidebar.collapsed .title-collapsed { display: block; font-size: 8.5px; letter-spacing: 0.1em; opacity: 0.7; color: rgba(255, 255, 255, 0.4); }
#sidebar.collapsed .nav-item { padding-left: 0; padding-right: 0; justify-content: center; }
#sidebar.collapsed .nav-item i { margin-right: 0; }
#sidebar.collapsed .nav-badge { position: absolute; top: 6px; right: 14px; margin: 0; }
#sidebar.collapsed .sidebar-profile-container { padding: 12px 8px; }
#sidebar.collapsed .user-profile-btn { padding: 8px; justify-content: center; }
#sidebar.collapsed .sidebar-collapsed-avatar { display: flex; }

/* ----------------------------------------------------------------------------
   19. MISC UTILITIES
   ---------------------------------------------------------------------------- */
.mobile-overlay { background: var(--bg-main); }
.hover\:bg-bg-hover:hover { background-color: var(--bg-hover); }
