/* ═══════════════════════════════════════════════════════════════════
   NavalStrike – Admin-Backend

   Eigene Gestaltung, bewusst NICHT css/main.css: Das Spiel bringt dort
   66 KB Messing, Wasser und Schiffsanimationen mit, von denen ein
   Leitstand nichts braucht. Was er braucht, ist Ruhe und Dichte – viele
   Zahlen auf wenig Platz, ohne dass es eng wird.

   Die Farbwelt bleibt dieselbe (Marineblau, Messing als Leitfarbe), damit
   erkennbar ist, wozu die Seite gehoert. Die Variablen stehen hier noch
   einmal statt per Verweis auf main.css: Das Backend laeuft auf einer
   eigenen Subdomain, und eine Datei weniger zu laden ist an dieser Stelle
   das bessere Geschaeft als die gemeinsame Quelle.

   Ausnahme: demo/admin-dashboard.php bindet main.css zusaetzlich ein,
   weil die Entwurfsseite ihr eigenes Drumherum daraus faerbt.
   ═══════════════════════════════════════════════════════════════════ */

:root {
    --ocean-900: #070d17;
    --ocean-800: #0c1522;
    --ocean-700: #121f31;
    --ocean-600: #1b2c43;
    --ocean-500: #253a56;
    --ocean-400: #34506f;
    --ocean-300: #4d6d92;
    --ocean-200: #7593b8;

    --accent-brass: #d4a53f;
    --accent-gold: #f0c368;
    --accent-steel: #5b8fc7;
    --accent-red: #d96852;
    --accent-green: #5a9e6f;
    --accent-orange: #d2853a;

    --text-primary: #e8eef7;
    --text-secondary: #9fb3cc;
    --text-muted: #6b7f99;

    --border-subtle: rgba(140, 175, 215, 0.16);
    --surface-card: rgba(18, 31, 49, 0.88);

    --space-xs: 4px;
    --space-sm: 8px;
    --space-md: 16px;
    --space-lg: 24px;
    --space-xl: 32px;

    --radius-sm: 4px;
    --radius-md: 8px;
    --radius-lg: 14px;

    /* Dieselben Schriften wie das Spiel, aus demselben Verzeichnis.
       Die Schreibmaschine traegt nur die Marke im Kopf – in Tabellen und
       Zahlen waere sie schlecht lesbar. */
    --font-main: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --font-display: 'Special Elite', 'Courier New', monospace;
    --font-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, monospace;
}

/* Die Schriftdateien liegen im Webspace des Spiels. Auf der eigenen
   Subdomain sind sie darueber nicht erreichbar, deshalb holt der Build
   sie mit (siehe .gitlab-ci.yml, Deploy des Backends). */
@font-face {
    font-family: 'Outfit';
    src: url('assets/fonts/outfit-var.woff2') format('woff2');
    font-weight: 100 900;
    font-display: swap;
}
@font-face {
    font-family: 'Special Elite';
    src: url('assets/fonts/special-elite-400.woff2') format('woff2');
    font-weight: 400;
    font-display: swap;
}
@font-face {
    font-family: 'JetBrains Mono';
    src: url('assets/fonts/jetbrains-mono-var.woff2') format('woff2');
    font-weight: 100 800;
    font-display: swap;
}

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

body {
    font-family: var(--font-main);
    background: var(--ocean-900);
    color: var(--text-primary);
    line-height: 1.6;
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
}

/* Die Entwurfsseite bringt ihr eigenes Drumherum mit und soll nicht
   randlos sein. */
body.admin-demo { padding-bottom: var(--space-xl); }

.admin-shell {
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 var(--space-lg);
}

/* ─── Kopf ────────────────────────────────────────────────────────── */

.admin-head {
    display: flex;
    align-items: center;
    gap: var(--space-lg);
    padding: var(--space-md) 0;
    margin-bottom: var(--space-lg);
    border-bottom: 1px solid var(--border-subtle);
    flex-wrap: wrap;
}

.admin-head__brand { display: flex; flex-direction: column; line-height: 1.2; }

.admin-head__mark {
    font-family: var(--font-display);
    font-size: 1.05rem;
    color: var(--accent-gold);
    letter-spacing: 0.02em;
}

.admin-head__title {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--text-muted);
}

.admin-head__user {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--space-md);
}

