import { useState, useEffect, useCallback, createContext, useContext } from "react";

// ── Color palette — Dark Ocean (glassmorphism, WCAG 2.1 AA) ────
const C = {
  pageBg: '#04101e',
  headerBg: 'linear-gradient(180deg, #020810 0%, #031120 50%, #04182e 100%)',
  card: 'rgba(8,28,52,0.72)',
  cardSoft: 'rgba(255,255,255,0.04)',
  cardBorder: 'rgba(255,255,255,0.10)',
  inputBg: 'rgba(255,255,255,0.08)',
  inputBorder: 'rgba(255,255,255,0.32)',
  inputFocus: '#22d3ee',
  primary: '#22d3ee',         // cyan-400 — ~8:1 on dark ✓
  primaryDark: '#0e7490',
  primaryLight: 'rgba(34,211,238,0.14)',
  secondary: '#2dd4bf',       // teal-400
  secondaryLight: 'rgba(45,212,191,0.14)',
  accent: '#818cf8',          // indigo-400
  accentLight: 'rgba(129,140,248,0.14)',
  // Status — WCAG AA konform auf dunklem Hintergrund (≥4,5:1)
  ok:    { bg: 'rgba(34,197,94,0.12)',  text: '#4ade80', border: 'rgba(74,222,128,0.30)',   badge: 'rgba(34,197,94,0.20)',  dot: '#22c55e', stripe: 'rgba(34,197,94,0.08)'   },
  low:   { bg: 'rgba(245,158,11,0.12)', text: '#fcd34d', border: 'rgba(252,211,77,0.30)',   badge: 'rgba(245,158,11,0.20)', dot: '#f59e0b', stripe: 'rgba(245,158,11,0.08)'  },
  high:  { bg: 'rgba(239,68,68,0.12)',  text: '#fca5a5', border: 'rgba(252,165,165,0.30)',  badge: 'rgba(239,68,68,0.20)',  dot: '#ef4444', stripe: 'rgba(239,68,68,0.08)'   },
  empty: { bg: 'transparent',           text: 'rgba(240,249,255,0.50)', border: 'rgba(255,255,255,0.12)', badge: 'rgba(255,255,255,0.08)', dot: 'rgba(255,255,255,0.30)', stripe: 'transparent' },
  txt1: '#f0f9ff',                        // ~20:1 on dark ✓
  txt2: 'rgba(240,249,255,0.82)',          // ~13:1 ✓
  txt3: 'rgba(240,249,255,0.60)',          // ~8:1 ✓
  txt4: 'rgba(240,249,255,0.45)',          // ~4.8:1 ✓ WCAG AA
  shadow: '0 4px 24px rgba(0,0,0,0.50)',
  shadowMd: '0 8px 40px rgba(0,0,0,0.60)',
  shadowLg: '0 20px 64px rgba(0,0,0,0.70)',
};
// Glassmorphism helper — spread into card/modal style objects
const GLASS = { backdropFilter: 'blur(16px)', WebkitBackdropFilter: 'blur(16px)' };

// ── Data ───────────────────────────────────────────────────────
const SOLLWERTE = {
  pH:   { min: 6.5,  max: 6.8,  unit: "",      label: "pH-Wert",         icon: "⚗️" },
  KH:   { min: 4,    max: 6,    unit: "°dKH",  label: "Karbonathärte",   icon: "🪨" },
  GH:   { min: 3,    max: 10,   unit: "°dGH",  label: "Gesamthärte",     icon: "💧" },
  CO2:  { min: 20,   max: 30,   unit: "mg/l",  label: "CO₂",             icon: "🌿" },
  NO3:  { min: 10,   max: 25,   unit: "mg/l",  label: "Nitrat (NO₃)",    icon: "🧪" },
  NO2:  { min: 0,    max: 0.1,  unit: "mg/l",  label: "Nitrit (NO₂)",    icon: "☠️" },
  PO4:  { min: 0.1,  max: 0.4,  unit: "mg/l",  label: "Phosphat (PO₄)",  icon: "🌱" },
  Fe:   { min: 0.05, max: 0.2,  unit: "mg/l",  label: "Eisen (Fe)",      icon: "⚙️" },
  K:    { min: 5,    max: 15,   unit: "mg/l",  label: "Kalium (K)",      icon: "🔋" },
  Mg:   { min: 7,    max: 15,   unit: "mg/l",  label: "Magnesium (Mg)",  icon: "✨" },
  Ca:   { min: 20,   max: 40,   unit: "mg/l",  label: "Calcium (Ca)",    icon: "🦴" },
  NH4:  { min: 0,    max: 0.25, unit: "mg/l",  label: "Ammonium (NH₄)",  icon: "⚠️" },
  O2:   { min: 6,    max: 10,   unit: "mg/l",  label: "Sauerstoff (O₂)", icon: "💨" },
  Temp: { min: 22,   max: 26,   unit: "°C",    label: "Temperatur",      icon: "🌡️" },
  Leit: { min: 150,  max: 500,  unit: "μS/cm", label: "Leitfähigkeit",   icon: "⚡" },
};
const PARAM_KEYS = Object.keys(SOLLWERTE);

const DUENGER_DB = [
  {
    id: "npk",
    name: "Aqua Rebell Makro Basic NPK",
    kurz: "NPK",
    farbe: "#16a34a", icon: "🌿", typ: "Makro",
    link: "https://www.aquasabi.de/Aqua-Rebell-Makro-Basic-NPK",
    zweck: "NO₃ + PO₄ + K + Mg – Grundversorgung",
    notiz: "Hebt gleichzeitig NO₃, PO₄, K und Mg an. Eisen/PO₄-Dünger zeitversetzt geben.",
    pro1ml100L: { NO3: 0.25, PO4: 0.025, K: 0.325, Mg: 0.025 },
  },
  {
    id: "gh-boost-n",
    name: "Aqua Rebell Advanced GH Boost N",
    kurz: "GH Boost N",
    farbe: "#7c3aed", icon: "🧬", typ: "Makro",
    link: "https://www.aquasabi.de/Aqua-Rebell-Advanced-GH-Boost-N",
    zweck: "NO₃ (kaliumfrei) + Mg + etwas Ca",
    notiz: "KEIN Kalium – beste Wahl wenn K bereits im Soll. Hebt Mg und leicht Ca mit an.",
    pro1ml100L: { NO3: 0.748, Mg: 0.137, Ca: 0.016 },
  },
  {
    id: "makro-nitrat",
    name: "Aqua Rebell Makro Basic Nitrat",
    kurz: "Makro Nitrat",
    farbe: "#15803d", icon: "💚", typ: "Makro",
    link: "https://www.aquasabi.de/Aqua-Rebell-Makro-Basic-Nitrat",
    zweck: "NO₃ + K (KNO₃-basiert)",
    notiz: "Enthält auch Kalium (NK-Dünger). Bei K-Überschuss lieber GH Boost N verwenden.",
    pro1ml100L: { NO3: 0.109, K: 0.030 },
  },
  {
    id: "makro-phosphat",
    name: "Aqua Rebell Makro Basic Phosphat",
    kurz: "Makro PO₄",
    farbe: "#dc2626", icon: "🔴", typ: "Makro",
    link: "https://www.aquasabi.de/Aqua-Rebell-Makro-Basic-Phosphat",
    zweck: "PO₄ Einzelkomponente (rein)",
    notiz: "Zeitversetzt zu Eisendünger geben (morgens Fe / abends PO₄). Nicht überdosieren.",
    pro1ml100L: { PO4: 0.065 },
  },
  {
    id: "makro-kalium",
    name: "Aqua Rebell Makro Basic Kalium",
    kurz: "Makro K",
    farbe: "#d97706", icon: "🟡", typ: "Makro",
    link: "https://www.aquasabi.de/Aqua-Rebell-Makro-Basic-Kalium",
    zweck: "K Einzelkomponente (rein, keine Nebenwirkungen)",
    notiz: "Reine K-Quelle ohne weitere Makronährstoffe. Zoobox: 10ml/100L = +2,5 mg/l K.",
    pro1ml100L: { K: 0.25 },
  },
  {
    id: "flowgrow",
    name: "Aqua Rebell Mikro Spezial Flowgrow",
    kurz: "Flowgrow",
    farbe: "#0284c7", icon: "⚙️", typ: "Mikro",
    link: "https://www.aquasabi.de/Aqua-Rebell-Mikro-Spezial-Flowgrow",
    zweck: "Fe + Spurenelemente (schnell, täglich) + K + Mg",
    notiz: "Sanft chelatiert – Fe sofort pflanzenaufnehmbar. Fe nach Zugabe im Test oft nicht messbar – normal! Morgens düngen.",
    pro1ml100L: { Fe: 0.041, K: 0.006, Mg: 0.010 },
  },
  {
    id: "basic-eisen",
    name: "Aqua Rebell Mikro Basic Eisen",
    kurz: "Basic Eisen",
    farbe: "#b45309", icon: "🔩", typ: "Mikro",
    link: "https://www.aquasabi.de/Aqua-Rebell-Mikro-Basic-Eisen",
    zweck: "Fe + Spurenelemente (stark chelatiert, Wochendünger)",
    notiz: "Stark chelatiert (EDTA/DTPA) – Fe dauerhaft nachweisbar. Ideal beim Wasserwechsel.",
    pro1ml100L: { Fe: 0.040, K: 0.006 },
  },
  {
    id: "spezial-eisen",
    name: "Aqua Rebell Mikro Spezial Eisen",
    kurz: "Spezial Eisen",
    farbe: "#92400e", icon: "🟤", typ: "Mikro",
    link: "https://www.aquasabi.de/Aqua-Rebell-Mikro-Spezial-Eisen",
    zweck: "Extra Fe (hoch dosiert) + Mn bei Eisenmangel",
    notiz: "Höherer Fe-Gehalt für Rotalgen-Prävention und intensive Rotfärbung. Nicht dauerhaft überdosieren.",
    pro1ml100L: { Fe: 0.039 },
  },
];

// ── Logic ──────────────────────────────────────────────────────
function berechneEmpfehlungen(istWerte, liter) {
  const ist = {};
  PARAM_KEYS.forEach(k => { const v = parseFloat(istWerte[k]); ist[k] = isNaN(v) ? null : v; });
  const ergebnis = [];
  for (const param of ["NO3", "PO4", "Fe", "K", "Mg", "Ca"]) {
    if (ist[param] === null) continue;
    const soll = SOLLWERTE[param];
    const ziel = (soll.min + soll.max) / 2;
    const diff = ziel - ist[param];
    if (diff <= 0.001) continue;
    const kandidaten = DUENGER_DB
      .filter(d => d.pro1ml100L[param] !== undefined)
      .map(d => {
        const mlNoetig = (diff / d.pro1ml100L[param]) * (liter / 100);
        const seiteneffekte = [];
        let blockiert = false;
        for (const [np, nv] of Object.entries(d.pro1ml100L)) {
          if (np === param) continue;
          const anhebung = nv * mlNoetig / (liter / 100);
          if (anhebung < 0.001) continue;
          const npIst = ist[np] ?? ((SOLLWERTE[np].min + SOLLWERTE[np].max) / 2);
          const npNach = npIst + anhebung;
          const npSoll = SOLLWERTE[np];
          if (!npSoll) continue;
          const problem = npNach > npSoll.max;
          if (problem) blockiert = true;
          seiteneffekte.push({ par: np, von: +npIst.toFixed(3), nach: +npNach.toFixed(3), anhebung: +anhebung.toFixed(3), problem });
        }
        return { duenger: d, mlNoetig, seiteneffekte, blockiert };
      })
      .sort((a, b) => {
        if (a.blockiert !== b.blockiert) return a.blockiert ? 1 : -1;
        return a.seiteneffekte.filter(s => s.problem).length - b.seiteneffekte.filter(s => s.problem).length;
      });
    ergebnis.push({ param, ist: ist[param], ziel, diff, empfehlung: kandidaten[0], alternativ: kandidaten.slice(1).filter(k => !k.blockiert), alleKandidaten: kandidaten });
  }
  return ergebnis;
}

function getStatus(key, value) {
  if (value === "" || value === null || value === undefined) return "leer";
  const v = parseFloat(value);
  if (isNaN(v)) return "leer";
  const { min, max } = SOLLWERTE[key];
  if (v < min) return "niedrig";
  if (v > max) return "hoch";
  return "ok";
}

// map internal status names to C keys
function statusToC(status) {
  if (status === "ok") return C.ok;
  if (status === "niedrig") return C.low;
  if (status === "hoch") return C.high;
  return C.empty;
}

// ── Responsive Breakpoint Hook ──────────────────────────────────
function useBreakpoint() {
  const [width, setWidth] = useState(typeof window !== "undefined" ? window.innerWidth : 1024);
  useEffect(() => {
    const handler = () => setWidth(window.innerWidth);
    window.addEventListener("resize", handler);
    return () => window.removeEventListener("resize", handler);
  }, []);
  return {
    isMobile:  width < 640,
    isTablet:  width >= 640 && width < 1024,
    isDesktop: width >= 1024,
    width,
  };
}

// ── StatusBadge ────────────────────────────────────────────────
function StatusBadge({ status }) {
  const cs = statusToC(status);
  // WCAG 1.4.1: Icon + Text (nie nur Farbe)
  // Alle Kontraste auf badge-Hintergrund geprüft (≥4,5:1):
  //   ok.text   #166534 auf #dcfce7 → 8,2:1 ✓
  //   low.text  #9a3412 auf #ffedd5 → 7,1:1 ✓
  //   high.text #991b1b auf #fee2e2 → 6,6:1 ✓
  //   empty.text #475569 auf #f1f5f9 → 5,4:1 ✓
  const labels = {
    ok:      { icon: "✓", text: "OK"          },
    niedrig: { icon: "↓", text: "Mangel"      },
    hoch:    { icon: "↑", text: "Überschuss"  },
    leer:    { icon: "–", text: "Offen"       },
  };
  const l = labels[status] || labels.leer;
  return (
    <span
      role="status"
      aria-label={`Status: ${l.text}`}
      style={{
        background: cs.badge,
        color: cs.text,
        border: `1.5px solid ${cs.border}`,
        borderRadius: 999,
        padding: "2px 9px",
        fontSize: 10,
        fontFamily: "'DM Mono', monospace",
        fontWeight: 700,
        whiteSpace: "nowrap",
        letterSpacing: "0.02em",
        display: "inline-flex",
        alignItems: "center",
        gap: 3,
      }}
    >
      <span aria-hidden="true">{l.icon}</span>
      {l.text}
    </span>
  );
}

