/* Preisschild-Sync — Anbindung an das gemeinsame Design-System
 *
 * Die Identität (Farben, Schrift, Radien, Schatten) kommt aus `tokens.css`,
 * verteilt aus dem Repo sentra-design-system. Hier stehen nur noch ALIASSE:
 * die Namen, die die Seiten dieses Projekts hundertfach benutzen, zeigen auf
 * die --cf-*-Token. Damit sieht SmartPricing aus wie RMS, ohne dass 800
 * Klassen-Attribute angefasst werden mussten.
 *
 * ⚠️ Neue Farben NICHT hier erfinden. Fehlt ein Ton, gehört er ins
 * Design-System (dort ergänzen, VERSION erhöhen, sync.sh) — sonst hat
 * SmartPricing wieder eine eigene Palette. `test_design_system.php` prüft das.
 *
 * Zuordnung nach ROLLE, nicht nach Zahl:
 *   Aktion/CTA  → near-black (--cf-primary), die Signatur des Systems
 *   Akzent      → Blau (--cf-blue-600) für Links, Aktive, Hervorhebung
 *   Marke       → Orange nur als Logo/Kennzeichen, nie als Knopf
 *   Neutrale    → True-Gray statt des früheren blaustichigen Slate
 *
 * Breakpoints (projektweit; keine anderen Werte verwenden):
 *    640px  Telefon quer / kleine Tablets
 *    768px  Tablet hoch — ab hier Tabellen als Karten
 *   1024px  Navigation: darunter Drawer, darüber stehende Seitenleiste
 *           (die Regel dazu liegt im Design-System, nicht hier)
 * CSS-Variablen sind in @media-Bedingungen nicht auswertbar, deshalb stehen die
 * Zahlen dort direkt; diese Liste ist die Referenz.
 *
 * Die Schriften werden im HTML-Head per <link rel=preconnect>+<link> geladen.
 * Ein zusätzlicher @import hier wäre ein zweiter, rendering-blockierender Request.
 */

:root {
    --font-sans: var(--cf-font-sans);
    --font-mono: var(--cf-font-mono);

    /* Brand — die Stufen tragen weiter ihre alten Namen, zeigen aber auf den
       Akzent-Blau-Verlauf des Systems. Das Teal ist damit vollständig weg. */
    --brand-50:  var(--cf-blue-50);
    --brand-100: var(--cf-blue-100);
    --brand-500: var(--cf-blue-500);
    --brand-600: var(--cf-blue-600);
    --brand-700: var(--cf-blue-700);
    /* Der Verlauf war die auffälligste Teal-Fläche (Hero-Band). Er wird
       near-black — dieselbe Rolle, die Sprache des Systems. */
    --brand-gradient: linear-gradient(135deg, var(--cf-gray-900) 0%, var(--cf-gray-800) 100%);
    --success-50:  var(--cf-success-tint);
    --success-100: var(--cf-success-bg);
    --success-500: var(--cf-success);
    --success-600: var(--cf-success-fg);

    --warning-50:  var(--cf-warning-tint);
    --warning-100: var(--cf-warning-bg);
    --warning-500: var(--cf-warning);
    --warning-600: var(--cf-warning-fg);

    --danger-50:  var(--cf-danger-tint);
    --danger-100: var(--cf-danger-bg);
    --danger-500: var(--cf-danger);
    --danger-600: var(--cf-danger-fg);

    --info-50:  var(--cf-blue-50);
    --info-100: var(--cf-info-bg);
    --info-500: var(--cf-info);
    --info-600: var(--cf-info-fg);

    --violet-50:  var(--cf-violet-tint);
    --violet-100: var(--cf-violet-line);
    --violet-500: var(--cf-violet);
    --violet-600: var(--cf-violet-fg);

    /* Neutrale Skala — True-Gray aus dem System, zugeordnet nach Rolle:
       --black Haupttext · --text-muted Nebentext · --gray-200 Ränder.
       Die Zahlen sind die SKALA (Flächen, Ränder, Glyphen), nicht die Rolle. */
    --black:    var(--cf-gray-900);
    --gray-900: var(--cf-gray-800);
    --gray-700: var(--cf-gray-600);
    --gray-500: var(--cf-gray-500);
    --gray-400: var(--cf-gray-400);
    --gray-300: var(--cf-gray-300);
    --gray-200: var(--cf-gray-200);
    --gray-100: var(--cf-gray-100);
    --gray-50:  var(--cf-gray-50);
    --white:    var(--cf-surface);

    /* Nebentext — eine Stufe DUNKLER als der Token des Design-Systems.
       Begründung steht in Zahlen: gray-400 (#A3A3A3) trägt auf Weiß nur
       2,5:1 und war trotzdem die Farbe von .text-muted — also von jedem
       Hilfetext, jeder Zeilenzahl und der Fußzeile im ganzen Portal.
       gray-500 (#737373) reicht mit 4,7:1 auf Weiß knapp, fällt aber auf
       getönten Flächen (--canvas 4,2:1 · --surface-3 4,3:1) wieder unter
       die Schwelle — und genau dort steht die Hälfte unserer Hilfetexte.
       gray-600 trägt auf ALLEN Flächen des Portals (≥7:1) und bleibt
       gegenüber dem fast schwarzen Haupttext klar als zweite Ebene lesbar.
       ⚠️ Nebentext holt seine Farbe von HIER, nicht aus der Skala oben —
       test_contrast.php hält das fest. */
    --text-muted: var(--cf-gray-600);

    /* Seitengrund hinter den weißen Karten — vorher war beides fast weiß */
    --canvas: var(--cf-canvas);

    /* Flächen + Ränder */
    --surface:       var(--cf-surface);
    --surface-2:     var(--cf-gray-50);
    --surface-3:     var(--cf-gray-100);
    --border-soft:   var(--cf-border);
    --border-strong: var(--cf-gray-300);

    /* Alt-Namen — Alias auf die kanonischen Werte oben.
       --accent ist der AKZENT (Blau), nicht die Aktion: Knöpfe holen sich
       ihr near-black direkt aus --cf-primary (cf-btn--primary). */
    --accent:       var(--cf-blue-600);
    --accent-light: var(--cf-blue-50);
    --accent-hover: var(--cf-blue-700);
    --red:         var(--cf-danger-fg);
    --red-light:   var(--cf-danger-tint);
    --radius:    var(--cf-radius-md);
    --radius-lg: var(--cf-radius-xl);

    /* Schatten */
    --shadow-lg: var(--cf-shadow-pop);
    --shadow-sm: 0 1px 2px rgba(10,10,10,0.04);
    --shadow-md: var(--cf-shadow-pop);
    --shadow-xl: var(--cf-shadow-modal);
    --text-sm:  13px;
    --transition: 0.15s ease;
    --ease-out:    cubic-bezier(0.2, 0.8, 0.2, 1);
    --dur-fast: 150ms;
    --dur-base: 220ms;
    --tap-target: 44px;
}

/* Reset */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* 14px-Basis ist Voraussetzung des Design-Systems: die Komponenten in
   components.css rechnen in rem darauf. Für die Seiten dieses Projekts ist die
   Umstellung folgenlos — sie rechnen durchweg in px (nachgemessen: keine
   einzige rem-Angabe in dieser Datei). */
