/* ============================================================
   planning.jsx — Calendar (Google-connected), Todo, Goals,
   Reading, Gratitude
   ============================================================ */

/* Google's multicolour "G" used on the connect button */
function GoogleGlyph({ size = 18 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 48 48" aria-hidden="true">
      <path fill="#FFC107" d="M43.611 20.083H42V20H24v8h11.303c-1.649 4.657-6.08 8-11.303 8-6.627 0-12-5.373-12-12s5.373-12 12-12c3.059 0 5.842 1.154 7.961 3.039l5.657-5.657C34.046 6.053 29.268 4 24 4 12.955 4 4 12.955 4 24s8.955 20 20 20 20-8.955 20-20c0-1.341-.138-2.65-.389-3.917z" />
      <path fill="#FF3D00" d="M6.306 14.691l6.571 4.819C14.655 15.108 18.961 12 24 12c3.059 0 5.842 1.154 7.961 3.039l5.657-5.657C34.046 6.053 29.268 4 24 4 16.318 4 9.656 8.337 6.306 14.691z" />
      <path fill="#4CAF50" d="M24 44c5.166 0 9.86-1.977 13.409-5.192l-6.19-5.238C29.211 35.091 26.715 36 24 36c-5.202 0-9.619-3.317-11.283-7.946l-6.522 5.025C9.505 39.556 16.227 44 24 44z" />
      <path fill="#1976D2" d="M43.611 20.083H42V20H24v8h11.303c-.792 2.237-2.231 4.166-4.087 5.571l.003-.002 6.19 5.238C36.971 39.205 44 34 44 24c0-1.341-.138-2.65-.389-3.917z" />
    </svg>
  );
}

/* Empty / not-connected state shown inside the agenda card */
function CalendarConnect({ onConnected }) {
  const [busy, setBusy] = useState(false);
  const connect = async () => {
    setBusy(true);
    try { await connectGoogleCalendar(); onConnected(); }
    finally { setBusy(false); }
  };
  return (
    <div className="cal-connect">
      <div className="cal-connect-glyph"><GoogleGlyph size={34} /></div>
      <div className="cal-connect-title">Verbind je Google Agenda</div>
      <div className="cal-connect-sub">Koppel je account om je afspraken, kleuren en meerdere agenda's hier te zien — automatisch gesynchroniseerd.</div>
      <button className="g-btn" onClick={connect} disabled={busy}>
        {busy ? <><span className="spinner" /> Verbinden…</> : <><GoogleGlyph /> Koppel Google Agenda</>}
      </button>
      <div className="cal-connect-note">Je gegevens blijven privé. Je kunt de koppeling altijd intrekken.</div>
    </div>
  );
}

