/* ==========================================================================
   VINTED MANAGER — "JARVIS" THEME
   Dark HUD-Interface: Neon Cyan/Blau + Orange-Akzent, Glassmorphism,
   Tech-Grid-Hintergrund, Micro-Animations.
   Alle bestehenden Klassen (Chat, Labels, Formulare …) bleiben funktional.
   ========================================================================== */

/* Fonts werden in base.html per <link> geladen (parallel statt blockierend). */

:root {
    /* Kernpalette */
    --bg: #04070d;
    --bg-2: #070d18;
    /* Etwas deckender als früher: erlaubt den Verzicht auf backdrop-filter
       (GPU-teuer, Hauptursache für Ruckeln) ohne sichtbaren Qualitätsverlust. */
    --panel: rgba(12, 22, 40, 0.88);
    --panel-solid: #0b1424;
    --border: rgba(0, 212, 255, 0.16);
    --border-strong: rgba(0, 212, 255, 0.45);

    --cyan: #00d4ff;
    --blue: #3b82f6;
    --orange: #ff9e3d;
    --text: #d5e4f7;
    --muted: #6d84a3;
    --gray: var(--muted);

    --success: #2dd4a7;
    --danger: #ff4d6d;
    --warn: #ffc247;

    /* Legacy-Aliase (alte Klassen erwarten diese Namen) */
    --green: var(--cyan);
    --dark: var(--text);
    --card: var(--panel-solid);

    --glow-cyan: 0 0 8px rgba(0, 212, 255, 0.55), 0 0 24px rgba(0, 212, 255, 0.18);
    --glow-orange: 0 0 8px rgba(255, 158, 61, 0.55), 0 0 24px rgba(255, 158, 61, 0.18);

    --font-head: 'Orbitron', 'Share Tech Mono', monospace;
    --font-body: 'Rajdhani', 'Segoe UI', sans-serif;
    --font-mono: 'Share Tech Mono', 'SF Mono', monospace;

    --r-panel: 14px;   /* runde Grundform … */
    --r-cut: 2px;      /* … mit „abgeschnittenen" Tech-Ecken via clip */

    /* ---- Design-System ------------------------------------------------
       Bis hierher gab es nur Farben, Schriften und zwei Radien. Alles
       andere -- Abstände, Ebenen, Schatten -- stand als Einzelwert im
       Stylesheet verteilt, weshalb dieselbe Kachel an zwei Stellen
       unterschiedlich aussah. Ab hier gilt: keine neuen Zufallswerte. */

    /* Ebenen. Tiefe entsteht durch gestaffelte Helligkeit, nicht durch
       Schlagschatten -- auf dunklem Grund wirken Schatten sonst wie Dreck. */
    --surface: #080f1b;        /* Fläche direkt auf dem Hintergrund */
    --surface-2: #0b1424;      /* Karte */
    --surface-3: #101c30;      /* Element auf einer Karte (Hover, Eingabe) */

    /* Text-Hierarchie: drei Stufen reichen, mehr wird beliebig. */
    --text-strong: #eaf4ff;    /* Kennzahlen, Überschriften */
    /* --text (Fließtext) und --muted (Labels) stehen oben. */

    /* Abstandsraster (4er-Schritte). */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 24px;
    --sp-6: 32px;

    /* Radien. --r-panel bleibt die Grundform großer Flächen. */
    --r-sm: 6px;
    --r-md: 10px;

    /* Schatten sparsam und nur zur Abhebung schwebender Elemente. */
    --sh-1: 0 1px 2px rgba(0, 0, 0, 0.4);
    --sh-2: 0 6px 18px rgba(0, 0, 0, 0.45);
    --sh-3: 0 12px 40px rgba(0, 0, 0, 0.55);

    /* Einheitliche Übergangsdauer: vorher .18s/.2s/.25s wild gemischt. */
    --t-schnell: .14s;
    --t-normal: .2s;
}

* { box-sizing: border-box; }

html { scrollbar-color: rgba(0, 212, 255, 0.35) transparent; }

body {
    font-family: var(--font-body);
    background: var(--bg);
    color: var(--text);
    margin: 0;
    min-height: 100vh;
    letter-spacing: 0.02em;
}

/* Tech-Grid + Ambient-Glows auf einer eigenen fixen Ebene.
   Vorher: background-attachment:fixed am body — das zwingt den Browser bei
   jedem Scrollen zum Neuzeichnen des Hintergrunds (ruckelt massiv, v. a. am
   Handy). Ein fixiertes Pseudo-Element liegt dagegen auf einer eigenen
   Compositor-Ebene und kostet beim Scrollen nichts. */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image:
        radial-gradient(ellipse 80% 50% at 20% -10%, rgba(59, 130, 246, 0.10), transparent 60%),
        radial-gradient(ellipse 60% 40% at 90% 110%, rgba(0, 212, 255, 0.05), transparent 60%),
        linear-gradient(rgba(0, 212, 255, 0.016) 1px, transparent 1px),
        linear-gradient(90deg, rgba(0, 212, 255, 0.016) 1px, transparent 1px);
    background-size: auto, auto, 56px 56px, 56px 56px;
    transform: translateZ(0);
}

::selection { background: rgba(0, 212, 255, 0.3); }

/* Sichtbarer Fokus-Ring für Tastatur-Navigation (überall, nicht nur Inputs).
   :focus-visible → erscheint nur bei Tastatur, stört Maus-Nutzer nicht. */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--cyan);
    outline-offset: 2px;
    border-radius: 6px;
}
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: none; }

h1, h2, h3 {
    font-family: var(--font-head);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: #eaf4ff;
}
h1 { font-size: 1.35rem; }
h1::after {
    content: "";
    display: block;
    width: 64px; height: 2px;
    margin-top: 6px;
    background: linear-gradient(90deg, var(--cyan), transparent);
    box-shadow: var(--glow-cyan);
}

a { color: var(--cyan); }

/* ==========================================================================
   APP-LAYOUT: Sidebar + Topbar + Main
   ========================================================================== */

.app { display: flex; min-height: 100vh; }