html {
    font-size: 14px;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

body {
    font-family: var(--font-sans);
    font-size: 14px;
    line-height: 1.5;
    color: var(--black);
    background: var(--canvas);
    min-height: 100vh;
}

h1, h2, h3, h4 {
    font-family: var(--font-sans);
    font-weight: 600;
    line-height: 1.25;
    color: var(--black);
    letter-spacing: -0.01em;
}

h1 { font-size: 22px; }
h2 { font-size: 18px; }
h3 { font-size: 16px; }
h4 { font-size: 14px; }

p { color: var(--text-muted); }

a {
    color: var(--accent);
    text-decoration: none;
    transition: color var(--transition);
}
a:hover { color: var(--accent-hover); }

code {
    font-family: var(--font-mono);
    font-size: 12px;
    background: var(--gray-100);
    padding: 2px 6px;
    border-radius: 3px;
    color: var(--gray-700);
}

/* Layout */
.container {
    max-width: 1600px;
    margin: 0 auto;
    padding: 0 clamp(16px, 3vw, 40px);
}

/* ─── Login ─── */


















/* ─── Navigation ───────────────────────────────────────────────
   Die Navigation ist seit 08/2026 der App-Rahmen des Design-Systems
   (.cf-app__side / .cf-app__top in components.css) — eine Seitenleiste, die
   ab 1024px steht und darunter als Drawer hinter dem Menü-Knopf liegt.

   Hier steht dazu bewusst NICHTS mehr: die frühere waagerechte Leiste mit
   Klappmenüs (.navbar, .nav-group…) ist ersatzlos entfallen, samt der
   gemessenen Umschaltpunkte 1060/950px. Sie hingen daran, dass neun bzw. fünf
   Menüpunkte nebeneinander passen mussten — in einer Seitenleiste gibt es
   dieses Platzproblem nicht mehr.

   ⚠️ Der Umschaltpunkt 1024px steht in components.css UND in app.js
   (initMobileNav). Beide Stellen müssen dieselbe Zahl nennen, sonst klappt der
   Drawer beim Vergrößern zu, bevor die Seitenleiste da ist.
   ------------------------------------------------------------- */

/* ─── Stats ─── */
.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 12px;
    margin-bottom: 24px;
}

.stat-card {
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-lg);
    padding: 20px;
    transition: border-color var(--transition);
}

.stat-card:hover { border-color: var(--gray-300); }

.stat-icon { display: none; }

.stat-label {
    font-size: 12px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 500;
    margin-bottom: 6px;
}

.stat-value {
    font-family: var(--font-mono);
    font-size: 28px;
    font-weight: 600;
    color: var(--black);
    line-height: 1;
    letter-spacing: -0.02em;
}

.stat-content { min-width: 0; }

@media (max-width: 900px) { .stat-grid { grid-template-columns: repeat(2, 1fr); }}
@media (max-width: 500px) { .stat-grid { grid-template-columns: 1fr 1fr; }}

/* ─── Cards ─── */
.card {
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 20px;
    border-bottom: 1px solid var(--gray-100);
    font-weight: 600;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.card-body { padding: 20px; }

.card-footer {
    padding: 14px 20px;
    background: var(--gray-50);
    border-top: 1px solid var(--gray-100);
}

/* ─── Forms ─── */
.form-group { margin-bottom: 16px; }

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

/* ─── Toggle ─── */
.toggle {
    position: relative;
    display: inline-flex;
    align-items: center;
    cursor: pointer;
}

.toggle input { position: absolute; opacity: 0; width: 0; height: 0; }

.toggle-slider {
    width: 40px;
    height: 22px;
    background: var(--gray-200);
    border-radius: 11px;
    position: relative;
    transition: background var(--transition);
}

.toggle-slider::before {
    content: '';
    position: absolute;
    width: 16px;
    height: 16px;
    background: var(--white);
    border-radius: 50%;
    top: 3px;
    left: 3px;
    transition: transform var(--transition);
    box-shadow: 0 1px 3px rgba(0,0,0,0.15);
}

.toggle input:checked + .toggle-slider { background: var(--accent); }
.toggle input:checked + .toggle-slider::before { transform: translateX(18px); }

/* ─── Master Toggle ─── */
.master-toggle {
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-lg);
    padding: 16px 20px;
    margin-bottom: 20px;
}

.master-toggle::before { display: none; }

.master-toggle-content h3 {
    font-size: 14px;
    font-weight: 600;
    margin-bottom: 2px;
}

.master-toggle-content p {
    font-size: 13px;
    color: var(--text-muted);
    margin: 0;
}

/* ─── Tabs ─── */
.tabs {
    display: flex;
    gap: 0;
    margin-bottom: 20px;
    border-bottom: 1px solid var(--gray-200);
}

.tab {
    padding: 10px 18px;
    font-size: 13px;
    font-weight: 500;
    font-family: var(--font-sans);
    color: var(--text-muted);
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    cursor: pointer;
    transition: all var(--transition);
}

.tab svg { display: none; }
.tab:hover { color: var(--black); }
.tab.active {
    color: var(--black);
    border-bottom-color: var(--black);
    font-weight: 600;
}

.tab-panel { display: none; }
.tab-panel.active { display: block; }

/* Tabellen auf schmalen Schirmen: das macht cf-table--stack aus dem
   Design-System (Zellrollen: cf-stack-title, cf-stack-block, cf-stack-empty,
   <td> ohne data-label). Der frühere Eigenbau .table-cards stand hier noch
   85 Zeilen lang, obwohl keine Tabelle ihn mehr trug — und mit ihm die
   einzigen Regeln für cell-full/cell-actions, die das Markup weiter ausgab. */

/* ─── Rule Cards ─── */
.rule-card {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 14px 16px;
    background: var(--gray-50);
    border: 1px solid var(--gray-100);
    border-radius: var(--radius);
    margin-bottom: 8px;
    transition: border-color var(--transition);
}

.rule-card:hover { border-color: var(--gray-200); }
.rule-card.disabled { opacity: 0.45; }

.rule-icon { display: none; }

.rule-content { flex: 1; min-width: 0; }

.rule-name {
    font-weight: 600;
    font-size: 14px;
    color: var(--black);
    margin-bottom: 2px;
}

.rule-details {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    font-size: 12px;
    color: var(--text-muted);
    font-family: var(--font-mono);
}

.rule-adjustment {
    font-family: var(--font-mono);
    font-size: 14px;
    font-weight: 600;
    padding: 4px 10px;
    border-radius: 4px;
    white-space: nowrap;
    background: var(--accent-light);
    color: var(--accent);
}

.rule-adjustment.negative { background: var(--red-light); color: var(--red); }

.rule-actions {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* ─── Day Selector ─── */
.day-selector {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

.day-btn {
    width: 40px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius);
    font-size: 12px;
    font-weight: 600;
    font-family: var(--font-mono);
    color: var(--text-muted);
    cursor: pointer;
    transition: all var(--transition);
}

.day-btn:hover { border-color: var(--gray-300); color: var(--black); }
.day-btn input { display: none; }

.day-btn.selected,
.day-btn:has(input:checked) {
    background: var(--black);
    border-color: var(--black);
    color: var(--white);
}

/* ─── Benutzer-Verwaltung: Card-Layout ─── */
.user-card {
    overflow: hidden;
}
.user-card-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
    padding: 16px 20px;
    border-bottom: 1px solid var(--gray-100);
    flex-wrap: wrap;
}
.user-card-identity {
    min-width: 0;
    flex: 1 1 auto;
}
.user-card-name {
    font-size: 15px;
    font-weight: 600;
    color: var(--black);
    margin-bottom: 6px;
    word-break: break-all;
}
.user-card-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 12px;
}
.user-card-actions {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    flex-shrink: 0;
}
/* Auf schmalen Schirmen reichten die Knöpfe über die Karte hinaus und wurden
   von deren overflow:hidden abgeschnitten — sie waren dort nicht erreichbar.
   Darum bekommt die Knopfreihe unterhalb dieser Breite eine eigene Zeile. */