.admin-head__name { font-size: 0.85rem; color: var(--text-secondary); }

/* Hinweis im Kopf, solange die Umgebung in Wartung ist. Rot, anders als
   die Messing-Zahl am Reiter: Hier ist tatsaechlich etwas zu. */
.admin-head__maintenance {
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--accent-red);
    border: 1px solid rgba(217, 104, 82, 0.5);
    background: rgba(217, 104, 82, 0.12);
    border-radius: 999px;
    padding: 3px 10px;
}
.admin-head__maintenance[hidden] { display: none; }

/* ─── Wartungsmodus ───────────────────────────────────────────────── */

.admin-maintenance {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-lg);
    flex-wrap: wrap;
    margin-bottom: var(--space-lg);
    transition: border-color 0.25s, background 0.25s;
}
.admin-maintenance .admin-card__note { min-height: 0; margin-bottom: 0; }
.admin-maintenance.is-active {
    border-color: rgba(217, 104, 82, 0.55);
    background: linear-gradient(0deg, rgba(217, 104, 82, 0.08), rgba(217, 104, 82, 0.08)), var(--surface-card);
}

.admin-maintenance__env {
    font-weight: 400;
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-left: var(--space-xs);
}

/* Der Knebelschalter aus dem Abo-Dialog des Spiels (css/profile.css,
   .billing-toggle): Beschriftung links und rechts, dazwischen das
   Messingbauteil. Die Bilder kopiert der Build nach assets/ui/, weil diese
   Subdomain nichts aus dem Webspace des Spiels laden kann. Links steht
   der Knopf auf Betrieb, rechts auf Wartung. */
.maintenance-toggle {
    display: grid;
    grid-template-columns: auto auto auto;
    align-items: center;
    gap: var(--space-sm) var(--space-md);
}

.maintenance-toggle__side {
    background: none;
    border: none;
    padding: 8px 4px;
    min-height: 44px;
    font-family: var(--font-display);
    font-size: 0.95rem;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    cursor: pointer;
    white-space: nowrap;
    transition: color 0.25s, text-shadow 0.25s;
}
.maintenance-toggle__side:hover:not(:disabled) { color: var(--text-secondary); }
.maintenance-toggle__side[aria-pressed="true"] {
    color: var(--accent-gold);
    text-shadow: 0 0 10px rgba(240, 195, 104, 0.4);
}
.maintenance-toggle__side--right[aria-pressed="true"] {
    color: var(--accent-red);
    text-shadow: 0 0 10px rgba(217, 104, 82, 0.45);
}
.maintenance-toggle__side:focus-visible {
    outline: 2px solid var(--accent-gold);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

.maintenance-toggle__rail {
    position: relative;
    width: 112px;
    /* Seitenverhaeltnis des Zuschnitts (564x192), damit das Messing nie
       verzerrt. */
    aspect-ratio: 564 / 192;
    background-color: transparent;
    background-image: url('assets/ui/knob-left.webp');
    background-size: 100% 100%;
    background-repeat: no-repeat;
    border: none;
    padding: 0;
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
    filter: drop-shadow(0 3px 10px rgba(0, 0, 0, 0.5));
    -webkit-tap-highlight-color: transparent;
}
.maintenance-toggle__rail[aria-checked="true"] {
    background-image: url('assets/ui/knob-right.webp');
}
.maintenance-toggle__rail:focus-visible {
    outline: 2px solid var(--accent-gold);
    outline-offset: 3px;
    border-radius: 999px;
}
/* Trefferflaeche auf 44px, ohne das Bauteil aufzublasen. */
.maintenance-toggle__rail::after {
    content: '';
    position: absolute;
    inset: -10px -6px;
}

/* Waehrend der Server schaltet: kein zweiter Klick, sichtbar gedaempft. */
.maintenance-toggle__rail:disabled,
.maintenance-toggle__side:disabled { cursor: progress; opacity: 0.6; }

/* ─── Reiter ──────────────────────────────────────────────────────── */

.admin-tabs { display: flex; gap: var(--space-xs); }

.admin-tab {
    font: inherit;
    font-size: 0.9rem;
    background: none;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    padding: var(--space-sm) var(--space-md);
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    transition: color 0.15s, background 0.15s, border-color 0.15s;
}

.admin-tab:hover { color: var(--text-primary); background: rgba(140, 175, 215, 0.06); }

.admin-tab.is-active {
    color: var(--accent-gold);
    border-color: rgba(212, 165, 63, 0.35);
    background: rgba(212, 165, 63, 0.08);
}

/* Die Zahl offener Meldungen. Rot waere Alarm; das ist es nicht, es ist
   Arbeit. Messing sagt "hier liegt etwas", ohne zu draengen. */
.admin-tab__badge {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    background: var(--accent-brass);
    color: var(--ocean-900);
    border-radius: 999px;
    padding: 1px 7px;
    font-weight: 600;
}

.admin-panel { display: none; }
.admin-panel.is-active { display: block; }

/* ─── Kennzahlen ──────────────────────────────────────────────────── */

.admin-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: var(--space-md);
    margin-bottom: var(--space-lg);
}

