// TUS Calendar — UI Components

const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ========== UTILITIES ==========
const STORAGE_KEY = 'tus_calendar_v4';
const CLOUD_API = '/api/state';
const CLOUD_SYNC_INTERVAL = 5000;  // 5 saniye polling
const CLOUD_SAVE_DEBOUNCE = 1500;  // 1.5 sn debounce

// ---- localStorage (yerel) ----
function loadState() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return null;
    return JSON.parse(raw);
  } catch { return null; }
}
function saveState(state) {
  try { localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); } catch {}
}

// ---- Cloud sync (Cloudflare KV) ----
async function cloudLoad() {
  try {
    const res = await fetch(CLOUD_API, { method: 'GET' });
    if (!res.ok) return null;
    const data = await res.json();
    if (data._empty) return null;
    return data;
  } catch { return null; }
}

let _cloudSaveTimer = null;
function cloudSave(state) {
  clearTimeout(_cloudSaveTimer);
  _cloudSaveTimer = setTimeout(async () => {
    try {
      const payload = { ...state, _localVersion: Date.now() };
      await fetch(CLOUD_API, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
    } catch { /* offline — sessiz fail */ }
  }, CLOUD_SAVE_DEBOUNCE);
}

// React Hook: ilk yüklemede cloud'dan çek, ardından 5 sn'de bir polling
function useCloudSync(stateRef, setStateRaw) {
  const lastCloudVersionRef = useRef(0);
  const isSyncingRef = useRef(false);

  // İlk yüklemede cloud'dan state çek
  useEffect(() => {
    let cancelled = false;
    (async () => {
      const remote = await cloudLoad();
      if (cancelled || !remote || !remote.days) return;
      const local = stateRef.current;
      const localVer = local?._localVersion || 0;
      const remoteVer = remote._cloudVersion || remote._localVersion || 0;
      // Cloud daha yeniyse local'i güncelle
      if (remoteVer > localVer) {
        lastCloudVersionRef.current = remoteVer;
        setStateRaw(remote);
        saveState(remote);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  // Polling: her 5 saniyede cloud'u kontrol et
  useEffect(() => {
    const interval = setInterval(async () => {
      if (isSyncingRef.current) return;
      isSyncingRef.current = true;
      try {
        const remote = await cloudLoad();
        if (!remote || !remote.days) return;
        const remoteVer = remote._cloudVersion || remote._localVersion || 0;
        if (remoteVer > lastCloudVersionRef.current) {
          lastCloudVersionRef.current = remoteVer;
          const local = stateRef.current;
          const localVer = local?._localVersion || 0;
          if (remoteVer > localVer) {
            setStateRaw(remote);
            saveState(remote);
          }
        }
      } catch { /* offline */ }
      finally { isSyncingRef.current = false; }
    }, CLOUD_SYNC_INTERVAL);
    return () => clearInterval(interval);
  }, []);
}

const TR_MONTHS = ['Ocak','Şubat','Mart','Nisan','Mayıs','Haziran','Temmuz','Ağustos','Eylül','Ekim','Kasım','Aralık'];
const TR_DAYS   = ['Pzt','Sal','Çar','Per','Cum','Cmt','Paz'];
const TR_DAYS_LONG = ['Pazartesi','Salı','Çarşamba','Perşembe','Cuma','Cumartesi','Pazar'];

function dayIdxMonFirst(d) {
  // 0=Mon ... 6=Sun
  return (d.getDay() + 6) % 7;
}

function startOfWeek(d) {
  const r = new Date(d);
  const idx = dayIdxMonFirst(r);
  r.setDate(r.getDate() - idx);
  r.setHours(0,0,0,0);
  return r;
}

// ========== COUNTDOWN HEADER ==========
function useNow(intervalMs = 1000) {
  const [now, setNow] = useState(new Date());
  useEffect(() => {
    const id = setInterval(() => setNow(new Date()), intervalMs);
    return () => clearInterval(id);
  }, [intervalMs]);
  return now;
}

function Countdown({ now }) {
  const tus = new Date(2026, 7, 26, 9, 0, 0);
  const ms = tus - now;
  const total = Math.max(0, ms);
  const days = Math.floor(total / 86400000);
  const hours = Math.floor((total % 86400000) / 3600000);
  const mins = Math.floor((total % 3600000) / 60000);
  const secs = Math.floor((total % 60000) / 1000);
  return (
    <div className="countdown">
      <div className="countdown__label">TUS'a kalan</div>
      <div className="countdown__digits">
        <Cell v={days} l="gün" big />
        <Sep />
        <Cell v={hours} l="saat" />
        <Sep />
        <Cell v={mins} l="dk" />
        <Sep />
        <Cell v={secs} l="sn" />
      </div>
    </div>
  );
}
function Cell({ v, l, big }) {
  return (
    <div className={'cdcell' + (big ? ' cdcell--big' : '')}>
      <div className="cdcell__v">{String(v).padStart(2,'0')}</div>
      <div className="cdcell__l">{l}</div>
    </div>
  );
}
function Sep() { return <div className="cdsep">:</div>; }

function DailyProgress({ day, tasks }) {
  const total = tasks.reduce((a, t) => a + (t.hours || 0), 0);
  const done  = tasks.filter(t => t.done).reduce((a, t) => a + (t.hours || 0), 0);
  const pct = total === 0 ? 0 : Math.min(100, (done / total) * 100);
  return (
    <div className="dprog">
      <div className="dprog__head">
        <span className="dprog__label">Bugün</span>
        <span className="dprog__val">{done.toFixed(1)} / {total.toFixed(0)} saat</span>
      </div>
      <div className="dprog__bar">
        <div className="dprog__fill" style={{ width: pct + '%' }} />
        <div className="dprog__ticks">
          {[2,4,6,8].map(h => (
            <div key={h} className="dprog__tick" style={{ left: (h / Math.max(total,8)) * 100 + '%' }} />
          ))}
        </div>
      </div>
    </div>
  );
}

// ========== TASK CARD ==========
function TaskCard({ task, onToggle, onEdit, onDelete, onDragStart, onDragOver, onDrop, compact, isNow }) {
  return (
    <div
      className={'task' + (task.done ? ' task--done' : '') + (task.locked ? ' task--locked' : '') + (isNow ? ' task--now' : '')}
      draggable={!task.locked}
      onDragStart={e => onDragStart && onDragStart(e, task)}
      onDragOver={e => onDragOver && onDragOver(e)}
      onDrop={e => onDrop && onDrop(e, task)}
    >
      <button className="task__check" onClick={() => {}} aria-label="status" style={{cursor:'default'}}>
        <span className="task__checkmark">{task.done ? '✓' : ''}</span>
      </button>
      <div className="task__body">
        <div className="task__title">
          <span className="task__name">{task.title}</span>
          {task.partIdx && task.partTotal && (
            <span className="task__part">{task.partIdx}/{task.partTotal}</span>
          )}
        </div>
        {task.partIdx && task.partTotal && task.partTotal > 1 && (
          <div className="tparts">
            {Array.from({length: task.partTotal}).map((_, i) => {
              const filled = i < task.partIdx;
              // Trafik ışığı: ilk kırmızı, son yeşil
              // HSL: 0 (kırmızı) → 60 (sarı) → 120 (yeşil)
              const hue = task.partTotal === 1 ? 120 : (i / (task.partTotal - 1)) * 120;
              const color = `hsl(${hue}, 55%, ${filled ? 58 : 82}%)`;
              return (
                <div
                  key={i}
                  className={'tpart' + (filled ? ' tpart--filled' : '')}
                  style={filled ? {background: color} : {}}
                />
              );
            })}
          </div>
        )}
        {!compact && (
          <div className="task__meta">
            <span className="task__hours">{task.hours}h</span>
            {task.kind && <span className="task__kind">{task.kind}</span>}
            {task.note && <span className="task__note">{task.note}</span>}
          </div>
        )}
        {task.reminder && !compact && (
          <div className="task__reminder">{task.reminder}</div>
        )}
      </div>
      {!task.locked && (
        <div className="task__actions">
          <button onClick={() => onEdit && onEdit(task)} title="Düzenle">✎</button>
          <button onClick={() => onDelete && onDelete(task)} title="Sil">×</button>
        </div>
      )}
    </div>
  );
}

// ========== WEEK VIEW ==========
function WeekView({ state, setState, weekStart, setWeekStart, todayStr, onEdit }) {
  const days = [];
  for (let i = 0; i < 7; i++) days.push(addDays(weekStart, i));

  const drag = useRef(null);

  const handleDragStart = (e, task) => {
    drag.current = task;
    e.dataTransfer.effectAllowed = 'move';
    try { e.dataTransfer.setData('text/plain', task.id); } catch {}
  };
  const handleDragOver = (e) => { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; };
  const handleDropToSlot = (e, dateStr, slot) => {
    e.preventDefault();
    const task = drag.current;
    if (!task) return;
    moveTask(task, dateStr, slot);
    drag.current = null;
  };

  const moveTask = (task, newDate, newSlot) => {
    setState(s => {
      const ns = JSON.parse(JSON.stringify(s));
      // remove from old
      const od = ns.days[task.date];
      if (od) {
        od[task.slot] = od[task.slot].filter(t => t.id !== task.id);
      }
      // add to new
      const nd = ns.days[newDate];
      if (!nd) return s;
      const clean = { ...task };
      delete clean.date; delete clean.slot;
      nd[newSlot] = [...nd[newSlot], clean];
      return ns;
    });
  };
  const toggleTask = (task) => {
    setState(s => {
      const ns = JSON.parse(JSON.stringify(s));
      const arr = ns.days[task.date][task.slot];
      const idx = arr.findIndex(t => t.id === task.id);
      if (idx >= 0) arr[idx].done = !arr[idx].done;
      return ns;
    });
  };
  const deleteTask = (task) => {
    setState(s => {
      const ns = JSON.parse(JSON.stringify(s));
      const arr = ns.days[task.date][task.slot];
      ns.days[task.date][task.slot] = arr.filter(t => t.id !== task.id);
      return ns;
    });
  };

  const weekLabel = (() => {
    const s = weekStart;
    const e = addDays(weekStart, 6);
    return `${s.getDate()} ${TR_MONTHS[s.getMonth()]} – ${e.getDate()} ${TR_MONTHS[e.getMonth()]}`;
  })();

  return (
    <div className="week">
      <div className="week__nav">
        <button className="btn" onClick={() => setWeekStart(addDays(weekStart, -7))}>‹ Önceki Hafta</button>
        <div className="week__title">{weekLabel}</div>
        <div style={{display:'flex', gap:8}}>
          <button className="btn btn--ghost" onClick={() => setWeekStart(startOfWeek(new Date()))}>Bu Hafta</button>
          <button className="btn" onClick={() => setWeekStart(addDays(weekStart, 7))}>Sonraki Hafta ›</button>
        </div>
      </div>

      <div className="week__grid">
        <div className="week__colhead week__colhead--slot"></div>
        {days.map((d, i) => {
          const ds = fmtDate(d);
          const isToday = ds === todayStr;
          const isSun = i === 6;
          return (
            <div key={ds} className={'week__colhead' + (isToday ? ' week__colhead--today' : '')}>
              <div className="week__day">{TR_DAYS[i]}</div>
              <div className="week__date">{d.getDate()} <span className="week__month">{TR_MONTHS[d.getMonth()].slice(0,3)}</span></div>
              {isToday && <div className="week__todaydot">BUGÜN</div>}
              {isSun && !isToday && <div className="week__sundot">light</div>}
            </div>
          );
        })}

        <div className="week__slotlabel">
          <div className="week__slotname">SABAH</div>
          <div className="week__slottime">08:00 – 12:00</div>
          <div className="week__slothours">4h</div>
        </div>
        {days.map(d => {
          const ds = fmtDate(d);
          const day = state.days[ds];
          return (
            <div key={ds+'m'} className="week__cell"
              onDragOver={handleDragOver}
              onDrop={e => handleDropToSlot(e, ds, 'morning')}
            >
              {day && day.phase && <div className="week__phase" style={{'--p': phaseColor(day.phase)}}>{shortPhase(day.phase)}</div>}
              {day && day.morning.map(t => (
                <TaskCard key={t.id} task={{...t, date: ds, slot: 'morning'}}
                  onDragStart={handleDragStart}
                  onToggle={toggleTask}
                  onEdit={onEdit}
                  onDelete={deleteTask}
                />
              ))}
              {day && day.morning.length === 0 && (
                <AddTaskBtn onAdd={() => onEdit({ __new: true, date: ds, slot: 'morning' })} />
              )}
            </div>
          );
        })}

        <div className="week__slotlabel">
          <div className="week__slotname">AKŞAM</div>
          <div className="week__slottime">18:00 – 22:00</div>
          <div className="week__slothours">4h</div>
        </div>
        {days.map(d => {
          const ds = fmtDate(d);
          const day = state.days[ds];
          return (
            <div key={ds+'e'} className="week__cell"
              onDragOver={handleDragOver}
              onDrop={e => handleDropToSlot(e, ds, 'evening')}
            >
              {day && day.evening.map(t => (
                <TaskCard key={t.id} task={{...t, date: ds, slot: 'evening'}}
                  onDragStart={handleDragStart}
                  onToggle={toggleTask}
                  onEdit={onEdit}
                  onDelete={deleteTask}
                />
              ))}
              {day && day.evening.length === 0 && (
                <AddTaskBtn onAdd={() => onEdit({ __new: true, date: ds, slot: 'evening' })} />
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function AddTaskBtn({ onAdd }) {
  return <button className="addbtn" onClick={onAdd}>+ Görev ekle</button>;
}

function shortPhase(p) {
  if (!p) return '';
  if (p.includes('Faz 1')) return 'FAZ 1';
  if (p.includes('Faz 2')) return 'FAZ 2';
  if (p.includes('Faz 3')) return 'FAZ 3';
  if (p === 'TUS') return 'TUS';
  return p;
}
function phaseColor(p) {
  if (!p) return '#444';
  if (p.includes('Faz 1')) return '#7FB069';
  if (p.includes('Faz 2')) return '#6FB3B8';
  if (p.includes('Faz 3')) return '#E06B6B';
  return '#E06B6B';
}

// ========== KANBAN ==========
function Kanban({ state, setState, todayStr }) {
  // Kanban sütunları: "Yapılacak" (bugün/yaklaşan), "Şu an" (bugün henüz bitmeyen), "Bitti" (son işaretlenenler)
  const today = state.days[todayStr];
  const yaklasan = [];
  const suAn = [];
  const bitti = [];

  // Bugün
  if (today) {
    for (const t of [...today.morning, ...today.evening]) {
      if (t.done) bitti.push({ ...t, date: todayStr, slot: today.morning.includes(t) ? 'morning' : 'evening' });
      else suAn.push({ ...t, date: todayStr, slot: today.morning.includes(t) ? 'morning' : 'evening' });
    }
  }
  // Sonraki 3 gün
  for (let i = 1; i <= 3; i++) {
    const ds = fmtDate(addDays(parseDate(todayStr), i));
    const d = state.days[ds];
    if (!d) continue;
    for (const t of d.morning) yaklasan.push({ ...t, date: ds, slot: 'morning' });
    for (const t of d.evening) yaklasan.push({ ...t, date: ds, slot: 'evening' });
  }
  // Son 5 bitti
  const allDone = [];
  for (const ds of Object.keys(state.days).sort().reverse()) {
    const d = state.days[ds];
    for (const t of d.morning) if (t.done) allDone.push({ ...t, date: ds, slot: 'morning' });
    for (const t of d.evening) if (t.done) allDone.push({ ...t, date: ds, slot: 'evening' });
    if (allDone.length > 8) break;
  }

  const toggleTask = (task) => {
    setState(s => {
      const ns = JSON.parse(JSON.stringify(s));
      const arr = ns.days[task.date][task.slot];
      const idx = arr.findIndex(t => t.id === task.id);
      if (idx >= 0) arr[idx].done = !arr[idx].done;
      return ns;
    });
  };

  return (
    <div className="kanban">
      <KanbanCol title="Yaklaşan" subtitle="Sonraki 3 gün" count={yaklasan.length} accent="#8DA9C4">
        {yaklasan.slice(0, 12).map(t => (
          <KanbanCard key={t.id + t.date + t.slot} task={t} onToggle={toggleTask} showDate />
        ))}
        {yaklasan.length === 0 && <Empty>Sonraki günlerde görev yok</Empty>}
      </KanbanCol>
      <KanbanCol title="Şu An" subtitle="Bugün" count={suAn.length} accent="#FFB84D" pulse>
        {suAn.map(t => (
          <KanbanCard key={t.id} task={t} onToggle={toggleTask} />
        ))}
        {suAn.length === 0 && <Empty>Bugün için görev yok veya hepsi bitti ✨</Empty>}
      </KanbanCol>
      <KanbanCol title="Bitti" subtitle="Son tamamlanan" count={allDone.length} accent="#7FB069">
        {allDone.slice(0, 10).map(t => (
          <KanbanCard key={t.id + t.date + t.slot} task={t} onToggle={toggleTask} showDate done />
        ))}
        {allDone.length === 0 && <Empty>Henüz bitmiş görev yok</Empty>}
      </KanbanCol>
    </div>
  );
}
function Empty({ children }) { return <div className="kempty">{children}</div>; }

function KanbanCol({ title, subtitle, count, accent, pulse, children }) {
  return (
    <div className="kcol" style={{'--accent': accent}}>
      <div className="kcol__head">
        <div>
          <div className="kcol__title">{title} {pulse && <span className="kcol__pulse" />}</div>
          <div className="kcol__sub">{subtitle}</div>
        </div>
        <div className="kcol__count">{count}</div>
      </div>
      <div className="kcol__body">{children}</div>
    </div>
  );
}
function KanbanCard({ task, onToggle, showDate, done }) {
  const d = showDate && task.date ? formatShortDate(task.date) : null;
  return (
    <div className={'kcard' + (task.done ? ' kcard--done' : '')} style={{'--accent': task.color || '#7FB069'}}>
      <button className="kcard__check" onClick={() => {}} style={{cursor:'default'}}>
        {task.done ? '✓' : ''}
      </button>
      <div className="kcard__body">
        <div className="kcard__title">
          {task.title}
          {task.partIdx && task.partTotal && (
            <span className="kcard__part"> · {task.partIdx}/{task.partTotal}</span>
          )}
        </div>
        <div className="kcard__meta">
          {d && <span>{d}</span>}
          <span>{task.slot === 'morning' ? 'Sabah' : 'Akşam'}</span>
          <span>{task.hours}h</span>
        </div>
      </div>
    </div>
  );
}
function formatShortDate(ds) {
  const d = parseDate(ds);
  return `${d.getDate()} ${TR_MONTHS[d.getMonth()].slice(0,3)}`;
}

// ========== EDIT MODAL ==========
function EditModal({ task, onSave, onClose }) {
  const isNew = task.__new;
  const [title, setTitle] = useState(task.title || '');
  const [hours, setHours] = useState(task.hours || 4);
  const [kind, setKind] = useState(task.kind || 'speetus');
  const [lesson, setLesson] = useState(task.lesson || '');
  const [color, setColor] = useState(task.color || '#7FB069');

  useEffect(() => {
    if (lesson && LESSON_BY_TAG[lesson]) setColor(LESSON_BY_TAG[lesson].color);
  }, [lesson]);

  const save = () => {
    const out = isNew
      ? makeTask({ title, hours: Number(hours), kind, lesson: lesson || undefined, color, date: task.date, slot: task.slot })
      : { ...task, title, hours: Number(hours), kind, lesson: lesson || undefined, color };
    onSave(out);
  };

  return (
    <div className="modal" onClick={onClose}>
      <div className="modal__body" onClick={e => e.stopPropagation()}>
        <div className="modal__head">
          <h3>{isNew ? 'Yeni Görev' : 'Görevi Düzenle'}</h3>
          <button className="modal__close" onClick={onClose}>×</button>
        </div>
        <div className="modal__row">
          <label>Başlık</label>
          <input value={title} onChange={e => setTitle(e.target.value)} autoFocus />
        </div>
        <div className="modal__row modal__row--split">
          <div>
            <label>Süre (saat)</label>
            <input type="number" min="0" max="10" step="0.5" value={hours} onChange={e => setHours(e.target.value)} />
          </div>
          <div>
            <label>Tür</label>
            <select value={kind} onChange={e => setKind(e.target.value)}>
              <option value="speetus">Speetus izleme</option>
              <option value="tts">TTS çözüm</option>
              <option value="book">Kitap okuma</option>
              <option value="vaka">Vaka kitabı</option>
              <option value="cikti">Çıktı-Çıkacak</option>
              <option value="deneme">Deneme</option>
              <option value="spot">Spot/Tekrar</option>
              <option value="exam-prep">İSG hazırlık</option>
            </select>
          </div>
        </div>
        <div className="modal__row">
          <label>Ders</label>
          <select value={lesson} onChange={e => setLesson(e.target.value)}>
            <option value="">—</option>
            {LESSONS.map(l => <option key={l.tag} value={l.tag}>{l.name}</option>)}
          </select>
        </div>
        <div className="modal__row">
          <label>Renk</label>
          <div className="palette">
            {['#E06B6B','#D4A574','#7FB069','#C77DFF','#6FB3B8','#F2A65A','#E88EB8','#5B8DEF','#B8956A','#8DA9C4','#9B89B3','#FFD166','#FFB84D'].map(c => (
              <button key={c} className={'swatch' + (c === color ? ' swatch--sel' : '')}
                style={{background: c}} onClick={() => setColor(c)} />
            ))}
          </div>
        </div>
        <div className="modal__actions">
          <button className="btn btn--ghost" onClick={onClose}>İptal</button>
          <button className="btn btn--primary" onClick={save}>{isNew ? 'Ekle' : 'Kaydet'}</button>
        </div>
      </div>
    </div>
  );
}

// ========== MACRO VIEW — GERÇEK TAKVIM (aya göre, 7 sütun) ==========
function MacroView({ state, todayStr, onJumpToWeek }) {
  const [detail, setDetail] = React.useState(null); // { ds, x, y }

  const PLAN_START_LOCAL = parseDate(fmtDate(window.PLAN_START));
  const PLAN_END = parseDate('2026-08-26');

  // Plan tarihlerinin ay bazında gruplanması
  const allDates = [];
  let cur = new Date(PLAN_START_LOCAL);
  while (cur <= PLAN_END) {
    allDates.push(fmtDate(cur));
    cur = addDays(cur, 1);
  }

  const dayInfo = (ds) => {
    const day = state.days[ds];
    if (!day) return null;
    const all = [...(day.morning || []), ...(day.evening || [])];
    const total = all.reduce((a, t) => a + (t.hours || 0), 0);
    const done = all.filter(t => t.done).reduce((a, t) => a + (t.hours || 0), 0);
    const pct = total === 0 ? 0 : done / total;

    const mTasks = day.morning || [];
    const eTasks = day.evening || [];
    const mH = mTasks.reduce((a, t) => a + (t.hours || 0), 0);
    const mDone = mTasks.filter(t => t.done).reduce((a, t) => a + (t.hours || 0), 0);
    const eH = eTasks.reduce((a, t) => a + (t.hours || 0), 0);
    const eDone = eTasks.filter(t => t.done).reduce((a, t) => a + (t.hours || 0), 0);
    const mColor = mTasks[0]?.color || '#c9c2b5';
    const eColor = eTasks[0]?.color || '#c9c2b5';

    const isOff = all[0]?.kind === 'off';
    const isExam = all[0]?.kind === 'exam';
    const isTus = all[0]?.kind === 'tus';
    const isLight = (day.note || '').includes('LIGHT');
    const isBuffer = (day.note || '').includes('BUFFER');
    const isBad = (day.note || '').includes('KÖTÜ');
    const isKibris = (day.note || '').includes('KIBRIS');

    return { day, all, total, done, pct, mH, mDone, eH, eDone, mColor, eColor,
      isOff, isExam, isTus, isLight, isBuffer, isBad, isKibris };
  };

  // Aya göre grupla
  const months = [];
  let curMonth = -1;
  allDates.forEach(ds => {
    const d = parseDate(ds);
    if (d.getMonth() !== curMonth) {
      curMonth = d.getMonth();
      months.push({ month: curMonth, year: d.getFullYear(), dates: [] });
    }
    months[months.length - 1].dates.push(ds);
  });

  // Faz progresleri
  const phases = [
    { name: 'FAZ 1', start: '2026-04-28', end: '2026-06-22' },
    { name: 'FAZ 2', start: '2026-06-23', end: '2026-07-26' },
    { name: 'FAZ 3', start: '2026-07-27', end: '2026-08-25' },
  ];

  const handleClick = (e, ds) => {
    const r = e.currentTarget.getBoundingClientRect();
    setDetail({
      ds,
      x: Math.min(r.left, window.innerWidth - 360),
      y: r.bottom + 6,
    });
  };

  return (
    <div className="cal">
      <div className="cal__head">
        <div className="cal__legend">
          <span className="lg"><i style={{background: '#2b2724'}}></i> planlanan</span>
          <span className="lg"><i style={{background: '#ece4d3'}}></i> light</span>
          <span className="lg"><i style={{background: '#e3ddcf'}}></i> buffer</span>
          <span className="lg"><i style={{background: 'repeating-linear-gradient(45deg, #d9cfbf 0 3px, #e8e3d9 3px 6px)'}}></i> tatil</span>
          <span className="lg"><i style={{background: '#f5d7a8'}}></i> İSG</span>
          <span className="lg"><i style={{background: '#d4a5a5'}}></i> TUS</span>
          <span className="lg"><i style={{background: 'repeating-linear-gradient(135deg, #f0d0d0 0 4px, #e8e3d9 4px 8px)'}}></i> kötü gün</span>
        </div>
        <div className="cal__stats">
          {phases.map(p => {
            const dates = allDates.filter(ds => ds >= p.start && ds <= p.end);
            const total = dates.length;
            const done = dates.filter(ds => {
              const info = dayInfo(ds);
              return info && info.pct >= 0.99 && info.total > 0;
            }).length;
            return (
              <div key={p.name} className="pstat">
                <div className="pstat__n">{done}/{total}</div>
                <div className="pstat__l">{p.name}</div>
              </div>
            );
          })}
        </div>
      </div>

      <div className="cal__months">
        {months.map((m, mi) => {
          // Ay ilk gününün hafta-içi indeksi (Pzt=0)
          const firstD = parseDate(m.dates[0]);
          const lastD = parseDate(m.dates[m.dates.length - 1]);
          const offsetStart = (firstD.getDay() + 6) % 7; // Pzt=0
          // Ay içindeki tüm günleri çıkar (1-31); sadece plan içindeki günleri dolduracağız
          const daysInMonth = new Date(m.year, m.month + 1, 0).getDate();
          const cells = [];
          // boş hücreler (ayın başındaki)
          for (let i = 0; i < (firstD.getDate() - 1 + offsetStart); i++) {
            cells.push({ empty: true, key: 'e' + i });
          }
          // ayın bütün günleri (plan içi + plan dışı)
          for (let dnum = 1; dnum <= daysInMonth; dnum++) {
            const d = new Date(m.year, m.month, dnum);
            const ds = fmtDate(d);
            const inPlan = ds >= fmtDate(PLAN_START_LOCAL) && ds <= fmtDate(PLAN_END);
            cells.push({ empty: !inPlan, ds, date: d, key: ds });
          }

          // Ay istatistiği
          const monthDates = m.dates;
          const monthDone = monthDates.filter(ds => {
            const i = dayInfo(ds);
            return i && i.pct >= 0.99 && i.total > 0;
          }).length;

          return (
            <div key={mi} className="month">
              <div className="month__head">
                <div className="month__name">{TR_MONTHS[m.month]}</div>
                <div className="month__count">{monthDone}/{monthDates.length}</div>
              </div>
              <div className="month__dow">
                {['P', 'S', 'Ç', 'P', 'C', 'C', 'P'].map((l, i) => <span key={i}>{l}</span>)}
              </div>
              <div className="month__grid">
                {cells.map(c => {
                  if (c.empty) return <div key={c.key} className="cday cday--empty"></div>;
                  const info = dayInfo(c.ds);
                  const isPast = c.ds < todayStr;
                  const isToday = c.ds === todayStr;
                  let cls = 'cday';
                  if (isPast) cls += ' cday--past';
                  if (isToday) cls += ' cday--today';
                  if (info) {
                    if (info.isTus) cls += ' cday--tus';
                    else if (info.isOff) cls += ' cday--off';
                    else if (info.isExam) cls += ' cday--exam';
                    else if (info.isBad) cls += ' cday--bad';
                    else if (info.isBuffer) cls += ' cday--buffer';
                    else if (info.isLight) cls += ' cday--light';
                  }
                  const mPct = info && info.mH > 0 ? (info.mDone / info.mH) : 0;
                  const ePct = info && info.eH > 0 ? (info.eDone / info.eH) : 0;
                  return (
                    <button
                      key={c.key}
                      className={cls}
                      onClick={(e) => handleClick(e, c.ds)}
                      title={`${c.date.getDate()} ${TR_MONTHS[c.date.getMonth()]}${info ? ` · ${info.total}h` : ''}`}
                    >
                      <div className="cday__n">{c.date.getDate()}</div>
                      {info && info.total > 0 && (
                        <div className="cday__hours">{info.total}h</div>
                      )}
                      {info && info.isTus && <div className="cday__icon">🎯</div>}
                      {info && info.isOff && <div className="cday__icon">✈</div>}
                      {info && info.isExam && <div className="cday__icon">✎</div>}
                      {info && !info.isOff && !info.isTus && !info.isExam && (
                        <div className="cday__halves">
                          <div className="cday__half">
                            <div className="cday__halfFill" style={{height: `${mPct * 100}%`, background: info.mColor}}></div>
                          </div>
                          <div className="cday__half">
                            <div className="cday__halfFill" style={{height: `${ePct * 100}%`, background: info.eColor}}></div>
                          </div>
                        </div>
                      )}
                    </button>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>

      {detail && (
        <CalDetail
          ds={detail.ds}
          x={detail.x}
          y={detail.y}
          info={dayInfo(detail.ds)}
          onClose={() => setDetail(null)}
          onGoWeek={() => { onJumpToWeek && onJumpToWeek(parseDate(detail.ds)); setDetail(null); }}
        />
      )}
    </div>
  );
}

function CalDetail({ ds, x, y, info, onClose, onGoWeek }) {
  React.useEffect(() => {
    const h = () => onClose();
    window.addEventListener('scroll', h, { once: true });
    const k = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', k);
    return () => { window.removeEventListener('scroll', h); window.removeEventListener('keydown', k); };
  }, []);
  const d = parseDate(ds);
  const dow = TR_DAYS_LONG[(d.getDay() + 6) % 7];
  if (!info) {
    return (
      <div className="cdetail" style={{left: x, top: y}} onClick={e => e.stopPropagation()}>
        <div className="cdetail__head">
          <div className="cdetail__date">{d.getDate()} {TR_MONTHS[d.getMonth()]}</div>
          <div className="cdetail__sub">{dow}</div>
        </div>
        <div style={{fontSize:12, color:'var(--ink-3)', fontStyle:'italic'}}>Plan dışı gün.</div>
      </div>
    );
  }
  return (
    <>
      <div style={{position:'fixed', inset:0, zIndex:59}} onClick={onClose}></div>
      <div className="cdetail" style={{left: x, top: y}} onClick={e => e.stopPropagation()}>
        <div className="cdetail__head">
          <div>
            <div className="cdetail__date">{d.getDate()} {TR_MONTHS[d.getMonth()]}</div>
            <div className="cdetail__sub">{dow} · {info.total}h planlı · {Math.round(info.pct*100)}% bitti</div>
          </div>
        </div>
        {info.day.note && <div className="cdetail__note">{info.day.note}</div>}
        {info.day.morning && info.day.morning.length > 0 && (
          <div className="cdetail__slot">
            <div className="cdetail__slotlabel">Sabah · 08-12</div>
            {info.day.morning.map(t => (
              <div key={t.id} className="cdetail__task">
                <span className="cdetail__task-dot" style={{background: t.color || '#c9c2b5'}}></span>
                <span className={'cdetail__task-title' + (t.done ? ' cdetail__task-done' : '')}>{t.title}{t.partIdx && t.partTotal ? ` · ${t.partIdx}/${t.partTotal}` : ''}</span>
                <span className="cdetail__task-hours">{t.hours}h</span>
              </div>
            ))}
          </div>
        )}
        {info.day.evening && info.day.evening.length > 0 && (
          <div className="cdetail__slot">
            <div className="cdetail__slotlabel">Akşam · 18-22</div>
            {info.day.evening.map(t => (
              <div key={t.id} className="cdetail__task">
                <span className="cdetail__task-dot" style={{background: t.color || '#c9c2b5'}}></span>
                <span className={'cdetail__task-title' + (t.done ? ' cdetail__task-done' : '')}>{t.title}{t.partIdx && t.partTotal ? ` · ${t.partIdx}/${t.partTotal}` : ''}</span>
                <span className="cdetail__task-hours">{t.hours}h</span>
              </div>
            ))}
          </div>
        )}
        <div className="cdetail__actions">
          <button className="btn btn--ghost" onClick={onClose}>Kapat</button>
          <button className="btn btn--primary" onClick={onGoWeek}>Bu haftaya git →</button>
        </div>
      </div>
    </>
  );
}

// ========== ScoreBadge: üst bar puan göstergesi ==========
function ScoreBadge({ state, todayStr, ghost }) {
  const totalEff = React.useMemo(() => GAMIFY.computeTotalEffective(state.days), [state]);
  const earned = GAMIFY.totalEarned(state.days, totalEff);
  const expected = GAMIFY.expectedByDate(todayStr, state.days, totalEff);
  const current = GAMIFY.START_SCORE + earned;

  const delta = earned - expected;
  const behind = delta < -0.01;

  return (
    <div className="sbadge">
      <div className="sbadge__main">
        <div className="sbadge__label">Puanım</div>
        <div className="sbadge__value">
          <span className="sbadge__num">{current.toFixed(2)}</span>
          <span className="sbadge__target"> / {GAMIFY.TARGET_SCORE}</span>
        </div>
      </div>
      <div className="sbadge__track">
        <div className="sbadge__fill" style={{width: `${Math.min(100, (earned / GAMIFY.DELTA_SCORE) * 100)}%`}}></div>
        <div className="sbadge__expected" style={{left: `${Math.min(100, (expected / GAMIFY.DELTA_SCORE) * 100)}%`}}></div>
      </div>
      <div className={'sbadge__delta' + (behind ? ' sbadge__delta--behind' : ' sbadge__delta--ahead')}>
        {behind ? `${Math.abs(delta).toFixed(2)} geride` : delta < 0.01 ? 'hedefte' : `+${delta.toFixed(2)} önde`}
      </div>
      {ghost && (
        <div key={ghost.key} className="sbadge__ghost">+{ghost.delta.toFixed(3)}</div>
      )}
    </div>
  );
}

// ========== PuanView ==========
function PointsView({ state, todayStr, onJumpToWeek }) {
  const totalEff = GAMIFY.computeTotalEffective(state.days);
  const earned = GAMIFY.totalEarned(state.days, totalEff);
  const current = GAMIFY.START_SCORE + earned;
  const expectedNow = GAMIFY.START_SCORE + GAMIFY.expectedByDate(todayStr, state.days, totalEff);

  const weeks = [];
  const start = parseDate(GAMIFY.PLAN_START_STR);
  const end = parseDate(GAMIFY.PLAN_END_STR);
  let cur = startOfWeek(start);
  let cumulativeMax = 0;
  let cumulativeEarned = 0;
  while (cur <= end) {
    const weekEnd = addDays(cur, 6);
    let wMax = 0, wEarned = 0;
    for (let i = 0; i < 7; i++) {
      const d = addDays(cur, i);
      const ds = fmtDate(d);
      if (ds < GAMIFY.PLAN_START_STR || ds > GAMIFY.PLAN_END_STR) continue;
      wMax += GAMIFY.dayMaxPoints(ds, state.days, totalEff);
      wEarned += GAMIFY.dayEarnedPoints(ds, state.days, totalEff);
    }
    cumulativeMax += wMax;
    cumulativeEarned += wEarned;
    const mf = GAMIFY.monthFactorFor(fmtDate(cur));
    const pct = wMax > 0 ? (wEarned / wMax) * 100 : 0;
    weeks.push({
      start: new Date(cur), end: weekEnd,
      wMax, wEarned, pct,
      cumMax: cumulativeMax,
      cumEarned: cumulativeEarned,
      projected: GAMIFY.START_SCORE + cumulativeMax,
      targetScore: GAMIFY.START_SCORE + cumulativeMax,
      factor: mf.factor,
      monthLabel: mf.label,
      isPast: fmtDate(weekEnd) < todayStr,
      isCurrent: todayStr >= fmtDate(cur) && todayStr <= fmtDate(weekEnd),
    });
    cur = addDays(cur, 7);
  }

  const delta = earned - GAMIFY.expectedByDate(todayStr, state.days, totalEff);

  // Achievement color + emoji based on percentage
  function achieveStyle(pct, isPast) {
    if (!isPast && pct === 0) return { color: 'var(--ink-3)', emoji: '' };
    if (pct >= 90) return { color: '#4ade80', emoji: '🏆' };
    if (pct >= 75) return { color: '#facc15', emoji: '⚡' };
    if (pct >= 50) return { color: '#f87171', emoji: '🔥' };
    if (isPast) return { color: '#6b7280', emoji: '💀' };
    return { color: 'var(--ink-3)', emoji: '' };
  }

  return (
    <div className="points">
      <div className="points__hero">
        <div className="points__block">
          <div className="points__label">Güncel Puanım</div>
          <div className="points__big">{current.toFixed(2)}</div>
          <div className="points__sub">başlangıç 58 · hedef {GAMIFY.TARGET_SCORE}</div>
        </div>
        <div className="points__block">
          <div className="points__label">Bugün olmam gereken</div>
          <div className="points__big points__big--muted">{expectedNow.toFixed(2)}</div>
          <div className={'points__sub ' + (delta >= 0 ? 'points__sub--ok' : 'points__sub--behind')}>
            {delta >= 0 ? `+${delta.toFixed(2)} önde` : `${delta.toFixed(2)} geride`}
          </div>
        </div>
        <div className="points__block">
          <div className="points__label">TUS'ta olacağım</div>
          <div className="points__big">~{(GAMIFY.START_SCORE + cumulativeMax).toFixed(1)}</div>
          <div className="points__sub">tüm planı %100 tamamlarsam</div>
        </div>
      </div>

      <div className="points__factors">
        <div className="points__sectionlabel">Ay Katsayıları</div>
        <div className="points__factorlist">
          {GAMIFY.MONTH_BOUNDS.map(m => {
            const isNow = todayStr >= m.start && todayStr <= m.end;
            return (
              <div key={m.idx} className={'factor' + (isNow ? ' factor--now' : '')}>
                <div className="factor__name">{m.label}</div>
                <div className="factor__mult">{m.factor.toFixed(2)}×</div>
                <div className="factor__dates">{formatShortDate(m.start)} – {formatShortDate(m.end)}</div>
                {isNow && <div className="factor__now">şu an</div>}
              </div>
            );
          })}
        </div>
        <div className="points__note">
          Aynı 1 saatin puan değeri zamana göre artar — 4. ayda 1 saat, 1. aydaki 2 saate bedel. FSRS olgunluğu + sınav yakınlığı etkisini modellar.
        </div>
      </div>

      <div className="points__weeks">
        <div className="points__sectionlabel">Haftalık Plan</div>
        <div className="ptable">
          <div className="ptable__head">
            <span className="ptable__h-num">#</span>
            <span className="ptable__h-date">Tarih</span>
            <span className="ptable__h-factor">Katsayı</span>
            <span className="ptable__h-progress">İlerleme</span>
            <span className="ptable__h-score">Hafta P.</span>
            <span className="ptable__h-target">Hedef</span>
          </div>
          {(() => {
            let streak = 0;
            return weeks.map((w, i) => {
              const ach = achieveStyle(w.pct, w.isPast);
              const barWidth = Math.min(100, w.pct);
              // Streak hesabı: arka arkaya ≥75% olan haftalar
              if (w.isPast && w.pct >= 75) {
                streak++;
              } else if (w.isPast) {
                streak = 0;
              }
              const showStreak = w.isPast && w.pct >= 75 && streak >= 2;
              return (
                <button
                  key={i}
                  className={'ptable__row' + (w.isCurrent ? ' ptable__row--now' : '') + (w.isPast ? ' ptable__row--past' : '') + (w.pct >= 90 && w.isPast ? ' ptable__row--complete' : '')}
                  onClick={() => onJumpToWeek && onJumpToWeek(w.start)}
                >
                  <span className="ptable__num">{i + 1}.</span>
                  <span className="ptable__date">
                    {formatShortDate(fmtDate(w.start))} – {formatShortDate(fmtDate(w.end))}
                    <span className="ptable__month-tag">{w.monthLabel}</span>
                  </span>
                  <span className="ptable__factor">{w.factor.toFixed(2)}×</span>
                  <span className="ptable__progress">
                    <span className="ptable__bar">
                      <span
                        className="ptable__bar-fill"
                        style={{ width: barWidth + '%', background: ach.color }}
                      />
                    </span>
                    <span className="ptable__pct" style={{ color: ach.color }}>
                      {w.isPast || w.isCurrent ? `${Math.round(w.pct)}%` : '—'}
                      {ach.emoji && <span className="ptable__emoji">{ach.emoji}</span>}
                      {showStreak && <span className="ptable__streak" title={streak + ' hafta üst üste ≥75%'}>🔥{streak}</span>}
                    </span>
                  </span>
                  <span className="ptable__w">
                    {w.wEarned > 0 && <span className="ptable__earned" style={{ color: ach.color }}>{w.wEarned.toFixed(2)}</span>}
                    <span className="ptable__max">{w.wEarned > 0 ? ' / ' : ''}{w.wMax.toFixed(2)}</span>
                  </span>
                  <span className="ptable__cum" style={w.isPast && w.pct >= 90 ? { color: '#4ade80' } : {}}>
                    {(GAMIFY.START_SCORE + w.cumEarned).toFixed(2)}
                    <span className="ptable__target-small"> / {w.targetScore.toFixed(1)}</span>
                  </span>
                </button>
              );
            });
          })()}
        </div>
      </div>

      {/* ===== TIRMANIŞIM — Her Puan Seviyesi ===== */}
      <div className="points__climb">
        <div className="points__sectionlabel">🏔️ TUS Tırmanışım</div>
        <div className="points__climb-sub">Her 1 puan = yüzlerce sıra. Dağın zirvesine çık.</div>
        <div className="climb">
          {GAMIFY.SCORE_RANKS.slice().reverse().map((r, idx, arr) => {
            const isReached = current >= r.score;
            const isCurrent = Math.floor(current) === r.score;
            const isNext = !isReached && (idx === arr.length - 1 || current >= arr[idx + 1].score);
            const progress = isCurrent ? ((current - r.score) * 100) : isReached ? 100 : 0;
            const prevRank = idx < arr.length - 1 ? arr[idx + 1] : null;
            const jumped = prevRank ? prevRank.rank - r.rank : 0;
            return (
              <div
                key={r.score}
                className={
                  'climb__step' +
                  (isReached ? ' climb__step--reached' : '') +
                  (isCurrent ? ' climb__step--current' : '') +
                  (isNext ? ' climb__step--next' : '')
                }
              >
                <div className="climb__score">
                  <span className="climb__t">T{r.score}</span>
                  {r.score === 72 && <span className="climb__flag">🎯</span>}
                  {r.score === 63 && <span className="climb__flag">⚡</span>}
                  {isCurrent && <span className="climb__you">← Sen</span>}
                </div>
                <div className="climb__bar-wrap">
                  <div className="climb__bar">
                    <div
                      className="climb__bar-fill"
                      style={{
                        width: progress + '%',
                        background: isReached
                          ? (r.score >= 70 ? '#4ade80' : r.score >= 65 ? '#22d3ee' : '#60a5fa')
                          : '#facc15'
                      }}
                    />
                  </div>
                </div>
                <div className="climb__rank">
                  <span className="climb__rank-num">~{r.rank.toLocaleString('tr-TR')}</span>
                  <span className="climb__rank-label">sıra</span>
                </div>
                <div className="climb__pct">
                  İlk %{r.pct}
                </div>
                {jumped > 0 && isReached && (
                  <div className="climb__jumped">
                    ↑{jumped.toLocaleString('tr-TR')} kişi geçildi
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

// ========== MissedView ==========
function MissedView({ state, todayStr }) {
  const totalEff = GAMIFY.computeTotalEffective(state.days);
  const missed = GAMIFY.missedByLesson(state.days, todayStr);
  const totalMissedH = missed.reduce((a, m) => a + m.missedH, 0);
  const totalMissedPts = missed.reduce((a, m) => {
    return a + m.days.reduce((aa, d) => {
      const pph = GAMIFY.pointsPerHour(d.ds, totalEff);
      return aa + d.hours * pph;
    }, 0);
  }, 0);

  if (missed.length === 0) {
    return (
      <div className="missed">
        <div className="missed__empty">
          <div className="missed__emptyicon">✓</div>
          <div className="missed__emptytitle">Kaçırılan yok</div>
          <div className="missed__emptysub">Geçmiş günleri tam tamamladın. Böyle devam.</div>
        </div>
      </div>
    );
  }

  return (
    <div className="missed">
      <div className="missed__head">
        <div className="missed__stat">
          <div className="missed__statn">{totalMissedH.toFixed(1)}h</div>
          <div className="missed__statl">Kaçırılan saat</div>
        </div>
        <div className="missed__stat">
          <div className="missed__statn missed__statn--red">−{totalMissedPts.toFixed(2)}</div>
          <div className="missed__statl">Kaçırılan puan</div>
        </div>
        <div className="missed__stat">
          <div className="missed__statn">{missed.length}</div>
          <div className="missed__statl">Etkilenen ders</div>
        </div>
      </div>

      <div className="missed__note">
        Geçmişte planlanmış ama tikli olmayan saatler. Telafi için hafta sonu veya buffer günlerinde yakala.
      </div>

      <div className="missed__list">
        {missed.map(m => {
          const pts = m.days.reduce((aa, d) => aa + d.hours * GAMIFY.pointsPerHour(d.ds, totalEff), 0);
          return (
            <div key={m.key} className="missedrow">
              <div className="missedrow__head">
                <span className="missedrow__dot" style={{background: m.color}}></span>
                <span className="missedrow__title">{m.title}</span>
                <span className="missedrow__h">{m.missedH.toFixed(1)}h</span>
                <span className="missedrow__p">−{pts.toFixed(2)}</span>
              </div>
              <div className="missedrow__days">
                {m.days.slice(0, 8).map((d, i) => (
                  <div key={i} className="missedrow__day">
                    <span className="missedrow__dayd">{formatShortDate(d.ds)}</span>
                    <span className="missedrow__dayt">{d.title}</span>
                    <span className="missedrow__dayh">{d.hours.toFixed(1)}h</span>
                  </div>
                ))}
                {m.days.length > 8 && <div className="missedrow__more">+{m.days.length - 8} gün daha</div>}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ========== RewardsView ==========
function RewardsView({ state, todayStr }) {
  const totalEff = GAMIFY.computeTotalEffective(state.days);
  const earned = GAMIFY.totalEarned(state.days, totalEff);
  const current = GAMIFY.START_SCORE + earned;
  const streak = GAMIFY.currentStreak(state.days, todayStr);
  const next = GAMIFY.nextMilestone(current);

  const todayMax = GAMIFY.dayMaxPoints(todayStr, state.days, totalEff);
  const todayEarned = GAMIFY.dayEarnedPoints(todayStr, state.days, totalEff);

  const weekStart = startOfWeek(parseDate(todayStr));
  let wMax = 0, wEarned = 0;
  for (let i = 0; i < 7; i++) {
    const ds = fmtDate(addDays(weekStart, i));
    wMax += GAMIFY.dayMaxPoints(ds, state.days, totalEff);
    wEarned += GAMIFY.dayEarnedPoints(ds, state.days, totalEff);
  }

  return (
    <div className="rewards">
      <div className="rewards__hero">
        <div className="rewards__streak">
          <div className="rewards__streaknum">{streak}</div>
          <div className="rewards__streaklabel">
            {streak > 0 ? 'gün arka arkaya' : 'seri başlat'}
          </div>
          <div className="rewards__streakbar">
            {Array.from({length: Math.max(7, streak + 1)}).map((_, i) => (
              <div key={i} className={'rdot' + (i < streak ? ' rdot--on' : '')}></div>
            ))}
          </div>
        </div>

        <div className="rewards__card">
          <div className="rewards__todaylabel">Bugün</div>
          <div className="rewards__todayn">
            <span className="rewards__todayearned">+{todayEarned.toFixed(2)}</span>
            <span className="rewards__todaymax"> / +{todayMax.toFixed(2)}</span>
          </div>
          <div className="rewards__todaybar">
            <div className="rewards__todayfill" style={{width: `${todayMax > 0 ? (todayEarned / todayMax) * 100 : 0}%`}}></div>
          </div>
          <div className="rewards__todaysub">
            {todayEarned === 0 && todayMax > 0 && 'Bugünün ilk bloğunu tıkla.'}
            {todayEarned > 0 && todayEarned < todayMax && `+${(todayMax - todayEarned).toFixed(2)} puan daha.`}
            {todayEarned >= todayMax && todayMax > 0 && '✓ Günü bitirdin.'}
            {todayMax === 0 && 'Bugün plan yok.'}
          </div>
        </div>

        <div className="rewards__card">
          <div className="rewards__todaylabel">Bu hafta</div>
          <div className="rewards__todayn">
            <span className="rewards__todayearned">+{wEarned.toFixed(2)}</span>
            <span className="rewards__todaymax"> / +{wMax.toFixed(2)}</span>
          </div>
          <div className="rewards__todaybar">
            <div className="rewards__todayfill" style={{width: `${wMax > 0 ? (wEarned / wMax) * 100 : 0}%`}}></div>
          </div>
          <div className="rewards__todaysub">hafta toplamı</div>
        </div>
      </div>

      <div className="rewards__section">
        <div className="rewards__sectionlabel">Milestones</div>
        <div className="milestones">
          {GAMIFY.MILESTONES.map(m => {
            const reached = current >= m.score;
            const isNext = !reached && next && next.score === m.score;
            // ADHD için emoji haritası
            const emoji = reached
              ? (m.score >= 72 ? '🏆' : m.score >= 69 ? '🔥' : m.score >= 66 ? '⚡' : m.score >= 63 ? '💪' : '✅')
              : isNext ? '🎯' : '';
            return (
              <div key={m.score} className={'milestone' + (reached ? ' milestone--done' : '') + (isNext ? ' milestone--next' : '')}>
                <div className="milestone__score">{m.score}</div>
                <div className="milestone__body">
                  <div className="milestone__label">{m.label}</div>
                  <div className="milestone__note">{m.note}</div>
                  {reached && (
                    <div className="milestone__checkpoint">✓ Checkpoint ulaşıldı</div>
                  )}
                </div>
                <div className="milestone__icon">
                  {emoji}
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  Countdown, DailyProgress, WeekView, Kanban, EditModal, MacroView, ScoreBadge, PointsView, MissedView, RewardsView,
  loadState, saveState, cloudSave, useCloudSync, useNow, startOfWeek, dayIdxMonFirst,
  TR_MONTHS, TR_DAYS, TR_DAYS_LONG, shortPhase, phaseColor,
});