/* ---- Sidebar ---- */
.sidebar {
    width: 216px;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    padding: 18px 12px;
    background: linear-gradient(180deg, rgba(10, 18, 34, 0.96), rgba(6, 11, 22, 0.96));
    border-right: 1px solid var(--border);
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.side-brand {
    font-family: var(--font-head);
    font-weight: 900;
    font-size: 1.02rem;
    letter-spacing: 0.18em;
    color: #eaf4ff;
    padding: 6px 10px 18px;
    text-shadow: var(--glow-cyan);
    white-space: nowrap;
}
.side-brand .cursor {
    color: var(--cyan);
    animation: blink 1.1s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

.side-nav { display: flex; flex-direction: column; gap: 2px; }

/* Gruppentitel: klein, ruhig, nicht anklickbar. Er soll die Liste
   gliedern, nicht mit den Menüpunkten um Aufmerksamkeit konkurrieren. */
.side-gruppe {
    font-family: var(--font-mono);
    font-size: 0.58rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--muted);
    opacity: 0.75;
    padding: 0 12px var(--sp-1);
    margin-top: var(--sp-4);
}
.side-gruppe:first-child { margin-top: 0; }

.side-nav a {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 12px;
    border-radius: 8px 8px 8px var(--r-cut);
    color: var(--muted);
    text-decoration: none;
    font-weight: 600;
    font-size: 0.95rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    border: 1px solid transparent;
    position: relative;
    transition: color .18s, background .18s, border-color .18s, transform .18s;
}
.side-nav a .ico {
    font-size: 0.95rem;
    width: 20px;
    text-align: center;
    color: var(--muted);
    transition: color .18s, text-shadow .18s, transform .18s;
}
.side-nav a:hover {
    color: var(--text);
    background: rgba(0, 212, 255, 0.06);
    transform: translateX(3px);
}
.side-nav a:hover .ico { color: var(--cyan); text-shadow: var(--glow-cyan); }

/* Aktiver Eintrag: erkennbar über Fläche, Textkontrast und die Kante links --
   nicht über eine kräftige Farbfläche. Der Cyan-Verlauf von vorher zog den
   Blick staerker an als der Seiteninhalt selbst. */
.side-nav a.active {
    color: var(--text-strong);
    background: var(--surface-3);
    border-color: var(--border);
}
.side-nav a.active .ico { color: var(--cyan); text-shadow: var(--glow-cyan); }
.side-nav a.active::before {
    content: "";
    position: absolute;
    left: -1px; top: 15%;
    height: 70%; width: 2px;
    background: var(--cyan);
    box-shadow: var(--glow-cyan);
    border-radius: 2px;
}

.side-foot {
    margin-top: auto;
    padding: 14px 10px 4px;
    font-family: var(--font-mono);
    font-size: 0.68rem;
    color: var(--muted);
    letter-spacing: 0.14em;
}

/* ---- Rechte Spalte ---- */
.main-col { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* ---- Topbar ---- */
.topbar {
    display: flex;
    align-items: center;
    gap: 24px;
    padding: 14px 28px;
    border-bottom: 1px solid var(--border);
    background: rgba(7, 13, 24, 0.82);
    /* Einziges Element mit Blur: sichtbar (Inhalt scrollt darunter durch)
       und nur eine schmale Leiste — vertretbare Kosten. */
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    position: sticky;
    top: 0;
    z-index: 50;
}

/* Zeigt den Namen der aktuellen Seite — vorher stand hier auf jeder Seite
   derselbe Satz, der keine Information trug. Das ist zugleich das <h1> der
   Seite, deshalb die h1-Deko (Versalien, Sperrung, Unterstrich) zurücknehmen. */
.top-title {
    margin: 0;
    min-width: 0;
    font-family: var(--font-body);
    font-size: 1.1rem;
    font-weight: 700;
    text-transform: none;
    letter-spacing: 0.03em;
    color: #eaf4ff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.top-title::after { content: none; }

/* Die Topbar trägt jetzt sieben Elemente statt vier. Bei 22px Abstand
   überliefe sie auf Laptop-Breite, deshalb enger und mit sanften Trennern
   zwischen den Gruppen (Suche | Status | Kontext | Ich) -- die Trennung macht
   die Reihe lesbar, ohne sie mit Rahmen zuzustellen. */
.top-right {
    /* Wächst in den freien Platz statt ihn über margin-left:auto zu
       verschlucken. Mit dem auto-Rand bekam die Gruppe nur ihre intrinsische
       Breite zugeteilt und brach um, obwohl daneben 200px frei waren --
       rechtsbündig wird sie jetzt über justify-content. */
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    min-width: 0;
    /* Umbruch als Auffangnetz statt als Regelfall: die Medienabfragen unten
       räumen die Leiste so weit ab, dass sie normalerweise einzeilig bleibt.
       Reicht das nicht (sehr lange Seitenüberschrift, zwischen zwei
       Haltepunkten, große Schrift), rutscht die Gruppe in eine zweite Zeile,
       statt rechts aus dem Fenster zu laufen -- dort waren Konto-Auswahl und
       Abmelden vorher schlicht nicht mehr erreichbar. */
    flex-wrap: wrap;
    justify-content: flex-end;
}
/* Alles behält seine Größe -- bis auf das Suchfeld. Es ist das einzige
   Element, das ohne Informationsverlust schmaler werden kann, und fängt
   deshalb den Platzmangel ab. Ohne diese Ausnahme schob eine lange
   Seitenüberschrift ("Benachrichtigungen") die halbe Leiste aus dem Bild. */
.top-right > * { flex: 0 0 auto; }
.top-right > .top-status,
.top-right > .account-switcher,
.top-right > .top-profil {
    border-left: 1px solid var(--border);
    padding-left: var(--sp-3);
}

/* ---- Suche (schickt an /inventory?q=) ---- */
.top-right > .top-suche {
    /* Wunschbreite 200px, darf aber bis 120px zusammengehen, bevor die
       Medienabfrage es ganz ausblendet. */
    flex: 0 1 200px;
    min-width: 120px;
}
.top-suche {
    position: relative;
    display: flex;
    align-items: center;
}
.top-suche-ico {
    position: absolute;
    left: 10px;
    font-size: 0.95rem;
    color: var(--muted);
    pointer-events: none;
}
.top-suche input {
    width: 100%;
    min-width: 0;
    padding: 7px 10px 7px 28px;
    min-height: 34px;
    font-family: var(--font-body);
    font-size: 0.86rem;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    transition: border-color var(--t-normal), background var(--t-normal);
}
.top-suche input::placeholder { color: var(--muted); }
.top-suche input:focus {
    outline: none;
    background: var(--surface-3);
    border-color: var(--border-strong);
}

/* ---- Agenten-Ampel ---- */
.top-agenten {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: 5px 10px;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--text);
    text-decoration: none;
    transition: border-color var(--t-normal), background var(--t-normal);
}
.top-agenten:hover { border-color: var(--border-strong); background: var(--surface-3); }
.top-agenten .lbl { color: var(--muted); }
.top-agenten-zahl {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    color: var(--text-strong);
}
/* Der Punkt trägt die Farbe, die Zahl daneben die Information -- wer die
   Farbe nicht unterscheiden kann, liest trotzdem "4/9". */
.top-agenten .pulse-dot { width: 7px; height: 7px; }
.top-agenten.ampel-gruen .pulse-dot { background: var(--success); box-shadow: 0 0 6px var(--success); }
.top-agenten.ampel-gelb  .pulse-dot { background: var(--warn);    box-shadow: 0 0 6px var(--warn); }
.top-agenten.ampel-rot   .pulse-dot { background: var(--danger);  box-shadow: 0 0 7px var(--danger); }
.top-agenten.ampel-gelb  { border-color: rgba(255, 194, 71, 0.35); }
.top-agenten.ampel-rot   { border-color: rgba(255, 77, 109, 0.4); }
/* Bereitschaft ist kein Fehler: grau und ohne Puls, damit es nicht nach
   Störung aussieht. */
.top-agenten.ampel-grau .pulse-dot {
    background: var(--muted);
    box-shadow: none;
    animation: none;
}

/* ---- Glocke ---- */
.top-glocke {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px; height: 34px;
    border-radius: var(--r-md);
    color: var(--muted);
    font-size: 1rem;
    text-decoration: none;
    transition: color var(--t-normal), background var(--t-normal);
}
.top-glocke:hover { color: var(--text-strong); background: var(--surface-3); }
.top-glocke.hat-neue { color: var(--warn); }
.top-glocke-zahl {
    position: absolute;
    top: 1px; right: 0;
    min-width: 15px;
    padding: 0 3px;
    border-radius: 8px;
    background: var(--danger);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 0.6rem;
    font-weight: 700;
    line-height: 15px;
    text-align: center;
}

/* ---- Profil ---- */
.top-profil { display: flex; align-items: center; gap: var(--sp-2); }
.top-profil-name {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    color: var(--text);
    font-size: 0.86rem;
    font-weight: 600;
    text-decoration: none;
    transition: color var(--t-normal);
}
.top-profil-name:hover { color: var(--text-strong); }
.top-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px; height: 26px;
    border-radius: 50%;
    background: var(--surface-3);
    border: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-strong);
}
.top-abmelden {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px;
    font-size: 0.78rem;
}
/* Das Symbol trägt nur am Handy; nebem dem Wort wäre es Dekoration. */
.top-abmelden-ico { display: none; }

.top-status {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 0.88rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--success);
}
.pulse-dot {
    width: 9px; height: 9px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--success);
    box-shadow: 0 0 6px var(--success);
    animation: pulse 1.8s ease-in-out infinite;
}
@keyframes pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.35); opacity: 0.55; }
}

.top-time { display: flex; align-items: baseline; gap: 10px; }
.top-clock {
    font-family: var(--font-mono);
    font-size: 1.1rem;
    color: var(--text);
    letter-spacing: 0.06em;
    font-variant-numeric: tabular-nums;
}
.top-date {
    font-size: 0.88rem;
    color: var(--muted);
}

/* Account-Switcher in der Topbar */
.account-switcher select {
    padding: 8px 12px;
    min-height: 38px;
    border: 1px solid var(--border);
    border-radius: 8px 8px 8px var(--r-cut);
    font-size: 0.9rem;
    font-weight: 600;
    font-family: var(--font-body);
    background: var(--panel-solid);
    color: var(--text);
    letter-spacing: 0.02em;
    transition: border-color .18s, box-shadow .18s;
}
.account-switcher select:hover { border-color: var(--border-strong); }

/* Zwischenbreiten: die Leiste wird in der Reihenfolge abgeräumt, in der die
   Elemente am wenigsten fehlen -- erst Datum, dann Suchfeld, dann die Wörter
   neben den Symbolen, zuletzt die Uhr.
   Diese Blöcke müssen NACH den Grundregeln von .top-time & Co. stehen: sie
   haben dieselbe Spezifität, also entscheidet die Reihenfolge. Weiter oben
   platziert wurden sie von "display:flex" wieder überstimmt. */
/* Die Schwellen sind gemessen, nicht geraten: Bezugsfall ist die längste
   Seitenüberschrift ("Benachrichtigungen") neben der vollen rechten Gruppe. */
@media (max-width: 1500px) {
    .top-date { display: none; }
    .top-profil-name .lbl { display: none; }
}
@media (max-width: 1400px) {
    /* Unter dieser Breite bliebe vom Suchfeld nur noch ein Stummel; die Seite
       Inventar hat ohnehin ein eigenes, vollwertiges Feld. */
    .top-right > .top-suche { display: none; }
}
@media (max-width: 1200px) {
    /* Ab hier nur noch Symbole plus Zahl: "Agenten 6/9" wird zu "● 6/9",
       "● Online" zum bloßen Punkt. Die Information steckt in Punktfarbe und
       Zahl, das Wort war die Verpackung. Beide behalten ihr title-Attribut. */
    .top-agenten .lbl, .top-status .lbl { display: none; }
    /* Uhr raus, bevor die Gruppe umbricht: sie ist Zierde, die Seiten-
       überschrift daneben ist es nicht. Vorher brach die Leiste bei
       "Benachrichtigungen" auf zwei Zeilen um und kürzte den Titel trotzdem. */
    .top-time { display: none; }
    /* Letzte Einsparung, damit die Gruppe einzeilig bleibt: Abmelden wird zum
       Ein-/Aus-Symbol. Beschriftung steckt in title und .sr-only. */
    .top-abmelden-ico { display: inline; font-size: 0.95rem; }
    .top-abmelden-wort { display: none; }
}