.admin-kpi {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-md);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.admin-kpi__label {
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
}

.admin-kpi__value {
    font-family: var(--font-mono);
    font-size: 1.9rem;
    font-weight: 600;
    color: var(--text-primary);
    line-height: 1.2;
}

.admin-kpi__trend { font-size: 0.78rem; color: var(--text-muted); }
.admin-kpi__trend.is-up { color: var(--accent-green); }
.admin-kpi__trend.is-down { color: var(--accent-steel); }
.admin-kpi__trend.is-warn { color: var(--accent-orange); }

/* ─── Karten ──────────────────────────────────────────────────────── */

/* Karten in einer Reihe werden gleich hoch, nicht jede so hoch wie ihr
   Inhalt – sonst steht eine Reihe aus drei Diagrammen auf drei
   verschiedenen Hoehen, je nachdem wie lang die Anmerkung darueber ist.
   Das Vorgabeverhalten von Grid (stretch) erledigt das; align-items: start
   stand hier vorher und verhinderte es. */
.admin-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: var(--space-md);
}

/* Die Anmerkungen auf eine gemeinsame Mindesthoehe bringen.
 *
 * Der naheliegende Weg waere, das Diagramm mit margin-top: auto nach unten
 * zu schieben – der ist aber falsch: Karten mit kurzer Anmerkung bekommen
 * dann eine Leerflaeche zwischen Text und Diagramm, die genau so gross
 * ist wie der laengste Nachbartext. Im Bild klaffte darueber die halbe
 * Karte.
 *
 * Stattdessen bekommt die Anmerkung selbst eine Mindesthoehe von zwei
 * Zeilen. Die Diagramme starten damit auf gleicher Linie, ohne dass
 * irgendwo Leere entsteht; eine dreizeilige Anmerkung waechst weiterhin
 * ueber das Mass hinaus und schiebt nur ihre eigene Karte. */
.admin-card__note { min-height: calc(2 * 1.55em); }

/* Karten ohne Anmerkung: Der Abstand, den die Anmerkung sonst nach unten
   traegt, muss trotzdem da sein. */
.admin-card__title + .admin-chart { margin-top: var(--space-md); }

.admin-card {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-md) var(--space-md) var(--space-lg);
}

/* Ueber die volle Breite – fuer Zeitverlaeufe und die quadratischen
   Raster, die nebeneinander zu schmal wuerden. */
.admin-card--wide { grid-column: 1 / -1; }
.admin-card--flat { background: none; border-style: dashed; }

.admin-card__title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: var(--space-xs);
}

.admin-card__note {
    font-size: 0.8rem;
    color: var(--text-muted);
    line-height: 1.55;
    margin-bottom: var(--space-md);
    max-width: 70ch;
}

.admin-card__note code,
.admin-card code {
    font-family: var(--font-mono);
    font-size: 0.88em;
    color: var(--accent-brass);
}

.admin-card__foot {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    margin-top: var(--space-md);
    padding-top: var(--space-md);
    border-top: 1px solid var(--border-subtle);
    flex-wrap: wrap;
}

/* ─── Diagramme ───────────────────────────────────────────────────── */

/* Feste Hoehe, weil Chart.js mit maintainAspectRatio: false zeichnet:
   Ohne sie faellt das Feld auf 0 Pixel zusammen und das Diagramm bleibt
   unsichtbar. */
.admin-chart { position: relative; height: 260px; }
.admin-chart--tall { height: 360px; }