@media (max-width: 768px) {
    .user-card-actions {
        width: 100%;
        flex-shrink: 1;
        padding-top: 12px;
        border-top: 1px solid var(--gray-100);
    }
    .user-card-actions .cf-btn,
    .user-card-actions form { flex: 1 1 auto; }
    .user-card-actions form .cf-btn { width: 100%; }
}
.user-card-pwreset {
    padding: 12px 20px;
    background: var(--gray-50);
    border-bottom: 1px solid var(--gray-100);
}
.user-card-pwreset form {
    flex-wrap: wrap;
}
.user-card-body {
    padding: 16px 20px;
}
.user-card-shops-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    margin-bottom: 8px;
}
.user-card-shops-admin {
    font-size: 13px;
    color: var(--gray-700, var(--black));
}
.shop-permissions-table {
    table-layout: auto;
    font-size: 13px;
}
.shop-permissions-table .shop-name {
    font-weight: 500;
    margin-right: 8px;
}
.shop-permissions-table tr.is-unassigned td {
    color: var(--text-muted);
}
.shop-permissions-table tr.is-unassigned .shop-name {
    color: var(--text-muted);
    font-weight: 400;
}

/* ─── Permission Chips (Benutzer-Verwaltung) ─── */
.permissions-form {
    display: inline-flex;
    gap: 4px;
    align-items: center;
}
.permission-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    /* Die Trefferfläche des Ankreuzfeldes ist dieser Chip — das Kästchen
       selbst misst 13px. Mit 2px Polsterung blieb der ganze Chip darunter,
       und die Rechte eines Benutzers ließen sich am Telefon nur zielend
       umstellen. 6px heben ihn über die 24px der Norm. */
    padding: 6px 10px;
    border: 1px solid var(--gray-200);
    border-radius: var(--radius);
    font-size: 11px;
    color: var(--text-muted);
    cursor: pointer;
    background: var(--gray-50);
    transition: all var(--transition);
}
.permission-chip input { margin: 0; }
.permission-chip:has(input:checked) {
    background: var(--black);
    border-color: var(--black);
    color: var(--white);
}

/* ─── Category Pills ─── */
.category-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.category-pill {
    display: inline-flex;
    align-items: center;
    padding: 5px 12px;
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius);
    font-size: 12px;
    font-weight: 500;
    color: var(--text-muted);
    cursor: pointer;
    transition: all var(--transition);
}

.category-pill:hover { border-color: var(--gray-300); color: var(--black); }
.category-pill input { display: none; }

.category-pill.selected,
.category-pill:has(input:checked) {
    background: var(--black);
    border-color: var(--black);
    color: var(--white);
}

/* ─── Artikelauswahl in den SmartPricing-Regeln ─── */
/* Loest das <select multiple> mit Strg/Cmd ab: anhaken statt Strg-Klicken, damit ein
   Klick daneben nicht die ganze Auswahl loescht und die Auswahl auf einem Tablet
   ueberhaupt moeglich ist. Farben ausschliesslich ueber Token (siehe Farb-Lint). */
.picker-search {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 6px;
}

.picker-search .picker-query { flex: 1 1 auto; }
.picker-add-all { white-space: nowrap; flex: 0 0 auto; }

.picker-list {
    max-height: 220px;
    overflow-y: auto;
    border: 1px solid var(--gray-200);
    border-radius: var(--radius);
    background: var(--white);
}

.picker-row {
    display: flex;
    align-items: center;
    gap: 10px;
    /* 40px hoch: eine Zeile, die man auf dem Tablet trifft (WCAG 2.2 AA: 24px Minimum). */
    min-height: 40px;
    padding: 6px 12px;
    border-bottom: 1px solid var(--gray-100);
    cursor: pointer;
    font-size: 13px;
    color: var(--gray-900);
    transition: background var(--transition);
}

/* ⚠️ `display: flex` aus der Klasse schlaegt das `[hidden]`-Attribut (Klassen-Selektor
   gewinnt gegen die UA-Regel) — ohne diese Zeile blendet die Suche NICHTS aus und der
   Knopf "Alle Treffer uebernehmen" steht auch dann da, wenn es keine gibt. Im Bild
   sofort sichtbar, im Code nicht. */
.picker-row[hidden],
.picker-add-all[hidden] { display: none; }

.picker-row:last-of-type { border-bottom: none; }
.picker-row:hover { background: var(--gray-50); }
.picker-row.selected { background: var(--accent-light); }
.picker-row input[type="checkbox"] { flex: 0 0 auto; width: 16px; height: 16px; cursor: pointer; }

.picker-id {
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--text-muted);
    min-width: 72px;
}

.picker-name { flex: 1 1 auto; }

.picker-empty {
    margin: 0;
    padding: 14px 12px;
    font-size: 13px;
    color: var(--text-muted);
}

.picker-count { font-weight: 400; color: var(--text-muted); }

.picker-chosen {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}

.picker-chosen:empty { display: none; }

/* Der Chip ist ein Knopf: ein Klick nimmt den Artikel wieder heraus. */
.picker-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    background: var(--black);
    border: 1px solid var(--black);
    border-radius: var(--radius);
    color: var(--white);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.picker-chip::after { content: '\00d7'; font-size: 14px; line-height: 1; opacity: 0.75; }
.picker-chip:hover { background: var(--gray-700); border-color: var(--gray-700); }

.picker-clear {
    padding: 4px 10px;
    background: transparent;
    border: 1px dashed var(--gray-300);
    border-radius: var(--radius);
    color: var(--text-muted);
    font-size: 12px;
    cursor: pointer;
}

.picker-clear:hover { color: var(--black); border-color: var(--gray-500); }

@media (max-width: 640px) {
    .picker-search { flex-wrap: wrap; }
    .picker-add-all { width: 100%; }
    .picker-id { min-width: 0; }
}

/* ─── Time Range ─── */
.time-range {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
}

.time-input { display: flex; flex-direction: column; gap: 4px; }

.time-input label {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* Das Uhrzeit-Feld ist ein Auswahlfeld mit 24 vollen Stunden (siehe smartpricing.php):
   `<input type="time" step="3600">` zeigte die Minutenspalte trotzdem an und bot damit
   an, was beim Speichern abgelehnt wird. Gleiche Optik wie das frühere Feld. */
.time-input select.hour-select {
    padding: 8px 12px;
    border: 1px solid var(--gray-200);
    border-radius: var(--radius);
    font-size: 14px;
    font-family: var(--font-mono);
    font-weight: 500;
    width: 110px;
    text-align: center;
    background: var(--white);
    color: var(--black);
}

.time-input input {
    padding: 8px 12px;
    border: 1px solid var(--gray-200);
    border-radius: var(--radius);
    font-size: 14px;
    font-family: var(--font-mono);
    font-weight: 500;
    width: 110px;
    text-align: center;
    background: var(--white);
    color: var(--black);
    transition: border-color var(--transition);
}

.time-input input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-light);
}

.time-range-separator {
    /* contrast-lint: decorative — der Gedankenstrich zwischen "von" und "bis"
       sagt nichts aus, was die beiden beschrifteten Felder daneben nicht
       schon sagen. Dunkler gesetzt zöge er den Blick auf sich, statt die
       Felder zu trennen. */
    font-size: 18px;
    color: var(--gray-300);
    padding-bottom: 8px;
}