.container {
    max-width: 1180px;
    width: 100%;
    margin: 0 auto;
    padding: 26px 32px 60px;
    animation: rise .4s ease both;
}
@keyframes rise {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   FLASH / PANELS / GRID
   ========================================================================== */

.flash {
    padding: 10px 16px;
    border-radius: 8px 8px 8px var(--r-cut);
    margin-bottom: 16px;
    font-size: 0.92rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    border: 1px solid;
    animation: rise .3s ease both;
}
.flash-success { background: rgba(45, 212, 167, 0.1); color: var(--success); border-color: rgba(45, 212, 167, 0.35); }
.flash-error   { background: rgba(255, 77, 109, 0.1);  color: var(--danger);  border-color: rgba(255, 77, 109, 0.35); }
.flash-warning { background: rgba(255, 194, 71, 0.1);  color: var(--warn);    border-color: rgba(255, 194, 71, 0.35); }

/* Glass-Panel mit Neon-Kante oben */
.card {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--r-panel) var(--r-panel) var(--r-panel) var(--r-cut);
    padding: 20px;
    margin-bottom: 20px;
    position: relative;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 8px 24px -12px rgba(0, 0, 0, 0.6);
    transition: border-color .25s, box-shadow .25s;
}
.card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(0, 212, 255, 0.35), transparent);
}
.card:hover {
    border-color: rgba(0, 212, 255, 0.3);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 10px 30px -14px rgba(0, 0, 0, 0.7), 0 0 30px rgba(0, 212, 255, 0.06);
}

/* HUD-Eckwinkel unten rechts — „eckig trifft rund" ohne extra Markup */
.card::after {
    content: "";
    position: absolute;
    right: 8px; bottom: 8px;
    width: 12px; height: 12px;
    border-right: 1px solid var(--border-strong);
    border-bottom: 1px solid var(--border-strong);
    opacity: 0;
    transition: opacity .25s;
    pointer-events: none;
}
.card:hover::after { opacity: 0.7; }

/* Nur für Screenreader (z. B. Spaltenüberschrift ohne sichtbaren Text) */
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Sprungmarke zur Tastaturbedienung */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 8px;
    z-index: 200;
    padding: 10px 16px;
    background: var(--panel-solid);
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    color: var(--cyan);
    text-decoration: none;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    font-size: 0.8rem;
}
.skip-link:focus { left: 8px; box-shadow: var(--glow-cyan); }

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px;
}

/* Feste Spaltenzahl: „Bestand" (3 Kacheln) und „Finanzen" (4 Kacheln) stehen
   untereinander -- mit auto-fit bekämen sie unterschiedliche Spaltenbreiten
   und die beiden Blöcke würden sichtbar gegeneinander verrutschen. */
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1040px) {
    .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- KPI-Cards ---- */
.stat {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--r-panel) var(--r-panel) var(--r-panel) var(--r-cut);
    padding: 16px;
    text-align: left;
    position: relative;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 8px 24px -14px rgba(0, 0, 0, 0.6);
    transition: transform .22s, border-color .22s, box-shadow .22s;
    animation: rise .45s ease both;
}
.grid .stat:nth-child(2) { animation-delay: .04s; }
.grid .stat:nth-child(3) { animation-delay: .08s; }
.grid .stat:nth-child(4) { animation-delay: .12s; }
.grid .stat:nth-child(5) { animation-delay: .16s; }
.grid .stat:nth-child(6) { animation-delay: .20s; }
.grid .stat:nth-child(7) { animation-delay: .24s; }

.stat::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--cyan), transparent);
    opacity: 0.28;
    transition: opacity .22s;
}
/* Ecken-Marker wie ein HUD-Ziel — nur beim Hover, sonst zu viel Rauschen */
.stat::after {
    content: "";
    position: absolute;
    right: 6px; top: 6px;
    width: 10px; height: 10px;
    border-top: 1px solid var(--border-strong);
    border-right: 1px solid var(--border-strong);
    opacity: 0;
    transition: opacity .22s;
}
.stat:hover::after { opacity: 0.6; }
.stat:hover {
    transform: translateY(-3px);
    border-color: var(--border-strong);
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4), 0 0 22px rgba(0, 212, 255, 0.1);
}
.stat:hover::before { opacity: 1; }

/* Label über den Wert: die Kachel liest sich dann wie eine Beschriftung mit
   Ergebnis, und die große Zahl steht als letztes im Blick. */
.stat .label {
    color: var(--muted);
    font-size: 0.68rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-weight: 600;
    margin-bottom: 8px;
}
.stat .value {
    /* Bewusst NICHT Orbitron: dessen Null ist durchgestrichen und sieht dann
       aus wie das Ø-Zeichen für „Durchschnitt". Bei Geldbeträgen fatal. */
    font-family: var(--font-body);
    letter-spacing: 0.01em;
    /* skaliert mit, damit vierstellige Beträge die Karte nicht sprengen */
    font-size: clamp(1.5rem, 2.4vw, 2.05rem);
    font-weight: 700;
    color: #eaf4ff;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
    text-shadow: 0 0 10px rgba(0, 212, 255, 0.18);
    white-space: nowrap;
    line-height: 1.05;
}
/* Akzent-Varianten */
.stat.accent-orange .value { text-shadow: 0 0 10px rgba(255, 158, 61, 0.22); color: #ffe9d1; }
.stat.accent-orange::before { background: linear-gradient(90deg, transparent, var(--orange), transparent); }
.stat.accent-green .value { text-shadow: 0 0 10px rgba(45, 212, 167, 0.22); color: #d9fff4; }
.stat.accent-green::before { background: linear-gradient(90deg, transparent, var(--success), transparent); }

/* ==========================================================================
   HUD-ELEMENTE: Ringe, Progressbars, Statuszeile
   ========================================================================== */

.hud-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 16px;
}

.hud-ring-box { display: flex; align-items: center; gap: 16px; }

/* Zwei Quoten nebeneinander in einer Karte */
.hud-pair {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 18px 24px;
}

.hud-ring { width: 92px; height: 92px; flex: 0 0 auto; position: relative; }
.hud-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.hud-ring .track { fill: none; stroke: rgba(0, 212, 255, 0.14); stroke-width: 8; }
.hud-ring .bar {
    fill: none;
    stroke: var(--cyan);
    stroke-width: 8;
    stroke-linecap: round;
    filter: drop-shadow(0 0 5px rgba(0, 212, 255, 0.7));
    stroke-dasharray: 264;           /* 2 * PI * r(42) */
    stroke-dashoffset: 264;
    animation: ringIn 1.2s cubic-bezier(.4, 0, .2, 1) .2s forwards;
}
.hud-ring.orange .bar { stroke: var(--orange); filter: drop-shadow(0 0 5px rgba(255, 158, 61, 0.7)); }
@keyframes ringIn { to { stroke-dashoffset: var(--target, 264); } }

.hud-ring-label { position: relative; }
/* Prozentwert sitzt im Ring: bei 0 % ist der Ring sonst komplett leer und
   sieht aus, als wäre die Anzeige kaputt. */
.hud-ring-val {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-body);   /* siehe .stat .value — Orbitron-Null */
    font-weight: 700;
    font-size: 1.15rem;
    color: #eaf4ff;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 0 12px rgba(0, 212, 255, 0.4);
}
.hud-ring-sub {
    font-size: 0.78rem;
    color: var(--text);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    font-weight: 600;
}
.hud-ring-note {
    font-size: 0.72rem;
    color: var(--muted);
    margin-top: 3px;
    font-variant-numeric: tabular-nums;
}

/* Futuristischer Fortschrittsbalken mit Scanner-Schimmer */
.tech-bar {
    height: 8px;
    border-radius: 4px;
    background: rgba(0, 212, 255, 0.08);
    border: 1px solid var(--border);
    overflow: hidden;
    position: relative;
}
.tech-bar .fill {
    height: 100%;
    width: 0;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--blue), var(--cyan));
    box-shadow: var(--glow-cyan);
    animation: barIn 1.1s cubic-bezier(.4, 0, .2, 1) .3s forwards;
    position: relative;
}
.tech-bar .fill.orange { background: linear-gradient(90deg, #c96a12, var(--orange)); box-shadow: var(--glow-orange); }
@keyframes barIn { to { width: var(--target, 0%); } }
.tech-bar .fill::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.35), transparent);
    transform: translateX(-100%);
    /* Begrenzt statt infinite: Dauer-Animationen halten den Compositor
       permanent wach und kosten am Handy spürbar Akku und Flüssigkeit. */
    animation: scan 2.6s ease-in-out 1.4s 3;
}
@keyframes scan { to { transform: translateX(100%); } }

.tech-bar-row { margin-bottom: 14px; }
.tech-bar-head {
    display: flex;
    justify-content: space-between;
    font-family: var(--font-mono);
    font-size: 0.74rem;
    letter-spacing: 0.1em;
    color: var(--muted);
    text-transform: uppercase;
    margin-bottom: 6px;
}
.tech-bar-head b { color: var(--text); font-weight: 400; }