/* Ladezeichen eines einzelnen Diagramms (AdminCharts.ladend/leer).
 *
 * Liegt UEBER der Canvas statt an ihrer Stelle: Das Feld behaelt seine
 * Hoehe, und beim Erscheinen des Diagramms springt nichts. Moeglich ist
 * das, weil .admin-chart ohnehin position: relative traegt – fuer die
 * Tooltips von Chart.js.
 *
 * Das Streifenmuster ist dasselbe wie beim fehlenden Bildschirmfoto
 * (.admin-shot--placeholder): Im Leitstand soll "hier ist noch nichts"
 * ueberall gleich aussehen, statt je Stelle neu erfunden zu werden. */
.admin-chart__lade {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: var(--space-md);

    color: var(--text-muted);
    font-size: 0.82rem;

    background:
        repeating-linear-gradient(
            45deg,
            rgba(140, 175, 215, 0.04),
            rgba(140, 175, 215, 0.04) 10px,
            transparent 10px,
            transparent 20px
        ),
        var(--ocean-800);
    border-radius: var(--radius-md);

    animation: admin-chart-lade 1.8s ease-in-out infinite;
}

/* Kommt gar nichts mehr, hoert auch das Pulsieren auf: Eine Flaeche, die
   weiterpulst, behauptet, es ginge weiter. */
.admin-chart__lade[data-leer] { animation: none; }

@keyframes admin-chart-lade {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.55; }
}

/* Dieselbe Ruecksicht wie im Spiel (css/main.css): Wer Bewegung
   abbestellt hat, bekommt die Flaeche ohne Puls – die Aussage steht im
   Text, nicht in der Animation. */
@media (prefers-reduced-motion: reduce) {
    .admin-chart__lade { animation: none; }
}

/* Die beiden Spielfeldraster sind quadratisch (10x10) und sollen es
   bleiben.
 *
 * aspect-ratio allein genuegt nicht: Chart.js zeichnet mit
 * maintainAspectRatio: false in die gemessene Flaeche, und auf einer
 * Karte ueber die volle Breite geriet das Raster winzig und stand
 * verloren in der Mitte. Deshalb wird die KARTE schmaler gehalten, nicht
 * nur das Feld darin – ueber die Breite der Karte selbst.
 *
 * 520px sind zehn Zellen zu gut 50 Pixel; darunter werden die
 * Beschriftungen der Spalten eng. */
.admin-chart--square {
    height: auto;
    aspect-ratio: 1 / 1;
    width: 100%;
    max-width: 520px;
    margin: 0 auto;
}

/* Die Karte eines Rasters braucht nicht die volle Breite. Sie steht
   trotzdem in der eigenen Zeile (admin-card--wide), weil zwei Raster
   nebeneinander auf schmalen Schirmen unlesbar wuerden. */
.admin-card--grid { max-width: 600px; }

.admin-chart__missing {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: var(--text-muted);
    font-size: 0.85rem;
    border: 1px dashed var(--border-subtle);
    border-radius: var(--radius-md);
}

/* ─── Werkzeugleiste ──────────────────────────────────────────────── */

.admin-toolbar {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    margin-bottom: var(--space-md);
    flex-wrap: wrap;
}

.admin-toolbar__right {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}

.admin-filters { display: flex; gap: var(--space-sm); flex-wrap: wrap; align-items: flex-end; }

.admin-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    font-size: 0.82rem;
    color: var(--text-secondary);
    background: rgba(140, 175, 215, 0.05);
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    padding: 5px var(--space-md) 5px var(--space-sm);
    cursor: pointer;
    user-select: none;
}

.admin-chip input { accent-color: var(--accent-brass); cursor: pointer; }
.admin-chip span { font-family: var(--font-mono); font-size: 0.76rem; color: var(--text-muted); }

.admin-chip.is-active {
    color: var(--text-primary);
    border-color: rgba(212, 165, 63, 0.4);
    background: rgba(212, 165, 63, 0.1);
}
.admin-chip.is-active span { color: var(--accent-gold); }

.admin-field { display: flex; flex-direction: column; gap: 3px; }
.admin-field > span {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
}

.admin-select,
.admin-search {
    font: inherit;
    font-size: 0.86rem;
    background: var(--ocean-800);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    padding: var(--space-sm) var(--space-md);
}

.admin-search { min-width: 230px; }
.admin-select:focus,
.admin-search:focus { outline: none; border-color: rgba(212, 165, 63, 0.5); }