/* ─── Slider ─── */
.slider-container { padding: 4px 0; }

.slider {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 4px;
    background: var(--gray-200);
    border-radius: 2px;
    outline: none;
    border: none;
}

.slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 18px;
    height: 18px;
    background: var(--black);
    border-radius: 50%;
    cursor: pointer;
}

.slider::-moz-range-thumb {
    width: 18px;
    height: 18px;
    background: var(--black);
    border-radius: 50%;
    cursor: pointer;
    border: none;
}

.slider-value {
    text-align: center;
    font-family: var(--font-mono);
    font-size: 18px;
    font-weight: 600;
    color: var(--black);
    margin-top: 8px;
}

/* ─── Settings ─── */
.settings-section {
    margin-bottom: 28px;
    padding-bottom: 28px;
    border-bottom: 1px solid var(--gray-100);
}

.settings-section:last-child {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}

.settings-section-title {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 16px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.settings-section-title::before { display: none; }

/* ─── Row/Col (shops.php compat) ─── */
.row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
}

/* ─── Utilities ─── */
.mb-0 { margin-bottom: 0 !important; }
.mb-1 { margin-bottom: 8px !important; }
.mb-2 { margin-bottom: 16px !important; }
.mb-3 { margin-bottom: 24px !important; }
.mb-4 { margin-bottom: 32px !important; }
.mt-1 { margin-top: 8px !important; }
.mt-2 { margin-top: 16px !important; }
.mt-3 { margin-top: 24px !important; }

.text-center { text-align: center; }
.text-muted { color: var(--text-muted); }
.text-success { color: var(--accent); }
.text-danger { color: var(--red); }
.text-primary { color: var(--accent); }
.text-sm { font-size: 12px; }

.font-medium { font-weight: 500; }
.font-bold { font-weight: 600; }

.flex { display: flex; }
.flex-wrap { flex-wrap: wrap; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.justify-end { justify-content: flex-end; }
.gap-1 { gap: 6px; }
.gap-2 { gap: 12px; }
.gap-3 { gap: 18px; }

.divider {
    height: 1px;
    background: var(--gray-100);
    margin: 14px 0;
}

/* ─── Responsive ───────────────────────────────────────────────
   Die Navigation bringt ihre eigenen Regeln mit (Design-System, .cf-app*).
   Hier steht, was am Seiteninhalt hängt.
   ------------------------------------------------------------- */
@media (max-width: 768px) {
    .container { padding: 0 16px; }

    .page-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 12px;
    }
    /* Aktionen im Seitenkopf sollen auf schmalen Schirmen die volle
       Breite bekommen, statt als Streifen rechts zu kleben. */
    .page-header > .page-header-actions,
    .page-header > div:last-child:not(:only-child) {
        width: 100%;
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
    }

    .rule-card { flex-direction: column; align-items: flex-start; }
    .rule-actions {
        width: 100%;
        justify-content: flex-end;
        padding-top: 10px;
        border-top: 1px solid var(--gray-100);
        margin-top: 10px;
    }

    .tabs, .tabs-v2 {
        overflow-x: auto;
        flex-wrap: nowrap;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .tabs::-webkit-scrollbar, .tabs-v2::-webkit-scrollbar { display: none; }
    .tab, .tab-v2 { white-space: nowrap; flex-shrink: 0; }

    /* Bedienelemente auf Fingergrösse bringen. Knöpfe deckt das
       Design-System selbst ab (.cf-btn), hier nur die Formularfelder. */
    .form-input, .form-select, select, input[type="text"], input[type="password"],
    input[type="number"], input[type="date"], input[type="time"] {
        min-height: var(--tap-target);
        /* 16px verhindert, dass iOS beim Antippen in das Feld hineinzoomt. */
        font-size: 16px;
    }

    /* Dialoge fahren von unten ein und nutzen die volle Breite, statt als
       winziges Fenster mittig zu stehen. */
    .diag-modal-bg { padding: 0; align-items: flex-end; }
    .diag-modal {
        max-height: 92dvh;
        border-radius: 16px 16px 0 0;
        padding: 20px 16px calc(20px + env(safe-area-inset-bottom));
    }
    .diag-modal-close { min-width: var(--tap-target); min-height: var(--tap-target); }
}

/* ─── Footer ─── */
.site-footer {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 24px;
    margin-top: 48px;
    font-size: 12px;
    font-family: var(--font-mono);
    color: var(--text-muted);
    border-top: 1px solid var(--gray-100);
}

/* ─── CSV Status Card ─── */
.csv-status-card {
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.csv-status-card .csv-directory {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 20px;
    background: var(--gray-50);
    border-bottom: 1px solid var(--gray-100);
    font-size: 12px;
    color: var(--text-muted);
}

.csv-status-card .csv-directory code {
    font-size: 11px;
}

/* ─── Section Card ─── */
.section-card {
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-lg);
    overflow: hidden;
    margin-bottom: 16px;
}

.section-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 20px;
    border-bottom: 1px solid var(--gray-100);
    cursor: pointer;
    user-select: none;
    transition: background var(--transition);
}

.section-card-header:hover {
    background: var(--gray-50);
}

.section-card-header h4 {
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    font-weight: 600;
}

.section-card-header .toggle-icon {
    font-size: 12px;
    color: var(--text-muted);
    transition: transform var(--transition);
}

.section-card-header.open .toggle-icon {
    transform: rotate(180deg);
}

.section-card-body {
    padding: 20px;
}

.section-card-body.collapsed {
    display: none;
}

/* ─── Status Text ─── */
.status-text-ok {
    color: var(--accent);
    font-weight: 600;
    font-size: 12px;
}

.status-text-error {
    color: var(--red);
    font-weight: 600;
    font-size: 12px;
}

/* ─── Product Table ─── */
.product-table .search-bar {
    padding: 12px 20px;
    border-bottom: 1px solid var(--gray-100);
}

.product-table .search-bar input {
    width: 100%;
    max-width: 320px;
    padding: 8px 12px;
    font-size: 13px;
    font-family: var(--font-sans);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius);
    background: var(--gray-50);
    color: var(--black);
    transition: border-color var(--transition), box-shadow var(--transition);
}

.product-table .search-bar input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-light);
    background: var(--white);
}

/* ─── Print ─── */
@media print {
    .cf-app__side, .cf-app__top, .site-footer, .cf-btn, .toggle { display: none !important; }
    .cf-app__main { margin-left: 0; }
    body { background: white; }
    .card { box-shadow: none; border: 1px solid var(--gray-300); }
}

/* ─── Scrollbar ─── */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--gray-50); }
::-webkit-scrollbar-thumb { background: var(--gray-300); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--gray-400); }

/* ─── Weather Display ─── */
.weather-display {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--gray-700);
    flex-wrap: wrap;
}

.weather-temp {
    font-family: var(--font-mono);
    font-weight: 600;
    font-size: 15px;
    color: var(--black);
}

.weather-sep {
    /* contrast-lint: decorative — der Mittelpunkt trennt "gefühlt" von
       "Luftfeuchte" auf der Wetterkachel und trägt keine eigene Aussage. */
    color: var(--gray-300);
}

.weather-condition {
    font-weight: 500;
}

.weather-humidity {
    color: var(--text-muted);
}