/* ==========================================================================
   TABELLEN
   ========================================================================== */

table {
    width: 100%;
    border-collapse: collapse;
    background: transparent;
    border-radius: 10px;
    overflow: hidden;
}

th, td {
    text-align: left;
    padding: 11px 12px;
    border-bottom: 1px solid rgba(0, 212, 255, 0.08);
    font-size: 0.92rem;
}

th {
    background: rgba(0, 212, 255, 0.05);
    color: var(--cyan);
    font-family: var(--font-mono);
    font-weight: 400;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.14em;
}

tbody tr, table tr { transition: background .15s; }
tr:hover td { background: rgba(0, 212, 255, 0.04); }
tbody tr:last-child td { border-bottom: none; }

td a { text-decoration: none; }
td a:hover { text-shadow: var(--glow-cyan); }

/* Zahlenspalten: rechtsbündig + Ziffern gleicher Breite → Beträge fluchten
   untereinander und lassen sich zeilenweise vergleichen. */
th.num, td.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
    white-space: nowrap;
}

/* Freitext-Spalten dürfen nicht die ganze Tabelle sprengen. */
td.cell-text { max-width: 34ch; line-height: 1.45; }

/* Delta gegenüber dem aktuellen Preis */
.delta { font-family: var(--font-mono); font-size: 0.74rem; margin-left: 6px; }
.delta-down { color: var(--warn); }
.delta-up { color: var(--success); }

/* Horizontales Scrollen bleibt in der Tabelle, statt die Seite zu verbreitern. */
.table-wrap { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Noch nicht abgehakte Benachrichtigung. Bewusst über einen Balken links und
   nicht nur über Schriftfarbe markiert -- Farbe allein ist bei Rot-Grün-Schwäche
   keine verlässliche Unterscheidung. */
tr.row-unread td { background: rgba(0, 229, 255, 0.05); }
tr.row-unread td:first-child { box-shadow: inset 3px 0 0 var(--cyan); }

/* ==========================================================================
   BUTTONS / BADGES / FORMULARE
   ========================================================================== */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 36px;
    padding: 8px 18px;
    border-radius: 8px 8px 8px var(--r-cut);
    background: linear-gradient(135deg, rgba(0, 212, 255, 0.18), rgba(59, 130, 246, 0.18));
    color: var(--cyan);
    text-decoration: none;
    border: 1px solid var(--border-strong);
    cursor: pointer;
    font-size: 0.82rem;
    font-weight: 700;
    font-family: var(--font-body);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    transition: box-shadow .2s, transform .2s, background .2s, color .2s;
}
.btn:hover {
    box-shadow: var(--glow-cyan);
    transform: translateY(-1px);
    color: #eaf9ff;
}
.btn:active { transform: translateY(0); }

.btn-secondary {
    background: rgba(109, 132, 163, 0.12);
    color: var(--text);
    border-color: rgba(109, 132, 163, 0.4);
}
.btn-secondary:hover { box-shadow: 0 0 10px rgba(109, 132, 163, 0.4); }

.btn-danger {
    background: rgba(255, 77, 109, 0.14);
    color: var(--danger);
    border-color: rgba(255, 77, 109, 0.45);
}
.btn-danger:hover { box-shadow: 0 0 10px rgba(255, 77, 109, 0.5); }

.btn-outline { background: transparent; color: var(--cyan); border: 1px solid var(--border-strong); }

/* Ohne diese Regel sieht ein gesperrter Knopf aus wie ein bereiter -- beim
   Sammelloeschen im Inventar waere das die falsche Einladung. */
.btn:disabled, .btn:disabled:hover {
    opacity: 0.4;
    cursor: not-allowed;
    box-shadow: none;
}

.badge {
    padding: 3px 10px;
    border-radius: 4px;
    font-size: 0.7rem;
    font-weight: 600;
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    background: rgba(109, 132, 163, 0.15);
    color: var(--muted);
    border: 1px solid rgba(109, 132, 163, 0.3);
}
.badge-online { background: rgba(45, 212, 167, 0.12); color: var(--success); border-color: rgba(45, 212, 167, 0.4); }
.badge-sold   { background: rgba(59, 130, 246, 0.12); color: #7db4ff; border-color: rgba(59, 130, 246, 0.4); }
.badge-draft  { background: rgba(255, 194, 71, 0.12); color: var(--warn); border-color: rgba(255, 194, 71, 0.4); }
.badge-ok     { background: rgba(45, 212, 167, 0.12); color: var(--success); border-color: rgba(45, 212, 167, 0.4); }

form label {
    display: block;
    margin-top: 12px;
    margin-bottom: 4px;
    font-size: 0.74rem;
    font-weight: 600;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.12em;
}

/* password und email standen hier lange nicht drin. Folge: jedes Passwortfeld
   der App (Anmeldung, Passwort ändern, Benutzerverwaltung) blieb ein weißer
   Browser-Kasten mit schwarzer Schrift auf dunklem Grund -- auf der Anmelde-
   seite der einzige helle Fleck überhaupt.
   [type=search] gehört bewusst NICHT dazu: die Topbar-Suche bringt ihre eigene
   Gestaltung mit (.top-suche input), steht aber weiter oben im Stylesheet und
   würde bei gleicher Spezifität von hier aus überschrieben. */
input[type=text], input[type=password], input[type=email],
input[type=number], input[type=date], input[type=file],
select, textarea {
    width: 100%;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: 8px 8px 8px var(--r-cut);
    font-size: 0.95rem;
    font-family: var(--font-body);
    background: rgba(4, 9, 17, 0.6);
    color: var(--text);
    transition: border-color .18s, box-shadow .18s;
}
input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--border-strong);
    box-shadow: 0 0 0 3px rgba(0, 212, 255, 0.12), var(--glow-cyan);
}
input::placeholder, textarea::placeholder { color: rgba(109, 132, 163, 0.6); }

textarea { min-height: 100px; }

.checkbox-group label {
    display: inline-block;
    margin-right: 16px;
    font-weight: 500;
    color: var(--text);
    text-transform: none;
    letter-spacing: 0.02em;
    font-size: 0.92rem;
}
.checkbox-group input { width: auto; margin-right: 6px; accent-color: var(--cyan); }

.warning-box {
    background: rgba(255, 158, 61, 0.08);
    border: 1px solid rgba(255, 158, 61, 0.4);
    color: var(--orange);
    padding: 14px 16px;
    border-radius: 10px 10px 10px var(--r-cut);
    font-size: 0.9rem;
    margin-bottom: 16px;
}

.section-title {
    font-family: var(--font-head);
    font-size: 0.86rem;
    font-weight: 700;
    margin-bottom: 14px;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--cyan);
    display: flex;
    align-items: center;
    gap: 10px;
}
.section-title::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg, rgba(0, 212, 255, 0.35), transparent);
}

/* ==========================================================================
   KUNDEN-CHAT
   ========================================================================== */

.chat-draft {
    border: 1px solid var(--border);
    border-left: 3px solid var(--cyan);
    border-radius: 8px;
    padding: 12px 14px;
    margin-bottom: 14px;
    background: rgba(0, 212, 255, 0.04);
}

.chat-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 0.9rem;
    margin-bottom: 8px;
}

.chat-reason {
    background: rgba(255, 194, 71, 0.1);
    color: var(--warn);
    border: 1px solid rgba(255, 194, 71, 0.3);
    border-radius: 6px;
    padding: 6px 10px;
    font-size: 0.82rem;
    margin-bottom: 8px;
}

.chat-line { display: flex; margin-bottom: 10px; }
.chat-line.von-kunde { justify-content: flex-start; }
.chat-line.von-mir { justify-content: flex-end; }

.chat-bubble {
    max-width: 70%;
    padding: 10px 13px;
    border-radius: 12px;
    font-size: 0.92rem;
    white-space: pre-wrap;
    word-break: break-word;
    background: rgba(109, 132, 163, 0.12);
    border: 1px solid rgba(109, 132, 163, 0.2);
}
.chat-line.von-mir .chat-bubble {
    background: rgba(0, 212, 255, 0.09);
    border-color: var(--border);
}
.chat-bubble.offen {
    background: rgba(255, 158, 61, 0.07);
    border: 1px dashed rgba(255, 158, 61, 0.5);
}

.chat-stamp { font-size: 0.72rem; color: var(--muted); margin-top: 4px; font-family: var(--font-mono); }

.inline-form { display: inline-block; margin-top: 8px; }
.muted { color: var(--muted); font-size: 0.85rem; }

.flex-between { display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap; }

/* Aktionsleiste einer Seite. Seit der Seitentitel oben in der Topbar steht,
   stehen hier nur noch die Buttons — deshalb rechtsbündig statt space-between. */