/* ─── Knoepfe ─────────────────────────────────────────────────────── */

.admin-btn {
    font: inherit;
    font-size: 0.85rem;
    background: rgba(140, 175, 215, 0.08);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    padding: var(--space-sm) var(--space-md);
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}

.admin-btn:hover { background: rgba(140, 175, 215, 0.14); }

.admin-btn--primary {
    background: rgba(212, 165, 63, 0.16);
    border-color: rgba(212, 165, 63, 0.45);
    color: var(--accent-gold);
}
.admin-btn--primary:hover { background: rgba(212, 165, 63, 0.24); }

.admin-btn--ghost { background: none; color: var(--text-secondary); }
.admin-btn--ghost:hover { background: rgba(140, 175, 215, 0.08); }

.admin-btn:disabled { opacity: 0.45; cursor: not-allowed; }

.admin-hint { font-size: 0.78rem; color: var(--text-muted); line-height: 1.5; }

.admin-hint--bar {
    padding: var(--space-sm) var(--space-md);
    background: rgba(140, 175, 215, 0.04);
    border-left: 2px solid var(--border-subtle);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    margin-bottom: var(--space-md);
    max-width: 90ch;
}

/* ─── Lagebericht ─────────────────────────────────────────────────── */

.admin-digest { font-size: 0.88rem; line-height: 1.7; max-width: 80ch; }
.admin-digest h3 {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--accent-brass);
    margin: var(--space-md) 0 var(--space-xs);
}
.admin-digest h3:first-child { margin-top: 0; }
.admin-digest ol, .admin-digest ul { padding-left: 1.4em; }
.admin-digest li { margin-bottom: var(--space-xs); }
.admin-digest p { color: var(--text-secondary); }
.admin-digest strong { color: var(--text-primary); }
.admin-digest em { color: var(--accent-brass); font-style: normal; font-family: var(--font-mono); font-size: 0.9em; }

/* ─── Rueckmeldungen ──────────────────────────────────────────────── */

.admin-feedback { display: flex; flex-direction: column; gap: var(--space-sm); }

.admin-report {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-md);
}

/* Offene Meldungen bekommen eine Messingkante an der Seite. Kein
   Farbwechsel der ganzen Karte: Die Liste soll ruhig bleiben, auch wenn
   die Haelfte offen ist. */
.admin-report.is-open { border-left: 2px solid rgba(212, 165, 63, 0.55); }

.admin-report__bar {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
    margin-bottom: var(--space-sm);
}

.admin-report__id {
    font-family: var(--font-mono);
    font-size: 0.8rem;
    color: var(--text-muted);
}

.admin-report__meta {
    font-size: 0.78rem;
    color: var(--text-muted);
}

.admin-report__time {
    margin-left: auto;
    font-size: 0.78rem;
    color: var(--text-muted);
}

.admin-report__summary {
    font-size: 0.92rem;
    color: var(--text-primary);
    margin-bottom: var(--space-sm);
    max-width: 90ch;
}

/* Rohtext einer noch nicht eingeordneten Meldung: kursiv und blasser, um
   ihn von einer Zusammenfassung zu unterscheiden. */
.admin-report__summary--raw {
    font-style: italic;
    color: var(--text-secondary);
}

.admin-report__tags { display: flex; gap: var(--space-xs); flex-wrap: wrap; }

.admin-sev {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 2px var(--space-sm);
    border-radius: var(--radius-sm);
    font-weight: 600;
}

.admin-sev--blocking { background: rgba(217, 104, 82, 0.2); color: var(--accent-red); }
.admin-sev--annoying { background: rgba(210, 133, 58, 0.2); color: var(--accent-orange); }
.admin-sev--minor    { background: rgba(212, 165, 63, 0.16); color: var(--accent-brass); }
.admin-sev--praise   { background: rgba(90, 158, 111, 0.2); color: var(--accent-green); }

.admin-status {
    font-size: 0.72rem;
    padding: 2px var(--space-sm);
    border-radius: 999px;
    border: 1px solid var(--border-subtle);
    color: var(--text-muted);
}
.admin-status--new   { border-color: rgba(212, 165, 63, 0.45); color: var(--accent-gold); }
.admin-status--seen  { border-color: rgba(91, 143, 199, 0.4); color: var(--accent-steel); }
.admin-status--fixed { border-color: rgba(90, 158, 111, 0.4); color: var(--accent-green); }