function CalendarWidget() {
  const today = new Date();
  const [weekOffset, setWeekOffset] = useState(0);
  const [tick, setTick] = useState(0);
  const [selEvent, setSelEvent] = useState(null);

  const status = useAsync(() => getCalendarStatus(), [tick]);
  const connected = status.data && status.data.connected;
  const calendars = (status.data && status.data.calendars) || [];

  const monday = addDays(startOfWeek(today), weekOffset * 7);
  const days = Array.from({ length: 7 }, (_, i) => addDays(monday, i));
  const sun = addDays(monday, 6);

  const ev = useAsync(
    () => connected ? fetchCalendarEvents(monday.toISOString(), addDays(sun, 1).toISOString()) : Promise.resolve([]),
    [tick, weekOffset, connected]
  );
  const events = ev.data || [];

  const H0 = 7, H1 = 22;
  const hours = H1 - H0;
  const ROW = 30;
  const gridH = hours * ROW;
  const yFor = (h) => (h - H0) * ROW;

  const m0 = NL_MONTHS[monday.getMonth()].slice(0, 3);
  const m1 = NL_MONTHS[sun.getMonth()].slice(0, 3);
  const weekRange = monday.getMonth() === sun.getMonth()
    ? `${monday.getDate()} – ${sun.getDate()} ${m0} ${monday.getFullYear()}`
    : `${monday.getDate()} ${m0} – ${sun.getDate()} ${m1} ${sun.getFullYear()}`;
  const nowH = today.getHours() + today.getMinutes() / 60;
  const showNow = weekOffset === 0;

  const toggleCal = async (id, enabled) => { await setCalendarEnabled(id, enabled); setTick(t => t + 1); };

  return (
    <div className="card fade-in" style={{ animationDelay: "0.08s" }}>
      <div className="wh">
        <div className="wh-l">
          <div className="wh-ico" style={{ background: "var(--accent-weak)", color: "var(--accent)" }}><Icon name="calendar" /></div>
          <div style={{ minWidth: 0, flex: 1 }}>
            <div className="wh-title">Agenda</div>
            <div className="wh-sub">{connected ? weekRange : "Niet gekoppeld"}</div>
          </div>
        </div>
        {connected && (
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span className="chip" style={{ background: "var(--surface-3)" }} title={status.data.email}>
              <span style={{ display: "inline-flex", gap: 2 }}>
                <span style={{ width: 7, height: 7, borderRadius: 99, background: "#4285F4" }} />
                <span style={{ width: 7, height: 7, borderRadius: 99, background: "#EA4335" }} />
                <span style={{ width: 7, height: 7, borderRadius: 99, background: "#FBBC04" }} />
              </span>
              {ev.loading ? "Synct…" : "Gesynct"}
            </span>
            <button className="round-btn" onClick={() => setWeekOffset(w => w - 1)}><Icon name="chevL" /></button>
            <button className="btn btn-sm btn-ghost" onClick={() => setWeekOffset(0)}>Vandaag</button>
            <button className="round-btn" onClick={() => setWeekOffset(w => w + 1)}><Icon name="chevR" /></button>
          </div>
        )}
      </div>

      {!status.data ? (
        <div style={{ flex: 1, display: "grid", placeItems: "center", minHeight: 300 }}><span className="spinner spinner-lg" /></div>
      ) : !connected ? (
        <CalendarConnect onConnected={() => setTick(t => t + 1)} />
      ) : (
        <>
          {/* calendar legend / toggles */}
          <div className="cal-legend">
            {calendars.map(c => (
              <button key={c.id} className={"cal-leg" + (c.enabled ? "" : " off")} onClick={() => toggleCal(c.id, !c.enabled)} title={c.enabled ? "Verbergen" : "Tonen"}>
                <span className="cal-leg-dot" style={{ background: c.enabled ? c.color : "var(--text-3)" }} />
                {c.name}
              </button>
            ))}
          </div>

          {/* day headers */}
          <div style={{ display: "grid", gridTemplateColumns: "44px repeat(7, 1fr)", marginBottom: 4 }}>
            <div />
            {days.map((d, i) => {
              const isToday = sameDay(d, today);
              return (
                <div key={i} style={{ textAlign: "center", padding: "2px 0" }}>
                  <div style={{ fontSize: 10.5, fontWeight: 700, color: isToday ? "var(--accent)" : "var(--text-3)", textTransform: "uppercase" }}>{NL_DAYS[d.getDay()]}</div>
                  <div style={{
                    margin: "2px auto 0", width: 26, height: 26, borderRadius: 9, display: "grid", placeItems: "center",
                    fontSize: 13, fontWeight: 700, fontFamily: "var(--mono)",
                    background: isToday ? "var(--accent)" : "transparent",
                    color: isToday ? "#fff" : "var(--text)",
                  }}>{d.getDate()}</div>
                </div>
              );
            })}
          </div>

          {/* time grid */}
          <div style={{ position: "relative", display: "grid", gridTemplateColumns: "44px repeat(7, 1fr)", flex: 1, overflowY: "auto", maxHeight: 460, opacity: (ev.loading && events.length === 0) ? 0.4 : 1, transition: "opacity .2s" }}>
            <div style={{ position: "relative", height: gridH }}>
              {Array.from({ length: hours + 1 }).map((_, i) => (
                <div key={i} style={{ position: "absolute", top: i * ROW - 6, right: 8, fontSize: 9.5, color: "var(--text-3)", fontWeight: 600, fontFamily: "var(--mono)" }}>
                  {i % 1 === 0 ? `${H0 + i}` : ""}
                </div>
              ))}
            </div>
            {days.map((d, di) => {
              const isToday = sameDay(d, today);
              const dayEvents = events.filter(e => sameDay(new Date(e.start), d));
              return (
                <div key={di} style={{ position: "relative", height: gridH, borderLeft: "1px solid var(--border)", background: isToday ? "var(--accent-soft)" : "transparent" }}>
                  {Array.from({ length: hours }).map((_, i) => (
                    <div key={i} style={{ position: "absolute", top: i * ROW, left: 0, right: 0, height: ROW, borderTop: "1px solid var(--border)" }} />
                  ))}
                  {showNow && isToday && nowH >= H0 && nowH <= H1 && (
                    <div style={{ position: "absolute", top: yFor(nowH), left: 0, right: 0, height: 2, background: "var(--accent)", zIndex: 5 }}>
                      <div style={{ position: "absolute", left: -3, top: -3, width: 8, height: 8, borderRadius: 99, background: "var(--accent)" }} />
                    </div>
                  )}
                  {dayEvents.map((e, ei) => {
                    const s = new Date(e.start), en = new Date(e.end);
                    const startH = s.getHours() + s.getMinutes() / 60;
                    const endH = en.getHours() + en.getMinutes() / 60;
                    const top = yFor(startH);
                    const h = (endH - startH) * ROW;
                    const sel = selEvent && selEvent.id === e.id;
                    return (
                      <button key={e.id} onClick={() => setSelEvent(e)}
                        style={{
                          position: "absolute", top: top + 1, left: 2, right: 2, height: h - 2,
                          background: sel ? e.color : "color-mix(in srgb, " + e.color + " 16%, var(--surface))",
                          borderLeft: `2.5px solid ${e.color}`, borderRadius: 6,
                          padding: "3px 5px", textAlign: "left", overflow: "hidden",
                          color: sel ? "#fff" : "var(--text)", transition: "all 0.15s", zIndex: sel ? 6 : 1,
                          boxShadow: sel ? "var(--shadow)" : "none",
                        }}>
                        <div style={{ fontSize: 10.5, fontWeight: 700, lineHeight: 1.15, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{e.title}</div>
                        {h > 34 && <div style={{ fontSize: 9, fontWeight: 600, opacity: 0.8, fontFamily: "var(--mono)" }}>{fmtHour(startH)}–{fmtHour(endH)}</div>}
                      </button>
                    );
                  })}
                </div>
              );
            })}
          </div>
        </>
      )}
      {selEvent && <EventDetailModal event={selEvent} onClose={() => setSelEvent(null)} />}
    </div>
  );
}
function fmtHour(h) {
  const hh = Math.floor(h);
  const mm = Math.round((h - hh) * 60);
  return `${hh}:${mm.toString().padStart(2, "0")}`;
}

function TodoWidget() {
  const [todos, setTodos] = useLocalState("todos", TODOS_SEED);
  const [text, setText] = useState("");
  const [filter, setFilter] = useState("open");
  const TAGS = [
    { tag: "Persoonlijk", color: "var(--lilac)" },
    { tag: "Werk", color: "var(--blue)" },
    { tag: "Financieel", color: "var(--sage)" },
    { tag: "Gezondheid", color: "var(--teal)" },
    { tag: "Sport", color: "var(--accent)" },
    { tag: "Groei", color: "var(--amber)" },
  ];
  const [tagIdx, setTagIdx] = useState(0);
  const open = todos.filter(t => !t.done).length;

  const add = () => {
    const t = text.trim();
    if (!t) return;
    const tg = TAGS[tagIdx];
    setTodos(ts => [{ id: "t" + Date.now(), text: t, done: false, tag: tg.tag, color: tg.color }, ...ts]);
    setText("");
  };
  const toggle = (id) => setTodos(ts => ts.map(t => t.id === id ? { ...t, done: !t.done } : t));
  const del = (id) => setTodos(ts => ts.filter(t => t.id !== id));
  const shown = todos.filter(t => filter === "all" ? true : filter === "open" ? !t.done : t.done);

  return (
    <div className="card fade-in" style={{ animationDelay: "0.1s" }}>
      <WHead icon="check" title="Taken" sub={`${open} open`} accent />
      <div style={{ display: "flex", gap: 8, marginBottom: 8 }}>
        <input value={text} onChange={e => setText(e.target.value)} onKeyDown={e => e.key === "Enter" && add()}
          placeholder="Nieuwe taak…"
          style={{ flex: 1, height: 38, border: "1px solid var(--border)", background: "var(--surface-2)", borderRadius: 10, padding: "0 12px", fontSize: 13.5, outline: "none" }} />
        <button className="btn btn-accent" style={{ width: 38, padding: 0 }} onClick={add}><Icon name="plus" /></button>
      </div>
      <div style={{ display: "flex", flexWrap: "wrap", gap: 5, marginBottom: 12 }}>
        {TAGS.map((t, i) => (
          <button key={t.tag} onClick={() => setTagIdx(i)}
            style={{ display: "inline-flex", alignItems: "center", gap: 5, padding: "3px 9px", borderRadius: 999, fontSize: 11.5, fontWeight: 650,
              background: tagIdx === i ? "color-mix(in srgb, " + t.color + " 16%, transparent)" : "var(--surface-3)",
              color: tagIdx === i ? t.color : "var(--text-3)",
              border: tagIdx === i ? `1px solid color-mix(in srgb, ${t.color} 35%, transparent)` : "1px solid transparent", transition: "all 0.15s" }}>
            <span style={{ width: 7, height: 7, borderRadius: 99, background: t.color }} />{t.tag}
          </button>
        ))}
      </div>
      <div className="seg" style={{ marginBottom: 12, alignSelf: "flex-start" }}>
        {[["open","Open"],["all","Alle"],["done","Klaar"]].map(([k, l]) => (
          <button key={k} className={filter === k ? "on" : ""} onClick={() => setFilter(k)}>{l}</button>
        ))}
      </div>
      <div style={{ display: "grid", gap: 6, flex: 1, overflowY: "auto", maxHeight: 360 }}>
        {shown.length === 0 && <div style={{ textAlign: "center", color: "var(--text-3)", fontSize: 13, padding: "20px 0", fontWeight: 600 }}>Niets hier — lekker bezig! 🎉</div>}
        {shown.map(t => (
          <div key={t.id} className="todo-row" style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 10px", borderRadius: 10, background: "var(--surface-2)", border: "1px solid var(--border)" }}>
            <button onClick={() => toggle(t.id)} style={{
              width: 20, height: 20, borderRadius: 7, flexShrink: 0, display: "grid", placeItems: "center",
              border: t.done ? "none" : "1.8px solid var(--border-strong)",
              background: t.done ? "var(--good)" : "transparent", color: "#fff", transition: "all 0.15s",
            }}>{t.done && <Icon name="check" width="13" height="13" />}</button>
            <span style={{ flex: 1, fontSize: 13.5, fontWeight: 600, minWidth: 0,
              textDecoration: t.done ? "line-through" : "none", color: t.done ? "var(--text-3)" : "var(--text)" }}>{t.text}</span>
            <span className="chip" style={{ background: "transparent", color: t.color, fontSize: 10.5, padding: "2px 7px", border: `1px solid color-mix(in srgb, ${t.color} 30%, transparent)` }}>{t.tag}</span>
            <button className="todo-del" onClick={() => del(t.id)} style={{ color: "var(--text-3)", width: 22, height: 22, display: "grid", placeItems: "center", borderRadius: 6 }}><Icon name="minus" width="15" height="15" /></button>
          </div>
        ))}
      </div>
    </div>
  );
}

function GoalsWidget() {
  const [goals] = useLocalState("goals", GOALS_SEED);
  const [open, setOpen] = useState(false);
  return (
    <div className="card fade-in" style={{ animationDelay: "0.12s" }}>
      {open && <GoalsDetail onClose={() => setOpen(false)} />}
      <WHead icon="target" title="Doelen 2026" sub={`${goals.length} actief`} accent action={<>Alle <Icon name="chevR" /></>} onAction={() => setOpen(true)} />
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, flex: 1 }}>
        {goals.map(g => {
          const pct = clamp(Math.round((g.cur / g.target) * 100), 0, 100);
          const fmtV = (v) => g.unit === "€" ? fmtEur(v) : g.unit === "%" ? v + "%" : v + (g.unit ? " " + g.unit : "");
          return (
            <div key={g.id} style={{ padding: 14, borderRadius: 14, background: "var(--surface-2)", border: "1px solid var(--border)", display: "flex", gap: 12, alignItems: "center" }}>
              <Ring value={pct} max={100} size={56} stroke={6} color={g.color}>
                <span className="mono" style={{ fontSize: 12.5, fontWeight: 700 }}>{pct}%</span>
              </Ring>
              <div style={{ minWidth: 0, flex: 1 }}>
                <div style={{ fontSize: 13, fontWeight: 700, lineHeight: 1.25 }}>{g.name}</div>
                <div className="mono" style={{ fontSize: 11.5, color: "var(--text-2)", fontWeight: 600, marginTop: 5 }}>{fmtV(g.cur)} / {fmtV(g.target)}</div>
                <div style={{ display: "flex", alignItems: "center", gap: 5, marginTop: 4, fontSize: 10.5, color: "var(--text-3)", fontWeight: 600 }}>
                  <Icon name="clock" width="11" height="11" /> {g.due}
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

const BOOK_COLORS = ["var(--lilac)", "var(--blue)", "var(--sage)", "var(--accent)", "var(--amber)", "var(--rose)", "var(--teal)"];

function ReadingWidget() {
  const [reading, setReading] = useLocalState("reading_data", READING_SEED);
  const [editing, setEditing] = useState(false);
  const [editPage, setEditPage] = useState(false);
  const [showDetail, setShowDetail] = useState(false);

  // Draft state for the "nieuw boek" form
  const [draft, setDraft] = useState({});
  // Draft for page update
  const [draftPage, setDraftPage] = useState("");

  const b = reading.current;
  const pct = Math.round((b.page / b.pages) * 100);

  function openEdit() { setDraft({ ...b }); setEditing(true); }
  function saveEdit() {
    const pages = Math.max(1, parseInt(draft.pages) || b.pages);
    const page  = Math.min(parseInt(draft.page) || b.page, pages);
    setReading(r => ({ ...r, current: { ...draft, pages, page } }));
    setEditing(false);
  }
  function openPage() { setDraftPage(String(b.page)); setEditPage(true); }
  function savePage() {
    const p = Math.min(Math.max(0, parseInt(draftPage) || 0), b.pages);
    if (p === b.pages) {
      // Boek afgerond!
      setReading(r => ({
        ...r,
        finishedThisYear: r.finishedThisYear + 1,
        current: { ...b, page: b.pages },
      }));
    } else {
      setReading(r => ({ ...r, current: { ...b, page: p } }));
    }
    setEditPage(false);
  }
  function finishBook() {
    setReading(r => ({ ...r, finishedThisYear: r.finishedThisYear + 1, current: { ...b, page: b.pages } }));
    setEditing(false);
  }

  const inputStyle = { height: 34, border: "1px solid var(--border)", background: "var(--surface-2)", borderRadius: 8, padding: "0 10px", fontSize: 12.5, outline: "none", width: "100%", color: "var(--text)" };

  return (
    <div className="card fade-in" style={{ animationDelay: "0.14s" }}>
      {showDetail && <ReadingDetail onClose={() => setShowDetail(false)} />}
      <WHead icon="book" title="Lezen" sub={`${reading.finishedThisYear} van ${reading.yearGoal} dit jaar`} accent action={<>Alle boeken <Icon name="chevR" /></>} onAction={() => setShowDetail(true)} />

      {/* Bewerk-knop */}
      {!editing && <div style={{ textAlign: "right", marginBottom: 4 }}><button onClick={openEdit} style={{ fontSize: 11, fontWeight: 700, color: "var(--text-3)", background: "none", border: "none", cursor: "pointer" }}>✎ Bewerk huidig boek</button></div>}

      {/* Bewerkformulier */}
      {editing && (
        <div style={{ display: "flex", flexDirection: "column", gap: 8, marginBottom: 12, padding: 12, background: "var(--surface-2)", borderRadius: 10, border: "1px solid var(--border)" }}>
          <input style={inputStyle} placeholder="Titel" value={draft.title || ""} onChange={e => setDraft(d => ({ ...d, title: e.target.value }))} />
          <input style={inputStyle} placeholder="Auteur" value={draft.author || ""} onChange={e => setDraft(d => ({ ...d, author: e.target.value }))} />
          <div style={{ display: "flex", gap: 6 }}>
            <input style={{ ...inputStyle, width: "50%" }} placeholder="Huidige pagina" type="number" value={draft.page || ""} onChange={e => setDraft(d => ({ ...d, page: e.target.value }))} />
            <input style={{ ...inputStyle, width: "50%" }} placeholder="Totaal pagina's" type="number" value={draft.pages || ""} onChange={e => setDraft(d => ({ ...d, pages: e.target.value }))} />
          </div>
          <div style={{ display: "flex", gap: 6, marginTop: 2 }}>
            {BOOK_COLORS.map(c => (
              <div key={c} onClick={() => setDraft(d => ({ ...d, color: c }))} style={{ width: 20, height: 20, borderRadius: 99, background: c, cursor: "pointer", border: draft.color === c ? "2px solid var(--text)" : "2px solid transparent" }} />
            ))}
          </div>
          <div style={{ display: "flex", gap: 6, marginTop: 2 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 6, flex: 1 }}>
              <span style={{ fontSize: 11.5, color: "var(--text-3)", fontWeight: 600 }}>Gelezen dit jaar:</span>
              <button onClick={() => setReading(r => ({ ...r, finishedThisYear: Math.max(0, r.finishedThisYear - 1) }))} style={{ width: 24, height: 24, borderRadius: 6, border: "1px solid var(--border)", background: "var(--surface)", cursor: "pointer", fontWeight: 700 }}>−</button>
              <span style={{ fontSize: 13, fontWeight: 700, minWidth: 20, textAlign: "center" }}>{reading.finishedThisYear}</span>
              <button onClick={() => setReading(r => ({ ...r, finishedThisYear: r.finishedThisYear + 1 }))} style={{ width: 24, height: 24, borderRadius: 6, border: "1px solid var(--border)", background: "var(--surface)", cursor: "pointer", fontWeight: 700 }}>+</button>
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
              <span style={{ fontSize: 11.5, color: "var(--text-3)", fontWeight: 600 }}>Doel:</span>
              <input style={{ ...inputStyle, width: 52 }} type="number" value={reading.yearGoal} onChange={e => setReading(r => ({ ...r, yearGoal: Math.max(1, parseInt(e.target.value) || 1) }))} />
            </div>
          </div>
          <div style={{ display: "flex", gap: 6, marginTop: 2 }}>
            <button className="btn btn-accent" style={{ flex: 1, height: 34 }} onClick={saveEdit}>Opslaan</button>
            <button className="btn" style={{ height: 34 }} onClick={finishBook}>✓ Afgerond</button>
            <button className="btn" style={{ height: 34 }} onClick={() => setEditing(false)}>Annuleer</button>
          </div>
        </div>
      )}

      {/* Boekkaart */}
      {!editing && (
        <div style={{ display: "flex", gap: 14, flex: 1 }}>
          <div style={{ width: 64, height: 92, borderRadius: 8, background: `linear-gradient(150deg, ${b.color}, color-mix(in srgb, ${b.color} 60%, #000))`,
            flexShrink: 0, boxShadow: "var(--shadow)", display: "flex", flexDirection: "column", justifyContent: "flex-end", padding: 8, color: "#fff" }}>
            <div style={{ fontSize: 9.5, fontWeight: 800, lineHeight: 1.1 }}>{b.title}</div>
          </div>
          <div style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }}>
            <div style={{ fontSize: 13.5, fontWeight: 700 }}>{b.title}</div>
            <div style={{ fontSize: 11.5, color: "var(--text-3)", fontWeight: 600 }}>{b.author}</div>
            <div style={{ marginTop: "auto" }}>
              <div style={{ display: "flex", justifyContent: "space-between", fontSize: 11, fontWeight: 600, color: "var(--text-2)", marginBottom: 5 }}>
                {editPage ? (
                  <div style={{ display: "flex", gap: 5, alignItems: "center" }}>
                    <span className="mono">p.</span>
                    <input autoFocus style={{ ...inputStyle, width: 60, height: 26, fontSize: 12 }} type="number" value={draftPage} onChange={e => setDraftPage(e.target.value)} onKeyDown={e => e.key === "Enter" && savePage()} />
                    <span className="mono">/ {b.pages}</span>
                    <button onClick={savePage} style={{ fontSize: 11, fontWeight: 700, color: "var(--accent)", background: "none", border: "none", cursor: "pointer" }}>✓</button>
                  </div>
                ) : (
                  <span className="mono" onClick={openPage} style={{ cursor: "pointer", textDecoration: "underline dotted" }} title="Klik om pagina bij te werken">p. {b.page} / {b.pages}</span>
                )}
                <span>{pct}%</span>
              </div>
              <div className="bar"><i style={{ width: pct + "%", background: b.color }} /></div>
            </div>
          </div>
        </div>
      )}

      <div className="divider" />
      <div style={{ display: "flex", gap: 4 }}>
        {Array.from({ length: reading.yearGoal }).map((_, i) => (
          <div key={i} style={{ flex: 1, height: 6, borderRadius: 99, background: i < reading.finishedThisYear ? "var(--lilac)" : "var(--surface-3)" }} />
        ))}
      </div>
    </div>
  );
}

function GratitudeWidget() {
  const [list, setList] = useLocalState("gratitude", GRATITUDE_SEED);
  const [text, setText] = useState("");
  const add = () => {
    const t = text.trim(); if (!t) return;
    setList(l => [{ id: "gr" + Date.now(), text: t, date: "Vandaag" }, ...l].slice(0, 8));
    setText("");
  };
  return (
    <div className="card fade-in" style={{ animationDelay: "0.16s" }}>
      <WHead icon="heart" title="Dankbaarheid" sub="Waar ben je blij mee?" accent />
      <div style={{ display: "flex", gap: 8, marginBottom: 12 }}>
        <input value={text} onChange={e => setText(e.target.value)} onKeyDown={e => e.key === "Enter" && add()}
          placeholder="Vandaag ben ik dankbaar voor…"
          style={{ flex: 1, height: 38, border: "1px solid var(--border)", background: "var(--surface-2)", borderRadius: 10, padding: "0 12px", fontSize: 13, outline: "none" }} />
        <button className="btn btn-accent" style={{ width: 38, padding: 0 }} onClick={add}><Icon name="plus" /></button>
      </div>
      <div style={{ display: "grid", gap: 8, flex: 1, overflowY: "auto", maxHeight: 220 }}>
        {list.map(g => (
          <div key={g.id} style={{ display: "flex", gap: 10, padding: "10px 12px", borderRadius: 12, background: "var(--accent-soft)", border: "1px solid color-mix(in srgb, var(--accent) 14%, transparent)" }}>
            <Icon name="sparkle" width="15" height="15" style={{ color: "var(--accent)", flexShrink: 0, marginTop: 2 }} />
            <div style={{ minWidth: 0 }}>
              <div style={{ fontSize: 13, fontWeight: 600, lineHeight: 1.3 }}>{g.text}</div>
              <div style={{ fontSize: 10.5, color: "var(--text-3)", fontWeight: 600, marginTop: 2 }}>{g.date}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ════════════════════════════════════════════════════════════
   READING DETAIL MODAL
   ════════════════════════════════════════════════════════════ */
function ReadingDetail({ onClose }) {
  const [reading, setReading] = useLocalState("reading_data", READING_SEED);
  const [tab, setTab] = useState("nu"); // nu | wil | gelezen
  const [showAdd, setShowAdd] = useState(false);
  const [draft, setDraft] = useState({ title: "", author: "", pages: "", color: "var(--lilac)", status: "nu" });

  const inputStyle = { height: 34, border: "1px solid var(--border)", background: "var(--surface-2)", borderRadius: 8, padding: "0 10px", fontSize: 12.5, outline: "none", width: "100%", color: "var(--text)" };

  function addBook() {
    if (!draft.title.trim()) return;
    const book = {
      id: "bk" + Date.now(),
      title: draft.title.trim(),
      author: draft.author.trim() || "Onbekend",
      page: 0,
      pages: Math.max(1, parseInt(draft.pages) || 200),
      color: draft.color,
      status: draft.status,
      addedDate: new Date().toLocaleDateString("nl-NL"),
    };
    if (draft.status === "nu" && !reading.current.title) {
      setReading(r => ({ ...r, current: book, books: [...(r.books || []), book] }));
    } else {
      setReading(r => ({ ...r, books: [...(r.books || []), book] }));
    }
    setDraft({ title: "", author: "", pages: "", color: "var(--lilac)", status: "nu" });
    setShowAdd(false);
  }

  function removeBook(id) {
    setReading(r => ({ ...r, books: (r.books || []).filter(b => b.id !== id) }));
  }

  function finishBook(book) {
    const finished = { ...book, status: "gelezen", finishedDate: new Date().toLocaleDateString("nl-NL") };
    setReading(r => ({
      ...r,
      finishedThisYear: r.finishedThisYear + 1,
      books: (r.books || []).map(b => b.id === book.id ? finished : b),
    }));
  }

  function setCurrent(book) {
    setReading(r => ({ ...r, current: book }));
  }

  const allBooks = reading.books || [];
  const nuBooks = allBooks.filter(b => b.status === "nu");
  const wilBooks = allBooks.filter(b => b.status === "wil");
  const gelezenBooks = allBooks.filter(b => b.status === "gelezen");

  const TABS = [
    { key: "nu", label: "📖 Aan het lezen", count: nuBooks.length },
    { key: "wil", label: "📚 Wil ik lezen", count: wilBooks.length },
    { key: "gelezen", label: "✅ Gelezen", count: gelezenBooks.length },
  ];

  const shownBooks = tab === "nu" ? nuBooks : tab === "wil" ? wilBooks : gelezenBooks;

  return (
    <ModalShell icon="book" title="Mijn Boeken" sub={`${reading.finishedThisYear} van ${reading.yearGoal} gelezen dit jaar`} onClose={onClose} wide>
      {/* Tabs */}
      <div style={{ display: "flex", gap: 6, marginBottom: 16 }}>
        {TABS.map(t => (
          <button key={t.key} onClick={() => setTab(t.key)} style={{
            padding: "7px 14px", borderRadius: 10, fontSize: 12.5, fontWeight: 700, cursor: "pointer",
            background: tab === t.key ? "var(--accent)" : "var(--surface-2)",
            color: tab === t.key ? "#fff" : "var(--text-3)",
            border: "1px solid " + (tab === t.key ? "var(--accent)" : "var(--border)"),
          }}>{t.label} {t.count > 0 && <span style={{ opacity: 0.75 }}>({t.count})</span>}</button>
        ))}
        <button onClick={() => setShowAdd(v => !v)} style={{ marginLeft: "auto", padding: "7px 14px", borderRadius: 10, fontSize: 12.5, fontWeight: 700, cursor: "pointer", background: "var(--surface-2)", border: "1px solid var(--border)", color: "var(--text)" }}>
          + Voeg toe
        </button>
      </div>

      {/* Toevoeg-formulier */}
      {showAdd && (
        <div style={{ padding: 14, background: "var(--surface-2)", borderRadius: 12, border: "1px solid var(--border)", marginBottom: 16, display: "flex", flexDirection: "column", gap: 8 }}>
          <div style={{ display: "flex", gap: 8 }}>
            <input style={inputStyle} placeholder="Titel *" value={draft.title} onChange={e => setDraft(d => ({ ...d, title: e.target.value }))} />
            <input style={inputStyle} placeholder="Auteur" value={draft.author} onChange={e => setDraft(d => ({ ...d, author: e.target.value }))} />
          </div>
          <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
            <input style={{ ...inputStyle, width: 120 }} placeholder="Pagina's" type="number" value={draft.pages} onChange={e => setDraft(d => ({ ...d, pages: e.target.value }))} />
            <select style={{ ...inputStyle, width: 160 }} value={draft.status} onChange={e => setDraft(d => ({ ...d, status: e.target.value }))}>
              <option value="nu">📖 Aan het lezen</option>
              <option value="wil">📚 Wil ik lezen</option>
              <option value="gelezen">✅ Al gelezen</option>
            </select>
            <div style={{ display: "flex", gap: 5, marginLeft: 4 }}>
              {BOOK_COLORS.map(c => (
                <div key={c} onClick={() => setDraft(d => ({ ...d, color: c }))} style={{ width: 18, height: 18, borderRadius: 99, background: c, cursor: "pointer", border: draft.color === c ? "2px solid var(--text)" : "2px solid transparent" }} />
              ))}
            </div>
            <button className="btn btn-accent" style={{ marginLeft: "auto", height: 34, whiteSpace: "nowrap" }} onClick={addBook}>Toevoegen</button>
          </div>
        </div>
      )}

      {/* Boekenlijst */}
      <div style={{ display: "grid", gap: 10 }}>
        {shownBooks.length === 0 && (
          <div style={{ textAlign: "center", padding: "30px 0", color: "var(--text-3)", fontSize: 13.5, fontWeight: 600 }}>
            {tab === "nu" ? "Geen boeken — voeg er een toe!" : tab === "wil" ? "Je leeslijst is leeg." : "Nog geen boeken afgerond dit jaar."}
          </div>
        )}
        {shownBooks.map(book => {
          const pct = book.pages ? Math.round((book.page / book.pages) * 100) : 0;
          const isCurrent = reading.current && reading.current.id === book.id;
          return (
            <div key={book.id} style={{ display: "flex", gap: 14, padding: 14, borderRadius: 14, background: "var(--surface-2)", border: "1px solid " + (isCurrent ? "var(--accent)" : "var(--border)"), alignItems: "center" }}>
              <div style={{ width: 48, height: 68, borderRadius: 7, background: `linear-gradient(150deg, ${book.color}, color-mix(in srgb, ${book.color} 55%, #000))`, flexShrink: 0, display: "flex", alignItems: "flex-end", padding: 6, color: "#fff" }}>
                <div style={{ fontSize: 8, fontWeight: 800, lineHeight: 1.1 }}>{book.title}</div>
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13.5, fontWeight: 700 }}>{book.title} {isCurrent && <span style={{ fontSize: 10.5, color: "var(--accent)", fontWeight: 700, marginLeft: 4 }}>● actief</span>}</div>
                <div style={{ fontSize: 12, color: "var(--text-3)", fontWeight: 600 }}>{book.author}</div>
                {tab === "nu" && (
                  <div style={{ marginTop: 8 }}>
                    <div style={{ display: "flex", justifyContent: "space-between", fontSize: 11, fontWeight: 600, color: "var(--text-2)", marginBottom: 4 }}>
                      <span>p. {book.page} / {book.pages}</span><span>{pct}%</span>
                    </div>
                    <div className="bar"><i style={{ width: pct + "%", background: book.color }} /></div>
                  </div>
                )}
                {tab === "gelezen" && book.finishedDate && (
                  <div style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 600, marginTop: 4 }}>Afgerond: {book.finishedDate}</div>
                )}
                {tab === "wil" && book.addedDate && (
                  <div style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 600, marginTop: 4 }}>Toegevoegd: {book.addedDate}</div>
                )}
              </div>
              <div style={{ display: "flex", flexDirection: "column", gap: 6, flexShrink: 0 }}>
                {tab === "nu" && !isCurrent && (
                  <button className="btn btn-sm" onClick={() => setCurrent(book)} style={{ fontSize: 11 }}>Actief</button>
                )}
                {tab === "nu" && (
                  <button className="btn btn-sm" onClick={() => finishBook(book)} style={{ fontSize: 11 }}>✓ Klaar</button>
                )}
                {tab === "wil" && (
                  <button className="btn btn-sm" onClick={() => { setReading(r => ({ ...r, books: (r.books||[]).map(b => b.id===book.id ? {...b,status:"nu"} : b) })); setTab("nu"); }} style={{ fontSize: 11 }}>Beginnen</button>
                )}
                <button onClick={() => removeBook(book.id)} style={{ width: 28, height: 28, borderRadius: 8, border: "1px solid var(--border)", background: "none", cursor: "pointer", color: "var(--text-3)", fontSize: 14, display: "grid", placeItems: "center" }}>×</button>
              </div>
            </div>
          );
        })}
      </div>
    </ModalShell>
  );
}

/* ════════════════════════════════════════════════════════════
   GOALS DETAIL MODAL
   ════════════════════════════════════════════════════════════ */
function GoalsDetail({ onClose }) {
  const [goals, setGoals] = useLocalState("goals", GOALS_SEED);
  const [showAdd, setShowAdd] = useState(false);
  const [editId, setEditId] = useState(null);
  const [draft, setDraft] = useState({ name: "", cat: "Groei", cur: "", target: "", unit: "", color: "var(--lilac)", due: "" });

  const inputStyle = { height: 34, border: "1px solid var(--border)", background: "var(--surface-2)", borderRadius: 8, padding: "0 10px", fontSize: 12.5, outline: "none", width: "100%", color: "var(--text)" };
  const CATS = ["Financieel", "Gezondheid", "Groei", "Werk", "Relaties", "Persoonlijk"];

  function saveGoal() {
    if (!draft.name.trim()) return;
    if (editId) {
      setGoals(gs => gs.map(g => g.id === editId ? { ...g, ...draft, cur: parseFloat(draft.cur)||0, target: parseFloat(draft.target)||100 } : g));
      setEditId(null);
    } else {
      setGoals(gs => [...gs, { id: "g" + Date.now(), ...draft, cur: parseFloat(draft.cur)||0, target: parseFloat(draft.target)||100 }]);
    }
    setDraft({ name: "", cat: "Groei", cur: "", target: "", unit: "", color: "var(--lilac)", due: "" });
    setShowAdd(false);
  }

  function startEdit(g) {
    setDraft({ name: g.name, cat: g.cat, cur: String(g.cur), target: String(g.target), unit: g.unit||"", color: g.color, due: g.due||"" });
    setEditId(g.id);
    setShowAdd(true);
  }

  function updateProgress(id, delta) {
    setGoals(gs => gs.map(g => g.id === id ? { ...g, cur: Math.max(0, Math.min(g.target, Math.round((g.cur + delta) * 10) / 10)) } : g));
  }

  return (
    <ModalShell icon="target" title="Doelen 2026" sub={`${goals.length} actieve doelen`} onClose={onClose} wide>
      {/* Toevoeg-knop */}
      <div style={{ display: "flex", justifyContent: "flex-end", marginBottom: 14 }}>
        <button onClick={() => { setShowAdd(v => !v); setEditId(null); setDraft({ name: "", cat: "Groei", cur: "", target: "", unit: "", color: "var(--lilac)", due: "" }); }} style={{ padding: "7px 16px", borderRadius: 10, fontSize: 12.5, fontWeight: 700, cursor: "pointer", background: "var(--accent)", color: "#fff", border: "none" }}>
          + Nieuw doel
        </button>
      </div>

      {/* Formulier */}
      {showAdd && (
        <div style={{ padding: 14, background: "var(--surface-2)", borderRadius: 12, border: "1px solid var(--border)", marginBottom: 16, display: "flex", flexDirection: "column", gap: 8 }}>
          <input style={inputStyle} placeholder="Naam van het doel *" value={draft.name} onChange={e => setDraft(d => ({ ...d, name: e.target.value }))} />
          <div style={{ display: "flex", gap: 8 }}>
            <select style={{ ...inputStyle, flex: 1 }} value={draft.cat} onChange={e => setDraft(d => ({ ...d, cat: e.target.value }))}>
              {CATS.map(c => <option key={c}>{c}</option>)}
            </select>
            <input style={{ ...inputStyle, flex: 1 }} placeholder="Deadline (bijv. dec 2026)" value={draft.due} onChange={e => setDraft(d => ({ ...d, due: e.target.value }))} />
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            <input style={{ ...inputStyle, flex: 1 }} placeholder="Huidige waarde" type="number" value={draft.cur} onChange={e => setDraft(d => ({ ...d, cur: e.target.value }))} />
            <input style={{ ...inputStyle, flex: 1 }} placeholder="Doelwaarde" type="number" value={draft.target} onChange={e => setDraft(d => ({ ...d, target: e.target.value }))} />
            <input style={{ ...inputStyle, width: 80 }} placeholder="Eenheid (€, km, %)" value={draft.unit} onChange={e => setDraft(d => ({ ...d, unit: e.target.value }))} />
          </div>
          <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
            {BOOK_COLORS.map(c => (
              <div key={c} onClick={() => setDraft(d => ({ ...d, color: c }))} style={{ width: 20, height: 20, borderRadius: 99, background: c, cursor: "pointer", border: draft.color === c ? "2px solid var(--text)" : "2px solid transparent" }} />
            ))}
            <button className="btn btn-accent" style={{ marginLeft: "auto", height: 34 }} onClick={saveGoal}>{editId ? "Opslaan" : "Toevoegen"}</button>
            <button className="btn" style={{ height: 34 }} onClick={() => { setShowAdd(false); setEditId(null); }}>Annuleer</button>
          </div>
        </div>
      )}

      {/* Doelen lijst */}
      <div style={{ display: "grid", gap: 12 }}>
        {goals.map(g => {
          const pct = clamp(Math.round((g.cur / g.target) * 100), 0, 100);
          const fmtV = v => g.unit === "€" ? fmtEur(v) : v + (g.unit ? " " + g.unit : "");
          return (
            <div key={g.id} style={{ padding: 16, borderRadius: 14, background: "var(--surface-2)", border: "1px solid var(--border)", display: "flex", gap: 16, alignItems: "center" }}>
              <Ring value={pct} max={100} size={60} stroke={6} color={g.color}>
                <span className="mono" style={{ fontSize: 12.5, fontWeight: 700 }}>{pct}%</span>
              </Ring>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  <div style={{ fontSize: 14, fontWeight: 700 }}>{g.name}</div>
                  <span style={{ fontSize: 10.5, color: "var(--text-3)", fontWeight: 700, background: "var(--surface-3)", padding: "2px 8px", borderRadius: 99 }}>{g.cat}</span>
                </div>
                <div className="mono" style={{ fontSize: 12, color: "var(--text-2)", fontWeight: 600, marginTop: 6 }}>{fmtV(g.cur)} / {fmtV(g.target)}</div>
                <div style={{ marginTop: 8 }}>
                  <div className="bar"><i style={{ width: pct + "%", background: g.color, transition: "width 0.4s" }} /></div>
                </div>
                {g.due && <div style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 600, marginTop: 5, display: "flex", alignItems: "center", gap: 4 }}><Icon name="clock" width="11" height="11" /> {g.due}</div>}
              </div>
              {/* Voortgang knoppen */}
              <div style={{ display: "flex", flexDirection: "column", gap: 6, alignItems: "center" }}>
                <div style={{ display: "flex", gap: 4 }}>
                  <button onClick={() => updateProgress(g.id, -1)} style={{ width: 28, height: 28, borderRadius: 8, border: "1px solid var(--border)", background: "none", cursor: "pointer", fontWeight: 700, fontSize: 16, color: "var(--text-3)" }}>−</button>
                  <button onClick={() => updateProgress(g.id, 1)} style={{ width: 28, height: 28, borderRadius: 8, border: "1px solid var(--accent)", background: "var(--accent)", cursor: "pointer", fontWeight: 700, fontSize: 16, color: "#fff" }}>+</button>
                </div>
                <button onClick={() => startEdit(g)} style={{ fontSize: 11, fontWeight: 700, color: "var(--text-3)", background: "none", border: "none", cursor: "pointer" }}>✎ Bewerk</button>
                <button onClick={() => setGoals(gs => gs.filter(x => x.id !== g.id))} style={{ fontSize: 11, fontWeight: 700, color: "var(--bad)", background: "none", border: "none", cursor: "pointer" }}>× Verwijder</button>
              </div>
            </div>
          );
        })}
      </div>
    </ModalShell>
  );
}

Object.assign(window, { CalendarWidget, TodoWidget, GoalsWidget, ReadingWidget, GratitudeWidget, GoogleGlyph, ReadingDetail, GoalsDetail });