.page-actions { display: flex; justify-content: flex-end; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Leerzustand: ruhiger Platzhalter statt nackter Textzeile */
.empty {
    padding: 22px 16px;
    text-align: center;
    color: var(--muted);
    font-size: 0.9rem;
    border: 1px dashed var(--border);
    border-radius: 10px 10px 10px var(--r-cut);
    background: rgba(0, 212, 255, 0.02);
}
.mt-16 { margin-top: 16px; }
.mt-24 { margin-top: 26px; }
.text-muted { color: var(--muted); font-size: 0.85rem; }
.photo-thumb {
    width: 60px; height: 60px;
    object-fit: cover;
    border-radius: 6px;
    margin-right: 6px;
    cursor: zoom-in;
    border: 1px solid var(--border);
    transition: box-shadow .2s, transform .2s;
}
.photo-thumb:hover { box-shadow: var(--glow-cyan); transform: scale(1.05); }

/* ==========================================================================
   LIGHTBOX
   ========================================================================== */

.lightbox-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(2, 5, 10, 0.92);
    z-index: 1000;
    align-items: center;
    justify-content: center;
    padding: 32px;
    cursor: zoom-out;
    backdrop-filter: blur(6px);
}
.lightbox-overlay.open { display: flex; }
.lightbox-overlay img {
    max-width: 100%;
    max-height: 100%;
    border-radius: 8px;
    border: 1px solid var(--border-strong);
    box-shadow: 0 0 60px rgba(0, 212, 255, 0.15), 0 8px 32px rgba(0, 0, 0, 0.6);
}

.lightbox-close {
    position: absolute;
    top: 20px; right: 28px;
    color: var(--cyan);
    font-size: 2rem;
    line-height: 1;
    cursor: pointer;
    user-select: none;
    text-shadow: var(--glow-cyan);
}

/* ==========================================================================
   VERSANDSCHEINE
   ========================================================================== */

.label-pages { display: flex; flex-wrap: wrap; gap: 20px; }

.label-page {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: 8px 8px 8px var(--r-cut);
    background: var(--panel);
}
.label-crop {
    position: relative;
    display: block;
    width: 240px;
    flex: 0 0 auto;
    cursor: crosshair;
    touch-action: none;
    user-select: none;
    background: #fff;   /* Labels bleiben weiß — Druckvorlage */
    border: 1px solid var(--border-strong);
    line-height: 0;
}
.label-crop img { width: 100%; height: auto; display: block; pointer-events: none; }
.crop-box {
    position: absolute;
    border: 2px solid var(--cyan);
    background: rgba(0, 212, 255, 0.15);
    pointer-events: none;
    box-shadow: var(--glow-cyan);
}
.label-page-meta {
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 0.85rem;
    min-width: 90px;
}
.label-page-meta label { margin: 0; font-weight: 500; text-transform: none; letter-spacing: 0.02em; }
.label-page-meta input { width: auto; margin-right: 6px; }
.label-result {
    width: 120px; height: 180px;
    object-fit: contain;
    background: #fff;
    border: 1px solid var(--border-strong);
    border-radius: 4px;
    cursor: zoom-in;
    margin: 0;
}
.label-select { display: inline-flex; align-items: center; gap: 8px; margin: 0; }
.label-select input { width: auto; margin: 0; }
.label-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.print-frame {
    width: 100%;
    height: 70vh;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--panel-solid);
}

/* ==========================================================================
   DIENST-AMPEL (Dashboard) — vorher Inline-Style im Template
   ========================================================================== */

.dienst-liste { display: flex; flex-direction: column; gap: 8px; }
.dienst-zeile { display: flex; align-items: center; gap: 10px; }
.dienst-punkt { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.dienst-gruen { background: var(--success); box-shadow: 0 0 6px rgba(45, 212, 167, .6); }
.dienst-gelb  { background: var(--warn);    box-shadow: 0 0 6px rgba(255, 194, 71, .6); }
.dienst-rot   { background: var(--danger);  box-shadow: 0 0 6px rgba(255, 77, 109, .6); }
/* grau = Agent läuft nur auf Abruf, Stille ist kein Fehler */
.dienst-grau  { background: var(--muted); opacity: .7; }

/* Agenten-Zentrale: Karten-Raster mit Mini-Log pro Agent */

/* Kopfzeile: Titel links, Zählwerk rechts. Auf schmalen Karten rutscht das
   Zählwerk unter den Titel, statt ihn zu quetschen. */
.kz-kopf {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-4);
}
.kz-kopf .section-title { margin-bottom: 0; }
.kz-bilanz {
    margin-left: auto;
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3);
    font-size: 0.78rem;
    color: var(--muted);
}
.kz-zahl { display: inline-flex; align-items: baseline; gap: 5px; }
.kz-zahl b {
    font-family: var(--font-mono);
    font-size: 0.95rem;
    font-variant-numeric: tabular-nums;
}
.kz-zahl.ampel-rot b   { color: var(--danger); }
.kz-zahl.ampel-gelb b  { color: var(--warn); }
.kz-zahl.ampel-gruen b { color: var(--success); }
.kz-zahl.ampel-grau b  { color: var(--muted); }

.agenten-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 14px; }

/* Die Karte ist ein Link auf den Chat mit genau diesem Agenten. Deshalb hier
   die Link-Deko zurücknehmen -- die Karte soll wie eine Kachel wirken, nicht
   wie ein blauer Textlink. */
.agent-karte {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border);
    border-left: 2px solid var(--muted);
    border-radius: 10px 10px 10px var(--r-cut);
    padding: 13px 14px;
    background: rgba(0, 212, 255, 0.02);
    color: inherit;
    text-decoration: none;
    transition: border-color var(--t-normal), background var(--t-normal),
                transform var(--t-normal);
}
.agent-karte:hover {
    background: rgba(0, 212, 255, 0.05);
    border-color: var(--border-strong);
    transform: translateY(-1px);
}
.agent-karte:focus-visible {
    outline: 2px solid var(--border-strong);
    outline-offset: 2px;
}
.agent-karte.ampel-gruen { border-left-color: var(--success); }
.agent-karte.ampel-gelb  { border-left-color: var(--warn); }
.agent-karte.ampel-rot   { border-left-color: var(--danger); }
.agent-karte.ampel-grau  { border-left-color: var(--muted); }

.agent-kopf { display: flex; align-items: center; gap: 9px; }
.agent-kopf b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Zustand zusätzlich als Wort: die Ampelfarbe allein ist bei Rot-Grün-Schwäche
   keine verlässliche Unterscheidung. */
.agent-status {
    margin-left: auto;
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.12em;
    padding: 2px 7px;
    border-radius: 4px;
    border: 1px solid;
    text-transform: uppercase;
}
.ampel-gruen .agent-status { color: var(--success); border-color: rgba(45, 212, 167, .35); background: rgba(45, 212, 167, .08); }
.ampel-gelb  .agent-status { color: var(--warn);    border-color: rgba(255, 194, 71, .35); background: rgba(255, 194, 71, .08); }
.ampel-rot   .agent-status { color: var(--danger);  border-color: rgba(255, 77, 109, .35); background: rgba(255, 77, 109, .08); }
.ampel-grau  .agent-status { color: var(--muted);   border-color: rgba(109, 132, 163, .3); background: rgba(109, 132, 163, .08); }

.agent-detail { margin: 7px 0 0; line-height: 1.45; }

.agent-log {
    list-style: none;
    margin: 10px 0 0;
    padding: 9px 0 0;
    border-top: 1px dashed var(--border);
    font-size: 0.8rem;
    line-height: 1.5;
}
.agent-log li {
    display: flex;
    gap: 8px;
    margin-top: 3px;
    color: var(--text);
}
/* Nur der Text kürzt -- die Uhrzeit bleibt immer vollständig lesbar. */
.agent-log li > span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agent-zeit { flex: 0 0 auto; color: var(--muted); font-family: var(--font-mono); font-size: 0.72rem; }

/* ==========================================================================
   MOBILE — PWA vom Home-Bildschirm
   ========================================================================== */