.admin-tag {
    font-size: 0.74rem;
    font-family: var(--font-mono);
    padding: 1px var(--space-sm);
    border-radius: var(--radius-sm);
    background: rgba(140, 175, 215, 0.08);
    color: var(--text-secondary);
}

.admin-tag--bug { background: rgba(217, 104, 82, 0.14); color: #e59182; }
.admin-tag--praise { background: rgba(90, 158, 111, 0.16); color: #87c49a; }
.admin-tag--dup { background: rgba(155, 123, 184, 0.16); color: #bfa5d4; }
.admin-tag--unclear { background: rgba(107, 127, 153, 0.16); }
.admin-tag--note { background: rgba(212, 165, 63, 0.14); color: var(--accent-brass); }

/* Eine Einordnung, der das Modell selbst nicht traut, soll nicht wie
   eine sichere aussehen. */
.admin-tag--unsure {
    background: rgba(107, 127, 153, 0.12);
    color: var(--text-muted);
    border: 1px dashed var(--border-subtle);
}
.admin-tag--sure { background: rgba(90, 158, 111, 0.12); color: #87c49a; }

.admin-tag--pending {
    background: none;
    border: 1px dashed rgba(212, 165, 63, 0.4);
    color: var(--accent-brass);
}

/* ─── Eine Meldung im Detail ──────────────────────────────────────── */

.admin-report__detail { margin-top: var(--space-md); }

.admin-report__detail > summary {
    font-size: 0.82rem;
    color: var(--text-secondary);
    cursor: pointer;
    padding: var(--space-xs) 0;
    user-select: none;
}
.admin-report__detail > summary:hover { color: var(--accent-gold); }

.admin-report__body {
    padding-top: var(--space-md);
    margin-top: var(--space-sm);
    border-top: 1px solid var(--border-subtle);
}

.admin-report__body h4 {
    font-size: 0.76rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--accent-brass);
    margin: var(--space-md) 0 var(--space-xs);
}
.admin-report__body h4:first-child { margin-top: 0; }
.admin-report__body p { font-size: 0.88rem; color: var(--text-secondary); max-width: 85ch; }

.admin-kv { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.admin-kv th {
    text-align: left;
    font-weight: 500;
    color: var(--text-muted);
    padding: 3px var(--space-md) 3px 0;
    white-space: nowrap;
    vertical-align: top;
    width: 1%;
}
.admin-kv td { padding: 3px 0; color: var(--text-secondary); font-family: var(--font-mono); font-size: 0.95em; }

.admin-console {
    font-family: var(--font-mono);
    font-size: 0.76rem;
    line-height: 1.65;
    background: var(--ocean-900);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    padding: var(--space-sm) var(--space-md);
    color: #e59182;
    overflow-x: auto;
    white-space: pre;
}

.admin-shot {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    overflow: hidden;
    max-width: 640px;
}
.admin-shot img { display: block; width: 100%; height: auto; }

/* Scheitert das Laden, tritt eine Textmeldung an die Stelle des Bildes
   (siehe admin.js). Ohne Innenabstand klebte sie am Rahmen – der war
   fuer ein randlos sitzendes Bild gemacht. */
.admin-shot .admin-empty { padding: var(--space-lg) var(--space-md); }

.admin-shot--placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 16 / 9;
    background: repeating-linear-gradient(
        45deg,
        rgba(140, 175, 215, 0.04),
        rgba(140, 175, 215, 0.04) 10px,
        transparent 10px,
        transparent 20px
    );
    color: var(--text-muted);
    font-size: 0.82rem;
    text-align: center;
}
.admin-shot--placeholder small { font-family: var(--font-mono); font-size: 0.9em; opacity: 0.7; }

.admin-note {
    font: inherit;
    font-size: 0.85rem;
    width: 100%;
    max-width: 640px;
    background: var(--ocean-800);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    padding: var(--space-sm) var(--space-md);
    resize: vertical;
}
.admin-note:focus { outline: none; border-color: rgba(212, 165, 63, 0.5); }

.admin-report__actions {
    display: flex;
    gap: var(--space-sm);
    margin-top: var(--space-md);
    flex-wrap: wrap;
}

/* ─── Grenzen der Daten ───────────────────────────────────────────── */

.admin-limits { list-style: none; display: grid; gap: var(--space-sm); }
.admin-limits li {
    font-size: 0.84rem;
    color: var(--text-muted);
    line-height: 1.6;
    padding-left: var(--space-md);
    border-left: 2px solid var(--border-subtle);
    max-width: 85ch;
}
.admin-limits strong { color: var(--text-secondary); }

/* ─── Anmeldung ───────────────────────────────────────────────────── */

/* [hidden] muss staerker sein als jede display-Regel.
 *
 * Das Attribut hidden setzt im Browser nur eine VORGABE (display: none aus
 * dem User-Agent-Stylesheet). Jede Regel aus dieser Datei ist staerker –
 * und .admin-login traegt display: flex. Das Ergebnis war, dass der
 * Anmeldekasten auch nach erfolgreicher Anmeldung sichtbar blieb und das
 * Dashboard darunter stand.
 *
 * Die Regel gilt bewusst fuer ALLE Elemente, nicht nur fuer die beiden
 * Bereiche: Auch die Fehlermeldung und die Zahl offener Meldungen werden
 * ueber hidden geschaltet, und dieselbe Falle wartet dort beim naechsten
 * display-Zusatz. */
[hidden] { display: none !important; }

.admin-login {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-lg);
}

.admin-login__box {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-xl);
    max-width: 420px;
    width: 100%;
    text-align: center;
}

.admin-login__mark {
    font-family: var(--font-display);
    font-size: 1.3rem;
    color: var(--accent-gold);
    display: block;
    margin-bottom: var(--space-xs);
}

.admin-login__title {
    font-size: 0.76rem;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--text-muted);
    margin-bottom: var(--space-lg);
}