/* ─── Field Mapping Widget ─── */
.field-mapping-display { display: flex; align-items: center; gap: 6px; }
.field-mapping-row { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.mapping-arrow { color: var(--text-muted); font-size: 14px; flex-shrink: 0; }

/* ─── Import Dir Inline Edit ─── */
.import-dir-display {
    display: flex;
    align-items: center;
    gap: 6px;
}

::selection { background: var(--brand-500); color: var(--white); }

/* =============================================================
   Erweiterte Komponenten (Hero, Stat-Cards, Rule-Cards, Charts …)
   Die Design-Tokens dieser Komponenten stehen im :root ganz oben —
   hier stehen nur noch die Komponenten selbst.
   ============================================================= */

/* ─── Status Pill ───
   War fuer den frueheren schwarzen Kopfbalken gemacht (weiss auf halbtransparent)
   und damit auf hellem Grund unsichtbar. Der Balken ist seit dem Umstieg auf den
   Seitenkopf des Design-Systems weg, also traegt die Pille jetzt dieselbe Sprache
   wie cf-badge: heller Grund, dunkle Schrift, feiner Rand.
   ⚠️ Bleibt vorerst Projekt-Klasse, aber NICHT weil cf-badge keinen Punkt
   koennte — es kann (`.cf-badge .cf-dot`). Der Grund ist allein die Groesse:
   status-pill ist hoeher und traegt in einigen Faellen einen ANIMIERTEN Punkt
   (pulse-dot). Zusammen mit .chip und den sieben Pillen in den Seiten-<style>
   gehoert das in einem Zug auf cf-badge umgestellt — neun Fassungen derselben
   Sache sind genau die Stelle, an der die Produkte auseinanderlaufen. */
.status-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 11px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.01em;
    background: var(--surface-2);
    color: var(--gray-700);
    border: 1px solid var(--border-soft);
}

/* on-surface ist seit dem Wegfall des dunklen Balkens der Normalfall und
   bleibt nur als Alias stehen, damit bestehendes Markup nicht bricht. */
.status-pill.on-surface { background: var(--surface-2); color: var(--gray-700); border-color: var(--border-soft); }
.status-pill.success   { background: var(--success-50);  color: var(--success-600); border-color: var(--success-100); }
.status-pill.warning   { background: var(--warning-50);  color: var(--warning-600); border-color: var(--warning-100); }
.status-pill.danger    { background: var(--danger-50);   color: var(--danger-600);  border-color: var(--danger-100); }
.status-pill.info      { background: var(--info-50);     color: var(--info-600);    border-color: var(--info-100); }
.status-pill.brand     { background: var(--brand-50);    color: var(--brand-700);   border-color: var(--brand-100); }
.status-pill.violet    { background: var(--violet-50);   color: var(--violet-600);  border-color: var(--violet-100); }

/* ─── Pulse Dot (Live-Indicator) ─── */
.pulse-dot {
    position: relative;
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--success-500);
    box-shadow: 0 0 0 0 rgba(16,185,129,0.6);
    animation: pulse-glow 2s ease-in-out infinite;
    flex-shrink: 0;
}
.pulse-dot.warning { background: var(--warning-500); box-shadow: 0 0 0 0 rgba(245,158,11,0.55); animation: pulse-glow-warn 2s ease-in-out infinite; }
.pulse-dot.idle    { background: var(--gray-300); animation: none; box-shadow: none; }

/* ─── Stat Card v2 ─── */
.stat-card-v2 {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: 14px;
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    position: relative;
    overflow: hidden;
    transition: transform var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out);
}

.stat-card-v2::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: var(--brand-gradient);
    opacity: 0.9;
}

.stat-card-v2.is-brand::before   { background: var(--brand-gradient); }
.stat-card-v2.is-success::before { background: var(--success-500); }
.stat-card-v2.is-warning::before { background: var(--warning-500); }
.stat-card-v2.is-info::before    { background: var(--info-500); }
.stat-card-v2.is-violet::before  { background: var(--violet-500); }

.stat-card-v2:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-xl);
    border-color: var(--border-strong);
}

.stat-card-v2 .stat-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.stat-card-v2 .stat-card-label {
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    font-weight: 600;
}

.stat-card-v2 .stat-card-badge {
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--surface-3);
    color: var(--gray-700);
}
.stat-card-v2 .stat-card-badge.up   { background: var(--success-50); color: var(--success-600); }
.stat-card-v2 .stat-card-badge.down { background: var(--danger-50);  color: var(--danger-600); }

.stat-card-v2 .stat-card-value {
    font-family: var(--font-mono);
    font-size: 30px;
    font-weight: 700;
    color: var(--black);
    letter-spacing: -0.02em;
    line-height: 1;
}

.stat-card-v2 .stat-card-sparkline {
    height: 40px;
    margin-top: -4px;
}

.stat-card-v2 .stat-card-foot {
    font-size: 12px;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    gap: 6px;
}

.stat-grid-v2 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 14px;
    margin-bottom: 22px;
}
@media (max-width: 600px) { .stat-grid-v2 { grid-template-columns: 1fr 1fr; }}
@media (max-width: 420px) { .stat-grid-v2 { grid-template-columns: 1fr; }}

/* ─── Soft Card ─── */
.soft-card {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: 14px;
    padding: 18px 20px;
    box-shadow: var(--shadow-sm);
    transition: box-shadow var(--dur-base) var(--ease-out),
                transform var(--dur-base) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out);
}
.soft-card:hover { box-shadow: var(--shadow-md); }
.soft-card.no-hover:hover { box-shadow: var(--shadow-sm); transform: none; }

.soft-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
    gap: 12px;
    flex-wrap: wrap;
}

.soft-card-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
}

.soft-card-title svg { width: 14px; height: 14px; }

/* ─── Panel Grid ─── */
.panel-grid {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: 16px;
    margin-bottom: 22px;
    align-items: stretch;
}
.panel-grid > .col-4  { grid-column: span 4; }
.panel-grid > .col-6  { grid-column: span 6; }
.panel-grid > .col-8  { grid-column: span 8; }
.panel-grid > .col-12 { grid-column: span 12; }
@media (max-width: 900px) {
    .panel-grid > .col-4,
    .panel-grid > .col-6,
    .panel-grid > .col-8 { grid-column: span 12; }}

/* ─── Weather Widget ───
   design-lint: allow-literal-colors — Wetterlagen sind Bildsprache, keine
   Markenfarben: Orange heisst Sonne, Grau heisst Wolke, Blau heisst Regen.
   Diese Toene ins Design-System zu heben waere falsch — RMS hat kein Wetter,
   und ein "Marken-Orange" fuer Sonnenschein waere eine Bedeutung zu viel. */