// ── GaugeBar ───────────────────────────────────────────────────
function GaugeBar({ paramKey, value, param, gaugeId }) {
  if (!value || isNaN(parseFloat(value))) return null;
  const v = parseFloat(value);
  const { min, max } = param;
  const pad = (max - min) * 0.5;
  const lo = min - pad, total = max + pad - lo;
  const pct = Math.min(100, Math.max(0, ((v - lo) / total) * 100));
  const minP = ((min - lo) / total) * 100;
  const maxP = ((max - lo) / total) * 100;
  const status = getStatus(paramKey, value);
  const cs = statusToC(status);
  // WCAG 1.4.1: Statusbeschreibung als Text, nicht nur Farbe
  const statusText = status === "ok" ? "im Sollbereich" : status === "niedrig" ? "unter Sollbereich" : "über Sollbereich";
  const fmtV = v < 0.01 ? v.toFixed(3) : v < 10 ? v.toFixed(2) : v.toFixed(1);
  return (
    <div style={{ marginTop: 8 }} id={gaugeId}>
      {/* Wert-Anzeige über der Gauge (WCAG 1.4.1: Wert auch als Text) */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 4 }}>
        <span style={{ fontSize: 10, color: cs.text, fontFamily: "'DM Mono', monospace", fontWeight: 700 }}>
          {fmtV} {param.unit || "pH"}
        </span>
        <span style={{ fontSize: 10, color: C.txt3, fontFamily: "'DM Mono', monospace" }}>
          {statusText}
        </span>
      </div>

      {/* Gauge-Track */}
      <div
        role="img"
        aria-label={`${param.label}: ${fmtV} ${param.unit || "pH"}, ${statusText}. Sollbereich: ${min}–${max} ${param.unit || "pH"}`}
        style={{ height: 10, borderRadius: 5, background: 'rgba(255,255,255,0.10)', position: "relative", overflow: "visible",
          border: '1px solid rgba(255,255,255,0.16)',
        }}
      >
        {/* Sollbereich — grün hinterlegt mit Schraffur für Farbblinde */}
        <div style={{
          position: "absolute",
          left: `${minP}%`,
          width: `${maxP - minP}%`,
          height: "100%",
          background: `linear-gradient(135deg, rgba(34,197,94,0.20) 25%, rgba(34,197,94,0.32) 25%, rgba(34,197,94,0.32) 50%, rgba(34,197,94,0.20) 50%, rgba(34,197,94,0.20) 75%, rgba(34,197,94,0.32) 75%)`,
          backgroundSize: "8px 8px",
          borderRadius: 4,
        }} />
        {/* Sollbereich-Rahmen */}
        <div style={{
          position: "absolute",
          left: `${minP}%`,
          width: `${maxP - minP}%`,
          height: "100%",
          border: `1.5px solid rgba(34,197,94,0.55)`,
          borderRadius: 4,
          boxSizing: "border-box",
        }} />
        {/* Positionsmarker — Dreieck + Punkt (Form ≠ nur Farbe) */}
        <div style={{
          position: "absolute",
          left: `calc(${pct}% - 6px)`,
          top: "50%",
          transform: "translateY(-50%)",
          width: 12,
          height: 12,
          borderRadius: "50%",
          background: cs.dot,
          border: "2.5px solid rgba(4,16,30,0.9)",
          boxShadow: `0 0 0 1.5px ${cs.dot}`,
          transition: "left 0.4s ease",
          zIndex: 2,
        }} />
      </div>

      {/* Skala-Beschriftung */}
      <div style={{ display: "flex", justifyContent: "space-between", marginTop: 3, fontFamily: "'DM Mono', monospace" }}>
        <span style={{ fontSize: 9, color: C.txt4 }}>{param.min}{param.unit}</span>
        <span style={{ fontSize: 9, color: '#4ade80', fontWeight: 600 }}>✓ Soll</span>
        <span style={{ fontSize: 9, color: C.txt4 }}>{param.max}{param.unit}</span>
      </div>
    </div>
  );
}

// ── ParamCard ──────────────────────────────────────────────────
// Statusklasse für CSS-Streifenmuster (WCAG 1.4.1: Farbe ≠ einziges Merkmal)
function statusClass(status) {
  if (status === "ok") return "param-card status-ok";
  if (status === "niedrig") return "param-card status-low";
  if (status === "hoch") return "param-card status-high";
  return "param-card";
}

function ParamCard({ paramKey, value, onChange, showInfo, onToggleInfo }) {
  const param = SOLLWERTE[paramKey];
  const status = getStatus(paramKey, value);
  const cs = statusToC(status);
  const inputId = `input-${paramKey}`;
  return (
    <div
      className={statusClass(status)}
      role="group"
      aria-label={`${param.label} – ${status === "ok" ? "im Sollbereich" : status === "niedrig" ? "Mangelwert" : status === "hoch" ? "Überschuss" : "nicht gemessen"}`}
      style={{
        background: cs.bg,                      // ← Subtiler Statushintergrund
        border: `1.5px solid ${cs.border}`,
        borderLeft: `5px solid ${cs.dot}`,      // ← Dicker Farbbalken links
        borderRadius: 16,
        padding: "14px 14px 12px 14px",
        boxShadow: C.shadow,
        position: "relative",
      }}
    >
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 8 }}>
        <label htmlFor={inputId} style={{ display: "flex", alignItems: "center", gap: 7, cursor: "pointer" }}>
          <span style={{ fontSize: 16 }} aria-hidden="true">{param.icon}</span>
          <span style={{ color: C.txt1, fontSize: 13, fontWeight: 700 }}>{param.label}</span>
        </label>
        <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
          <StatusBadge status={status} />
          <button
            onClick={() => onToggleInfo(paramKey)}
            aria-label={`Sollwert-Info für ${param.label} ${showInfo ? "ausblenden" : "anzeigen"}`}
            aria-expanded={showInfo}
            style={{
              background: showInfo ? C.primaryLight : "rgba(255,255,255,0.7)",
              border: `1.5px solid ${showInfo ? C.primary : '#94a3b8'}`, // ≥3:1 auf cs.bg
              cursor: "pointer",
              color: showInfo ? C.primary : C.txt3,
              fontSize: 11,
              borderRadius: 6,
              width: 24,
              height: 24,
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              padding: 0,
              fontWeight: 700,
            }}
          >ⓘ</button>
        </div>
      </div>

      {showInfo && (
        <div
          role="note"
          style={{
            background: C.primaryLight,
            borderRadius: 8,
            padding: "6px 10px",
            color: C.txt2,
            fontSize: 11,
            marginBottom: 8,
            borderLeft: `3px solid ${C.primary}`,
            fontFamily: "'DM Mono', monospace",
          }}
        >
          📏 Sollbereich: <strong>{param.min}–{param.max} {param.unit || "pH"}</strong>
        </div>
      )}

      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
        <input
          id={inputId}
          type="number"
          value={value}
          onChange={e => onChange(paramKey, e.target.value)}
          placeholder={`z. B. ${((param.min + param.max) / 2).toFixed(param.min < 1 ? 2 : 1)}`}
          step={["°C", "°dKH", "°dGH"].includes(param.unit) ? "0.1" : "0.01"}
          aria-label={`${param.label} Messwert${param.unit ? " in " + param.unit : ""}, Sollbereich ${param.min} bis ${param.max}`}
          aria-describedby={value ? `gauge-${paramKey}` : undefined}
          style={{
            background: "rgba(255,255,255,0.07)",
            border: `2px solid ${value ? cs.dot : 'rgba(255,255,255,0.28)'}`,
            borderRadius: 10,
            color: C.txt1,
            fontSize: 17,
            padding: "7px 11px",
            width: "100%",
            fontFamily: "'DM Mono', monospace",
            fontWeight: 600,
          }}
        />
        {/* Einheit: #475569 auf cs.bg ≥ 4,5:1 ✓ */}
        <span aria-hidden="true" style={{ color: C.txt3, fontSize: 12, whiteSpace: "nowrap", fontFamily: "'DM Mono', monospace", minWidth: 34, fontWeight: 600 }}>
          {param.unit || "pH"}
        </span>
      </div>
      <GaugeBar paramKey={paramKey} value={value} param={param} gaugeId={`gauge-${paramKey}`} />
    </div>
  );
}

// ── SummaryBanner ──────────────────────────────────────────────
function SummaryBanner({ values, isDesktop }) {
  let ok = 0, warn = 0, missing = 0;
  PARAM_KEYS.forEach(k => {
    const s = getStatus(k, values[k]);
    if (s === "ok") ok++;
    else if (s === "leer") missing++;
    else warn++;
  });
  const score = Math.round((ok / PARAM_KEYS.length) * 100);
  const scoreCs = score >= 80 ? C.ok : score >= 50 ? C.low : C.high;
  const barGradient = score >= 80
    ? `linear-gradient(90deg, ${C.secondary}, #34d399)`
    : score >= 50
    ? `linear-gradient(90deg, ${C.accent}, #fbbf24)`
    : `linear-gradient(90deg, #ef4444, #f97316)`;

  return (
    <div
      role="status"
      aria-live="polite"
      aria-label={`Wasserqualität: ${score}%, ${ok} Parameter OK, ${warn} Abweichungen, ${missing} nicht gemessen`}
      style={{
        background: C.card, ...GLASS,
        borderRadius: 20,
        boxShadow: C.shadowMd,
        padding: isDesktop ? "20px 24px" : "14px 16px",
        marginBottom: 14,
        border: `1.5px solid ${scoreCs.border}`,
      }}
    >
      <div style={{ display: "flex", alignItems: "center", gap: isDesktop ? 20 : 14, marginBottom: 12 }}>
        {/* Score — Text + Farbe + Form (3 Merkmale, WCAG 1.4.1 ✓) */}
        <div style={{
          textAlign: "center",
          flexShrink: 0,
          background: scoreCs.badge,
          borderRadius: 16,
          padding: isDesktop ? "12px 18px" : "8px 12px",
          border: `2px solid ${scoreCs.border}`,
        }}>
          <div style={{
            fontSize: isDesktop ? 44 : 34,
            fontWeight: 900,
            color: scoreCs.text,        // #166534/#9a3412/#991b1b — alle ≥6:1 auf badge ✓
            fontFamily: "'DM Mono', monospace",
            lineHeight: 1,
          }}>{score}<span style={{ fontSize: isDesktop ? 22 : 16 }}>%</span></div>
          <div style={{ fontSize: 10, color: scoreCs.text, marginTop: 2, fontWeight: 700, opacity: 0.8 }}>Wasserqualität</div>
        </div>
        {/* Stats */}
        <div style={{ flex: 1, display: "flex", flexDirection: "column", gap: 5 }}>
          <span style={{
            background: C.ok.badge,
            color: C.ok.text,
            borderRadius: 999,
            padding: "3px 10px",
            fontSize: 11,
            fontWeight: 700,
            display: "inline-flex",
            alignItems: "center",
            gap: 5,
            alignSelf: "flex-start",
          }}>
            <span style={{ width: 7, height: 7, borderRadius: "50%", background: C.ok.dot, display: "inline-block" }} />
            {ok} im Soll
          </span>
          <span style={{
            background: C.low.badge,
            color: C.low.text,
            borderRadius: 999,
            padding: "3px 10px",
            fontSize: 11,
            fontWeight: 700,
            display: "inline-flex",
            alignItems: "center",
            gap: 5,
            alignSelf: "flex-start",
          }}>
            <span style={{ width: 7, height: 7, borderRadius: "50%", background: C.low.dot, display: "inline-block" }} />
            {warn} Abweichung{warn !== 1 ? "en" : ""}
          </span>
          <span style={{
            background: C.empty.badge,
            color: C.empty.text,
            borderRadius: 999,
            padding: "3px 10px",
            fontSize: 11,
            fontWeight: 700,
            display: "inline-flex",
            alignItems: "center",
            gap: 5,
            alignSelf: "flex-start",
          }}>
            <span style={{ width: 7, height: 7, borderRadius: "50%", background: C.empty.dot, display: "inline-block" }} />
            {missing} offen
          </span>
        </div>
      </div>
      {/* Progress bar */}
      <div style={{ height: 8, borderRadius: 4, background: 'rgba(255,255,255,0.10)', overflow: "hidden" }}>
        <div style={{
          height: "100%",
          borderRadius: 4,
          background: barGradient,
          width: `${score}%`,
          transition: "width 0.5s ease",
        }} />
      </div>
    </div>
  );
}

// ── Formatter ──────────────────────────────────────────────────
function fmt(n) {
  if (n === undefined || n === null) return "–";
  return n < 0.01 ? n.toFixed(3) : n < 10 ? n.toFixed(2) : n.toFixed(1);
}