.admin-login__text {
    font-size: 0.86rem;
    color: var(--text-secondary);
    margin-bottom: var(--space-lg);
    line-height: 1.6;
}

.admin-login .admin-btn { width: 100%; padding: var(--space-md); font-size: 0.92rem; }

.admin-login__error {
    font-size: 0.84rem;
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-md);
    text-align: left;
    line-height: 1.55;
}
.admin-login__error.is-denied {
    background: rgba(210, 133, 58, 0.12);
    border: 1px solid rgba(210, 133, 58, 0.4);
    color: #e5a86f;
}
.admin-login__error.is-error {
    background: rgba(217, 104, 82, 0.12);
    border: 1px solid rgba(217, 104, 82, 0.4);
    color: #e59182;
}

/* ─── Fehlerprotokoll ─────────────────────────────────────────────── */

/* Eine Protokollzeile, wie PHP sie geschrieben hat: Festbreite, weil
   Pfade, Kennungen und Zeilennummern darin zaehlen, und umbrechend,
   weil manche Meldung ueber mehrere hundert Zeichen geht. */
.admin-log-line {
    font-family: var(--font-mono);
    font-size: 0.82rem;
    color: var(--text-primary);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    margin: var(--space-xs) 0 0;
}

.admin-log-more {
    display: flex;
    justify-content: center;
    margin-top: var(--space-md);
}

/* ─── Zustaende ───────────────────────────────────────────────────── */

.admin-empty,
.admin-loading {
    padding: var(--space-xl);
    text-align: center;
    color: var(--text-muted);
    font-size: 0.88rem;
}

.admin-toast {
    position: fixed;
    bottom: var(--space-lg);
    left: 50%;
    transform: translateX(-50%);
    background: var(--ocean-700);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    padding: var(--space-sm) var(--space-lg);
    font-size: 0.86rem;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
    z-index: 100;
}
.admin-toast.is-error { border-color: rgba(217, 104, 82, 0.5); color: #e59182; }

/* ─── Schmale Fenster ─────────────────────────────────────────────── */

@media (max-width: 720px) {
    .admin-shell { padding: 0 var(--space-md); }

    .admin-head { gap: var(--space-sm); }
    .admin-head__user { width: 100%; order: 3; justify-content: space-between; }
    .admin-tabs { width: 100%; order: 2; overflow-x: auto; }

    .admin-toolbar__right { margin-left: 0; width: 100%; }
    .admin-search { flex: 1; min-width: 0; }

    .admin-report__time { margin-left: 0; width: 100%; }

    .admin-chart { height: 220px; }
    .admin-chart--tall { height: 300px; }
}