.weather-widget {
    position: relative;
    border-radius: 14px;
    overflow: hidden;
    padding: 16px 18px;
    color: var(--white);
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
    background: linear-gradient(135deg, #0ea5e9 0%, #38bdf8 100%);
    box-shadow: 0 10px 30px rgba(14,165,233,0.22);
}
.weather-widget[data-condition="clear"]        { background: linear-gradient(135deg, #fb923c 0%, #f59e0b 50%, #fbbf24 100%); box-shadow: 0 10px 30px rgba(245,158,11,0.22); }
.weather-widget[data-condition="clouds"]       { background: linear-gradient(135deg, #64748b 0%, #94a3b8 100%); box-shadow: 0 10px 30px rgba(100,116,139,0.22); }
.weather-widget[data-condition="rain"]         { background: linear-gradient(135deg, #0369a1 0%, #0ea5e9 100%); box-shadow: 0 10px 30px rgba(14,165,233,0.28); }
.weather-widget[data-condition="drizzle"]      { background: linear-gradient(135deg, #0369a1 0%, #0ea5e9 100%); }
.weather-widget[data-condition="thunderstorm"] { background: linear-gradient(135deg, #1e293b 0%, #475569 100%); }
.weather-widget[data-condition="snow"]         { background: linear-gradient(135deg, #64748b 0%, #cbd5e1 100%); color: #0f172a; }
.weather-widget[data-condition="mist"]         { background: linear-gradient(135deg, #94a3b8 0%, #cbd5e1 100%); color: #0f172a; }

.weather-widget > canvas.weather-canvas {
    position: absolute !important;
    inset: 0 !important;
    z-index: 0 !important;
    pointer-events: none;
    width: 100% !important;
    height: 100% !important;
}

.weather-widget > *:not(canvas) { position: relative; z-index: 1; }

.weather-widget-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 0;
}
.weather-widget-label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.85;
}

.weather-main {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}
.weather-big-temp {
    font-family: var(--font-mono);
    font-size: 32px;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1;
}
.weather-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.weather-info-condition {
    font-size: 15px;
    font-weight: 600;
    text-transform: capitalize;
}
.weather-info-meta {
    font-size: 12px;
    opacity: 0.82;
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}
.weather-trigger {
    font-size: 12px;
    background: rgba(255,255,255,0.14);
    border: 1px solid rgba(255,255,255,0.22);
    color: var(--white);
    padding: 6px 10px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 10px;
}
.weather-widget[data-condition="snow"] .weather-trigger,
.weather-widget[data-condition="mist"] .weather-trigger { color: #0f172a; background: rgba(15,23,42,0.08); border-color: rgba(15,23,42,0.14); }

.weather-icon-sun {
    display: inline-block;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: radial-gradient(circle, #fff 0%, #fde68a 60%, rgba(255,255,255,0) 72%);
    box-shadow: 0 0 32px rgba(255,255,255,0.35);
    animation: spin-slow 24s linear infinite;
    flex-shrink: 0;
}
/* design-lint: end */

/* ─── Timeline (SmartPricing Phase) ─── */
.phase-timeline {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
/* Lag frueher auf dem dunklen Kopfbalken (weiss auf halbtransparent) und war
   nach dessen Wegfall auf hellem Grund nicht mehr zu lesen. */
.phase-step {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    border-radius: 999px;
    background: var(--surface-2);
    border: 1px solid var(--border-soft);
    color: var(--text-muted);
    font-size: 12px;
    font-weight: 500;
}
.phase-step.active {
    background: var(--black);
    color: var(--white);
    font-weight: 600;
    border-color: transparent;
}
.phase-step .step-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    opacity: 0.6;
}
.phase-step.active .step-dot { opacity: 1; background: var(--success-500); animation: pulse-glow 2s ease-in-out infinite; }
.phase-arrow {
    color: var(--text-muted);
    font-weight: 700;
}

/* ─── Chips (Kategorie/Regel-Typ) ─── */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    background: var(--surface-3);
    color: var(--gray-700);
    border: 1px solid var(--border-soft);
}
.chip.brand   { background: var(--brand-50);   color: var(--brand-700);   border-color: var(--brand-100); }
.chip.warning { background: var(--warning-50); color: var(--warning-600); border-color: var(--warning-100); }
.chip.violet  { background: var(--violet-50);  color: var(--violet-600);  border-color: var(--violet-100); }
.chip.success { background: var(--success-50); color: var(--success-600); border-color: var(--success-100); }
.chip.danger  { background: var(--danger-50);  color: var(--danger-600);  border-color: var(--danger-100); }

/* ─── Rule Card v2 ─── */
.rule-card-v2 {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px 14px 18px;
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-left: 3px solid var(--brand-500);
    border-radius: 12px;
    margin-bottom: 10px;
    transition: box-shadow var(--dur-base) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out),
                transform var(--dur-base) var(--ease-out);
    position: relative;
}
.rule-card-v2:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.rule-card-v2.disabled { opacity: 0.5; }

.rule-card-v2.type-time    { border-left-color: var(--brand-500); }
.rule-card-v2.type-weather { border-left-color: var(--warning-500); }
.rule-card-v2.type-event   { border-left-color: var(--violet-500); }

.rule-card-v2.is-active {
    box-shadow: 0 0 0 1px var(--success-500), 0 4px 14px rgba(16,185,129,0.18);
    animation: border-glow 3s ease-in-out infinite;
}

.rule-card-v2-icon {
    width: 38px;
    height: 38px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    flex-shrink: 0;
}
.rule-card-v2.type-time .rule-card-v2-icon    { background: var(--brand-50);   color: var(--brand-700); }
.rule-card-v2.type-weather .rule-card-v2-icon { background: var(--warning-50); color: var(--warning-600); }
.rule-card-v2.type-event .rule-card-v2-icon   { background: var(--violet-50); color: var(--violet-600); }

.rule-card-v2-body { flex: 1; min-width: 0; }
.rule-card-v2-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    font-size: 14px;
    margin-bottom: 4px;
    flex-wrap: wrap;
}
.rule-card-v2-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--text-muted);
}
.rule-card-v2-meta .chip { margin-right: 2px; }

.rule-adjust-badge {
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: 14px;
    padding: 6px 12px;
    border-radius: 10px;
    background: var(--brand-50);
    color: var(--brand-700);
    white-space: nowrap;
}
.rule-adjust-badge.positive { background: var(--success-50); color: var(--success-600); }
.rule-adjust-badge.negative { background: var(--danger-50);  color: var(--danger-600); }

.rule-card-v2-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

@media (max-width: 768px) {
    .rule-card-v2 { flex-wrap: wrap; }
    .rule-card-v2-actions {
        width: 100%;
        justify-content: flex-end;
        padding-top: 10px;
        border-top: 1px solid var(--border-soft);
        margin-top: 6px;
    }}

/* ─── Tabs v2 (mit Icons + Counts) ─── */
.tabs-v2 {
    display: flex;
    gap: 4px;
    padding: 4px;
    background: var(--surface-2);
    border-radius: 12px;
    margin-bottom: 18px;
    flex-wrap: wrap;
}
.tab-v2 {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-muted);
    background: transparent;
    border: none;
    cursor: pointer;
    transition: all var(--dur-fast) var(--ease-out);
    font-family: var(--font-sans);
}
.tab-v2:hover { color: var(--black); }
.tab-v2.active {
    color: var(--brand-700);
    background: var(--surface);
    font-weight: 600;
    box-shadow: var(--shadow-sm);
}
.tab-v2 .tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    background: var(--surface-3);
    color: var(--gray-700);
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    font-family: var(--font-mono);
}
.tab-v2.active .tab-count { background: var(--brand-100); color: var(--brand-700); }
.tab-v2 .tab-emoji { font-size: 15px; line-height: 1; }

/* ─── Filter Chips (Products) ─── */
.filter-bar {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-soft);
    background: var(--surface-2);
}
.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border-radius: 999px;
    background: var(--surface);
    color: var(--gray-700);
    border: 1px solid var(--border-soft);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--dur-fast) var(--ease-out);
}
.filter-chip:hover { border-color: var(--border-strong); color: var(--black); }
.filter-chip.active {
    background: var(--black);
    color: var(--white);
    border-color: var(--black);
}

.search-input {
    position: relative;
    display: inline-flex;
    align-items: center;
    max-width: 320px;
    flex: 1;
}
.search-input input {
    width: 100%;
    padding: 8px 32px 8px 34px;
    font-size: 13px;
    border: 1px solid var(--border-soft);
    border-radius: 10px;
    background: var(--surface);
    transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.search-input input:focus {
    outline: none;
    border-color: var(--brand-500);
    box-shadow: 0 0 0 3px var(--brand-50);
}
.search-input .search-icon {
    position: absolute;
    left: 10px;
    width: 16px;
    height: 16px;
    color: var(--text-muted);
    pointer-events: none;
}
.search-input .search-clear {
    position: absolute;
    right: 8px;
    width: 18px;
    height: 18px;
    display: none;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--gray-200);
    color: var(--gray-700);
    cursor: pointer;
    font-size: 12px;
    border: none;
}
.search-input.has-value .search-clear { display: inline-flex; }

/* ─── Shop Cards Grid ─── */
.shop-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 16px;
}
.shop-card {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-radius: 14px;
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    transition: transform var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out);
    position: relative;
    overflow: hidden;
}
.shop-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: var(--brand-gradient);
}
.shop-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-xl);
}
.shop-card-head {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    justify-content: space-between;
}
.shop-card-title {
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.01em;
}
.shop-card-code {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-muted);
    background: var(--surface-3);
    padding: 2px 8px;
    border-radius: 6px;
    display: inline-block;
    margin-top: 4px;
}
.shop-card-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    padding: 10px 12px;
    background: var(--surface-2);
    border-radius: 10px;
    border: 1px solid var(--border-soft);
}
.shop-card-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}
.shop-card-stat-value {
    font-family: var(--font-mono);
    font-size: 16px;
    font-weight: 700;
    color: var(--black);
}
.shop-card-stat-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    font-weight: 600;
}
.shop-card-actions {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

/* ─── Skeleton ─── */
.skeleton {
    background: linear-gradient(90deg, var(--surface-3) 0%, var(--surface-2) 50%, var(--surface-3) 100%);
    background-size: 200% 100%;
    animation: shimmer 1.5s ease-in-out infinite;
    border-radius: 8px;
}
.skeleton.h-16 { height: 16px; }
.skeleton.h-24 { height: 24px; }
.skeleton.h-32 { height: 32px; }
.skeleton.h-40 { height: 40px; }

/* ─── Chart Container ─── */
.chart-container { width: 100%; min-height: 120px; }
.chart-container.tall { min-height: 280px; }

/* ─── Live Pulse on Badge ─── */
.live-indicator {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--success-50);
    color: var(--success-600);
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border: 1px solid var(--success-100);
}