@media (max-width: 800px) {
    .app { flex-direction: column; }

    /* Sidebar wird zur festen Bottom-Tab-Bar wie in einer nativen App:
       Icons oben, Label darunter, horizontal wischbar, Daumen-erreichbar.
       Vorher klebte sie oben und fraß wertvolle Bildschirmhöhe. */
    .sidebar {
        position: fixed;
        left: 0; right: 0; bottom: 0;
        top: auto;
        width: 100%;
        height: auto;
        flex-direction: row;
        align-items: stretch;
        gap: 0;
        padding: 6px 8px calc(6px + env(safe-area-inset-bottom));
        border-right: none;
        border-top: 1px solid var(--border);
        background: rgba(6, 11, 22, 0.97);
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-x: contain;
        z-index: 100;
        scrollbar-width: none;
        box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.45);
    }
    .sidebar::-webkit-scrollbar { display: none; }
    /* Gruppentitel gehören in die senkrechte Liste. In der waagerechten
       Bottom-Nav wären sie nur Wörter zwischen den Icons. */
    .side-brand, .side-foot, .side-gruppe { display: none; }

    .side-nav { flex-direction: row; gap: 2px; }
    .side-nav a {
        flex-direction: column;
        justify-content: center;
        gap: 3px;
        min-width: 68px;
        min-height: 48px;          /* komfortables Touch-Ziel */
        padding: 6px 8px;
        font-size: 0.6rem;
        letter-spacing: 0.04em;
        text-align: center;
        border-radius: 10px;
        white-space: nowrap;
    }
    .side-nav a .ico { width: auto; font-size: 1.15rem; }
    .side-nav a:hover { transform: none; background: none; }
    .side-nav a.active::before { display: none; }
    .side-nav a.active { background: rgba(0, 212, 255, 0.12); border-color: transparent; }

    /* Topbar: kompakt, ohne Blur (am Handy die teuerste Einzeloperation).
       Uhr raus — die Statusleiste des Handys zeigt die Zeit ohnehin. */
    .topbar {
        flex-wrap: wrap;
        gap: 10px;
        padding: 10px 12px;
        padding-top: calc(10px + env(safe-area-inset-top));
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(7, 13, 24, 0.97);
    }
    .top-right { gap: 8px; }
    .top-time { display: none; }
    .top-status .lbl { display: none; }  /* Pulspunkt genügt */
    .account-switcher select { min-height: 44px; max-width: 44vw; }
    /* Trenner weg: bei acht Pixeln Abstand stehen die Striche dichter an den
       Symbolen als die Symbole aneinander. */
    .top-right > .top-status,
    .top-right > .account-switcher,
    .top-right > .top-profil { border-left: none; padding-left: 0; }
    /* Ampel und Glocke bleiben -- gerade am Handy will man sehen, ob ein
       Agent hängt, ohne die Seite Agenten zu öffnen. Nur der Text fällt weg. */
    .top-agenten { padding: 5px 8px; }
    .top-glocke, .top-agenten { min-height: 34px; }
    /* Größerer Tippbereich; das Einklappen auf das Symbol erledigt bereits
       die 1050px-Abfrage weiter oben. */
    .top-abmelden { padding: 8px 10px; }

    /* Unten Platz lassen, damit die Tab-Bar nichts verdeckt */
    .container { padding: 14px 12px calc(84px + env(safe-area-inset-bottom)); }

    .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    .stat { padding: 13px 14px; }
    .card { padding: 16px 14px; }
    .hud-row { grid-template-columns: 1fr; }
    .hud-ring { width: 72px; height: 72px; }

    /* Hover-Effekte sind Touch-Ballast: lösen beim Tippen kurz aus und
       machen das Scrollen unruhig. */
    .stat:hover, .card:hover, .btn:hover, .photo-thumb:hover { transform: none; box-shadow: none; }

    table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    /* 16px verhindert, dass iOS beim Antippen eines Feldes hineinzoomt. */
    input, select, textarea, button, .btn { font-size: 16px; }
    /* komfortable Touch-Ziele */
    .btn { min-height: 44px; }
    td.cell-text { max-width: none; }
    .flex-between { flex-wrap: wrap; gap: 8px; }
    .print-frame { height: 55vh; }
}

/* ==========================================================================
   AMBIENT — „das System lebt"
   Gehört zu static/ambient.js. Alle Anzeigen stammen aus echten
   Browser-Ereignissen, nicht aus erfundenen Werten.
   ========================================================================== */

/* ---- Cursor-Licht: weicher Schein folgt dem Zeiger über die Panels ---- */
.card {
    background:
        radial-gradient(260px circle at var(--mx, -300px) var(--my, -300px), rgba(0, 212, 255, 0.07), transparent 62%),
        var(--panel);
}
.stat {
    background:
        radial-gradient(200px circle at var(--mx, -300px) var(--my, -300px), rgba(0, 212, 255, 0.09), transparent 60%),
        var(--panel);
}
.stat.accent-orange {
    background:
        radial-gradient(200px circle at var(--mx, -300px) var(--my, -300px), rgba(255, 158, 61, 0.10), transparent 60%),
        var(--panel);
}
.stat.accent-green {
    background:
        radial-gradient(200px circle at var(--mx, -300px) var(--my, -300px), rgba(45, 212, 167, 0.10), transparent 60%),
        var(--panel);
}

/* ---- Boot-Sweep beim Seitenaufbau ---- */
.boot-sweep {
    position: fixed;
    left: 0; right: 0; top: 0;
    height: 26vh;
    z-index: 900;
    pointer-events: none;
    background: linear-gradient(180deg,
        transparent 0%,
        rgba(0, 212, 255, 0.03) 44%,
        rgba(0, 212, 255, 0.20) 50%,
        rgba(0, 212, 255, 0.03) 56%,
        transparent 100%);
    animation: bootSweep .6s cubic-bezier(.4, 0, .2, 1) forwards;
}
@keyframes bootSweep {
    from { transform: translateY(-26vh); opacity: 1; }
    to   { transform: translateY(100vh); opacity: 0; }
}

/* ---- Statuszustände in der Topbar ---- */
.top-status .lbl { transition: color .3s; }
.top-status.is-idle { color: var(--muted); }
.top-status.is-idle .pulse-dot {
    background: var(--muted);
    box-shadow: 0 0 6px var(--muted);
    animation-duration: 4.5s;
}
.top-status.is-offline { color: var(--danger); }
.top-status.is-offline .pulse-dot {
    background: var(--danger);
    box-shadow: 0 0 6px var(--danger);
    animation-duration: .9s;
}

/* ---- SYS-LOG in der Sidebar ---- */
.side-foot { display: flex; flex-direction: column; gap: 10px; }
.sys-log {
    font-family: var(--font-mono);
    font-size: 0.6rem;
    line-height: 1.7;
    letter-spacing: 0.06em;
    color: var(--muted);
    min-height: 2.1em;
}
.sys-log-line {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sys-log-line::before { content: "› "; opacity: 0.5; }
.sys-ver { font-size: 0.62rem; opacity: 0.45; }

/* ==========================================================================
   ANMELDUNG — eigenständige Seite ohne Sidebar und Topbar
   Wer hier landet, ist nicht angemeldet und soll nichts sehen, was er nicht
   sehen darf. Die Seite trägt deshalb das Layout allein und muss den HUD-Ton
   des Rests aus eigener Kraft treffen.
   ========================================================================== */

.login-seite {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    margin: 0;
    padding: var(--sp-5) var(--sp-4);
}

/* Feste Breite statt Prozent: das Formular hat zwei kurze Felder, in die
   Fläche gezogen wirkt es verloren. */
.login-box {
    width: 100%;
    max-width: 380px;
    animation: rise .45s ease both;
}

/* ---- Markenkopf: derselbe Schriftzug wie in der Sidebar ---- */
.login-marke {
    font-family: var(--font-head);
    font-weight: 900;
    font-size: 1.5rem;
    letter-spacing: 0.2em;
    color: var(--text-strong);
    text-align: center;
    text-shadow: var(--glow-cyan);
    /* Das Sperren schiebt optisch nach rechts; der Ausgleich zentriert ihn. */
    text-indent: 0.2em;
}
.login-marke .cursor {
    color: var(--cyan);
    animation: blink 1.1s steps(1) infinite;
}

/* Kicker unter dem Namen. Bewusst eine reine Beschriftung und keine
   erfundene Statusmeldung -- die Seite kennt vor der Anmeldung nichts,
   worüber sie berichten könnte. */
.login-kicker {
    font-family: var(--font-mono);
    font-size: 0.6rem;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--muted);
    text-align: center;
    margin-top: var(--sp-2);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
}
/* Zwei Linien, die den Kicker einfassen: gibt dem Kopf einen Abschluss,
   ohne eine weitere Farbe einzuführen. */
.login-kicker::before,
.login-kicker::after {
    content: "";
    height: 1px;
    width: 34px;
    background: linear-gradient(90deg, transparent, var(--border-strong));
}
.login-kicker::after { transform: scaleX(-1); }

.login-box .card { margin-top: var(--sp-5); margin-bottom: var(--sp-3); }

/* Das erste Feld im Formular bringt sonst seinen 12px-Rand von form label
   mit und reißt eine Lücke unter die Kartenkante. */
.login-box form label:first-of-type { margin-top: 0; }

/* Exakt 16px, nicht die 0.95rem der übrigen Formulare: iOS Safari zoomt beim
   Antippen automatisch in die Seite, sobald ein Feld kleiner als 16px schreibt.
   Die Anmeldeseite hat keine Navigation, aus der man sich wieder herauszoomen
   könnte, und die App läuft am iPhone vom Home-Bildschirm. */
.login-box input[type="text"],
.login-box input[type="password"] {
    font-size: 16px;
    min-height: 42px;
}

.login-box .btn {
    width: 100%;
    margin-top: var(--sp-5);
    /* Etwas höher als der Standardknopf: er ist das einzige Ziel der Seite. */
    min-height: 42px;
    letter-spacing: 0.16em;
}

/* Erklärtext der Ersteinrichtung. */
.login-hinweis {
    font-size: 0.86rem;
    line-height: 1.5;
    color: var(--muted);
    margin: 0 0 var(--sp-4);
    padding-bottom: var(--sp-4);
    border-bottom: 1px solid var(--border);
}
.login-hinweis strong { color: var(--text); }

/* Fußzeile: greift die Systemkennung aus der Sidebar auf, damit die
   Anmeldeseite erkennbar zur selben Anwendung gehört. */
.login-fuss {
    text-align: center;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.14em;
    color: var(--muted);
    opacity: 0.5;
}

/* Auf kleinen Geräten trägt die Karte die Seite allein -- der Rahmen um den
   Rahmen (Seitenpolster plus Kartenrand) wird dort zu eng. */