// ── EmpfehlungsKarte ───────────────────────────────────────────
function EmpfehlungsKarte({ rec, liter }) {
  const [showAlt, setShowAlt] = useState(false);
  const [showDetail, setShowDetail] = useState(false);
  const param = SOLLWERTE[rec.param];
  const emp = rec.empfehlung;
  const d = emp.duenger;
  const ml = emp.mlNoetig;

  return (
    <div
      className="rec-card"
      style={{
        background: C.card, ...GLASS,
        borderRadius: 16,
        border: `1px solid ${C.cardBorder}`,
        borderLeft: `4px solid ${d.farbe}`,
        boxShadow: C.shadow,
        marginBottom: 12,
        overflow: "hidden",
      }}
    >
      <div onClick={() => setShowDetail(s => !s)} style={{ padding: "13px 15px", cursor: "pointer" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 10 }}>
          <div>
            <div style={{ color: C.txt3, fontSize: 10, fontFamily: "'DM Mono', monospace", marginBottom: 3, fontWeight: 600 }}>
              {param.icon} {param.label} — Mangel
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
              <span style={{ color: C.high.text, fontFamily: "'DM Mono', monospace", fontSize: 14, fontWeight: 700 }}>{fmt(rec.ist)} {param.unit}</span>
              <span style={{ color: C.txt4, fontSize: 12 }}>→</span>
              <span style={{ color: C.ok.text, fontFamily: "'DM Mono', monospace", fontSize: 14, fontWeight: 700 }}>{fmt(rec.ziel)} {param.unit}</span>
              <span style={{ color: C.txt4, fontSize: 9, background: C.empty.badge, borderRadius: 4, padding: "1px 5px" }}>Sollmitte</span>
            </div>
          </div>
          <span style={{ color: C.txt4, fontSize: 12, transition: "transform 0.2s", display: "inline-block", transform: showDetail ? "rotate(180deg)" : "rotate(0deg)" }}>▼</span>
        </div>

        {/* Fertilizer pill */}
        <div style={{
          background: `${d.farbe}10`,
          border: `1px solid ${d.farbe}35`,
          borderRadius: 12,
          padding: "10px 12px",
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
          gap: 10,
        }}>
          <div style={{ flex: 1 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 3 }}>
              <span style={{ fontSize: 15 }}>{d.icon}</span>
              <span style={{ color: C.txt1, fontSize: 12, fontWeight: 700 }}>{d.name}</span>
              {emp.blockiert && (
                <span style={{ background: C.high.badge, color: C.high.text, fontSize: 9, padding: "1px 6px", borderRadius: 6, fontWeight: 700 }}>⚠ Konflikt</span>
              )}
            </div>
            <div style={{ color: C.txt3, fontSize: 10 }}>{d.zweck}</div>
          </div>
          <div style={{ textAlign: "right", flexShrink: 0 }}>
            <div style={{ color: d.farbe, fontSize: 24, fontWeight: 900, fontFamily: "'DM Mono', monospace", lineHeight: 1 }}>{fmt(ml)}<span style={{ fontSize: 13 }}> ml</span></div>
            <div style={{ color: C.txt4, fontSize: 9, fontFamily: "'DM Mono', monospace" }}>für {liter} L</div>
          </div>
        </div>

        {emp.seiteneffekte.length > 0 && (
          <div style={{ marginTop: 8, display: "flex", flexWrap: "wrap", gap: 4 }}>
            {emp.seiteneffekte.map(s => (
              <span key={s.par} style={{
                background: s.problem ? C.high.badge : C.empty.badge,
                border: `1px solid ${s.problem ? C.high.border : C.empty.border}`,
                color: s.problem ? C.high.text : C.txt3,
                fontSize: 10,
                padding: "2px 7px",
                borderRadius: 6,
                fontFamily: "'DM Mono', monospace",
              }}>
                {s.problem ? "⚠" : "+"} {SOLLWERTE[s.par]?.label || s.par}: {fmt(s.von)}→{fmt(s.nach)} {SOLLWERTE[s.par]?.unit}
              </span>
            ))}
          </div>
        )}
      </div>

      {showDetail && (
        <div style={{ padding: "0 15px 13px", borderTop: `1px solid ${C.cardBorder}` }}>
          {/* Calculation */}
          <div style={{ background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 10, padding: "10px 12px", marginTop: 10 }}>
            <div style={{ color: C.primary, fontSize: 10, fontWeight: 800, marginBottom: 6, fontFamily: "'DM Mono', monospace", letterSpacing: "0.05em" }}>BERECHNUNG</div>
            <div style={{ color: C.txt2, fontSize: 11, lineHeight: 1.9, fontFamily: "'DM Mono', monospace" }}>
              Fehlende Menge:&nbsp;<span style={{ color: C.accent }}>{fmt(rec.diff)} mg/l {param.unit}</span><br />
              1 ml {d.kurz} / 100 L hebt {rec.param} um:&nbsp;<span style={{ color: C.txt2 }}>{d.pro1ml100L[rec.param]} mg/l</span><br />
              Formel: {fmt(rec.diff)} ÷ {d.pro1ml100L[rec.param]} × ({liter}÷100)<br />
              <span style={{ color: d.farbe, fontWeight: 800 }}>= {fmt(ml)} ml für {liter} L Wasser</span>
            </div>
          </div>

          {/* Note */}
          <div style={{
            marginTop: 8,
            background: C.primaryLight,
            borderRadius: 9,
            padding: "8px 11px",
            color: C.txt2,
            fontSize: 11,
            borderLeft: `3px solid ${C.primary}`,
            lineHeight: 1.6,
          }}>
            💡 {d.notiz}
          </div>

          {emp.blockiert && (
            <div style={{
              marginTop: 8,
              background: C.high.bg,
              borderRadius: 9,
              padding: "8px 11px",
              color: C.high.text,
              fontSize: 11,
              borderLeft: `3px solid ${C.high.dot}`,
              lineHeight: 1.6,
            }}>
              ⚠️ Dieser Dünger würde einen anderen Parameter über den Sollwert heben. Erwäge eine Alternative oder reduziere die Menge.
            </div>
          )}

          {/* Alternatives */}
          {rec.alleKandidaten.length > 1 && (
            <div style={{ marginTop: 10 }}>
              <button
                onClick={() => setShowAlt(s => !s)}
                style={{
                  background: C.cardSoft,
                  border: `1px solid ${C.cardBorder}`,
                  borderRadius: 8,
                  color: C.txt3,
                  fontSize: 11,
                  padding: "5px 11px",
                  cursor: "pointer",
                  fontWeight: 600,
                }}
              >
                {showAlt ? "▲" : "▼"} {rec.alleKandidaten.length - 1} weitere Dünger
              </button>
              {showAlt && rec.alleKandidaten.slice(1).map(alt => (
                <div key={alt.duenger.id} style={{
                  marginTop: 6,
                  background: `${alt.duenger.farbe}0a`,
                  border: `1px solid ${alt.duenger.farbe}30`,
                  borderRadius: 10,
                  padding: "8px 11px",
                  display: "flex",
                  justifyContent: "space-between",
                  alignItems: "center",
                }}>
                  <div>
                    <div style={{ color: C.txt1, fontSize: 11, fontWeight: 700 }}>{alt.duenger.icon} {alt.duenger.name}</div>
                    <div style={{ color: C.txt3, fontSize: 10 }}>{alt.duenger.zweck}</div>
                    {alt.blockiert && <span style={{ color: C.high.text, fontSize: 9 }}>⚠ würde anderen Parameter überschreiten</span>}
                    {alt.seiteneffekte.filter(s => !s.problem).map(s => (
                      <span key={s.par} style={{ color: C.txt4, fontSize: 9, marginRight: 5 }}>
                        +{SOLLWERTE[s.par]?.label}: +{fmt(s.anhebung)} {SOLLWERTE[s.par]?.unit}
                      </span>
                    ))}
                  </div>
                  <div style={{
                    color: alt.blockiert ? C.high.text : alt.duenger.farbe,
                    fontFamily: "'DM Mono', monospace",
                    fontSize: 15,
                    fontWeight: 800,
                    flexShrink: 0,
                    marginLeft: 10,
                  }}>
                    {fmt(alt.mlNoetig)} ml
                  </div>
                </div>
              ))}
            </div>
          )}

          <a href={d.link} target="_blank" rel="noopener noreferrer" style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 4,
            marginTop: 10,
            color: d.farbe,
            fontSize: 11,
            textDecoration: "none",
            fontWeight: 600,
            borderBottom: `1.5px dashed ${d.farbe}60`,
            paddingBottom: 1,
          }}>
            🔗 Aquasabi Shop →
          </a>
        </div>
      )}
    </div>
  );
}