/* ─── Slider Live Preview ─── */
.slider-live-preview {
    margin-top: 10px;
    padding: 10px 14px;
    background: var(--surface-2);
    border: 1px solid var(--border-soft);
    border-radius: 10px;
    font-size: 13px;
    color: var(--gray-700);
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-mono);
}
.slider-live-preview .arrow { color: var(--text-muted); }
.slider-live-preview .new-price { color: var(--brand-700); font-weight: 700; }
.slider-live-preview.negative .new-price { color: var(--danger-600); }

/* ─── Time Range Visualizer ─── */
.time-range-visualizer {
    position: relative;
    height: 32px;
    background: var(--surface-3);
    border-radius: 8px;
    overflow: hidden;
    margin-top: 8px;
}
.time-range-visualizer .tr-band {
    position: absolute;
    top: 0;
    bottom: 0;
    background: var(--brand-gradient);
    opacity: 0.85;
}
.time-range-visualizer .tr-scale {
    position: absolute;
    inset: 0;
    display: flex;
    font-size: 9px;
    color: var(--text-muted);
    font-family: var(--font-mono);
}
.time-range-visualizer .tr-tick {
    flex: 1;
    border-left: 1px dashed var(--border-soft);
    padding: 2px 0 0 2px;
}
.time-range-visualizer .tr-tick:first-child { border-left: none; }

/* ─── Login Split ─── */






/* ─── Utility additions ─── */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
@media (max-width: 700px) { .grid-2, .grid-3 { grid-template-columns: 1fr; }}

.price-delta-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 8px;
    border-radius: 6px;
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 700;
}
.price-delta-badge.up   { background: var(--success-50); color: var(--success-600); }
.price-delta-badge.down { background: var(--danger-50);  color: var(--danger-600); }
.price-delta-badge.flat { background: var(--surface-3);  color: var(--text-muted); }

/* ─── Rule Edit Form (inline) ─── */
.rule-edit-form {
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-left: 3px solid var(--brand-500);
    border-radius: 12px;
    padding: 18px 20px;
    margin: -6px 0 14px;
    box-shadow: var(--shadow-sm);
    animation: fade-up 220ms var(--ease-out) both;
}

/* Die Anmeldeseite laeuft ohne App-Rahmen (showNav=false); nur die
   Fusszeile muss dort noch weichen. */

/* ─── Log-Ansicht ───
   Dunkle Fläche mit farbigen Stufen. Stand vorher zweimal fast zeichengleich
   in den Seiten-<style>-Blöcken von dashboard.php und diagnostics.php; die
   Stufen-Farben waren nach der Token-Umstellung sogar byte-identisch. */
.log-view {
    background: var(--black);
    color: var(--gray-300);
    padding: 12px 16px;
    border-radius: 8px;
    font-family: var(--font-mono);
    font-size: 11px;
    line-height: 1.5;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-word;
}
.level-ERROR   { color: var(--danger-500); }
.level-WARNING { color: var(--warning-500); }
.level-INFO    { color: var(--info-500); }
.level-DEBUG   { color: var(--text-muted); }

/* ============================================================
   Marken-Zeichen (Logo)
   Nur Maße und Beschnitt — die Farben stecken in der SVG-Datei selbst
   (ein Zeichen folgt keinem Theme). Eigene Klassen statt Modifier auf
   .cf-app__brand-mark: die Klasse gehört dem Design-System.
   ============================================================ */
.brand-logo {
    display: block;
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    border-radius: 7px;   /* wie das Zeichen des Systems, damit die Kopfzeile ruhig bleibt */
    overflow: hidden;
}
.brand-logo img { display: block; width: 100%; height: 100%; }

/* Kleine Marke auf dunklem Grund (linke Spalte der Anmeldeseite). */
.brand-logo-sm {
    display: block;
    flex-shrink: 0;
    width: 30px;
    height: 30px;
    border-radius: 8px;
}

/* Volle Fassung über dem Anmeldeformular. */

/* ═══════════════════════════════════════════════════════════════════════
   Anmeldeseite
   ═══════════════════════════════════════════════════════════════════════

   Aufbau nach dem Vorbild des RMS-Portals, damit die Reihe zusammengehört:
   links eine vollflächige Bildspalte, rechts das Formular auf Weiß.

   ⚠️ RANDLOS, nicht als schwebende Karte. Das war der augenfälligste
   Unterschied zum RMS: dort füllen die beiden Spalten den ganzen Schirm,
   hier stand eine 980px-Karte mit Schatten in der Mitte. Bei zwei Produkten
   nebeneinander liest sich das nicht wie „dieselbe Familie", sondern wie
   „zwei Häuser".
   ══════════════════════════════════════════════════════════════════════ */

.login {
    display: grid;
    grid-template-columns: minmax(0, 45fr) minmax(0, 55fr);
    min-height: 100dvh;
}

/* Die Anmeldeseite bringt ihren eigenen Rahmen mit — der Seitenrand und die
   mittige Ausrichtung des Layouts gelten hier nicht. */