@media (max-width: 420px) {
    .login-seite { padding: var(--sp-4) var(--sp-3); }
    .login-marke { font-size: 1.25rem; letter-spacing: 0.16em; }
    .login-box .card { padding: var(--sp-4); }
}

/* Reduzierte Bewegung respektieren */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ---------- Chancen ---------- */

.chancen-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
}

/* Acht Spalten passen auf kein Telefon, und die allgemeine Tabellenregel
   arbeitet hier gegen .table-wrap: `width: 100%` presst die Tabelle in den
   Rahmen, `overflow: hidden` schneidet die herausragenden Spalten (Marge,
   Archivieren) danach ab. Der Rahmen bekommt nichts zu scrollen, weil die
   Tabelle formal hineinpasst -- die Spalten sind schlicht weg. Mindestbreite
   plus sichtbarer Ueberlauf geben dem Rahmen die echte Breite zu scrollen. */
.chancen-tabelle { min-width: 820px; overflow: visible; }

.chancen-abteilungen {
    display: flex;
    gap: var(--sp-2);
    flex-wrap: wrap;
    margin-top: var(--sp-3);
}

.abteilung {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--border);
    border-radius: 8px;
    text-decoration: none;
    color: var(--muted);
}

.abteilung-aktiv { border-color: var(--cyan); color: var(--text); }
.abteilung-still { opacity: 0.6; cursor: default; }

.abteilung-zahl {
    font-variant-numeric: tabular-nums;
    background: rgba(255, 255, 255, 0.06);
    border-radius: 6px;
    padding: 0 var(--sp-2);
}

/* Der Ausloeser sagt, WARUM die Ware knapp wird -- drei sehr verschiedene
   Geschaefte. Farblich getrennt, weil man beim Ueberfliegen der Liste sofort
   erkennen will, ob eine Frist laeuft (Nachfrage) oder nicht (Angebot endet). */
.ausloeser {
    display: inline-block;
    font-size: 0.75rem;
    padding: 1px var(--sp-2);
    border-radius: 6px;
    border: 1px solid currentColor;
    white-space: nowrap;
}

.ausloeser-nachfrage { color: var(--warn); }
.ausloeser-angebot_endet { color: var(--success); }
.ausloeser-produktion_knapp { color: var(--cyan); }

.chancen-filter {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex-wrap: wrap;
}

.chancen-filter input[type="number"] { width: 6rem; }

/* Bestseller-Seite: die Verkaufsquote ist die Kernzahl -- heisse Gruppen
   leuchten, duenne Stichproben treten zurueck, statt mit einer Zahl zu
   protzen, die nur Rauschen ist. */
.bs-filter label { white-space: nowrap; }
.bs-feld { display: inline-flex; align-items: center; gap: 0.45rem; }
/* Die globale 100%-Breite der Felder wuerde aus der Filterzeile einen
   Turm machen: hier sitzen Feld und Beschriftung nebeneinander. */
.bs-filter select, .bs-filter input[type="text"] { width: auto; min-width: 9rem; }
.bs-filter input[type="number"] { width: 5.5rem; }
.bs-filter input[type="checkbox"] { width: auto; margin-right: 0.3rem; }
.bs-quote { font-weight: 700; }
.bs-heiss { color: var(--success); text-shadow: 0 0 10px rgba(45, 212, 167, 0.25); }
.bs-schwach { color: var(--muted); font-weight: 500; }
.bs-warn { color: var(--warn); }

/* Der Score ist die wichtigste Zahl der Seite -- er soll aus der Tabelle
   herausstechen, ohne dass man die Legende nachschlagen muss. */
.chance-score {
    display: inline-block;
    min-width: 2.5rem;
    padding: 0.15rem 0.5rem;
    border-radius: 6px;
    border: 1px solid transparent;
    font-weight: 700;
    text-align: center;
}

.stufe-extrem      { background: rgba(255, 77, 109, 0.15); color: var(--danger); border-color: rgba(255, 77, 109, 0.45); }
.stufe-hoch        { background: rgba(255, 194, 71, 0.15); color: var(--warn);   border-color: rgba(255, 194, 71, 0.45); }
.stufe-interessant { background: rgba(45, 212, 167, 0.13); color: var(--success); border-color: rgba(45, 212, 167, 0.4); }
.stufe-watchlist   { background: rgba(109, 132, 163, 0.13); color: var(--muted); border-color: rgba(109, 132, 163, 0.35); }
.stufe-ignorieren  { background: transparent; color: var(--muted); border-color: rgba(109, 132, 163, 0.25); }

/* Unbestaetigte Chancen: sichtbar, aber zurueckgenommen. Sie stehen ohnehin
   am Ende der Liste -- das Ausgrauen verhindert, dass ein alter Score beim
   Ueberfliegen noch wie ein aktueller Befund wirkt. */
.chance-veraltet { opacity: 0.55; }
.chance-veraltet:hover { opacity: 1; }

/* ==========================================================================
   NOTIZEN
   Der Notizblock zwischen Mensch und Agenten (templates/notizen.html).
   Zwei Spalten, in jeder eine Liste von Kacheln -- keine Tabelle, weil eine
   Notiz aus Fliesstext besteht und Zeilen sonst unterschiedlich hoch werden.
   ========================================================================== */

.notiz-spalten {
    display: grid;
    /* Ab ~760px Gesamtbreite nebeneinander, darunter untereinander. Eine
       Notizkachel unter 340px wird durch die Aktionsknöpfe unleserlich. */
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: var(--sp-4);
    align-items: start;
}

.notiz-liste {
    list-style: none;
    margin: var(--sp-4) 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.notiz {
    background: var(--surface-3);
    border: 1px solid var(--border);
    border-radius: var(--r-md) var(--r-md) var(--r-md) var(--r-cut);
    padding: var(--sp-3);
}

/* Dringend wird über einen Balken links markiert, nicht nur über die Farbe
   des Chips -- dieselbe Überlegung wie bei tr.row-unread. */
.notiz.ist-dringend { box-shadow: inset 3px 0 0 var(--danger); }

.notiz-kopf {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--sp-2);
}

.notiz-titel {
    color: var(--text-strong);
    font-weight: 600;
    font-size: 1rem;
    text-decoration: none;
    line-height: 1.3;
}
.notiz-titel:hover { text-shadow: var(--glow-cyan); }

.notiz-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-1) var(--sp-3);
    margin-top: var(--sp-2);
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--muted);
}

.notiz-faellig { color: var(--warn); }

/* Der Text kommt aus einem <textarea>: Zeilenumbrüche sind Absicht. */
.notiz-text {
    white-space: pre-wrap;
    margin: var(--sp-2) 0 0;
    line-height: 1.45;
    font-size: 0.93rem;
}

.notiz-aktionen {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2);
    margin-top: var(--sp-3);
}
.notiz-aktionen form {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin: 0;
}
/* Die Knöpfe stehen zu mehreren in einer Zeile -- in voller Größe würden sie
   die Kachel dominieren, die die Notiz selbst tragen soll. */
.notiz-aktionen .btn {
    min-height: 30px;
    padding: 5px 12px;
    font-size: 0.7rem;
    letter-spacing: 0.08em;
}
/* Ein Formular mit Freitextfeld bekommt eine eigene Zeile. Zwischen den
   Knoepfen eingereiht ergaebe die Leiste sonst eine einzige lange Wurst, in
   der man weder Feld noch Knopf zuordnen kann. */
.notiz-aktionen .notiz-aktion-breit { flex: 1 1 100%; }

/* Freitextfelder in der Aktionsleiste (Ergebnis, Begründung) dürfen nicht die
   volle Breite der Formularregel beanspruchen. */
.notiz-aktionen input[type=text] {
    width: auto;
    min-width: 12rem;
    flex: 1 1 12rem;
    padding: 5px 10px;
    font-size: 0.85rem;
}

/* Dringlichkeits-Chip. Gleiche Bauform wie .badge, aber eigene Klasse: die
   Stufe ist eine Skala und keine Statusmarke. */
.prio {
    padding: 2px 9px;
    border-radius: 4px;
    border: 1px solid rgba(109, 132, 163, 0.3);
    background: rgba(109, 132, 163, 0.12);
    color: var(--muted);
    font-family: var(--font-mono);
    font-size: 0.66rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    white-space: nowrap;
}
.prio-1 { background: rgba(255, 77, 109, 0.14); color: var(--danger); border-color: rgba(255, 77, 109, 0.45); }
.prio-3 { opacity: 0.7; }

.notiz-formzeile {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 0 var(--sp-4);
}