// ── DuengerTab ─────────────────────────────────────────────────
function DuengerTab({ values, bp }) {
  const [liter, setLiter] = useState(60);
  const emp = berechneEmpfehlungen(values, liter);
  const hoch = PARAM_KEYS.filter(k => getStatus(k, values[k]) === "hoch" && ["NO3", "PO4", "Fe", "K", "Mg", "Ca"].includes(k));
  const ohneWerte = ["NO3", "PO4", "Fe", "K", "Mg", "Ca"].every(k => !values[k]);

  const linksPanel = (
    <div>
      {/* Info card */}
      <div style={{
        background: C.primaryLight,
        border: `1px solid rgba(34,211,238,0.25)`,
        borderRadius: 12,
        padding: "11px 14px",
        marginBottom: 12,
        color: C.txt2,
        fontSize: 11,
        lineHeight: 1.7,
      }}>
        <div style={{ color: C.primary, fontWeight: 800, marginBottom: 3, fontSize: 12 }}>🧮 Ist → Soll Dünger-Rechner</div>
        Messwerte im Tab <b>Messen</b> eingeben → App berechnet die exakte Düngermenge für jeden Mangelwert und prüft Seiteneffekte auf andere Parameter.
      </div>

      {/* Volume */}
      <div style={{
        background: C.card,
        border: `1px solid ${C.cardBorder}`,
        borderRadius: 12,
        padding: "12px 14px",
        marginBottom: 12,
        boxShadow: C.shadow,
      }}>
        <div style={{ color: C.txt2, fontSize: 11, marginBottom: 8, fontWeight: 700 }}>🪣 Netto-Wasservolumen</div>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <input
            type="number"
            value={liter}
            onChange={e => setLiter(Math.max(1, parseInt(e.target.value) || 1))}
            min={1} max={2000}
            style={{
              background: C.inputBg,
              border: `1.5px solid ${C.inputBorder}`,
              borderRadius: 10,
              color: C.primary,
              fontSize: 22,
              fontWeight: 900,
              padding: "6px 12px",
              width: "100%",
              fontFamily: "'DM Mono', monospace",
            }}
          />
          <span style={{ color: C.txt3, fontSize: 14, fontFamily: "'DM Mono', monospace", fontWeight: 700 }}>L</span>
        </div>
        <input
          type="range"
          min={10} max={500}
          value={Math.min(liter, 500)}
          onChange={e => setLiter(parseInt(e.target.value))}
          style={{ width: "100%", marginTop: 10, accentColor: C.primary }}
        />
      </div>

      {/* Table */}
      <div style={{
        background: C.card,
        border: `1px solid ${C.cardBorder}`,
        borderRadius: 12,
        padding: "12px 14px",
        boxShadow: C.shadow,
      }}>
        <div style={{ color: C.txt2, fontSize: 10, fontWeight: 800, marginBottom: 8, letterSpacing: "0.04em" }}>📊 Nährstoffgehalt pro 1 ml / 100 L</div>
        <div style={{ overflowX: "auto", WebkitOverflowScrolling: "touch" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 10, fontFamily: "'DM Mono', monospace", minWidth: 320 }}>
            <thead>
              <tr style={{ borderBottom: `2px solid ${C.cardBorder}` }}>
                <th style={{ textAlign: "left", color: C.txt3, padding: "4px 5px", fontWeight: 700 }}>Dünger</th>
                {["NO3", "PO4", "Fe", "K", "Mg", "Ca"].map(p => (
                  <th key={p} style={{ textAlign: "right", color: C.txt3, padding: "4px 5px", fontWeight: 700 }}>{p}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {DUENGER_DB.map(d => (
                <tr key={d.id} style={{ borderBottom: `1px solid ${C.cardBorder}` }}>
                  <td style={{ color: d.farbe, padding: "5px 5px", whiteSpace: "nowrap", fontWeight: 700 }}>{d.icon} {d.kurz}</td>
                  {["NO3", "PO4", "Fe", "K", "Mg", "Ca"].map(p => (
                    <td key={p} style={{ textAlign: "right", color: d.pro1ml100L[p] ? C.txt2 : C.txt4, padding: "5px 5px" }}>
                      {d.pro1ml100L[p] || "–"}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div style={{ color: C.txt4, fontSize: 9, marginTop: 6 }}>Werte in mg/l · Quellen: Aquasabi / Zoobox / Garnelenhaus / Aqua-Rebell.de</div>
      </div>
    </div>
  );

  const rechtsPanel = (
    <div>
      {ohneWerte && (
        <div style={{
          textAlign: "center",
          padding: "50px 20px",
          color: C.txt4,
          background: C.card,
          borderRadius: 16,
          border: `1px solid ${C.cardBorder}`,
          boxShadow: C.shadow,
        }}>
          <div style={{ fontSize: 40, marginBottom: 10 }}>💧</div>
          <div style={{ color: C.txt2, fontWeight: 600, marginBottom: 4 }}>Noch keine Nährstoffwerte gemessen.</div>
          <span style={{ fontSize: 11, color: C.txt3 }}>Trage NO₃, PO₄, Fe, K, Mg oder Ca im Tab „Messen" ein.</span>
        </div>
      )}
      {emp.length > 0 && (
        <>
          <div style={{
            color: C.low.text,
            fontSize: 11,
            fontFamily: "'DM Mono', monospace",
            marginBottom: 10,
            fontWeight: 700,
            background: C.low.badge,
            display: "inline-block",
            borderRadius: 6,
            padding: "3px 10px",
          }}>↓ {emp.length} Mangelwert{emp.length > 1 ? "e" : ""} erkannt</div>
          {emp.map(rec => <EmpfehlungsKarte key={rec.param} rec={rec} liter={liter} />)}
        </>
      )}
      {!ohneWerte && emp.length === 0 && hoch.length === 0 && (
        <div style={{
          background: C.ok.bg,
          border: `1px solid ${C.ok.border}`,
          borderRadius: 14,
          padding: "18px",
          textAlign: "center",
          color: C.ok.text,
          fontSize: 13,
          fontWeight: 700,
        }}>
          ✓ Alle Nährstoffe im Sollbereich!<br />
          <span style={{ fontSize: 11, fontWeight: 400, color: C.ok.text, opacity: 0.8 }}>Kein Dünger nötig.</span>
        </div>
      )}
      {hoch.length > 0 && (
        <div style={{
          marginTop: 10,
          background: C.high.bg,
          border: `1px solid ${C.high.border}`,
          borderRadius: 14,
          padding: "12px 14px",
        }}>
          <div style={{ color: C.high.text, fontSize: 11, fontWeight: 800, marginBottom: 6 }}>↑ Überschuss – Teilwasserwechsel empfohlen</div>
          {hoch.map(k => (
            <div key={k} style={{ color: C.txt2, fontSize: 11, marginBottom: 3, fontFamily: "'DM Mono', monospace" }}>
              {SOLLWERTE[k].icon} {SOLLWERTE[k].label}: {values[k]} {SOLLWERTE[k].unit} → max. {SOLLWERTE[k].max}
            </div>
          ))}
          <div style={{ color: C.txt3, fontSize: 10, marginTop: 6 }}>25–50% Wasserwechsel reduziert Überschüsse.</div>
        </div>
      )}
    </div>
  );

  if (bp.isDesktop) {
    return (
      <div style={{ display: "grid", gridTemplateColumns: "340px 1fr", gap: 20, alignItems: "flex-start" }}>
        {linksPanel}
        {rechtsPanel}
      </div>
    );
  }
  return <div>{linksPanel}{rechtsPanel}</div>;
}

// ── LogEntry ───────────────────────────────────────────────────
function LogEntry({ entry, onDelete, isDesktop }) {
  const [exp, setExp] = useState(false);
  const okCount = PARAM_KEYS.filter(k => getStatus(k, entry.values[k]) === "ok").length;
  const filledCount = PARAM_KEYS.filter(k => entry.values[k] !== "" && entry.values[k] !== undefined).length;

  return (
    <div style={{
      background: C.card, ...GLASS,
      border: `1px solid ${C.cardBorder}`,
      borderRadius: 14,
      marginBottom: 8,
      overflow: "hidden",
      boxShadow: C.shadow,
      transition: "box-shadow 0.2s, transform 0.18s",
    }}>
      <div onClick={() => setExp(e => !e)} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "11px 14px", cursor: "pointer" }}>
        <div>
          <div style={{ color: C.txt1, fontSize: 13, fontWeight: 700 }}>
            📅 {new Date(entry.date).toLocaleDateString("de-DE", { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit" })}
          </div>
          {entry.note && <div style={{ color: C.txt3, fontSize: 10, marginTop: 2 }}>{entry.note.slice(0, 50)}{entry.note.length > 50 ? "…" : ""}</div>}
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <span style={{
            background: C.ok.badge,
            color: C.ok.text,
            fontSize: 10,
            fontFamily: "'DM Mono', monospace",
            fontWeight: 700,
            borderRadius: 999,
            padding: "2px 9px",
          }}>
            {okCount}/{filledCount} OK
          </span>
          <span style={{ color: C.txt4, fontSize: 12, transition: "transform 0.2s", display: "inline-block", transform: exp ? "rotate(180deg)" : "rotate(0deg)" }}>▼</span>
        </div>
      </div>
      {exp && (
        <div style={{ padding: "0 14px 12px", borderTop: `1px solid ${C.cardBorder}` }}>
          <div style={{
            display: "grid",
            gridTemplateColumns: isDesktop ? "repeat(5, 1fr)" : "repeat(3, 1fr)",
            gap: 5,
            marginTop: 10,
          }}>
            {PARAM_KEYS.map(k => {
              const v = entry.values[k];
              if (!v) return null;
              const st = getStatus(k, v);
              const cs = statusToC(st);
              return (
                <div key={k} style={{
                  background: cs.bg,
                  borderRadius: 8,
                  padding: "5px 8px",
                  fontSize: 10,
                  color: cs.text,
                  fontFamily: "'DM Mono', monospace",
                  border: `1px solid ${cs.border}`,
                  fontWeight: 600,
                }}>
                  {SOLLWERTE[k].icon} {k}: {v} <span style={{ color: C.txt4, fontWeight: 400 }}>{SOLLWERTE[k].unit}</span>
                </div>
              );
            })}
          </div>
          {entry.note && (
            <div style={{ marginTop: 8, color: C.txt2, fontSize: 11, borderTop: `1px solid ${C.cardBorder}`, paddingTop: 8 }}>
              📝 {entry.note}
            </div>
          )}
          <button
            onClick={() => onDelete(entry.id)}
            style={{
              marginTop: 8,
              background: "none",
              border: `1px solid ${C.high.border}`,
              color: C.high.text,
              borderRadius: 7,
              padding: "4px 11px",
              fontSize: 10,
              cursor: "pointer",
              fontWeight: 600,
            }}
          >Löschen</button>
        </div>
      )}
    </div>
  );
}

// ── API client ─────────────────────────────────────────────────
const JWT_KEY = "aqua_jwt";
async function apiFetch(path, opts = {}) {
  const token = localStorage.getItem(JWT_KEY);
  const res = await fetch(`/api${path}`, {
    ...opts,
    headers: { "Content-Type": "application/json", ...(token ? { Authorization: `Bearer ${token}` } : {}), ...opts.headers },
  });
  if (!res.ok) { const e = await res.json().catch(() => ({})); throw new Error(e.error || `HTTP ${res.status}`); }
  return res.json();
}

// ── Auth context ────────────────────────────────────────────────
const AuthCtx = createContext(null);
function useAuth() { return useContext(AuthCtx); }

// ── Global CSS injection (shared) ──────────────────────────────
function GlobalStyles() {
  useEffect(() => {
    const s = document.createElement("style");
    s.id = "aqua-global";
    s.textContent = `
      * { box-sizing: border-box; }
      body {
        background: radial-gradient(ellipse at 50% 0%, #0a2040 0%, #04101e 60%, #020c18 100%);
        min-height: 100vh;
      }
      *:focus-visible { outline: 3px solid #22d3ee; outline-offset: 3px; border-radius: 6px; }
      button:focus-visible, a:focus-visible { outline: 3px solid #22d3ee; outline-offset: 3px; border-radius: 6px; }
      input[type=number]:focus, textarea:focus, input[type=text]:focus, input[type=password]:focus {
        outline: 3px solid #22d3ee; outline-offset: 0; border-color: #22d3ee !important; box-shadow: 0 0 0 3px rgba(34,211,238,0.22) !important;
      }
      .param-card {
        transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
        cursor: default;
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
      }
      .param-card:hover { transform: translateY(-2px); box-shadow: 0 12px 40px rgba(0,0,0,0.55), 0 0 0 1px rgba(34,211,238,0.15) !important; }
      .status-ok  { background-image: repeating-linear-gradient(135deg, rgba(34,197,94,0.07) 0px, rgba(34,197,94,0.07) 2px, transparent 2px, transparent 12px); }
      .status-low { background-image: repeating-linear-gradient(135deg, rgba(245,158,11,0.07) 0px, rgba(245,158,11,0.07) 2px, transparent 2px, transparent 12px); }
      .status-high{ background-image: repeating-linear-gradient(135deg, rgba(239,68,68,0.07) 0px, rgba(239,68,68,0.07) 2px, transparent 2px, transparent 12px); }
      .tab-pill { transition: all 0.2s ease; }
      .tab-pill:hover { background: rgba(34,211,238,0.12) !important; color: #22d3ee !important; }
      .tab-pill.active { background: rgba(34,211,238,0.18) !important; color: #22d3ee !important; box-shadow: 0 0 0 1px rgba(34,211,238,0.4), 0 2px 12px rgba(34,211,238,0.2) !important; }
      .rec-card {
        transition: box-shadow 0.18s, transform 0.18s;
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
      }
      .rec-card:hover { transform: translateY(-1px); box-shadow: 0 8px 32px rgba(0,0,0,0.5) !important; }
      .btn-primary { transition: all 0.2s ease; }
      .btn-primary:hover { filter: brightness(1.12); transform: translateY(-1px); box-shadow: 0 8px 28px rgba(34,211,238,0.35) !important; }
      .modal-overlay { position: fixed; inset: 0; background: rgba(2,8,16,0.75); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); z-index: 100; display: flex; align-items: center; justify-content: center; padding: 16px; }
      input[type=range] { -webkit-appearance: none; height: 6px; border-radius: 3px; background: rgba(255,255,255,0.15); cursor: pointer; }
      input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; border-radius: 50%; background: #22d3ee; cursor: pointer; box-shadow: 0 2px 8px rgba(34,211,238,0.5); border: 2px solid rgba(4,16,30,0.9); }
      ::-webkit-scrollbar { width: 5px; height: 5px; }
      ::-webkit-scrollbar-track { background: rgba(255,255,255,0.04); }
      ::-webkit-scrollbar-thumb { background: rgba(34,211,238,0.25); border-radius: 3px; }
      ::-webkit-scrollbar-thumb:hover { background: rgba(34,211,238,0.45); }
      input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; }
      select { color-scheme: dark; }
      option { background: #0d1f36; color: #f0f9ff; }
    `;
    if (!document.getElementById("aqua-global")) document.head.appendChild(s);
    return () => { const el = document.getElementById("aqua-global"); if (el) el.remove(); };
  }, []);
  return null;
}

// ── LoginScreen ─────────────────────────────────────────────────
function LoginScreen({ onLogin }) {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError]       = useState("");
  const [loading, setLoading]   = useState(false);

  async function handleSubmit(e) {
    e.preventDefault();
    if (!username || !password) { setError("Bitte alle Felder ausfüllen."); return; }
    setLoading(true); setError("");
    try {
      const data = await apiFetch("/auth/login", { method: "POST", body: JSON.stringify({ username, password }) });
      localStorage.setItem(JWT_KEY, data.token);
      onLogin(data);
    } catch (err) {
      setError(err.message || "Anmeldung fehlgeschlagen.");
    } finally { setLoading(false); }
  }

  return (
    <div style={{ minHeight: "100vh", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", padding: 20, background: "radial-gradient(ellipse at 50% 0%, #0a2040 0%, #04101e 60%, #020c18 100%)" }}>
      {/* Header image card */}
      <div style={{ width: "100%", maxWidth: 420, borderRadius: "24px 24px 0 0", overflow: "hidden", position: "relative", height: 160 }}>
        <div style={{ position: "absolute", inset: 0, backgroundImage: "url('/aquascape.jpg')", backgroundSize: "cover", backgroundPosition: "center 40%" }} />
        <div style={{ position: "absolute", inset: 0, background: "linear-gradient(180deg, rgba(5,37,64,0.5) 0%, rgba(5,37,64,0.82) 100%)" }} />
        <div style={{ position: "absolute", inset: 0, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 8 }}>
          <span style={{ fontSize: 42 }}>🐠</span>
          <div style={{ color: "#fff", fontSize: 22, fontWeight: 800, letterSpacing: "0.01em" }}>Aquarium Logbuch</div>
          <div style={{ color: "rgba(255,255,255,0.6)", fontSize: 11, fontFamily: "'DM Mono', monospace" }}>Ist→Soll · Dünger-Rechner · Logbuch</div>
        </div>
      </div>
      {/* Login form */}
      <form onSubmit={handleSubmit} style={{ width: "100%", maxWidth: 420, background: 'rgba(6,18,38,0.88)', ...GLASS, borderRadius: "0 0 24px 24px", border: '1px solid rgba(34,211,238,0.15)', borderTop: 'none', padding: "28px 28px 32px", boxShadow: C.shadowLg }}>
        <div style={{ marginBottom: 16 }}>
          <label htmlFor="login-user" style={{ display: "block", color: C.txt2, fontSize: 12, fontWeight: 700, marginBottom: 6 }}>Benutzername</label>
          <input id="login-user" type="text" autoComplete="username" value={username} onChange={e => setUsername(e.target.value)}
            style={{ width: "100%", background: C.inputBg, border: `1.5px solid ${C.inputBorder}`, borderRadius: 10, color: C.txt1, fontSize: 15, padding: "10px 13px", fontFamily: "inherit" }} />
        </div>
        <div style={{ marginBottom: 20 }}>
          <label htmlFor="login-pw" style={{ display: "block", color: C.txt2, fontSize: 12, fontWeight: 700, marginBottom: 6 }}>Passwort</label>
          <input id="login-pw" type="password" autoComplete="current-password" value={password} onChange={e => setPassword(e.target.value)}
            style={{ width: "100%", background: C.inputBg, border: `1.5px solid ${C.inputBorder}`, borderRadius: 10, color: C.txt1, fontSize: 15, padding: "10px 13px", fontFamily: "inherit" }} />
        </div>
        {error && <div role="alert" style={{ background: C.high.bg, border: `1px solid ${C.high.border}`, borderRadius: 8, padding: "8px 12px", color: C.high.text, fontSize: 12, marginBottom: 14 }}>{error}</div>}
        <button type="submit" disabled={loading} className="btn-primary"
          style={{ width: "100%", background: `linear-gradient(135deg, ${C.primaryDark}, ${C.primary})`, border: "none", borderRadius: 14, color: "#041018", fontSize: 16, fontWeight: 800, height: 52, cursor: loading ? "wait" : "pointer", boxShadow: `0 4px 20px rgba(34,211,238,0.35)` }}>
          {loading ? "Anmelden…" : "Anmelden →"}
        </button>
      </form>
    </div>
  );
}

// ── AquariumModal ───────────────────────────────────────────────
function AquariumModal({ aquariums, current, onSelect, onCreate, onDelete, onClose }) {
  const [newName, setNewName]   = useState("");
  const [newVol, setNewVol]     = useState(60);
  const [creating, setCreating] = useState(false);
  const [err, setErr]           = useState("");

  async function handleCreate(e) {
    e.preventDefault();
    if (!newName.trim()) { setErr("Name erforderlich"); return; }
    setCreating(true);
    try { await onCreate(newName.trim(), newVol); setNewName(""); setNewVol(60); setErr(""); }
    catch (e) { setErr(e.message); }
    finally { setCreating(false); }
  }

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div onClick={e => e.stopPropagation()} style={{ background: 'rgba(4,14,28,0.92)', ...GLASS, borderRadius: 20, border: '1px solid rgba(34,211,238,0.15)', padding: 24, width: "100%", maxWidth: 480, boxShadow: C.shadowLg, maxHeight: "85vh", overflowY: "auto" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 18 }}>
          <span style={{ color: C.txt1, fontSize: 17, fontWeight: 800 }}>🐟 Aquarien</span>
          <button onClick={onClose} style={{ background: "none", border: "none", color: C.txt3, fontSize: 20, cursor: "pointer", lineHeight: 1 }}>✕</button>
        </div>
        {aquariums.map(aq => (
          <div key={aq.id} style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 12px", borderRadius: 12, marginBottom: 6, background: current?.id === aq.id ? C.primaryLight : C.cardSoft, border: `1.5px solid ${current?.id === aq.id ? C.primary : C.cardBorder}`, cursor: "pointer" }}
            onClick={() => { onSelect(aq); onClose(); }}>
            <span style={{ flex: 1, color: C.txt1, fontWeight: current?.id === aq.id ? 700 : 500, fontSize: 13 }}>🐠 {aq.name}</span>
            <span style={{ color: C.txt4, fontSize: 11, fontFamily: "'DM Mono', monospace" }}>{aq.volume} L</span>
            {current?.id !== aq.id && (
              <button onClick={ev => { ev.stopPropagation(); if (window.confirm(`"${aq.name}" wirklich löschen?`)) onDelete(aq.id); }}
                style={{ background: "none", border: "none", color: C.high.dot, cursor: "pointer", fontSize: 14, padding: "2px 6px" }} aria-label={`${aq.name} löschen`}>✕</button>
            )}
          </div>
        ))}
        <form onSubmit={handleCreate} style={{ marginTop: 18, borderTop: `1px solid ${C.cardBorder}`, paddingTop: 16 }}>
          <div style={{ color: C.txt2, fontSize: 12, fontWeight: 700, marginBottom: 10 }}>+ Neues Aquarium</div>
          <div style={{ display: "flex", gap: 8, marginBottom: 8 }}>
            <input type="text" placeholder="Name" value={newName} onChange={e => setNewName(e.target.value)}
              style={{ flex: 1, background: C.inputBg, border: `1.5px solid ${C.inputBorder}`, borderRadius: 10, color: C.txt1, fontSize: 13, padding: "8px 11px" }} />
            <input type="number" placeholder="Liter" value={newVol} onChange={e => setNewVol(+e.target.value)}
              style={{ width: 80, background: C.inputBg, border: `1.5px solid ${C.inputBorder}`, borderRadius: 10, color: C.txt1, fontSize: 13, padding: "8px 11px", textAlign: "right" }} />
          </div>
          {err && <div style={{ color: C.high.text, fontSize: 11, marginBottom: 8 }}>{err}</div>}
          <button type="submit" disabled={creating} style={{ width: "100%", background: `linear-gradient(135deg, ${C.primaryDark}, ${C.primary})`, border: "none", borderRadius: 10, color: "#fff", fontSize: 13, fontWeight: 700, padding: "9px", cursor: "pointer" }}>
            {creating ? "Anlegen…" : "Aquarium anlegen"}
          </button>
        </form>
      </div>
    </div>
  );
}

// ── AdminPanel ──────────────────────────────────────────────────
function AdminPanel({ onClose }) {
  const [users, setUsers]     = useState([]);
  const [loading, setLoading] = useState(true);
  const [newUser, setNewUser] = useState({ username: "", password: "", displayName: "", role: "user" });
  const [err, setErr]         = useState("");
  const [ok, setOk]           = useState("");

  const loadUsers = useCallback(async () => {
    try { setUsers(await apiFetch("/users")); } catch {} finally { setLoading(false); }
  }, []);
  useEffect(() => { loadUsers(); }, [loadUsers]);

  async function createUser(e) {
    e.preventDefault(); setErr(""); setOk("");
    try {
      await apiFetch("/users", { method: "POST", body: JSON.stringify(newUser) });
      setOk(`Benutzer "${newUser.username}" angelegt.`);
      setNewUser({ username: "", password: "", displayName: "", role: "user" });
      loadUsers();
    } catch (e) { setErr(e.message); }
  }
  async function deleteUser(id, name) {
    if (!window.confirm(`Benutzer "${name}" wirklich löschen?`)) return;
    try { await apiFetch(`/users/${id}`, { method: "DELETE" }); loadUsers(); } catch (e) { setErr(e.message); }
  }

  const inputStyle = { width: "100%", background: C.inputBg, border: `1.5px solid ${C.inputBorder}`, borderRadius: 10, color: C.txt1, fontSize: 13, padding: "8px 11px", fontFamily: "inherit" };

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div onClick={e => e.stopPropagation()} style={{ background: 'rgba(4,14,28,0.92)', ...GLASS, borderRadius: 20, border: '1px solid rgba(34,211,238,0.15)', padding: 24, width: "100%", maxWidth: 560, boxShadow: C.shadowLg, maxHeight: "90vh", overflowY: "auto" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 20 }}>
          <span style={{ color: C.txt1, fontSize: 17, fontWeight: 800 }}>⚙️ Benutzerverwaltung</span>
          <button onClick={onClose} style={{ background: "none", border: "none", color: C.txt3, fontSize: 20, cursor: "pointer" }}>✕</button>
        </div>

        {/* User list */}
        {loading ? <div style={{ color: C.txt3, textAlign: "center", padding: 20 }}>Lade…</div> : (
          <div style={{ marginBottom: 20 }}>
            {users.map(u => (
              <div key={u.id} style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 12px", borderRadius: 10, marginBottom: 6, background: C.cardSoft, border: `1px solid ${C.cardBorder}` }}>
                <div style={{ flex: 1 }}>
                  <div style={{ color: C.txt1, fontSize: 13, fontWeight: 700 }}>{u.displayName || u.username}</div>
                  <div style={{ color: C.txt4, fontSize: 11, fontFamily: "'DM Mono', monospace" }}>@{u.username} · {u.role}</div>
                </div>
                <span style={{ background: u.role === "admin" ? C.primaryLight : C.ok.badge, color: u.role === "admin" ? C.primary : C.ok.text, fontSize: 10, padding: "2px 8px", borderRadius: 999, fontWeight: 700 }}>{u.role}</span>
                {u.id !== "admin-1" && (
                  <button onClick={() => deleteUser(u.id, u.username)} style={{ background: "none", border: `1px solid ${C.high.border}`, borderRadius: 6, color: C.high.text, fontSize: 11, padding: "3px 8px", cursor: "pointer" }}>Löschen</button>
                )}
              </div>
            ))}
          </div>
        )}

        {/* Create user form */}
        <form onSubmit={createUser} style={{ borderTop: `1px solid ${C.cardBorder}`, paddingTop: 16 }}>
          <div style={{ color: C.txt2, fontSize: 13, fontWeight: 700, marginBottom: 12 }}>+ Neuen Benutzer anlegen</div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginBottom: 8 }}>
            <div>
              <label style={{ display: "block", color: C.txt3, fontSize: 11, fontWeight: 600, marginBottom: 4 }}>Benutzername</label>
              <input type="text" value={newUser.username} onChange={e => setNewUser(u => ({ ...u, username: e.target.value }))} style={inputStyle} />
            </div>
            <div>
              <label style={{ display: "block", color: C.txt3, fontSize: 11, fontWeight: 600, marginBottom: 4 }}>Passwort</label>
              <input type="password" value={newUser.password} onChange={e => setNewUser(u => ({ ...u, password: e.target.value }))} style={inputStyle} />
            </div>
            <div>
              <label style={{ display: "block", color: C.txt3, fontSize: 11, fontWeight: 600, marginBottom: 4 }}>Anzeigename</label>
              <input type="text" value={newUser.displayName} onChange={e => setNewUser(u => ({ ...u, displayName: e.target.value }))} style={inputStyle} />
            </div>
            <div>
              <label style={{ display: "block", color: C.txt3, fontSize: 11, fontWeight: 600, marginBottom: 4 }}>Rolle</label>
              <select value={newUser.role} onChange={e => setNewUser(u => ({ ...u, role: e.target.value }))}
                style={{ ...inputStyle, cursor: "pointer" }}>
                <option value="user">user</option>
                <option value="admin">admin</option>
              </select>
            </div>
          </div>
          {err && <div role="alert" style={{ color: C.high.text, fontSize: 12, marginBottom: 8, background: C.high.bg, padding: "6px 10px", borderRadius: 6 }}>{err}</div>}
          {ok  && <div role="status" style={{ color: C.ok.text,   fontSize: 12, marginBottom: 8, background: C.ok.bg,   padding: "6px 10px", borderRadius: 6 }}>{ok}</div>}
          <button type="submit" style={{ width: "100%", background: `linear-gradient(135deg, ${C.primaryDark}, ${C.primary})`, border: "none", borderRadius: 10, color: "#fff", fontSize: 13, fontWeight: 700, padding: "10px", cursor: "pointer" }}>
            Benutzer anlegen
          </button>
        </form>
      </div>
    </div>
  );
}

// ── ReminderBanner ──────────────────────────────────────────────
function ReminderBanner({ aquariumId }) {
  const [reminder, setReminder]   = useState(null);
  const [showEdit, setShowEdit]   = useState(false);
  const [interval, setInterval_]  = useState(7);
  const [lastChange, setLastChange] = useState(new Date().toISOString().slice(0, 10));

  const load = useCallback(async () => {
    try { const r = await apiFetch(`/aquariums/${aquariumId}/reminder`); setReminder(r); if (r) { setInterval_(r.intervalDays); setLastChange(r.lastChange?.slice(0, 10) || new Date().toISOString().slice(0, 10)); } }
    catch {}
  }, [aquariumId]);
  useEffect(() => { if (aquariumId) load(); }, [aquariumId, load]);

  if (!reminder?.enabled) return (
    <button onClick={() => setShowEdit(true)} style={{ display: "block", width: "100%", textAlign: "left", background: C.cardSoft, border: `1px dashed ${C.cardBorder}`, borderRadius: 10, padding: "8px 14px", color: C.txt4, fontSize: 11, cursor: "pointer", marginBottom: 10 }}>
      ⏰ Wasserwechsel-Erinnerung einrichten →
      {showEdit && <ReminderEditModal aquariumId={aquariumId} onClose={() => { setShowEdit(false); load(); }} />}
    </button>
  );

  const last = new Date(reminder.lastChange);
  const next = new Date(last); next.setDate(next.getDate() + reminder.intervalDays);
  const today = new Date(); today.setHours(0,0,0,0);
  const daysLeft = Math.ceil((next - today) / 86400000);
  const due = daysLeft <= 0;
  const soon = daysLeft <= 2 && daysLeft > 0;

  const bg = due ? C.high.bg : soon ? C.low.bg : C.ok.bg;
  const border = due ? C.high.border : soon ? C.low.border : C.ok.border;
  const text = due ? C.high.text : soon ? C.low.text : C.ok.text;
  const msg = due ? `Wasserwechsel überfällig! (vor ${-daysLeft + 1} Tag${-daysLeft === 0 ? "" : "en"})` : soon ? `Wasserwechsel in ${daysLeft} Tag${daysLeft === 1 ? "" : "en"}` : `Nächster Wasserwechsel in ${daysLeft} Tagen`;

  async function markDone() {
    const today = new Date().toISOString();
    try { await apiFetch(`/aquariums/${aquariumId}/reminder`, { method: "PUT", body: JSON.stringify({ ...reminder, lastChange: today }) }); load(); }
    catch {}
  }

  return (
    <div role="status" aria-live="polite" style={{ background: bg, border: `1.5px solid ${border}`, borderRadius: 12, padding: "10px 14px", marginBottom: 12, display: "flex", alignItems: "center", gap: 10 }}>
      <span style={{ fontSize: 18 }}>{due ? "🚨" : soon ? "⏰" : "✅"}</span>
      <span style={{ flex: 1, color: text, fontSize: 12, fontWeight: 600 }}>{msg}</span>
      <button onClick={markDone} style={{ background: text, color: "#fff", border: "none", borderRadius: 8, padding: "4px 10px", fontSize: 11, fontWeight: 700, cursor: "pointer" }}>Erledigt</button>
      <button onClick={() => setShowEdit(true)} style={{ background: "none", border: `1px solid ${border}`, borderRadius: 8, padding: "4px 8px", color: text, fontSize: 11, cursor: "pointer" }}>⚙</button>
      {showEdit && <ReminderEditModal aquariumId={aquariumId} reminder={reminder} onClose={() => { setShowEdit(false); load(); }} />}
    </div>
  );
}

function ReminderEditModal({ aquariumId, reminder, onClose }) {
  const [interval_, setInterval_] = useState(reminder?.intervalDays ?? 7);
  const [lastChange, setLastChange] = useState(reminder?.lastChange?.slice(0, 10) ?? new Date().toISOString().slice(0, 10));
  async function save(e) {
    e.preventDefault();
    await apiFetch(`/aquariums/${aquariumId}/reminder`, { method: "PUT", body: JSON.stringify({ intervalDays: interval_, lastChange: new Date(lastChange).toISOString(), enabled: true }) });
    onClose();
  }
  async function disable() {
    await apiFetch(`/aquariums/${aquariumId}/reminder`, { method: "PUT", body: JSON.stringify({ ...(reminder||{}), enabled: false }) });
    onClose();
  }
  return (
    <div className="modal-overlay" onClick={onClose}>
      <form onSubmit={save} onClick={e => e.stopPropagation()} style={{ background: 'rgba(4,14,28,0.92)', ...GLASS, borderRadius: 18, border: '1px solid rgba(34,211,238,0.15)', padding: 24, width: "100%", maxWidth: 360, boxShadow: C.shadowLg }}>
        <div style={{ color: C.txt1, fontSize: 15, fontWeight: 800, marginBottom: 16 }}>⏰ Wasserwechsel-Erinnerung</div>
        <label style={{ display: "block", color: C.txt2, fontSize: 12, fontWeight: 600, marginBottom: 4 }}>Intervall (Tage)</label>
        <input type="number" min={1} max={90} value={interval_} onChange={e => setInterval_(+e.target.value)}
          style={{ width: "100%", background: C.inputBg, border: `1.5px solid ${C.inputBorder}`, borderRadius: 10, color: C.txt1, fontSize: 18, fontWeight: 700, padding: "8px 12px", fontFamily: "'DM Mono', monospace", marginBottom: 12 }} />
        <label style={{ display: "block", color: C.txt2, fontSize: 12, fontWeight: 600, marginBottom: 4 }}>Letzter Wasserwechsel</label>
        <input type="date" value={lastChange} onChange={e => setLastChange(e.target.value)}
          style={{ width: "100%", background: C.inputBg, border: `1.5px solid ${C.inputBorder}`, borderRadius: 10, color: C.txt1, fontSize: 14, padding: "8px 12px", marginBottom: 16 }} />
        <div style={{ display: "flex", gap: 8 }}>
          <button type="submit" style={{ flex: 2, background: `linear-gradient(135deg, ${C.primaryDark}, ${C.primary})`, border: "none", borderRadius: 10, color: "#fff", fontSize: 13, fontWeight: 700, padding: "10px", cursor: "pointer" }}>Speichern</button>
          {reminder?.enabled && <button type="button" onClick={disable} style={{ flex: 1, background: "none", border: `1px solid ${C.cardBorder}`, borderRadius: 10, color: C.txt3, fontSize: 12, cursor: "pointer" }}>Deaktivieren</button>}
          <button type="button" onClick={onClose} style={{ flex: 1, background: "none", border: `1px solid ${C.cardBorder}`, borderRadius: 10, color: C.txt3, fontSize: 12, cursor: "pointer" }}>Abbrechen</button>
        </div>
      </form>
    </div>
  );
}

// ── WissenTab ───────────────────────────────────────────────────
function WissenTab({ bp }) {
  const [open, setOpen] = useState(null);
  const sections = [
    {
      id: "stickstoff", icon: "🔄", title: "Der Stickstoffkreislauf", color: "#22d3ee",
      summary: "NH₄ → NO₂ → NO₃: Biologische Filterung durch Bakterien ist das Herzstück jedes Aquariums.",
      content: [
        { head: "Ammonium / Ammoniak (NH₄/NH₃)", text: "Entsteht durch Fischkot, Futterreste und Pflanzenzerfäll. Bei pH < 7 liegt es als ungiftiges NH₄ vor. Ab pH 7 wandelt es sich zunehmend in giftiges NH₃ um – bereits 0,1 mg/l NH₃ können Fische schädigen." },
        { head: "Nitrit (NO₂) — Gefahr!", text: "Nitrosomonas-Bakterien wandeln NH₄ in NO₂ um. Nitrit hemmt den Sauerstofftransport im Blut (Methämoglobinämie). Im eingefahrenen Aquarium sollte NO₂ dauerhaft < 0,1 mg/l sein. Nitrit-Spitzen treten beim Einfahren auf (4–8 Wochen)." },
        { head: "Nitrat (NO₃) — Pflanzennahrung", text: "Nitrospira-Bakterien oxidieren NO₂ zu vergleichsweise harmlosem NO₃. Pflanzen verbrauchen es aktiv. Ohne Pflanzen steigt NO₃ stetig an und muss durch Wasserwechsel entfernt werden. Ziel: 10–25 mg/l." },
        { head: "Einfahrzeit", text: "Ein neues Aquarium braucht 4–8 Wochen zum biologischen Einfahren. In dieser Zeit sind NH₄ und NO₂ erhöht — noch keine Fische einsetzen! Filtermedien nie mit Leitungswasser spülen (Chlor tötet Bakterien)." },
      ]
    },
    {
      id: "ph-kh-co2", icon: "⚗️", title: "pH · KH · CO₂ — Das Dreieck", color: "#a78bfa",
      summary: "Diese drei Werte hängen untrennbar zusammen. Wer einen verändert, beeinflusst automatisch die anderen.",
      content: [
        { head: "Karbonathärte (KH) als Puffer", text: "KH (Bikarbonat) puffert den pH-Wert. Eine hohe KH (> 6 °dKH) verhindert pH-Stürze, eine zu niedrige KH (< 3 °dKH) führt zu instabilem pH. Für Pflanzenaquarien gilt: 4–6 °dKH ist ideal – hart genug zum Puffern, weich genug für CO₂-Effizienz." },
        { head: "CO₂ und pH", text: "CO₂ löst sich in Wasser zu Kohlensäure (H₂CO₃) und senkt den pH. Die Formel: Bei KH = 6 und CO₂ = 25 mg/l ergibt sich pH ≈ 6,7. Tagsüber verbrauchen Pflanzen CO₂ → pH steigt. Nachts produzieren alle Lebewesen CO₂ → pH fällt. Eine natürliche Tagesschwankung von ± 0,5 ist normal." },
        { head: "Ziel-CO₂ für Pflanzen", text: "Pflanzen wachsen optimal bei 20–30 mg/l CO₂. Mit KH und pH lässt sich CO₂ schätzen: CO₂ = 3 × KH × 10^(7,0 − pH). CO₂ ≥ 30 mg/l kann Fische schädigen (Hyperkapnie). Nachts CO₂-Anlage ausschalten, morgens früh einschalten." },
        { head: "Fischgerechter pH", text: "Die meisten Süßwasserfische tolerieren pH 6,5–7,5. Südamerika (Diskus, Tetras): pH 6,0–6,8. Afrika (Malawisee): pH 7,8–8,5. Brückscher Richtlinie: Keine pH-Änderung > 0,2 pro Stunde." },
      ]
    },
    {
      id: "makro", icon: "🌿", title: "Makronährstoffe für Pflanzen", color: "#4ade80",
      summary: "NO₃, PO₄, K, Mg, Ca sind die Grundnahrung. Liebigs Minimum: Das knappste Element begrenzt das Wachstum.",
      content: [
        { head: "Stickstoff (NO₃) — Aufbaustoff", text: "Baustein für Aminosäuren, Proteine und Chlorophyll. Mangel: langsames Wachstum, gelbliche Alttriebe. Überschuss: weiches, weichhäutiges Gewebe, anfälliger für Algen. Ziel: 10–25 mg/l. Abgebaut durch Pflanzen und Wasserwechsel." },
        { head: "Phosphat (PO₄) — Energieträger", text: "Teil von ATP (Zellenenergie) und DNA. Mangel: rötliche Blätter, sehr langsames Wachstum. Viele Aquarianer fürchten PO₄ als Algenursache — falsch! Algen entstehen bei Ungleichgewicht, nicht bei hohem PO₄. Ziel: 0,1–0,4 mg/l. Eisen zeitversetzt dosieren." },
        { head: "Kalium (K) — Wasserhaushalt", text: "Regelt den Wasserhaushalt der Pflanzenzellen. Mangel: Löcher in Blättern, gelbe Blattränder. Oft unterschätzt — besonders in Leitungswasser ist K niedrig. Ziel: 5–15 mg/l. Hat kaum Seiteneffekte bei Überdosierung." },
        { head: "Magnesium (Mg) & Calcium (Ca)", text: "Mg ist zentrales Atom im Chlorophyll. Mangel: Blätter vergilben zwischen den Blattadern (Interchlorose). Ca stabilisiert Zellwände. Ca:Mg-Verhältnis ca. 3:1 anstreben. GH = Summe aus Ca und Mg (grob). Für Garnelen: GH 6–8 °dGH empfohlen." },
      ]
    },
    {
      id: "mikro", icon: "⚙️", title: "Mikronährstoffe & Eisen", color: "#fb923c",
      summary: "Spurenelemente und Eisen ermöglichen enzymatische Prozesse — in kleinen Mengen unverzichtbar.",
      content: [
        { head: "Eisen (Fe) — sichtbarster Mikronahrstoff", text: "Kofaktor für Chlorophyll-Synthese. Mangel: Junge Blätter vergilben (Interchlorose). Fe ist schwer löslich — chelatiert (EDTA, DTPA, Huminat) bleibt es verfügbar. 0,05–0,2 mg/l. Morgens dosieren, da Fe im Tageslicht photodegradiert." },
        { head: "Mangan (Mn), Bor (B), Zink (Zn)", text: "Mn: Kofaktor bei Photosynthese. Zn: Enzymaktivierung. Bor: Zellwandbildung. Bei Verwendung vollständiger Mikro-Dünger (z.B. Flowgrow) sind diese meist ausreichend abgedeckt." },
        { head: "Chelate — Transport im Wasser", text: "Metalle bilden im Wasser schwer lösliche Verbindungen. Chelatoren (EDTA, DTPA, Gluconat) halten sie löslich und bioverfügbar. Sanft chelatierte Produkte (Huminat/Gluconat) sind schnell verfügbar aber kurzlebig → täglich dosieren. EDTA-Chelate sind stabiler → wöchentlich." },
      ]
    },
    {
      id: "fische", icon: "🐟", title: "Wasserqualität & Fischgesundheit", color: "#38bdf8",
      summary: "Fische haben einen engen Toleranzbereich. Stressfreies Wasser ist die wichtigste Krankheitsprophylaxe.",
      content: [
        { head: "Temperatur", text: "Tropische Fische: 24–28 °C. Kaltwater (Goldfish): 15–22 °C. Schwankungen > 2 °C/Tag stressen Fische stark. Beim Wasserwechsel: immer temperiertes Wasser verwenden (max. 1 °C Differenz). Zu warmes Wasser reduziert O₂-Gehalt." },
        { head: "Sauerstoff (O₂)", text: "Fische benötigen ≥ 6 mg/l O₂. Kritisch < 4 mg/l. Sauerstoff wird bei höherer Temperatur schlechter gelöst (20 °C: ~9 mg/l, 28 °C: ~7,8 mg/l). CO₂-Düngung nachts abschalten! Ausreichend Wasserbewegung an der Oberfläche." },
        { head: "Leitfähigkeit (μS/cm)", text: "Spiegelt den Gesamtmineralgehalt. Tropenarten: 150–400 μS/cm. Afrikanische Cichliden: 400–800 μS/cm. Garnelen (Caridina): 100–200 μS/cm, (Neocaridina): 250–450 μS/cm. Ein plötzlicher Anstieg kann auf Verschmutzung hinweisen." },
        { head: "Stress und Immunsystem", text: "Schlechte Wasserqualität stresst Fische dauerhaft → schwächeres Immunsystem → erhöhte Anfälligkeit für Parasiten (Ichthyo, Velvet) und Bakterien. Regelmäßige Wassertests sind die beste Vorbeugung. Stress-Indikatoren: hektisches Schwimmen, Apathie, Atemprobleme." },
      ]
    },
    {
      id: "wasserwechsel", icon: "💧", title: "Wasserwechsel — Warum & Wie", color: "#2dd4bf",
      summary: "Regelmäßige Wasserwechsel sind die wichtigste Pflegemaßnahme — sie entfernen Schadstoffe, die keine Filterung abbaut.",
      content: [
        { head: "Was Wasserwechsel entfernt", text: "NO₃ (Nitrat) akkumuliert ohne Wasserwechsel. Gilvosin (Gelbfärbung). Hormone und Stoffwechselprodukte. Phosphate aus Futtermittelrückständen. Diese Stoffe werden durch keinen biologischen Filter dauerhaft eliminiert." },
        { head: "Empfehlung", text: "25–30% wöchentlich ist der Goldstandard für die meisten Aquarien. Stark besetzte Becken: 30–50%/Woche. Pflanzenaquarien mit wenig Fisch: 20–25%/Woche. Garnelenbecken: vorsichtiger — 10–15% alle 1–2 Wochen, da Garnelen empfindlicher auf Wasserparam-Schwankungen reagieren." },
        { head: "Richtiges Wasser aufbereiten", text: "Immer auf Aquarium-Temperatur temperieren. Chlor aus Leitungswasser entfernen (Wasseraufbereiter oder 24h stehen lassen). Mineralsalze ergänzen wenn nötig (bei weichem Leitungswasser). pH-Wert prüfen. Niemals Leitungswasser direkt ins Aquarium." },
        { head: "Anzeichen, dass ein Wasserwechsel überfällig ist", text: "NO₃ > 50 mg/l. Gelbliche Wasserfärbung. Fadenalgenwachstum ohne erkennbaren Grund. Fische 'stehen' an der Oberfläche. Schlechte Pflanzenfärbung trotz Düngung. pH-Sturz durch erschöpfte KH-Pufferkapazität." },
      ]
    },
  ];

  return (
    <div>
      <div style={{ background: C.primaryLight, border: `1px solid rgba(34,211,238,0.20)`, borderRadius: 12, padding: "10px 14px", marginBottom: 16, color: C.txt2, fontSize: 11, lineHeight: 1.7 }}>
        <strong>🔬 Quellen:</strong> Aquasabi · Flowgrow · AquaticPlantCentral · Tropica · The Aquarium Wiki · Dr. Kaspar Horst (CLSF)
      </div>
      <div style={{ display: "grid", gridTemplateColumns: bp.isMobile ? "1fr" : bp.isTablet ? "1fr 1fr" : "repeat(3, 1fr)", gap: 10 }}>
        {sections.map(sec => (
          <div key={sec.id} style={{ background: C.card, ...GLASS, border: `1.5px solid ${open === sec.id ? sec.color + "60" : C.cardBorder}`, borderLeft: `4px solid ${sec.color}`, borderRadius: 14, overflow: "hidden", boxShadow: C.shadow, transition: "border-color 0.2s, box-shadow 0.2s" }}>
            <button onClick={() => setOpen(o => o === sec.id ? null : sec.id)} style={{ width: "100%", background: "none", border: "none", padding: "14px 16px", cursor: "pointer", textAlign: "left" }}
              aria-expanded={open === sec.id} aria-controls={`wissen-${sec.id}`}>
              <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 5 }}>
                <span style={{ fontSize: 18 }} aria-hidden="true">{sec.icon}</span>
                <span style={{ color: C.txt1, fontSize: 13, fontWeight: 700 }}>{sec.title}</span>
                <span style={{ marginLeft: "auto", color: C.txt4, fontSize: 12, transition: "transform 0.2s", display: "inline-block", transform: open === sec.id ? "rotate(180deg)" : "none" }}>▾</span>
              </div>
              <p style={{ color: C.txt3, fontSize: 11, lineHeight: 1.6, margin: 0 }}>{sec.summary}</p>
            </button>
            {open === sec.id && (
              <div id={`wissen-${sec.id}`} style={{ borderTop: `1px solid ${C.cardBorder}`, padding: "12px 16px 14px" }}>
                {sec.content.map((item, i) => (
                  <div key={i} style={{ marginBottom: i < sec.content.length - 1 ? 12 : 0 }}>
                    <div style={{ color: sec.color, fontSize: 11, fontWeight: 800, marginBottom: 3 }}>{item.head}</div>
                    <p style={{ color: C.txt2, fontSize: 11, lineHeight: 1.75, margin: 0 }}>{item.text}</p>
                  </div>
                ))}
              </div>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

// ── SollwerteTab ────────────────────────────────────────────────
function SollwerteTab({ bp }) {
  return (
    <div>
      <div style={{ background: C.primaryLight, border: `1px solid rgba(34,211,238,0.20)`, borderRadius: 12, padding: "10px 14px", marginBottom: 12, color: C.txt2, fontSize: 11, lineHeight: 1.7 }}>
        <div style={{ color: C.primary, fontWeight: 800, marginBottom: 3 }}>🔬 Quellen</div>
        Aquasabi · Garnelio · Be-Smart-Aquarium · Greenscaping · Aquascape.de · OASE · Flowgrow
      </div>
      <div style={{ display: "grid", gridTemplateColumns: bp.isMobile ? "1fr" : bp.isTablet ? "1fr 1fr" : "repeat(3, 1fr)", gap: 9, marginBottom: 12 }}>
        {PARAM_KEYS.map(k => {
          const p = SOLLWERTE[k];
          return (
            <div key={k} style={{ background: C.card, ...GLASS, border: `1px solid ${C.cardBorder}`, borderRadius: 12, padding: "12px 14px", boxShadow: C.shadow }}>
              <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 5 }}>
                <span style={{ fontSize: 16 }}>{p.icon}</span>
                <span style={{ fontWeight: 700, color: C.txt1, fontSize: 12 }}>{p.label}</span>
              </div>
              <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 14, color: C.primary, fontWeight: 800 }}>
                {p.min} – {p.max} <span style={{ fontSize: 11, fontWeight: 400, color: C.txt3 }}>{p.unit || "pH"}</span>
              </div>
              <div style={{ marginTop: 6, height: 4, borderRadius: 2, background: "rgba(255,255,255,0.10)", position: "relative", overflow: "hidden" }}>
                <div style={{ position: "absolute", left: "20%", width: "60%", height: "100%", background: `linear-gradient(90deg, ${C.secondary}, #34d399)`, borderRadius: 2 }} />
              </div>
            </div>
          );
        })}
      </div>
      <div style={{ background: C.secondaryLight, border: `1px solid rgba(45,212,191,0.25)`, borderRadius: 12, padding: "11px 14px", fontSize: 11, lineHeight: 1.9, color: C.txt2 }}>
        <div style={{ color: C.secondary, fontWeight: 800, marginBottom: 4, fontSize: 12 }}>💡 Zusammenhänge</div>
        • pH + KH + CO₂ beeinflussen sich gegenseitig<br />
        • NO₃:PO₄ Verhältnis 16:1 (Redfield-Ratio)<br />
        • Ca:Mg Verhältnis ca. 3:1 anstreben<br />
        • Eisen morgens · Phosphat abends<br />
        • NPK hebt NO₃ + PO₄ + K + Mg gleichzeitig an
      </div>
    </div>
  );
}

// ── Underwater header SVG — photorealistic style ────────────────
function HeaderSVG() {
  return (
    <svg aria-hidden="true" focusable="false" viewBox="0 0 1400 160"
      preserveAspectRatio="xMidYMax slice"
      style={{ position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none", userSelect: "none" }}
      xmlns="http://www.w3.org/2000/svg">
      <defs>
        {/* Caustic light filter — organic water-surface shimmer */}
        <filter id="hdr-caustic" x="-5%" y="-5%" width="110%" height="110%">
          <feTurbulence type="fractalNoise" baseFrequency="0.035 0.018" numOctaves="5" seed="12" result="noise"/>
          <feColorMatrix type="matrix" values="0 0 0 0 0.7  0 0 0 0 0.85  0 0 0 0 1  0 0 0 14 -7" in="noise" result="causticMask"/>
          <feComposite in="SourceGraphic" in2="causticMask" operator="in"/>
        </filter>
        {/* Soft glow blur */}
        <filter id="hdr-glow"><feGaussianBlur stdDeviation="6"/></filter>
        <filter id="hdr-blur3"><feGaussianBlur stdDeviation="3"/></filter>
        <filter id="hdr-blur8"><feGaussianBlur stdDeviation="8"/></filter>

        {/* Light shaft gradient */}
        <linearGradient id="hdr-shaft" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="rgba(180,220,255,0.18)"/>
          <stop offset="70%" stopColor="rgba(180,220,255,0.06)"/>
          <stop offset="100%" stopColor="rgba(180,220,255,0)"/>
        </linearGradient>

        {/* Plant gradients — dark root to semi-transparent tip */}
        <linearGradient id="hdr-plant-a" x1="0" y1="1" x2="0" y2="0">
          <stop offset="0%" stopColor="#112b18" stopOpacity="1"/>
          <stop offset="40%" stopColor="#1e4a28" stopOpacity="0.85"/>
          <stop offset="100%" stopColor="#2a6535" stopOpacity="0.35"/>
        </linearGradient>
        <linearGradient id="hdr-plant-b" x1="0" y1="1" x2="0" y2="0">
          <stop offset="0%" stopColor="#0e2414" stopOpacity="1"/>
          <stop offset="50%" stopColor="#1a4020" stopOpacity="0.75"/>
          <stop offset="100%" stopColor="#265230" stopOpacity="0.25"/>
        </linearGradient>
        <linearGradient id="hdr-plant-c" x1="0" y1="1" x2="0" y2="0">
          <stop offset="0%" stopColor="#162e1c" stopOpacity="1"/>
          <stop offset="60%" stopColor="#254838" stopOpacity="0.7"/>
          <stop offset="100%" stopColor="#306040" stopOpacity="0.2"/>
        </linearGradient>

        {/* Substrate gradient */}
        <linearGradient id="hdr-substrate" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#1a1810"/>
          <stop offset="100%" stopColor="#0e0e08"/>
        </linearGradient>

        {/* Rock gradients */}
        <radialGradient id="hdr-rock1" cx="40%" cy="35%" r="60%">
          <stop offset="0%" stopColor="#2a2e38"/>
          <stop offset="100%" stopColor="#12151c"/>
        </radialGradient>
        <radialGradient id="hdr-rock2" cx="55%" cy="30%" r="65%">
          <stop offset="0%" stopColor="#242830"/>
          <stop offset="100%" stopColor="#0f1218"/>
        </radialGradient>

        {/* Fish gradient */}
        <linearGradient id="hdr-fish" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#7a8898" stopOpacity="0.55"/>
          <stop offset="45%" stopColor="#a8bcc8" stopOpacity="0.45"/>
          <stop offset="100%" stopColor="#8a9cac" stopOpacity="0.35"/>
        </linearGradient>
      </defs>

      {/* ── Caustic light layer (organic shimmer over scene) ──── */}
      <rect x="0" y="0" width="1400" height="160" fill="rgba(160,210,255,0.22)" filter="url(#hdr-caustic)"/>

      {/* ── Diffuse light glow areas (simulates light pooling) ── */}
      <g filter="url(#hdr-glow)" opacity="0.55">
        <ellipse cx="350" cy="50" rx="200" ry="55" fill="rgba(190,225,255,0.09)"/>
        <ellipse cx="820" cy="42" rx="240" ry="60" fill="rgba(190,225,255,0.1)"/>
        <ellipse cx="1180" cy="55" rx="180" ry="50" fill="rgba(190,225,255,0.08)"/>
      </g>

      {/* ── Light shafts (blurred, angled) ───────────────────── */}
      <g filter="url(#hdr-blur8)">
        <polygon points="190,0 220,160 140,160" fill="url(#hdr-shaft)" opacity="0.9"/>
        <polygon points="500,0 540,160 440,160" fill="url(#hdr-shaft)" opacity="1"/>
        <polygon points="840,0 890,160 780,160" fill="url(#hdr-shaft)" opacity="0.85"/>
        <polygon points="1150,0 1185,160 1095,160" fill="url(#hdr-shaft)" opacity="0.9"/>
        <polygon points="1340,0 1370,160 1300,160" fill="url(#hdr-shaft)" opacity="0.7"/>
      </g>

      {/* ── Substrate (gravel band, wavy horizon) ────────────── */}
      <path d="M0,148 C120,143 240,150 380,146 C520,142 640,149 780,145
               C920,141 1040,148 1180,144 C1300,141 1360,147 1400,144
               L1400,160 L0,160 Z"
            fill="url(#hdr-substrate)" opacity="0.95"/>
      {/* Substrate surface highlight */}
      <path d="M0,148 C120,143 240,150 380,146 C520,142 640,149 780,145
               C920,141 1040,148 1180,144 C1300,141 1360,147 1400,144"
            stroke="rgba(100,130,100,0.18)" strokeWidth="1.5" fill="none"/>

      {/* ── Rocks on substrate ────────────────────────────────── */}
      <g opacity="0.85">
        {/* Rock cluster left */}
        <path d="M55,160 C48,152 38,147 45,142 C50,138 62,139 72,143 C80,147 82,155 78,160 Z"
              fill="url(#hdr-rock1)"/>
        <path d="M72,160 C68,154 65,149 72,145 C77,142 88,143 94,148 C99,153 97,159 92,160 Z"
              fill="url(#hdr-rock2)"/>
        <path d="M44,160 C40,156 33,151 38,146 C43,143 52,145 56,150 C59,154 57,160 53,160 Z"
              fill="url(#hdr-rock2)" opacity="0.8"/>
        {/* Rock cluster right */}
        <path d="M1305,160 C1298,152 1290,147 1296,142 C1301,138 1313,140 1322,144 C1330,148 1331,156 1327,160 Z"
              fill="url(#hdr-rock1)"/>
        <path d="M1326,160 C1322,154 1318,149 1326,145 C1332,142 1342,144 1347,149 C1351,154 1349,160 1344,160 Z"
              fill="url(#hdr-rock2)"/>
        {/* Mid rock */}
        <path d="M680,160 C674,155 668,150 674,146 C679,143 690,145 697,149 C703,153 701,159 696,160 Z"
              fill="url(#hdr-rock1)" opacity="0.7"/>
      </g>

      {/* ── Background plants (blurred, suggest depth) ─────────── */}
      <g filter="url(#hdr-blur3)" opacity="0.6">
        {/* Far background tufts */}
        <path d="M220,160 C218,148 214,136 219,122 C222,112 226,104 224,92 C229,108 231,118 229,130 C232,142 230,154 228,160 Z" fill="url(#hdr-plant-b)"/>
        <path d="M240,160 C242,146 238,130 242,116 C245,105 249,96 246,82 C252,98 252,110 250,124 C252,138 249,152 247,160 Z" fill="url(#hdr-plant-b)"/>
        <path d="M950,160 C948,147 944,133 948,120 C951,109 955,101 952,88 C958,104 958,116 956,130 C958,143 955,155 953,160 Z" fill="url(#hdr-plant-b)"/>
        <path d="M968,160 C970,147 966,131 970,118 C973,107 977,98 974,85 C980,101 980,114 978,128 C980,141 977,153 975,160 Z" fill="url(#hdr-plant-b)"/>
      </g>

      {/* ── Foreground plant cluster — left ────────────────────── */}
      <g>
        {/* Tall center stem — filled blade shape */}
        <path d="M18,160 C14,148 10,132 14,112 C16,97 20,84 17,66 C17,52 19,42 20,30
                 C22,42 23,53 22,67 C24,86 26,99 24,114 C26,133 24,149 22,160 Z"
              fill="url(#hdr-plant-a)"/>
        {/* Left lean */}
        <path d="M30,160 C26,147 22,130 25,112 C27,98 30,87 27,72 C27,60 29,50 30,38
                 C33,50 34,61 32,73 C35,90 35,101 33,115 C35,132 34,148 32,160 Z"
              fill="url(#hdr-plant-a)" opacity="0.9"/>
        {/* Short foreground blade */}
        <path d="M10,160 C7,151 4,140 7,128 C9,118 12,110 10,100
                 C13,111 14,120 13,130 C14,141 13,153 11,160 Z"
              fill="url(#hdr-plant-c)" opacity="0.85"/>
        {/* Right side stem */}
        <path d="M44,160 C41,148 38,134 41,117 C43,104 47,93 44,79 C44,68 46,59 47,48
                 C50,60 51,70 49,80 C52,96 51,107 49,120 C51,136 50,150 48,160 Z"
              fill="url(#hdr-plant-b)"/>
        {/* Wide broad leaf */}
        <path d="M58,160 C53,149 48,135 52,118 C55,105 60,95 56,80
                 C62,96 63,109 60,122 C63,138 62,152 60,160 Z"
              fill="url(#hdr-plant-a)" opacity="0.75"/>
        {/* Extra narrow stems */}
        <path d="M70,160 C68,150 66,138 68,124 C70,113 73,104 71,92
                 C74,104 75,114 73,125 C75,139 74,152 72,160 Z"
              fill="url(#hdr-plant-b)" opacity="0.7"/>
        {/* Moss/algae tuft at base */}
        <ellipse cx="35" cy="157" rx="28" ry="5" fill="#1a3820" opacity="0.6"/>
      </g>

      {/* ── Foreground plant cluster — right ───────────────────── */}
      <g>
        <path d="M1382,160 C1386,148 1390,132 1386,112 C1384,97 1380,84 1383,66
                 C1383,52 1381,42 1380,30
                 C1378,42 1377,53 1378,67 C1376,86 1374,99 1376,114
                 C1374,133 1376,149 1378,160 Z"
              fill="url(#hdr-plant-a)"/>
        <path d="M1370,160 C1374,147 1378,130 1375,112 C1373,98 1370,87 1373,72
                 C1373,60 1371,50 1370,38
                 C1367,50 1366,61 1368,73 C1365,90 1365,101 1367,115
                 C1365,132 1366,148 1368,160 Z"
              fill="url(#hdr-plant-a)" opacity="0.9"/>
        <path d="M1390,160 C1393,151 1396,140 1393,128 C1391,118 1388,110 1390,100
                 C1387,111 1386,120 1387,130 C1386,141 1387,153 1389,160 Z"
              fill="url(#hdr-plant-c)" opacity="0.85"/>
        <path d="M1356,160 C1359,148 1362,134 1359,117 C1357,104 1353,93 1356,79
                 C1356,68 1354,59 1353,48
                 C1350,60 1349,70 1351,80 C1348,96 1349,107 1351,120
                 C1349,136 1350,150 1352,160 Z"
              fill="url(#hdr-plant-b)"/>
        <path d="M1342,160 C1347,149 1352,135 1348,118 C1345,105 1340,95 1344,80
                 C1338,96 1337,109 1340,122 C1337,138 1338,152 1340,160 Z"
              fill="url(#hdr-plant-a)" opacity="0.75"/>
        <path d="M1330,160 C1332,150 1334,138 1332,124 C1330,113 1327,104 1329,92
                 C1326,104 1325,114 1327,125 C1325,139 1326,152 1328,160 Z"
              fill="url(#hdr-plant-b)" opacity="0.7"/>
        <ellipse cx="1365" cy="157" rx="28" ry="5" fill="#1a3820" opacity="0.6"/>
      </g>

      {/* ── Mid-ground vegetation tufts ──────────────────────────── */}
      <g opacity="0.5" filter="url(#hdr-blur3)">
        <path d="M430,160 C427,152 424,142 427,132 C429,124 432,117 430,108
                 C433,118 434,126 432,134 C434,144 433,154 431,160 Z" fill="url(#hdr-plant-b)"/>
        <path d="M444,160 C447,151 444,139 447,129 C449,120 452,113 449,103
                 C453,114 454,123 452,132 C454,143 453,154 451,160 Z" fill="url(#hdr-plant-c)"/>
        <path d="M810,160 C807,153 805,143 808,133 C810,125 813,118 811,109
                 C814,120 815,128 813,136 C815,146 814,155 812,160 Z" fill="url(#hdr-plant-b)"/>
        <path d="M826,160 C829,151 826,140 829,130 C831,121 834,114 831,105
                 C835,116 836,125 834,134 C836,145 835,155 833,160 Z" fill="url(#hdr-plant-c)"/>
      </g>

      {/* ── Fish school — realistic silhouettes ───────────────── */}
      <g opacity="0.6">
        {/* Fish 1 — lead fish, largest */}
        <g transform="translate(638,68)">
          {/* Body */}
          <path d="M0,0 C8,-5 22,-7 34,-4 C44,-1 50,2 50,5 C50,8 44,11 34,13
                   C22,15 8,13 0,8 C-3,6 -3,3 0,0 Z" fill="url(#hdr-fish)"/>
          {/* Fork tail */}
          <path d="M0,4 C-8,0 -16,-6 -18,-10 C-15,-8 -8,-4 0,0 Z" fill="url(#hdr-fish)" opacity="0.8"/>
          <path d="M0,4 C-8,8 -16,14 -18,18 C-15,15 -8,10 0,8 Z" fill="url(#hdr-fish)" opacity="0.8"/>
          {/* Dorsal fin */}
          <path d="M18,-4 C20,-9 24,-12 28,-10 C26,-7 22,-4 20,0 Z" fill="rgba(160,185,200,0.4)"/>
          {/* Eye */}
          <circle cx="38" cy="4" r="2.2" fill="rgba(20,35,50,0.7)"/>
          <circle cx="38.7" cy="3.3" r="0.7" fill="rgba(200,220,240,0.6)"/>
        </g>
        {/* Fish 2 */}
        <g transform="translate(672,50)">
          <path d="M0,0 C7,-4 18,-6 28,-3 C36,-1 41,2 41,5 C41,7 36,10 28,11
                   C18,13 7,11 0,7 C-2,5 -2,2 0,0 Z" fill="url(#hdr-fish)"/>
          <path d="M0,4 C-6,-1 -13,-5 -15,-8 C-12,-6 -6,-2 0,1 Z" fill="url(#hdr-fish)" opacity="0.75"/>
          <path d="M0,4 C-6,9 -13,13 -15,16 C-12,13 -6,9 0,7 Z" fill="url(#hdr-fish)" opacity="0.75"/>
          <path d="M15,-3 C17,-8 20,-10 23,-8 C21,-5 18,-3 16,0 Z" fill="rgba(160,185,200,0.35)"/>
          <circle cx="31" cy="4" r="1.9" fill="rgba(20,35,50,0.7)"/>
          <circle cx="31.6" cy="3.4" r="0.6" fill="rgba(200,220,240,0.6)"/>
        </g>
        {/* Fish 3 */}
        <g transform="translate(710,80)">
          <path d="M0,0 C6,-3 16,-5 25,-3 C32,0 37,2 37,5 C37,7 32,9 25,10
                   C16,12 6,10 0,7 C-2,5 -2,2 0,0 Z" fill="url(#hdr-fish)"/>
          <path d="M0,4 C-6,0 -11,-4 -13,-7 C-10,-5 -5,-1 0,1 Z" fill="url(#hdr-fish)" opacity="0.75"/>
          <path d="M0,4 C-6,8 -11,12 -13,15 C-10,12 -5,9 0,7 Z" fill="url(#hdr-fish)" opacity="0.75"/>
          <circle cx="28" cy="4" r="1.7" fill="rgba(20,35,50,0.7)"/>
          <circle cx="28.6" cy="3.4" r="0.55" fill="rgba(200,220,240,0.6)"/>
        </g>
        {/* Fish 4 — lower, angled */}
        <g transform="translate(690,96)">
          <path d="M0,0 C5,-3 14,-4 22,-2 C28,0 33,3 33,5 C33,8 28,10 22,11
                   C14,12 5,10 0,7 C-2,5 -2,2 0,0 Z" fill="url(#hdr-fish)" opacity="0.9"/>
          <path d="M0,4 C-5,1 -10,-3 -12,-5 C-9,-4 -4,0 0,1 Z" fill="url(#hdr-fish)" opacity="0.7"/>
          <path d="M0,4 C-5,7 -10,11 -12,13 C-9,11 -4,8 0,7 Z" fill="url(#hdr-fish)" opacity="0.7"/>
          <circle cx="25" cy="4" r="1.5" fill="rgba(20,35,50,0.65)"/>
        </g>
        {/* Fish 5 — small straggler */}
        <g transform="translate(660,88)">
          <path d="M0,0 C4,-2 11,-4 18,-2 C23,0 27,2 27,4 C27,6 23,8 18,9
                   C11,10 4,9 0,6 C-1.5,5 -1.5,2 0,0 Z" fill="url(#hdr-fish)" opacity="0.8"/>
          <path d="M0,3 C-4,0 -8,-3 -9,-5 C-7,-3 -3,0 0,1 Z" fill="url(#hdr-fish)" opacity="0.65"/>
          <path d="M0,3 C-4,6 -8,9 -9,11 C-7,9 -3,7 0,5 Z" fill="url(#hdr-fish)" opacity="0.65"/>
          <circle cx="20" cy="3" r="1.3" fill="rgba(20,35,50,0.6)"/>
        </g>
      </g>

      {/* ── Floating micro-particles ──────────────────────────────── */}
      <g opacity="0.35">
        {[
          [180,45,1.8],[310,72,1.2],[490,38,1.6],[560,88,1.0],[740,52,1.5],
          [870,34,1.2],[1020,68,1.8],[1100,44,1.1],[1250,60,1.4],[1330,80,1.0],
          [420,100,0.9],[640,28,1.3],[780,110,1.0],[1060,30,1.6]
        ].map(([x,y,r],i) => (
          <circle key={i} cx={x} cy={y} r={r} fill="rgba(200,225,255,0.7)"/>
        ))}
      </g>

      {/* ── Water surface shimmer (top edge) ─────────────────────── */}
      <g filter="url(#hdr-blur3)" opacity="0.18">
        <path d="M0,3 C80,0 160,5 260,2 C360,-1 450,4 560,1 C660,-2 760,3 880,0
                 C990,-2 1100,3 1210,1 C1300,-1 1370,3 1400,1 L1400,0 L0,0 Z"
              fill="rgba(180,220,255,0.9)"/>
      </g>
    </svg>
  );
}

// ── App ─────────────────────────────────────────────────────────
export default function App() {
  const bp = useBreakpoint();
  const [auth, setAuth]               = useState(null);
  const [booting, setBooting]         = useState(true);
  const [aquariums, setAquariums]     = useState([]);
  const [aquarium, setAquarium]       = useState(null);
  const [tab, setTab]                 = useState("messen");
  const [values, setValues]           = useState(() => Object.fromEntries(PARAM_KEYS.map(k => [k, ""])));
  const [note, setNote]               = useState("");
  const [entries, setEntries]         = useState([]);
  const [infoKey, setInfoKey]         = useState(null);
  const [saved, setSaved]             = useState(false);
  const [saving, setSaving]           = useState(false);
  const [showAqModal, setShowAqModal] = useState(false);
  const [showAdmin, setShowAdmin]     = useState(false);
  const [loadingEntries, setLoadingEntries] = useState(false);

  // Boot: restore session
  useEffect(() => {
    const token = localStorage.getItem(JWT_KEY);
    if (!token) { setBooting(false); return; }
    apiFetch("/auth/me")
      .then(user => {
        setAuth({ token, user });
        return apiFetch("/aquariums");
      })
      .then(aqs => {
        setAquariums(aqs);
        if (aqs.length > 0) setAquarium(aqs[0]);
      })
      .catch(() => { localStorage.removeItem(JWT_KEY); })
      .finally(() => setBooting(false));
  }, []);

  // Load entries when aquarium changes
  useEffect(() => {
    if (!aquarium) { setEntries([]); return; }
    setLoadingEntries(true);
    apiFetch(`/aquariums/${aquarium.id}/entries`)
      .then(setEntries)
      .catch(() => setEntries([]))
      .finally(() => setLoadingEntries(false));
    setValues(Object.fromEntries(PARAM_KEYS.map(k => [k, ""])));
    setNote("");
  }, [aquarium]);

  const refreshAquariums = useCallback(async () => {
    const aqs = await apiFetch("/aquariums");
    setAquariums(aqs);
    setAquarium(a => aqs.find(x => x.id === a?.id) || aqs[0] || null);
  }, []);

  function handleLogin(data) {
    setAuth(data);
    apiFetch("/aquariums").then(aqs => { setAquariums(aqs); if (aqs.length > 0) setAquarium(aqs[0]); });
  }

  function handleLogout() {
    localStorage.removeItem(JWT_KEY);
    setAuth(null); setAquariums([]); setAquarium(null); setEntries([]);
  }

  async function handleSaveEntry() {
    if (!aquarium || !PARAM_KEYS.some(k => values[k] !== "")) return;
    setSaving(true);
    try {
      const entry = await apiFetch(`/aquariums/${aquarium.id}/entries`, { method: "POST", body: JSON.stringify({ values: { ...values }, note }) });
      setEntries(e => [entry, ...e]);
      setSaved(true); setTimeout(() => setSaved(false), 2200);
    } catch {}
    finally { setSaving(false); }
  }

  async function handleDeleteEntry(id) {
    if (!aquarium) return;
    await apiFetch(`/aquariums/${aquarium.id}/entries/${id}`, { method: "DELETE" });
    setEntries(e => e.filter(x => x.id !== id));
  }

  if (booting) return (
    <>
      <GlobalStyles />
      <div style={{ minHeight: "100vh", display: "flex", alignItems: "center", justifyContent: "center", background: 'radial-gradient(ellipse at 50% 0%, #0a2040 0%, #04101e 60%, #020c18 100%)' }}>
        <div style={{ textAlign: "center", color: C.txt2 }}><div style={{ fontSize: 40, marginBottom: 12 }}>🐠</div>Lade…</div>
      </div>
    </>
  );
  if (!auth) return <><GlobalStyles /><LoginScreen onLogin={handleLogin} /></>;

  const TABS = [
    ["messen",  "⚗️", "MESSEN"],
    ["duenger", "🧪", "DÜNGER"],
    ["logbuch", "📋", "LOG"],
    ["wissen",  "📚", "WISSEN"],
    ["info",    "📖", "SOLLWERTE"],
  ];
  if (auth.user.role === "admin") TABS.push(["admin", "⚙️", "ADMIN"]);

  const containerMaxWidth = bp.isMobile ? 500 : bp.isTablet ? 768 : 1280;

  const SpeichernPanel = (
    <div>
      <div style={{ marginBottom: 12 }}>
        <label style={{ color: C.txt3, fontSize: 11, display: "block", marginBottom: 5, fontWeight: 600 }}>📝 Notiz</label>
        <textarea value={note} onChange={e => setNote(e.target.value)} placeholder="Wasserwechsel, Düngung, Beobachtungen…" rows={3}
          style={{ width: "100%", background: C.inputBg, border: `1.5px solid ${C.inputBorder}`, borderRadius: 10, color: C.txt1, fontSize: 13, padding: "8px 11px", fontFamily: "inherit", resize: "none" }} />
      </div>
      <div style={{ display: "flex", gap: 8, marginBottom: 20 }}>
        <button className="btn-primary" onClick={handleSaveEntry} disabled={saving}
          style={{ flex: 2, background: saved ? `linear-gradient(135deg, #059669, ${C.secondary})` : `linear-gradient(135deg, ${C.primaryDark}, ${C.primary})`, border: "none", borderRadius: 14, color: "#041018", fontSize: 15, fontWeight: 800, height: 52, cursor: saving ? "wait" : "pointer", letterSpacing: "0.02em", boxShadow: saved ? "0 8px 24px rgba(45,212,191,0.35)" : `0 8px 24px rgba(34,211,238,0.30)` }}>
          {saved ? "✓ Gespeichert!" : saving ? "Speichern…" : "💾 Eintrag speichern"}
        </button>
        <button onClick={() => { setValues(Object.fromEntries(PARAM_KEYS.map(k => [k, ""]))); setNote(""); setSaved(false); }}
          style={{ flex: 1, background: C.card, border: `1.5px solid ${C.cardBorder}`, borderRadius: 14, color: C.txt3, fontSize: 13, fontWeight: 600, height: 52, cursor: "pointer" }}>
          ✕ Leeren
        </button>
      </div>
    </div>
  );

  const ParamGrid = (
    <div style={{ display: "grid", gridTemplateColumns: bp.isMobile ? "1fr" : "1fr 1fr", gap: 10 }}>
      {PARAM_KEYS.map(k => (
        <ParamCard key={k} paramKey={k} value={values[k]}
          onChange={(key, val) => { setValues(v => ({ ...v, [key]: val })); setSaved(false); }}
          showInfo={infoKey === k} onToggleInfo={key => setInfoKey(i => i === key ? null : key)} />
      ))}
    </div>
  );

  const MessenContent = bp.isDesktop
    ? (<div style={{ display: "grid", gridTemplateColumns: "1fr 360px", gap: 24, alignItems: "flex-start" }}>
        <div>{ParamGrid}</div>
        <div style={{ position: "sticky", top: 88 }}>
          {aquarium && <ReminderBanner aquariumId={aquarium.id} />}
          <SummaryBanner values={values} isDesktop />
          {SpeichernPanel}
        </div>
      </div>)
    : (<div>
        {aquarium && <ReminderBanner aquariumId={aquarium.id} />}
        <SummaryBanner values={values} isDesktop={false} />
        {ParamGrid}
        <div style={{ marginTop: 14 }}>{SpeichernPanel}</div>
      </div>);

  return (
    <AuthCtx.Provider value={{ auth, setAuth }}>
      <GlobalStyles />
      <div style={{ minHeight: "100vh", background: "transparent", fontFamily: "'Outfit', 'Segoe UI', system-ui, sans-serif", color: C.txt1, maxWidth: containerMaxWidth, margin: "0 auto", paddingBottom: 60 }}>

        {/* ── Sticky Header ──────────────────────────────────── */}
        <div style={{ background: C.headerBg, position: "sticky", top: 0, zIndex: 10, boxShadow: "0 4px 32px rgba(0,0,0,0.7), 0 1px 0 rgba(34,211,238,0.15)", overflow: "hidden", borderBottom: "1px solid rgba(34,211,238,0.12)" }}>
          {/* Photo background */}
          <div style={{ position: "absolute", inset: 0, backgroundImage: "url('/aquascape.jpg')", backgroundSize: "cover", backgroundPosition: "center 45%", opacity: 0.38 }} />
          <div style={{ position: "absolute", inset: 0, background: "linear-gradient(180deg, rgba(5,37,64,0.72) 0%, rgba(10,63,98,0.65) 55%, rgba(12,90,138,0.58) 100%)" }} />
          <HeaderSVG />

          {/* ── Aquarium selector row ─────────────────────────── */}
          <div style={{ padding: bp.isDesktop ? "14px 28px 10px" : "12px 16px 10px", position: "relative", zIndex: 1 }}>
            <button onClick={() => setShowAqModal(true)} aria-label="Aquarium wechseln"
              style={{ display: "flex", alignItems: "center", gap: 8, background: "rgba(34,211,238,0.08)", border: "1.5px solid rgba(34,211,238,0.22)", borderRadius: 12, padding: bp.isDesktop ? "7px 16px" : "6px 12px", cursor: "pointer", width: "100%", maxWidth: 420, transition: "all 0.2s", backdropFilter: "blur(8px)" }}>
              <span style={{ fontSize: bp.isDesktop ? 22 : 18 }}>🐠</span>
              <div style={{ flex: 1, textAlign: "left" }}>
                <div style={{ color: "#fff", fontSize: bp.isDesktop ? 18 : 14, fontWeight: 800, lineHeight: 1.2 }}>
                  {aquarium?.name || "Aquarium wählen"}
                </div>
                <div style={{ color: "rgba(255,255,255,0.6)", fontSize: 10, fontFamily: "'DM Mono', monospace" }}>
                  {aquarium ? `${aquarium.volume} L · ${entries.length} Einträge` : "Tippen zum Auswählen"}
                </div>
              </div>
              <span style={{ color: "rgba(255,255,255,0.55)", fontSize: 12 }}>▾</span>
            </button>
          </div>

          {/* ── Tab bar ──────────────────────────────────────────── */}
          <div style={{ padding: bp.isDesktop ? "0 28px" : "0 16px", position: "relative", zIndex: 1 }}>
            <div style={{ display: "flex", background: "rgba(0,0,0,0.18)", borderRadius: 999, padding: "3px", gap: 2 }}>
              {TABS.map(([k, icon, label]) => (
                <button key={k} className={`tab-pill${tab === k ? " active" : ""}`}
                  onClick={() => { setTab(k); if (k === "admin") setShowAdmin(true); }}
                  style={{ flex: 1, padding: bp.isDesktop ? "8px 6px" : "7px 4px", background: "transparent", border: "none", cursor: "pointer", color: tab === k ? C.primary : "rgba(255,255,255,0.75)", fontSize: bp.isDesktop ? 12 : 10, fontFamily: "'DM Mono', monospace", borderRadius: 999, fontWeight: tab === k ? 800 : 500, whiteSpace: "nowrap" }}>
                  {icon} {bp.isMobile && label.length > 5 ? label.slice(0, 4) : label}
                </button>
              ))}
            </div>
          </div>

          {/* ── User bar ─────────────────────────────────────────── */}
          <div style={{ background: "rgba(2,8,18,0.88)", borderTop: "1px solid rgba(34,211,238,0.10)", padding: bp.isDesktop ? "7px 28px" : "7px 16px", display: "flex", alignItems: "center", gap: 10, position: "relative", zIndex: 1 }}>
            {/* User info */}
            <span style={{ fontSize: 14 }} aria-hidden="true">👤</span>
            <div style={{ flex: 1 }}>
              <span style={{ color: "#e2eaf2", fontSize: 13, fontWeight: 700 }}>{auth.user.displayName || auth.user.username}</span>
              <span style={{ color: "rgba(255,255,255,0.4)", fontSize: 11, fontFamily: "'DM Mono', monospace", marginLeft: 8 }}>@{auth.user.username}</span>
              {auth.user.role === "admin" && (
                <span style={{ marginLeft: 8, background: "rgba(34,211,238,0.18)", color: "#22d3ee", fontSize: 9, fontWeight: 700, padding: "2px 7px", borderRadius: 999, fontFamily: "'DM Mono', monospace", letterSpacing: "0.04em", border: "1px solid rgba(34,211,238,0.3)" }}>ADMIN</span>
              )}
            </div>
            {/* Action buttons */}
            {auth.user.role === "admin" && (
              <button onClick={() => setShowAdmin(true)}
                style={{ background: "rgba(34,211,238,0.10)", border: "1px solid rgba(34,211,238,0.28)", borderRadius: 8, color: "#22d3ee", fontSize: 11, fontWeight: 700, padding: "5px 12px", cursor: "pointer", whiteSpace: "nowrap", transition: "all 0.2s" }}>
                ⚙ Verwaltung
              </button>
            )}
            <button onClick={handleLogout}
              style={{ background: "rgba(239,68,68,0.12)", border: "1px solid rgba(252,165,165,0.25)", borderRadius: 8, color: "#fca5a5", fontSize: 11, fontWeight: 700, padding: "5px 12px", cursor: "pointer", whiteSpace: "nowrap", transition: "all 0.2s" }}>
              → Abmelden
            </button>
          </div>
        </div>

        {/* ── Tab content ─────────────────────────────────────── */}
        <div style={{ padding: bp.isDesktop ? "20px 28px 0" : "14px 14px 0" }}>
          {tab === "messen"  && MessenContent}
          {tab === "duenger" && <DuengerTab values={values} bp={bp} />}
          {tab === "wissen"  && <WissenTab bp={bp} />}
          {tab === "info"    && <SollwerteTab bp={bp} />}
          {tab === "logbuch" && (
            <div>
              <div style={{ color: C.txt3, fontSize: 11, marginBottom: 10, fontFamily: "'DM Mono', monospace", fontWeight: 600 }}>{entries.length} Einträge</div>
              {loadingEntries ? <div style={{ textAlign: "center", color: C.txt3, padding: 30 }}>Lade…</div>
                : entries.length === 0
                ? (<div style={{ textAlign: "center", padding: "50px 20px", color: C.txt4, background: C.card, borderRadius: 16, border: `1px solid ${C.cardBorder}`, boxShadow: C.shadow }}>
                    <div style={{ fontSize: 40, marginBottom: 10 }}>📋</div>
                    <div style={{ color: C.txt2, fontWeight: 600 }}>Noch keine Messungen.</div>
                  </div>)
                : entries.map(e => <LogEntry key={e.id} entry={e} onDelete={handleDeleteEntry} isDesktop={bp.isDesktop} />)
              }
            </div>
          )}
        </div>

        {/* ── Modals ──────────────────────────────────────────── */}
        {showAqModal && (
          <AquariumModal aquariums={aquariums} current={aquarium}
            onSelect={aq => { setAquarium(aq); setTab("messen"); }}
            onCreate={async (name, volume) => { await apiFetch("/aquariums", { method: "POST", body: JSON.stringify({ name, volume }) }); await refreshAquariums(); }}
            onDelete={async id => { await apiFetch(`/aquariums/${id}`, { method: "DELETE" }); await refreshAquariums(); }}
            onClose={() => setShowAqModal(false)} />
        )}
        {showAdmin && <AdminPanel onClose={() => setShowAdmin(false)} />}

        {/* First-time: no aquarium */}
        {!aquarium && !booting && (
          <div style={{ textAlign: "center", padding: "60px 20px" }}>
            <div style={{ fontSize: 48, marginBottom: 16 }}>🐠</div>
            <div style={{ color: C.txt1, fontSize: 18, fontWeight: 700, marginBottom: 8 }}>Willkommen!</div>
            <div style={{ color: C.txt3, marginBottom: 20, fontSize: 13 }}>Lege dein erstes Aquarium an um loszulegen.</div>
            <button onClick={() => setShowAqModal(true)} className="btn-primary"
              style={{ background: `linear-gradient(135deg, ${C.primaryDark}, ${C.primary})`, border: "none", borderRadius: 14, color: "#fff", fontSize: 15, fontWeight: 700, padding: "13px 28px", cursor: "pointer" }}>
              + Erstes Aquarium anlegen
            </button>
          </div>
        )}
      </div>
    </AuthCtx.Provider>
  );
}