body:has(.login) { padding: 0; margin: 0; background: var(--white); }
body:has(.login) .container { padding: 0; margin: 0; max-width: none; }
body:has(.login) .site-footer { display: none; }


/* ── Bildspalte ──────────────────────────────────────────────────────── */

.login__brand {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 40px;
    overflow: hidden;
    color: var(--white);

    /* design-lint: allow-literal-colors — der Verlauf liegt UNTER dem Foto
       und muss deckend dunkel sein, damit weiße Schrift darauf trägt; die
       Token des Systems beschreiben Flächen für Text, nicht Bildgründe.
       ⚠️ Vorher lag hier ein Foto von einer FREMDEN Adresse (Unsplash):
       damit ging die Adresse jedes Anmeldenden an einen Dritten — auf der
       Seite, auf der man Zugangsdaten eingibt —, und ohne Netz stand die
       Spalte leer.
       Ein eigenes Foto kommt nach `assets/img/login-bg.jpg`; index.php
       reicht es dann als --login-bg herein. Liegt keines, trägt der Verlauf
       allein, und es entsteht KEIN Aufruf einer fehlenden Datei. */
    background-color: #0b1220;
    background-image:
        linear-gradient(155deg, rgba(11,18,32,0.72) 0%, rgba(11,18,32,0.92) 100%),
        var(--login-bg, none);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    /* design-lint: end */
}

.login__brand-top { display: flex; align-items: center; justify-content: space-between; }

.login__wordmark {
    display: inline-flex;
    align-items: center;
    gap: 11px;
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--white);
}
.login__wordmark img { display: block; border-radius: 9px; }

/* Breit genug, dass die Zeilen im Markup halten. Mit 30ch brach der Satz ein
   zweites Mal um und wurde aus drei Zeilen fünf — bei einer Aussage, die vom
   Rhythmus lebt, sieht das nach Zufall aus. */
.login__claim { max-width: 40ch; }
.login__claim h2 {
    font-size: clamp(28px, 3vw, 38px);
    text-wrap: balance;
    line-height: 1.12;
    letter-spacing: -0.025em;
    font-weight: 700;
    color: var(--white);
    margin: 0 0 14px;
}
.login__claim p {
    font-size: 15px;
    line-height: 1.6;
    margin: 0;
    /* design-lint: allow-literal-colors — Text auf dem Bildgrund; die
       Graustufen des Systems sind für helle Flächen gedacht. */
    color: rgba(255, 255, 255, 0.78);
    /* design-lint: end */
}

/* ── Formularspalte ──────────────────────────────────────────────────── */

.login__panel {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 40px clamp(24px, 6vw, 72px);
    background: var(--white);
}

.login__form-wrap {
    width: 100%;
    max-width: 400px;
    margin: auto;
}

.login__title {
    font-size: 30px;
    font-weight: 700;
    letter-spacing: -0.025em;
    margin: 0 0 6px;
    color: var(--black);
}
.login__subtitle {
    font-size: 14px;
    color: var(--gray-500);
    margin: 0 0 28px;
}

.login__error {
    background: var(--red-light);
    color: var(--red);
    padding: 11px 14px;
    border-radius: var(--radius);
    font-size: 13px;
    line-height: 1.5;
    margin-bottom: 20px;
    border-left: 3px solid var(--red);
}

.login__form { display: flex; flex-direction: column; gap: 18px; }
.login__field { display: flex; flex-direction: column; gap: 7px; }

/* Beschriftung ÜBER dem Feld, nicht als Platzhalter darin. Ein Platzhalter
   verschwindet beim Tippen — wer unterbrochen wird, sieht dann nicht mehr,
   was in welches Feld gehört. */
.login__label {
    font-size: 13px;
    font-weight: 600;
    color: var(--black);
}

.login__input-wrap { position: relative; display: flex; }

.login__input {
    width: 100%;
    padding: 11px 14px;
    font-size: 14px;
    font-family: var(--font-sans);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius);
    background: var(--white);
    color: var(--black);
    transition: border-color var(--transition), box-shadow var(--transition);
}
/* Der Platzhalter ist der einzige Hinweis darauf, was ins Feld gehört, bevor
   man tippt — er muss lesbar sein. gray-400 trägt 2,5:1. */
.login__input::placeholder { color: var(--text-muted); }
.login__input:hover { border-color: var(--gray-300); }
.login__input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-light);
}
.login__input-wrap .login__input { padding-right: 44px; }

.login__reveal {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: none;
    border-radius: var(--radius);
    color: var(--gray-500);
    cursor: pointer;
    transition: color var(--transition), background var(--transition);
}
.login__reveal svg { width: 18px; height: 18px; }
.login__reveal:hover { color: var(--black); background: var(--gray-50); }
.login__reveal.is-on { color: var(--accent); }
.login__reveal:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.login__submit {
    width: 100%;
    height: 46px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    font-size: 15px;
    font-weight: 600;
    font-family: var(--font-sans);
    color: var(--white);
    background: var(--black);
    border: none;
    border-radius: var(--radius);
    cursor: pointer;
    transition: background var(--transition);
    margin-top: 6px;
}
.login__submit svg { width: 17px; height: 17px; }
.login__submit:hover { background: var(--gray-900); }
.login__submit:active { background: var(--gray-700); }

/* Statt „Passwort vergessen?" und „Jetzt registrieren": der Satz, der hier
   tatsächlich weiterhilft. Beide Wege gibt es in diesem Portal nicht —
   Zugänge legt ein Operator an. */
.login__hint {
    margin: 22px 0 0;
    font-size: 13px;
    line-height: 1.6;
    color: var(--gray-500);
    text-align: center;
}

.login__foot {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 20px;
    flex-wrap: wrap;
    padding-top: 32px;
    font-size: 12px;
    /* gray-400 trüge hier 2,5:1 — und der Hinweis auf die verschlüsselte
       Verbindung ist genau das, was man auf einer Anmeldeseite lesen können
       muss. */
    color: var(--gray-500);
}
.login__foot-item { display: inline-flex; align-items: center; gap: 6px; }
.login__foot-item svg { width: 13px; height: 13px; }

/* ── Anmeldeseite auf schmalen Schirmen ──────────────────────────────────
   ⚠️ Diese Regeln stehen bewusst am ENDE des Login-Abschnitts. Standen sie
   davor, gewann bei gleicher Spezifität die spätere Basisregel, und die
   Media-Query blieb wirkungslos — sichtbar wurde das erst am Gerät. */
@media (max-width: 900px) {
    /* `auto 1fr` statt zweier gleich hoher Zeilen: sonst streckt das Raster
       den Kopf auf die halbe Höhe, obwohl darin nur zwei Zeilen stehen —
       und das Anmeldefeld rutscht unter den Falz. */
    .login {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: auto 1fr;
        min-height: 100dvh;
    }

    /* Die Bildspalte bleibt, wird aber zum Kopf statt zur halben Seite:
       die Marke sagt, wo man ist, der erklärende Absatz dagegen kostet auf
       dem Telefon die halbe Höhe, bevor man das erste Feld sieht. */
    .login__brand {
        padding: 26px 24px 30px;
        gap: 16px;
        justify-content: flex-start;
    }
    .login__claim p { display: none; }
    .login__claim h2 { font-size: 25px; margin-bottom: 0; }
    .login__panel { padding: 34px 24px 28px; }
    .login__title { font-size: 25px; }
    .login__subtitle { margin-bottom: 22px; }
    .login__foot { padding-top: 26px; }
}