.notiz-faden {
    list-style: none;
    margin: var(--sp-4) 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.notiz-eintrag {
    border: 1px solid var(--border);
    border-left: 3px solid rgba(109, 132, 163, 0.4);
    border-radius: var(--r-sm);
    background: rgba(255, 255, 255, 0.02);
    padding: var(--sp-2) var(--sp-3);
}
/* Wer geschrieben hat, soll man am Rand erkennen, ohne die Zeile zu lesen. */
.notiz-eintrag.vom-agenten { border-left-color: var(--cyan); }
.notiz-eintrag .notiz-meta { margin-top: 0; }

/* <summary> traegt .section-title -- und .section-title ist display:flex,
   was in Chrome den eingebauten Aufklapp-Pfeil verschluckt. Ohne Ersatz sieht
   die Zeile aus wie eine gewoehnliche Ueberschrift, die man nicht anklickt.
   Also eigener Pfeil davor; die Abschlusslinie (::after) bleibt, damit die
   Zeile wie jede andere Abschnittsueberschrift aussieht. */
.notiz-archiv-kopf { cursor: pointer; list-style: none; }
.notiz-archiv-kopf::-webkit-details-marker { display: none; }
.notiz-archiv-kopf::before {
    content: "\25B8";
    font-size: 0.9rem;
    line-height: 1;
    transition: transform var(--t-schnell);
}
details[open] > .notiz-archiv-kopf::before { transform: rotate(90deg); }

/* ==== Postfach ==== */
/* Die Chat-Uebersicht war eine Tabelle, deren einziger Einstieg ein winziges
   "oeffnen" am rechten Zeilenende war -- am Handy kaum zu treffen und in der
   Bottom-Nav-Ansicht halb aus dem Bild gescrollt. Seit 23.08.2026 ist jede
   Unterhaltung eine Karte, die als Ganzes der Link ist.
   Praefix pf-, damit diese Klassen den bestehenden chat-* Bausteinen (die der
   Gespraechsfaden weiterverwendet) nicht in die Quere kommen; ergaenzt wird
   nur, was fehlt. */

.pf-liste { display: flex; flex-direction: column; gap: var(--sp-2); }

.pf-karte {
    display: flex;
    gap: var(--sp-3);
    align-items: flex-start;
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--border);
    /* Der linke Streifen ist immer da, nur meist unsichtbar: faerbte man ihn
       erst bei Bedarf ein, sprangen markierte Karten um 3px in der Breite. */
    border-left: 3px solid transparent;
    border-radius: var(--r-md) var(--r-md) var(--r-md) var(--r-cut);
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
    transition: border-color var(--t-normal), background var(--t-normal);
}
.pf-karte:hover { border-color: var(--border-strong); background: var(--surface-3); }
/* Ohne eigenen Fokusrahmen waere die Karte per Tastatur unsichtbar -- der
   Standardrahmen des Browsers geht auf dem dunklen Grund unter. */
.pf-karte:focus-visible {
    outline: none;
    border-color: var(--border-strong);
    box-shadow: 0 0 0 3px rgba(0, 212, 255, 0.14);
}

/* Zwei Stufen von Dringlichkeit: ein wartender Entwurf ist eine Aufgabe
   (orange wie alle Freigaben der App), eine unbeantwortete Frage nur ein
   Hinweis (cyan). Beides gleich zu faerben wuerde die Aufgabe verstecken. */
.pf-karte-entwurf { border-left-color: var(--warn); }
.pf-karte-offen { border-left-color: var(--cyan); }
/* Erledigtes bleibt lesbar, tritt aber zurueck; beim Hover wieder voll da. */
.pf-karte-erledigt { opacity: 0.55; }
.pf-karte-erledigt:hover { opacity: 1; }

.pf-avatar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: rgba(0, 212, 255, 0.08);
    color: var(--cyan);
    font-family: var(--font-head);
    font-size: 0.95rem;
}

/* min-width:0 ist Pflicht: ohne sie sprengt ein langer Artikeltitel die
   Flexbox, statt sich kuerzen zu lassen. */
.pf-inhalt { flex: 1 1 auto; min-width: 0; }

.pf-zeile { display: flex; align-items: baseline; gap: var(--sp-2); min-width: 0; }

.pf-name {
    font-weight: 700;
    color: var(--text-strong);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pf-zeit {
    margin-left: auto;
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    color: var(--muted);
    white-space: nowrap;
}

.pf-artikelzeile {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--sp-2);
    margin-top: 2px;
    font-size: 0.88rem;
}
.pf-artikel { color: var(--text); overflow-wrap: anywhere; }
.pf-preis { font-family: var(--font-mono); font-size: 0.82rem; color: var(--cyan); }
/* Fehlende Zuordnung wird benannt, nicht geraten -- aber leise. */
.pf-hinweis { color: var(--muted); font-size: 0.8rem; font-style: italic; }

/* Zwei Zeilen Ausschnitt: eine reicht bei Vinted-Nachrichten selten fuer den
   Sinn, drei machen aus der Liste wieder eine Textwand. */
.pf-auszug {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: var(--sp-1);
    font-size: 0.86rem;
    line-height: 1.4;
    color: var(--muted);
}
.pf-sender { color: var(--text); font-weight: 600; }

.pf-marken { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--sp-2); }
.pf-badge-neu {
    background: rgba(0, 212, 255, 0.12);
    color: var(--cyan);
    border-color: rgba(0, 212, 255, 0.4);
}

/* ---- Gespraechsfaden (Detailseite) ---- */

.pf-kopf {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex-wrap: wrap;
    padding-bottom: var(--sp-3);
    margin-bottom: var(--sp-4);
    border-bottom: 1px solid var(--border);
}
.pf-kopf .pf-marken { margin-top: 0; margin-left: auto; }

.pf-faden { display: flex; flex-direction: column; }
/* Der Abstand steht hier zentral, damit Datumstrenner und Blasen denselben
   Rhythmus haben -- die 10px am .chat-line galten nur fuer Blasen. */
.pf-faden .chat-line { margin-bottom: var(--sp-3); }

/* Die Blase begrenzt sich jetzt selbst. Vorher stand die max-width am
   .chat-bubble, wodurch der Zeitstempel darunter ueber die volle Zeilenbreite
   lief und rechts ausgerichtete Nachrichten ihren Stempel links hatten. */
.pf-blase { max-width: 74%; min-width: 0; }
.pf-faden .chat-bubble { max-width: 100%; font-size: 0.95rem; line-height: 1.5; }
.pf-faden .von-mir .chat-stamp { text-align: right; }

/* Eine angeschnittene Ecke an der Sprecherseite: so ist auf einen Blick klar,
   wer redet, auch ohne den Stempel zu lesen. */
.pf-faden .von-kunde .chat-bubble { border-bottom-left-radius: var(--r-cut); }
.pf-faden .von-mir .chat-bubble { border-bottom-right-radius: var(--r-cut); }

/* Ein wartender Entwurf ist kein Verlauf, sondern eine Aufgabe -- er muss
   beim Ueberfliegen auffallen, ohne dass man die Stempelzeile liest. */
.pf-faden .chat-bubble.offen {
    background: rgba(255, 194, 71, 0.09);
    border: 1px solid rgba(255, 194, 71, 0.55);
    box-shadow: 0 0 0 3px rgba(255, 194, 71, 0.06);
}

/* Sprung zum Freigabe-Formular. Als Link im Stempel bzw. als Badge im Kopf --
   in langen Faeden liegt das Formular sonst weit unterhalb des Bildschirms. */
.pf-sprung { text-decoration: none; }
.pf-sprung:hover { text-decoration: underline; }

.pf-tagestrenner {
    align-self: center;
    margin: var(--sp-2) 0 var(--sp-3);
    padding: 2px 12px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: rgba(0, 212, 255, 0.03);
    font-family: var(--font-mono);
    font-size: 0.7rem;
    color: var(--muted);
}

/* Die Freigabe-Karte traegt denselben orangen Rand wie der Entwurf im Faden --
   der Sprung aus dem Stempel soll sichtbar dort landen. */
.pf-freigabe { border-color: rgba(255, 194, 71, 0.35); }
.pf-freigabe .chat-stamp { margin-top: 0; }

/* ---- Artikelzuordnung (Detailseite) ---- */
/* Ein Vorschlag muss als Vorschlag erkennbar bleiben: gestrichelter Rand statt
   voller Karte, damit ihn niemand fuer eine bestehende Zuordnung haelt. */
.pf-vorschlaege { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-4); }

.pf-vorschlag {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex-wrap: wrap;
    padding: var(--sp-3);
    border: 1px dashed var(--border-strong);
    border-radius: var(--r-md) var(--r-md) var(--r-md) var(--r-cut);
    background: rgba(0, 212, 255, 0.03);
}
.pf-vorschlag .btn { margin-left: auto; flex: 0 0 auto; }
/* Die Begruendung ist der eigentliche Inhalt des Vorschlags -- ohne sie waere
   er eine Behauptung, die niemand nachpruefen kann. */
.pf-grund { margin-top: var(--sp-1); font-size: 0.82rem; color: var(--muted); }

@media (max-width: 800px) {
    .pf-karte { padding: var(--sp-3); gap: var(--sp-2); }
    .pf-avatar { width: 32px; height: 32px; font-size: 0.85rem; }
    /* Am Handy ist die Zeile schmal: die Blase darf fast die volle Breite
       nutzen, sonst bleiben von langen Saetzen drei Woerter pro Zeile. */
    .pf-blase { max-width: 88%; }
    /* Im Kopf rutschen die Marken unter Name und Artikel, statt sie zu
       quetschen -- margin-left:auto ergaebe nach dem Umbruch eine leere Zeile. */
    .pf-kopf .pf-marken { margin-left: 0; }
    .pf-vorschlag .btn { margin-left: 0; width: 100%; }
}
