(function(){
// ============================================================
// views.jsx — SettingsPanel, ReviewModal, CalendarWeekView,
//             SlotAdder, downloadICS
// Depends on (window): THEMES, ACCENT_PRESETS, GLASS_PRESETS, applyTheme, applyGlass,
//   todayISO, localISO, getCatColor, prioCol, hexToRgba
// ============================================================

const { useState, useEffect } = React;

// ── NotesSendButton ──────────────────────────────────────────────────
function NotesSendButton({ notes, onClear, profile }){
  const [sendState, setSendState] = useState("idle");
  const send = async () => {
    if(!notes.trim())return;
    setSendState("sending");
    try{
      const uq=profile?`?user=${encodeURIComponent(profile)}`:'';
      const r=await fetch('/api/notes'+uq,{method:'POST',headers:{'Content-Type':'application/json',...authHeaders()},body:JSON.stringify({text:notes,ts:Date.now()})});
      setSendState(r.ok?"ok":"err");
      if(r.ok&&onClear)onClear();
    }catch{setSendState("err");}
    setTimeout(()=>setSendState("idle"),3000);
  };
  return(
    <button onClick={send} disabled={sendState==="sending"||!notes.trim()} style={{width:"100%",padding:"9px",fontSize:12,borderRadius:8,border:"1px solid var(--col-border)",color:sendState==="ok"?"#166534":sendState==="err"?"#b91c1c":"var(--col-accent)",background:"transparent",cursor:"pointer",fontWeight:500}}>
      {sendState==="sending"?window.t("settings.sending"):sendState==="ok"?window.t("settings.notesSent"):sendState==="err"?window.t("settings.notesError"):window.t("settings.notesSend")}
    </button>
  );
}

// ── SettingsPanel ────────────────────────────────────────────────────
function SettingsPanel({ settings, onSave, onClose }){
  const [s, setS] = useState(settings);
  const [openFeat, setOpenFeat] = useState(null);
  const [settingsTab, setSettingsTab] = useState("aussehen"); // FIXED: Einstellungen tabs added
  const notesKey = "planer_notes_" + (settings.profile || "");
  const [notes, setNotes] = useState(() => localStorage.getItem("planer_notes_" + (settings.profile || "")) || "");
  const [piAuth, setPiAuth] = useState({connected:false,pending:false,userCode:null,verUri:null});
  const [pwOpen, setPwOpen] = useState(false);
  const [pw, setPw] = useState({cur:"",nw:"",status:"",msg:""});
  const [unOpen, setUnOpen] = useState(false);
  const [un, setUn] = useState({nw:"",pw:"",status:"",msg:""});
  const [emOpen, setEmOpen] = useState(false);
  const [em, setEm] = useState({val:"",status:"",msg:""});
  const [reportSt, setReportSt] = useState("");
  const [usersModal, setUsersModal] = useState(null);
  const [overviewOpen, setOverviewOpen] = useState(false);
  const [overview, setOverview] = useState(null);

  // ?user= for per-profile Outlook tokens — uses SAVED settings.profile, not unsaved local state
  const uq = () => settings.profile ? `?user=${encodeURIComponent(settings.profile)}` : '';

  useEffect(()=>{
    fetch('/api/outlook-status'+uq(),{headers:{...authHeaders()}}).then(r=>r.json()).then(d=>{  // FIXED: add authHeaders
      setPiAuth(p=>({...p,connected:d.connected}));
    }).catch(()=>{});
  },[]);

  // FIXED: re-register push subscription on mount if permission already granted
  // (subscriptions can expire/become invalid; this keeps the server-side copy fresh)
  useEffect(()=>{
    if(typeof Notification!=='undefined'&&Notification.permission==='granted')subscribePush();
  },[]);

  async function subscribePush(){
    if(typeof Notification==='undefined'||!('serviceWorker' in navigator))return false;
    try{
      const reg = await navigator.serviceWorker.ready;
      const keyRes = await fetch('/api/push/key').then(r=>r.json());
      const raw = keyRes.publicKey;
      const padding = '='.repeat((4 - raw.length % 4) % 4);
      const base64 = (raw + padding).replace(/-/g,'+').replace(/_/g,'/');
      const rawData = atob(base64);
      const key = new Uint8Array([...rawData].map(c=>c.charCodeAt(0)));
      const sub = await reg.pushManager.subscribe({userVisibleOnly:true, applicationServerKey:key});
      const r = await fetch('/api/push/subscribe',{method:'POST',headers:{'Content-Type':'application/json',...authHeaders()},body:JSON.stringify(sub)});
      return r.ok;
    }catch(e){console.error('Push subscribe:',e);return false;}
  }

  useEffect(()=>{
    if(!piAuth.pending)return;
    const iv=setInterval(async()=>{
      try{
        const d=await fetch('/api/outlook-status'+uq(),{headers:{...authHeaders()}}).then(r=>r.json()); // FIXED: add authHeaders
        if(d.connected){setPiAuth({connected:true,pending:false,userCode:null,verUri:null});clearInterval(iv);}
        else if(!d.pending){setPiAuth(p=>({...p,pending:false}));clearInterval(iv);}
      }catch{}
    },3000);
    return()=>clearInterval(iv);
  },[piAuth.pending]);

  async function startPiAuth(){
    if(!s.azureClientId){alert(window.t("settings.azureMissing"));return;}
    try{
      const d=await fetch('/api/outlook-auth'+uq(),{method:'POST',headers:{'Content-Type':'application/json',...authHeaders()},body:JSON.stringify({clientId:s.azureClientId})}).then(r=>r.json()); // FIXED: add authHeaders
      if(d.user_code)setPiAuth({connected:false,pending:true,userCode:d.user_code,verUri:d.verification_uri});
      else alert(d.error||"Fehler");
    }catch(e){alert("Fehler: "+e.message);}
  }

  async function disconnectPiAuth(){
    await fetch('/api/outlook-auth'+uq(),{method:'DELETE',headers:{...authHeaders()}}).catch(()=>{}); // FIXED: add authHeaders
    setPiAuth({connected:false,pending:false,userCode:null,verUri:null});
  }

  async function doChangePw(){
    if(!pw.cur||!pw.nw)return;
    setPw(x=>({...x,status:"saving"}));
    try{
      const r=await fetch('/api/change-password',{method:'POST',headers:{'Content-Type':'application/json',...authHeaders()},body:JSON.stringify({currentPassword:pw.cur,newPassword:pw.nw})});
      const d=await r.json();
      if(r.ok)setPw({cur:"",nw:"",status:"ok",msg:window.t("settings.passwordChanged")});
      else setPw(x=>({...x,status:"err",msg:d.error||window.t("settings.error")}));
    }catch{setPw(x=>({...x,status:"err",msg:window.t("settings.networkError")}));}
  }
  async function doChangeUn(){
    if(!un.nw||!un.pw)return;
    setUn(x=>({...x,status:"saving"}));
    try{
      const r=await fetch('/api/change-username',{method:'POST',headers:{'Content-Type':'application/json',...authHeaders()},body:JSON.stringify({newUsername:un.nw,currentPassword:un.pw})});
      const d=await r.json();
      if(r.ok){window.setAuthToken(d.token,d.username);window.location.reload();}
      else setUn(x=>({...x,status:"err",msg:d.error||window.t("settings.error")}));
    }catch{setUn(x=>({...x,status:"err",msg:window.t("settings.networkError")}));}
  }
  async function loadOverview(){
    if(overviewOpen){setOverviewOpen(false);return;}
    setOverviewOpen(true);
    if(overview)return;
    try{
      const r=await fetch('/api/admin/overview',{headers:{...authHeaders()}});
      const d=await r.json();
      setOverview(Array.isArray(d)?d:[]);
    }catch{setOverview([]);}
  }
  async function openUsersModal(){
    setUsersModal("loading");
    try{
      const r=await fetch('/api/admin/users',{headers:{...authHeaders()}});
      const d=await r.json();
      setUsersModal(Array.isArray(d)?d:[]);
    }catch{setUsersModal([]);}
  }
  async function doSendReport(){
    setReportSt("sending");
    try{
      const r=await fetch('/api/admin/send-report',{headers:{...authHeaders()}});
      setReportSt(r.ok?"ok":"err");
    }catch{setReportSt("err");}
  }
  async function doChangeEm(){
    setEm(x=>({...x,status:"saving"}));
    try{
      const r=await fetch('/api/change-email',{method:'POST',headers:{'Content-Type':'application/json',...authHeaders()},body:JSON.stringify({email:em.val.trim()})});
      const d=await r.json();
      if(r.ok)setEm(x=>({...x,status:"ok",msg:d.email?window.t("settings.savedEmail",{email:d.email}):window.t("settings.emailRemoved")}));
      else setEm(x=>({...x,status:"err",msg:d.error||window.t("settings.error")}));
    }catch{setEm(x=>({...x,status:"err",msg:window.t("settings.networkError")}));}
  }

  const secTitle = (label) => (
    <div style={{display:"flex",alignItems:"center",gap:10,marginBottom:14}}>
      <span style={{fontSize:11,fontWeight:700,color:"var(--col-text-3)",textTransform:"uppercase",letterSpacing:"0.1em",whiteSpace:"nowrap"}}>{label}</span>
      <div style={{flex:1,height:1,background:"var(--col-border)"}}/>
    </div>
  );

  return (
    <div style={{position:"fixed",inset:0,background:"rgba(20,16,12,0.55)",zIndex:500,display:"flex",alignItems:"center",justifyContent:"center",padding:"16px"}} onClick={onClose}>
      <div style={{width:"100%",maxWidth:700,maxHeight:"92vh",background:"var(--col-bg)",borderRadius:18,boxShadow:"0 32px 80px rgba(0,0,0,0.28),0 4px 16px rgba(0,0,0,0.12)",overflow:"hidden",display:"flex",flexDirection:"column"}} onClick={e=>e.stopPropagation()}>

        {/* ── Header ── */}
        <div style={{padding:"20px 28px 18px",borderBottom:"1px solid var(--col-border)",display:"flex",alignItems:"center",justifyContent:"space-between",flexShrink:0}}>
          <div style={{display:"flex",alignItems:"center",gap:10}}>
            <span style={{fontSize:22,lineHeight:1}}>⚙</span>
            <span style={{fontSize:19,fontWeight:600,color:"var(--col-text)",fontFamily:"var(--serif)",letterSpacing:"-0.01em"}}>{t("settings.title")}</span>
          </div>
          <button onClick={onClose} style={{width:34,height:34,borderRadius:"50%",background:"var(--col-bg-sec)",border:"1px solid var(--col-border)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:16,color:"var(--col-text-sec)",cursor:"pointer",flexShrink:0}}>✕</button>
        </div>

        {/* ── Tab Navigation ── */}
        <div style={{display:"flex",borderBottom:"1px solid var(--col-border)",background:"var(--col-bg)",flexShrink:0}}>
          {[["aussehen",t("settings.tab.aussehen")],["verbindungen",t("settings.tab.verbindungen")],["hilfe",t("settings.tab.hilfe")]].map(([id,label])=>(
            <button key={id} onClick={()=>setSettingsTab(id)}
              style={{flex:1,padding:"10px 0",fontSize:12,fontWeight:settingsTab===id?600:400,
                color:settingsTab===id?"var(--col-accent)":"var(--col-text-sec)",
                background:"none",border:"none",borderBottom:settingsTab===id?"2px solid var(--col-accent)":"2px solid transparent",
                cursor:"pointer",letterSpacing:"0.01em"}}>
              {label}
            </button>
          ))}
        </div>

        {/* ── Scrollable content ── */}
        <div style={{overflowY:"auto",flex:1,padding:"28px"}}>

          {settingsTab==="aussehen"&&<>
          {/* Darstellung */}
          {secTitle(t("settings.section.darstellung"))}
          <div style={{background:"var(--col-bg-sec)",borderRadius:14,padding:"20px",marginBottom:28}}>

            <div style={{fontSize:12,fontWeight:600,color:"var(--col-text-sec)",marginBottom:12}}>{t("settings.colorWorld")}</div>
            <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:10,marginBottom:20}}>
              {Object.entries(THEMES).map(([key,th])=>{
                const sel=s.theme===key;
                const isDark=key==="ink"||key==="marine";
                return (
                  <button key={key} onClick={()=>{
                    const newAccent=th.accent||s.accent||"#A15C38";
                    setS(x=>({...x,theme:key,accent:newAccent}));
                    applyTheme(key,newAccent);
                  }} style={{borderRadius:10,overflow:"hidden",border:sel?"2px solid var(--col-accent)":"2px solid transparent",outline:sel?"none":"1px solid var(--col-border)",outlineOffset:-1,cursor:"pointer",background:"none",padding:0,boxShadow:sel?"0 2px 8px var(--col-accent-glow)":"none"}}>
                    <div style={{height:48,background:th.swatch,display:"flex",alignItems:"center",justifyContent:"center",gap:8}}>
                      <span style={{width:13,height:13,borderRadius:"50%",background:th.swatchSec,border:`1px solid ${isDark?"rgba(255,255,255,0.15)":"rgba(0,0,0,0.1)"}`}}/>
                      <span style={{width:13,height:13,borderRadius:"50%",background:th.accent||"#A15C38"}}/>
                    </div>
                    <div style={{padding:"6px 0",fontSize:11,fontWeight:500,color:isDark?"rgba(255,255,255,0.7)":"var(--col-text-sec)",textAlign:"center",background:th.swatchSec}}>{th.name}</div>
                  </button>
                );
              })}
            </div>

            <div style={{fontSize:12,fontWeight:600,color:"var(--col-text-sec)",marginBottom:10}}>{t("settings.accentColor")}</div>
            <div style={{display:"flex",gap:8,flexWrap:"wrap",alignItems:"center",marginBottom:4}}>
              {ACCENT_PRESETS.map(a=>{
                const sel=(s.accent||"#A15C38").toLowerCase()===a.hex.toLowerCase();
                return (
                  <button key={a.hex} title={a.name} onClick={()=>{setS(x=>({...x,accent:a.hex}));applyTheme(s.theme||"paper",a.hex);}} style={{width:28,height:28,borderRadius:"50%",background:a.hex,border:sel?"3px solid var(--col-text)":"2px solid transparent",padding:0,boxShadow:sel?"0 0 0 2px var(--col-bg)":"none",cursor:"pointer"}}/>
                );
              })}
              <label style={{display:"inline-flex",alignItems:"center",gap:6,marginLeft:2,fontSize:11,color:"var(--col-text-sec)",cursor:"pointer"}}>
                <input type="color" value={s.accent||"#A15C38"} onChange={e=>{setS(x=>({...x,accent:e.target.value}));applyTheme(s.theme||"paper",e.target.value);}} style={{width:28,height:28,padding:0,border:"2px solid var(--col-border)",borderRadius:"50%",cursor:"pointer",background:"none"}}/>
                {t("settings.ownColor")}
              </label>
              <span className="mono" style={{fontSize:10,color:"var(--col-text-3)",letterSpacing:"0.05em",marginLeft:4}}>{(s.accent||"#A15C38").toUpperCase()}</span>
            </div>

            <div style={{height:1,background:"var(--col-border)",margin:"18px 0"}}/>

            <div style={{fontSize:12,fontWeight:600,color:"var(--col-text-sec)",marginBottom:10}}>{t("settings.language")}</div>
            <div style={{display:"flex",gap:8,marginBottom:20}}>
              {[{k:"de",l:"Deutsch"},{k:"en",l:"English"}].map(({k,l})=>{
                const sel=(s.language||"de")===k;
                return (
                  <button key={k} onClick={()=>{setS(x=>({...x,language:k}));window.currentLang=k;}} style={{padding:"9px 14px",fontSize:12,borderRadius:8,border:sel?"2px solid var(--col-accent)":"1px solid var(--col-border)",background:sel?"var(--col-accent-wash)":"var(--col-bg)",color:sel?"var(--col-accent)":"var(--col-text-sec)",fontWeight:sel?600:400,cursor:"pointer"}}>
                    {l}
                  </button>
                );
              })}
            </div>

            <div style={{height:1,background:"var(--col-border)",margin:"18px 0"}}/>

            <div style={{fontSize:12,fontWeight:600,color:"var(--col-text-sec)",marginBottom:10}}>{t("settings.surface")}</div>
            <div style={{display:"flex",gap:8,marginBottom:(s.surface==="glass")?10:0}}>
              {[{k:"",l:t("settings.surfaceNormal")},{k:"glass",l:t("settings.surfaceGlass")}].map(({k,l})=>{
                const sel=(s.surface||"")=== k;
                return(
                  <button key={k} onClick={()=>{
                    const ns=k; const preset=s.glassPreset||"frost";
                    setS(x=>({...x,surface:ns}));
                    if(ns==="glass")applyGlass("glass",preset); else applyGlass("","");
                  }} style={{flex:1,padding:"9px",fontSize:12,borderRadius:8,border:sel?"2px solid var(--col-accent)":"1px solid var(--col-border)",background:sel?"var(--col-accent-wash)":"var(--col-bg)",color:sel?"var(--col-accent)":"var(--col-text-sec)",fontWeight:sel?600:400,cursor:"pointer"}}>
                    {l}
                  </button>
                );
              })}
            </div>
            {(s.surface==="glass")&&(
              <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:8,marginTop:8}}>
                {Object.entries(GLASS_PRESETS).map(([key,gp])=>{
                  const sel=(s.glassPreset||"frost")===key;
                  return(
                    <button key={key} onClick={()=>{setS(x=>({...x,glassPreset:key}));applyGlass("glass",key);}} style={{padding:"9px",fontSize:12,borderRadius:8,border:sel?"2px solid var(--col-accent)":"1px solid var(--col-border)",background:sel?"var(--col-accent-wash)":"var(--col-bg)",color:sel?"var(--col-accent)":"var(--col-text-sec)",fontWeight:sel?600:400,cursor:"pointer"}}>
                      {gp.name}
                    </button>
                  );
                })}
              </div>
            )}
          </div>

          {/* Benachrichtigungen */}
          {secTitle(t("settings.section.notifications"))}
          <div style={{background:"var(--col-bg-sec)",borderRadius:14,padding:"20px",marginBottom:28}}>
            <label style={{display:"flex",alignItems:"center",gap:10,padding:"7px 0",fontSize:13,color:"var(--col-text)",cursor:"pointer"}}>
              <input type="checkbox" checked={s.notifyTodos!==false} onChange={e=>setS(x=>({...x,notifyTodos:e.target.checked}))}/>
              {t("settings.notifyDeadlines")}
            </label>
            <label style={{display:"flex",alignItems:"center",gap:10,padding:"7px 0",fontSize:13,color:"var(--col-text)",cursor:"pointer"}}>
              <input type="checkbox" checked={s.calendarPush!==false} onChange={e=>setS(x=>({...x,calendarPush:e.target.checked}))}/>
              {t("settings.notifyCalendar")}
            </label>
            {s.calendarPush!==false&&(
              <div style={{display:"flex",alignItems:"center",gap:8,padding:"7px 0 7px 28px",fontSize:13,color:"var(--col-text-sec)"}}>
                {t("settings.minutesBefore")}
                <input type="number" min={1} max={120} value={s.calendarReminderMin??15} onChange={e=>setS(x=>({...x,calendarReminderMin:Math.max(1,Math.min(120,parseInt(e.target.value)||15))}))} style={{width:60,fontSize:13}}/>
              </div>
            )}
            <div style={{height:1,background:"var(--col-border)",margin:"14px 0"}}/>
            <label style={{display:"flex",alignItems:"center",gap:10,padding:"7px 0",fontSize:13,color:"var(--col-text)",cursor:"pointer"}}>
              <input type="checkbox" checked={!!s.habitEveningReminder?.enabled} onChange={e=>setS(x=>({...x,habitEveningReminder:{...(x.habitEveningReminder||{}),enabled:e.target.checked,time:x.habitEveningReminder?.time||"20:00"}}))}/>
              {t("settings.habitEveningReminder")}
            </label>
            {!!s.habitEveningReminder?.enabled&&(
              <div style={{display:"flex",alignItems:"center",gap:8,padding:"7px 0 7px 28px",fontSize:13,color:"var(--col-text-sec)"}}>
                {t("settings.time")}
                <input type="time" value={s.habitEveningReminder?.time||"20:00"} onChange={e=>setS(x=>({...x,habitEveningReminder:{...(x.habitEveningReminder||{}),time:e.target.value}}))} style={{fontSize:13}}/>
              </div>
            )}
            <div style={{height:1,background:"var(--col-border)",margin:"14px 0"}}/>
            <div style={{fontSize:12,fontWeight:600,color:"var(--col-text-sec)",marginBottom:8}}>{t("settings.quietHours")}</div>
            <div style={{fontSize:11,color:"var(--col-text-3)",marginBottom:10}}>{t("settings.quietHoursDesc")}</div>
            <div style={{display:"flex",alignItems:"center",gap:10,fontSize:13,color:"var(--col-text)"}}>
              <span>{t("settings.from")}</span>
              <input type="number" min={0} max={23} value={s.quietHoursStart??22} onChange={e=>setS(x=>({...x,quietHoursStart:Math.max(0,Math.min(23,parseInt(e.target.value)||0))}))} style={{width:55,fontSize:13}}/>
              <span>{t("settings.to")}</span>
              <input type="number" min={0} max={23} value={s.quietHoursEnd??8} onChange={e=>setS(x=>({...x,quietHoursEnd:Math.max(0,Math.min(23,parseInt(e.target.value)||0))}))} style={{width:55,fontSize:13}}/>
              <span>{t("settings.oclock")}</span>
            </div>
          </div>

          {/* Reflektieren anpassen */}
          {secTitle(t("settings.section.reflect"))}
          <div style={{background:"var(--col-bg-sec)",borderRadius:14,padding:"20px",marginBottom:28}}>
            <div style={{fontSize:12,color:"var(--col-text-sec)",marginBottom:14}}>{t("settings.reflectDesc")}</div>
            {[
              ["notiz",t("settings.module.notiz")],
              ["heatmap",t("settings.module.heatmap")],
              ["muster",t("settings.module.muster")],
              ["kpi",t("settings.module.kpi")],
              ["emailReport",t("settings.module.emailReport")],
              ["highlights",t("settings.module.highlights")],
              ["verschoben",t("settings.module.verschoben")],
              ["kategorien",t("settings.module.kategorien")],
              ["tagesplan",t("settings.module.tagesplan")],
              ["zeit",t("settings.module.zeit")],
              ["gewohnheiten",t("settings.module.gewohnheiten")],
              ["deadlines",t("settings.module.deadlines")],
            ].map(([key,label])=>{
              const checked=(s.statsModules||{})[key]!==false;
              return(
                <label key={key} style={{display:"flex",alignItems:"center",gap:10,padding:"7px 0",fontSize:13,color:"var(--col-text)",cursor:"pointer"}}>
                  <input type="checkbox" checked={checked} onChange={e=>setS(x=>({...x,statsModules:{...(x.statsModules||{}),[key]:e.target.checked}}))}/>
                  {label}
                </label>
              );
            })}
          </div>

          </>}
          {settingsTab==="verbindungen"&&<>
          {/* Profil */}
          {secTitle(t("settings.section.profile"))}
          <div style={{background:"var(--col-bg-sec)",borderRadius:14,padding:"20px",marginBottom:28}}>
            <div style={{marginBottom:14}}>
              <label style={{fontSize:12,fontWeight:500,color:"var(--col-text)",display:"block",marginBottom:5}}>{t("settings.yourName")}</label>
              <input value={s.name||""} onChange={e=>setS(x=>({...x,name:e.target.value}))} placeholder={t("settings.yourNamePlaceholder")} style={{width:"100%",boxSizing:"border-box",fontSize:13}}/>
            </div>
            <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"10px 0",borderBottom:"1px solid var(--col-border)"}}>{/* FIXED A2: profile input replaced with account row */}
              <div>
                <div style={{fontWeight:600,fontSize:14}}>{getAuthUsername()||"—"}</div>
                <div style={{fontSize:11,color:"var(--col-text-3)"}}>{t("settings.loggedIn")}</div>
              </div>
              <button type="button" onClick={()=>{window.clearAuthToken();window.location.reload();}} style={{fontSize:12,padding:"5px 12px",border:"1px solid var(--col-border)",borderRadius:6,background:"transparent",cursor:"pointer",color:"var(--col-text-2)"}}>{t("settings.logout")}</button>{/* FIXED B5a: Abmelden button works correctly */}
            </div>
            {/* Passwort ändern */}
            <div style={{marginTop:10}}>
              <button type="button" onClick={()=>setPwOpen(o=>!o)} style={{width:"100%",display:"flex",justifyContent:"space-between",alignItems:"center",padding:"8px 0",background:"none",border:"none",cursor:"pointer",fontSize:12,color:"var(--col-text-sec)",fontWeight:500}}>
                {t("settings.changePassword")}<span style={{fontSize:9,color:"var(--col-text-3)"}}>{pwOpen?"▲":"▼"}</span>
              </button>
              {pwOpen&&(<div style={{display:"flex",flexDirection:"column",gap:7,paddingBottom:8}}>
                <input type="password" placeholder={t("settings.currentPassword")} value={pw.cur} onChange={e=>setPw(x=>({...x,cur:e.target.value}))} style={{fontSize:12,width:"100%",boxSizing:"border-box"}}/>
                <input type="password" placeholder={t("settings.newPassword")} value={pw.nw} onChange={e=>setPw(x=>({...x,nw:e.target.value}))} style={{fontSize:12,width:"100%",boxSizing:"border-box"}}/>
                {pw.status&&<div style={{fontSize:11,color:pw.status==="ok"?"#166534":"#b91c1c"}}>{pw.msg}</div>}
                <button type="button" onClick={doChangePw} disabled={pw.status==="saving"||!pw.cur||!pw.nw} style={{padding:"7px",fontSize:12,borderRadius:6,border:"1px solid var(--col-accent)",background:"transparent",color:"var(--col-accent)",cursor:"pointer"}}>{pw.status==="saving"?t("settings.saving"):t("settings.savePassword")}</button>
              </div>)}
            </div>
            {/* Benutzername ändern */}
            <div style={{borderTop:"1px solid var(--col-border)",marginTop:4}}>
              <button type="button" onClick={()=>setUnOpen(o=>!o)} style={{width:"100%",display:"flex",justifyContent:"space-between",alignItems:"center",padding:"8px 0",background:"none",border:"none",cursor:"pointer",fontSize:12,color:"var(--col-text-sec)",fontWeight:500}}>
                {t("settings.changeUsername")}<span style={{fontSize:9,color:"var(--col-text-3)"}}>{unOpen?"▲":"▼"}</span>
              </button>
              {unOpen&&(<div style={{display:"flex",flexDirection:"column",gap:7,paddingBottom:4}}>
                <input placeholder={t("settings.newUsername")} value={un.nw} onChange={e=>setUn(x=>({...x,nw:e.target.value}))} autoCapitalize="none" style={{fontSize:12,width:"100%",boxSizing:"border-box"}}/>
                <input type="password" placeholder={t("settings.confirmCurrentPassword")} value={un.pw} onChange={e=>setUn(x=>({...x,pw:e.target.value}))} style={{fontSize:12,width:"100%",boxSizing:"border-box"}}/>
                {un.status&&<div style={{fontSize:11,color:un.status==="err"?"#b91c1c":"#166534"}}>{un.msg}</div>}
                <button type="button" onClick={doChangeUn} disabled={un.status==="saving"||!un.nw||!un.pw} style={{padding:"7px",fontSize:12,borderRadius:6,border:"1px solid var(--col-accent)",background:"transparent",color:"var(--col-accent)",cursor:"pointer"}}>{un.status==="saving"?t("settings.saving"):t("settings.saveUsername")}</button>
              </div>)}
            </div>
            {/* E-Mail ändern */}
            <div style={{borderTop:"1px solid var(--col-border)",marginTop:4}}>
              <button type="button" onClick={()=>{
                if(!emOpen){fetch('/api/me',{headers:{...authHeaders()}}).then(r=>r.json()).then(d=>{if(d.email!==undefined)setEm(x=>({...x,val:d.email}));}).catch(()=>{});}
                setEmOpen(o=>!o);
              }} style={{width:"100%",display:"flex",justifyContent:"space-between",alignItems:"center",padding:"8px 0",background:"none",border:"none",cursor:"pointer",fontSize:12,color:"var(--col-text-sec)",fontWeight:500}}>
                {t("settings.changeEmail")}<span style={{fontSize:9,color:"var(--col-text-3)"}}>{emOpen?"▲":"▼"}</span>
              </button>
              {emOpen&&(<div style={{display:"flex",flexDirection:"column",gap:7,paddingBottom:4}}>
                <input type="email" placeholder={t("auth.emailPlaceholder")} value={em.val} onChange={e=>setEm(x=>({...x,val:e.target.value,status:"",msg:""}))} style={{fontSize:12,width:"100%",boxSizing:"border-box"}}/>
                {em.status&&<div style={{fontSize:11,color:em.status==="err"?"#b91c1c":"#166534"}}>{em.msg}</div>}
                <button type="button" onClick={doChangeEm} disabled={em.status==="saving"} style={{padding:"7px",fontSize:12,borderRadius:6,border:"1px solid var(--col-accent)",background:"transparent",color:"var(--col-accent)",cursor:"pointer"}}>{em.status==="saving"?t("settings.saving"):t("settings.saveEmail")}</button>
              </div>)}
            </div>
          </div>

          {/* Admin — nur für oliver */}
          {window.getAuthUsername()==="oliver"&&<>
            {secTitle(t("settings.section.admin"))}
            <div style={{background:"var(--col-bg-sec)",borderRadius:14,padding:"20px",marginBottom:28}}>
              <div style={{fontSize:12,color:"var(--col-text-sec)",marginBottom:12}}>{t("settings.weeklyReportInfo")}</div>
              {reportSt==="ok"&&<div style={{fontSize:11,color:"#166534",marginBottom:8}}>{t("settings.reportSent")}</div>}
              {reportSt==="err"&&<div style={{fontSize:11,color:"#b91c1c",marginBottom:8}}>{t("settings.reportError")}</div>}
              <div style={{display:"flex",gap:8,flexWrap:"wrap"}}>
                <button type="button" onClick={doSendReport} disabled={reportSt==="sending"} style={{fontSize:12,padding:"7px 14px",borderRadius:6,border:"1px solid var(--col-accent)",background:"transparent",color:"var(--col-accent)",cursor:"pointer"}}>{reportSt==="sending"?t("settings.sending"):t("settings.sendReportNow")}</button>
                <button type="button" onClick={openUsersModal} style={{fontSize:12,padding:"7px 14px",borderRadius:6,border:"1px solid var(--col-border)",background:"transparent",color:"var(--col-text-sec)",cursor:"pointer"}}>{t("settings.showAllAccounts")}</button>
                <button type="button" onClick={loadOverview} style={{fontSize:12,padding:"7px 14px",borderRadius:6,border:"1px solid var(--col-border)",background:"transparent",color:"var(--col-text-sec)",cursor:"pointer"}}>{overviewOpen?t("settings.hideOverview"):t("settings.showOverview")}</button>
              </div>
              {overviewOpen&&(
                <div style={{marginTop:14}}>
                  {overview===null
                    ?<div style={{fontSize:12,color:"var(--col-text-sec)"}}>{t("settings.loading")}</div>
                    :overview.length===0
                      ?<div style={{fontSize:12,color:"var(--col-text-sec)"}}>{t("settings.noData")}</div>
                      :overview.map((u,i)=>(
                        <div key={u.username} style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"10px 0",borderTop:i>0?"1px solid var(--col-border)":"none"}}>
                          <span style={{fontSize:13,fontWeight:600,color:"var(--col-text)"}}>{u.username}</span>
                          <div style={{display:"flex",gap:14,fontSize:11,color:"var(--col-text-sec)"}}>
                            <span>{u.openTodos} {t("settings.open")}</span>
                            <span>{u.upcomingExams} {t("settings.exams")}</span>
                            <span style={{fontFamily:"var(--mono)"}}>{u.lastActivity||"—"}</span>
                          </div>
                        </div>
                      ))
                  }
                </div>
              )}
            </div>
          </>}

          {/* Konten-Modal */}
          {usersModal!==null&&<div style={{position:"fixed",inset:0,background:"rgba(20,16,12,0.6)",zIndex:600,display:"flex",alignItems:"center",justifyContent:"center",padding:16}} onClick={()=>setUsersModal(null)}>
            <div style={{background:"var(--col-bg)",borderRadius:14,padding:"24px",width:"100%",maxWidth:420,maxHeight:"80vh",overflowY:"auto",boxShadow:"0 24px 60px rgba(0,0,0,0.3)"}} onClick={e=>e.stopPropagation()}>
              <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:18}}>
                <span style={{fontSize:15,fontWeight:600,color:"var(--col-text)"}}>{t("settings.registeredAccounts")}</span>
                <button type="button" onClick={()=>setUsersModal(null)} style={{width:28,height:28,borderRadius:"50%",border:"1px solid var(--col-border)",background:"var(--col-bg-sec)",fontSize:13,color:"var(--col-text-sec)",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}}>✕</button>
              </div>
              {usersModal==="loading"
                ?<div style={{fontSize:12,color:"var(--col-text-sec)",textAlign:"center",padding:20}}>{t("settings.loading")}</div>
                :usersModal.length===0
                  ?<div style={{fontSize:12,color:"var(--col-text-sec)"}}>{t("settings.noAccountsFound")}</div>
                  :usersModal.map((u,i)=>(
                    <div key={u.username} style={{padding:"12px 0",borderBottom:i<usersModal.length-1?"1px solid var(--col-border)":"none"}}>
                      <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:3}}>
                        <span style={{fontSize:13,fontWeight:600,color:"var(--col-text)"}}>{u.username}</span>
                        <span style={{fontSize:10,color:"var(--col-text-3)",fontFamily:"var(--mono)"}}>{u.created}</span>
                      </div>
                      <div style={{fontSize:11,color:"var(--col-text-sec)"}}>{u.email||<span style={{color:"var(--col-text-3)"}}>{t("settings.noEmailOnFile")}</span>}</div>
                    </div>
                  ))
              }
            </div>
          </div>}

          {/* Integrationen */}
          {secTitle(t("settings.section.integrations"))}
          <div style={{background:"var(--col-bg-sec)",borderRadius:14,padding:"20px",marginBottom:28}}>
            <div style={{fontSize:13,fontWeight:600,color:"var(--col-text)",marginBottom:10}}>Microsoft Outlook</div>
            <label style={{fontSize:12,color:"var(--col-text)",display:"block",marginBottom:5}}>{t("settings.azureClientId")}</label>
            <input value={s.azureClientId} onChange={e=>setS(x=>({...x,azureClientId:e.target.value}))} placeholder={t("settings.azurePlaceholder")} style={{width:"100%",boxSizing:"border-box",fontSize:12,marginBottom:6}}/>{/* FIXED E8: Azure placeholder clarified */}
            <p style={{fontSize:11,color:"var(--col-text-sec)",marginBottom:12,lineHeight:1.5}}>{t("settings.azureHelp")}</p>
            <div style={{background:"var(--col-bg)",borderRadius:8,padding:"10px 12px",marginBottom:0,border:"1px solid var(--col-border)"}}>
              <div style={{fontSize:11,fontWeight:600,color:"var(--col-text-sec)",marginBottom:4}}>{t("settings.redirectUriLabel")}</div>
              <div style={{fontSize:11,color:"var(--col-text)",wordBreak:"break-all",fontFamily:"monospace",background:"var(--col-bg-sec)",padding:"5px 7px",borderRadius:4,border:"1px solid var(--col-border)"}}>{window.location.href.split("?")[0].split("#")[0].replace(/\/[^/]*$/,'/Mein%20Planer.html')}</div>{/* FIXED B3: redirect URI uses correct filename */}
              <div style={{fontSize:10,color:"var(--col-text-sec)",marginTop:4,lineHeight:1.4}}>{t("settings.redirectUriHelp")}</div>
              {/localhost|127\.0\.0\.1/.test(window.location.href)&&<div style={{fontSize:10,color:"#b45309",marginTop:4,lineHeight:1.4}}>{t("settings.localDevWarning")}</div>}{/* FIXED: Warnung wenn Dev-URL statt Pi-URL */}
            </div>
            <div style={{height:1,background:"var(--col-border)",margin:"16px 0"}}/>
            <div style={{fontSize:13,fontWeight:600,color:"var(--col-text)",marginBottom:10}}>{t("settings.piOutlook")}</div>
            {piAuth.connected
              ?<div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"10px 12px",borderRadius:8,background:"var(--col-bg)",border:"1px solid var(--col-border)"}}>
                 <span style={{fontSize:12,color:"#166534"}}>{t("settings.piConnected")}</span>
                 <button onClick={disconnectPiAuth} style={{fontSize:11,padding:"4px 10px",borderRadius:20,border:"1px solid var(--col-border)",color:"var(--col-text-sec)",background:"transparent",cursor:"pointer"}}>{t("settings.disconnect")}</button>
               </div>
              :piAuth.userCode
                ?<div style={{padding:"12px",borderRadius:8,background:"var(--col-bg)",border:"1px solid var(--col-border)"}}>
                   <div style={{fontSize:12,color:"var(--col-text)",marginBottom:6}}>{t("settings.openOnDevice")}</div>
                   <div style={{fontSize:12,fontWeight:600,color:"var(--col-accent)",marginBottom:6,wordBreak:"break-all",fontFamily:"monospace"}}>{piAuth.verUri}</div>
                   <div style={{fontSize:12,color:"var(--col-text)",marginBottom:6}}>{t("settings.enterCode")}</div>
                   <div style={{fontSize:26,fontWeight:700,letterSpacing:"0.15em",color:"var(--col-accent)",fontFamily:"monospace",marginBottom:8}}>{piAuth.userCode}</div>
                   <div style={{fontSize:11,color:"var(--col-text-sec)"}}>{t("settings.waitingConfirmation")}</div>
                 </div>
                :<button onClick={startPiAuth} style={{width:"100%",padding:"9px",fontSize:12,borderRadius:8,border:"1px solid var(--col-accent)",color:"var(--col-accent)",background:"transparent",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",gap:6}}>{/* FIXED: emoji replaced with SVG */}<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>{t("settings.connectPiOutlook")}</button>
            }
          </div>

          </>}
          {settingsTab==="aussehen"&&<>
          {/* App */}
          {secTitle(t("settings.section.app"))}
          <div style={{background:"var(--col-bg-sec)",borderRadius:14,padding:"20px",marginBottom:28}}>
            <div style={{fontSize:12,fontWeight:600,color:"var(--col-text-sec)",marginBottom:10}}>{t("settings.workHours")}</div>
            <div style={{display:"flex",gap:12,marginBottom:18}}>
              <div style={{flex:1}}><label style={{fontSize:12,color:"var(--col-text)",display:"block",marginBottom:5}}>{t("settings.from2")}</label><input type="time" value={s.workStart} onChange={e=>setS(x=>({...x,workStart:e.target.value}))} style={{width:"100%"}}/></div>
              <div style={{flex:1}}><label style={{fontSize:12,color:"var(--col-text)",display:"block",marginBottom:5}}>{t("settings.to2")}</label><input type="time" value={s.workEnd} onChange={e=>setS(x=>({...x,workEnd:e.target.value}))} style={{width:"100%"}}/></div>
            </div>
            {'Notification' in window ? (
              Notification.permission === 'granted'
                ? <div style={{fontSize:12,color:"#166534",padding:"10px 14px",borderRadius:8,border:"1px solid #bbf7d0",background:"#f0fdf4"}}>{t("settings.pushActive")}</div>
                : <button onClick={async()=>{
                    const perm = await Notification.requestPermission();
                    if(perm === 'granted')await subscribePush();
                  }} style={{width:"100%",padding:"10px",fontSize:12,borderRadius:8,border:"1px solid var(--col-border)",color:"var(--col-text)",background:"var(--col-bg)",display:"flex",alignItems:"center",justifyContent:"center",gap:6}}>{/* FIXED: emoji replaced with SVG */}<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>{t("settings.enableNotifications")}</button>
            ) : <div style={{fontSize:12,color:"var(--col-text-sec)"}}>{t("settings.notificationsUnsupported")}</div>}
          </div>

          {secTitle(t("settings.section.studyTimer"))}
          <div style={{background:"var(--col-bg-sec)",borderRadius:14,padding:"16px 20px",marginBottom:28}}>
            <div style={{display:"flex",alignItems:"center",justifyContent:"space-between"}}>
              <div>
                <div style={{fontSize:12,fontWeight:600,color:"var(--col-text)"}}>{t("settings.showSeconds")}</div>
                <div style={{fontSize:11,color:"var(--col-text-sec)",marginTop:2}}>{s.timerSeconds!==false?"1:23:45":"1:23 / 23 min"}</div>
              </div>
              <input type="checkbox" checked={s.timerSeconds!==false} onChange={e=>setS(x=>({...x,timerSeconds:e.target.checked}))} style={{width:18,height:18,cursor:"pointer"}}/>
            </div>
            <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginTop:12,paddingTop:12,borderTop:"1px solid var(--col-border)"}}>
              <div>
                <div style={{fontSize:12,fontWeight:600,color:"var(--col-text)"}}>{t("settings.trackTimeOnDone")}</div>
                <div style={{fontSize:11,color:"var(--col-text-sec)",marginTop:2}}>{t("settings.studyPopupDesc")}</div>
              </div>
              <input type="checkbox" checked={s.learnPopup!==false} onChange={e=>setS(x=>({...x,learnPopup:e.target.checked}))} style={{width:18,height:18,cursor:"pointer"}}/>
            </div>
          </div>

          </>}
          {settingsTab==="hilfe"&&<>
          {/* Notizen */}
          {secTitle(t("settings.section.notes"))}
          <div style={{marginBottom:28}}>
            <div style={{fontSize:11,color:"var(--col-text-3)",marginBottom:8,lineHeight:1.4}}>{t("settings.notesDesc")}</div>
            <textarea
              value={notes}
              onChange={e => { setNotes(e.target.value); localStorage.setItem(notesKey, e.target.value); }}
              placeholder={t("settings.notesPlaceholder")}
              style={{width:"100%",boxSizing:"border-box",fontSize:12,fontFamily:"var(--mono)",padding:"10px 12px",borderRadius:10,border:"1px solid var(--col-border)",background:"var(--col-bg-sec)",color:"var(--col-text)",resize:"vertical",minHeight:80,marginBottom:8,lineHeight:1.5}}
            />
            <NotesSendButton notes={notes} onClear={()=>{setNotes("");localStorage.setItem(notesKey,"");}} profile={settings.profile}/>
          </div>

          {/* Hilfe */}
          {secTitle(t("settings.section.help"))}
          <div style={{background:"var(--col-accent-wash)",border:"1px solid var(--col-accent)",borderRadius:10,padding:"14px 16px",marginBottom:12}}>
            <div style={{fontSize:12,fontWeight:600,color:"var(--col-accent)",marginBottom:10}}>{t("settings.quickstart")}</div>
            {[
              ["1",t("settings.qs1Title"),t("settings.qs1Desc")],
              ["2",t("settings.qs2Title"),t("settings.qs2Desc")],
              ["3",t("settings.qs3Title"),t("settings.qs3Desc")],
              ["4",t("settings.qs4Title"),t("settings.qs4Desc")],
            ].map(([n,t,d])=>(
              <div key={n} style={{display:"flex",gap:10,marginBottom:8,alignItems:"flex-start"}}>
                <span style={{width:20,height:20,borderRadius:"50%",background:"var(--col-accent)",color:"var(--col-bg)",fontSize:11,fontWeight:700,display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,marginTop:1}}>{n}</span>
                <div>
                  <div style={{fontSize:12,fontWeight:600,color:"var(--col-text)",marginBottom:2}}>{t}</div>
                  <div style={{fontSize:11,color:"var(--col-text-sec)",lineHeight:1.45}}>{d}</div>
                </div>
              </div>
            ))}
          </div>
          {[
            {key:"tabs", label:t("settings.faq.tabsLabel"), items:[
              {k:"Heute",         v:t("settings.faq.tabs.Heute")},
              {k:"Aufgaben",      v:t("settings.faq.tabs.Aufgaben")},
              {k:"Inbox",         v:t("settings.faq.tabs.Inbox")},
              {k:"Plan",          v:t("settings.faq.tabs.Plan")},
              {k:"Gewohnheiten",  v:t("settings.faq.tabs.Gewohnheiten")},
              {k:"Reflektieren",  v:t("settings.faq.tabs.Reflektieren")},
              {k:"Studienplan",  v:t("settings.faq.tabs.Studienplan")},
              {k:"Kalender",      v:t("settings.faq.tabs.Kalender")},
            ]},
            {key:"aufgaben", label:t("settings.faq.aufgabenLabel"), items:[
              {k:"Dauer",          v:t("settings.faq.aufgaben.Dauer")},
              {k:"Priorität",      v:t("settings.faq.aufgaben.Priorität")},
              {k:"Kategorie",      v:t("settings.faq.aufgaben.Kategorie")},
              {k:"Wiederholung",   v:t("settings.faq.aufgaben.Wiederholung")},
              {k:"Wiedervorlage",  v:t("settings.faq.aufgaben.Wiedervorlage")},
              {k:"Unteraufgaben",  v:t("settings.faq.aufgaben.Unteraufgaben")},
              {k:"Irgendwann",     v:t("settings.faq.aufgaben.Irgendwann")},
              {k:"Löschen rückgängig",v:t("settings.faq.aufgaben.LöschenRückgängig")},
            ]},
            {key:"mehrpersonen", label:t("settings.faq.mehrpersonenLabel"), items:[
              {k:"Konto erstellen", v:t("settings.faq.mehrpersonen.KontoErstellen")},
              {k:"Getrennte Daten", v:t("settings.faq.mehrpersonen.GetrennteDaten")},
              {k:"Wechseln",        v:t("settings.faq.mehrpersonen.Wechseln")},
              {k:"PW / Name ändern",v:t("settings.faq.mehrpersonen.PWNameÄndern")},
            ]},
            {key:"kb", label:t("settings.faq.kbLabel"), items:[
              {k:"1 – 6",   v:t("settings.faq.kb.1-6")},
              {k:"N",       v:t("settings.faq.kb.N")},
              {k:"Ctrl+K",  v:t("settings.faq.kb.CtrlK")},
              {k:"Esc",     v:t("settings.faq.kb.Esc")},
            ]},
          ].map(({key,label,items})=>(
            <div key={key} style={{marginBottom:6,border:"1px solid var(--col-border)",borderRadius:10,overflow:"hidden"}}>
              <button onClick={()=>setOpenFeat(f=>f===key?null:key)} style={{width:"100%",textAlign:"left",padding:"10px 14px",fontSize:12,fontWeight:600,color:"var(--col-text)",background:"var(--col-bg-sec)",border:"none",cursor:"pointer",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                {label}<span style={{fontSize:10,color:"var(--col-text-3)"}}>{openFeat===key?"▲":"▼"}</span>
              </button>
              {openFeat===key&&(
                <div style={{padding:"12px 16px",background:"var(--col-bg)",display:"flex",flexDirection:"column",gap:8}}>
                  {items.map(({k,v})=>(
                    <div key={k} style={{fontSize:11,lineHeight:1.5}}>
                      <span style={{fontWeight:600,color:"var(--col-accent)"}}>{k}</span>
                      <span style={{color:"var(--col-text-3)",margin:"0 5px"}}>—</span>
                      <span style={{color:"var(--col-text)"}}>{v}</span>
                    </div>
                  ))}
                </div>
              )}
            </div>
          ))}
          </>}

        </div>

        {/* ── Footer ── */}
        <div style={{padding:"16px 28px",borderTop:"1px solid var(--col-border)",flexShrink:0,background:"var(--col-bg)"}}>
          <button onClick={()=>{onSave(s);onClose();}} style={{width:"100%",padding:"12px",fontSize:14,borderRadius:10,background:"var(--col-accent)",color:"var(--col-bg)",fontWeight:600,letterSpacing:"0.01em"}}>{t("settings.save")}</button>
        </div>

      </div>
    </div>
  );
}

// ── ReviewModal ──────────────────────────────────────────────────────
function ReviewModal({ todos, exams, today, onClose, onMoveAll }){
  const done = todos.filter(t => t.done && !t.deletedAt && (t.doneAt ? localISO(new Date(t.doneAt)) : null) === today).length;
  const allOpen = todos.filter(t => !t.done && !t.deletedAt && !t.recurring && (!t.plannedDay || t.plannedDay === today));
  const studyBlockIds = new Set((exams||[]).flatMap(e=>(e.studyBlocks||[]).map(b=>b.todoId)).filter(Boolean));
  const studyOpen = allOpen.filter(t => studyBlockIds.has(t.id));
  const regularOpen = allOpen.filter(t => !studyBlockIds.has(t.id));
  return (
    <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:2000}} onClick={onClose}>
      <div style={{background:"var(--col-bg)",borderRadius:16,padding:"1.5rem",width:340,boxShadow:"0 20px 60px rgba(0,0,0,0.3)",animation:"fadeSlideIn 0.3s ease"}} onClick={e=>e.stopPropagation()}>
        <div style={{fontSize:18,fontWeight:700,color:"var(--col-accent)",textAlign:"center",marginBottom:4}}>{window.t("review.title")}</div>
        <div style={{fontSize:13,color:"var(--col-text-sec)",textAlign:"center",marginBottom:16}}>{done>0?window.t("review.doneSummary",{n:done,plural:done!==1?"n":""}):window.t("review.noneDoneYet")}</div>
        {regularOpen.length>0 && (
          <>
            <div style={{fontSize:12,fontWeight:600,color:"var(--col-text-sec)",marginBottom:8}}>{window.t("review.stillOpen",{n:regularOpen.length})}</div>
            <div style={{maxHeight:120,overflowY:"auto",marginBottom:12}}>{regularOpen.map(t=><div key={t.id} style={{fontSize:12,padding:"4px 8px",borderRadius:6,background:"var(--col-bg-sec)",marginBottom:4,color:"var(--col-text)"}}>{t.text}</div>)}</div>
            <button onClick={onMoveAll} style={{width:"100%",padding:"10px",fontSize:13,borderRadius:10,background:"var(--col-accent)",color:"var(--col-bg)",fontWeight:600,marginBottom:12}}>{window.t("review.moveAllTomorrow")}</button>
          </>
        )}
        {studyOpen.length>0 && (
          <div style={{marginBottom:12}}>
            <div style={{fontSize:12,fontWeight:600,color:"var(--col-text-sec)",marginBottom:6}}>{window.t("review.studyBlocksToday",{n:studyOpen.length})}</div>
            <div style={{maxHeight:80,overflowY:"auto"}}>{studyOpen.map(t=><div key={t.id} style={{fontSize:11,padding:"3px 8px",borderRadius:6,background:"var(--col-bg-sec)",marginBottom:3,color:"var(--col-text-sec)",fontFamily:"var(--mono)"}}>{t.text}</div>)}</div>
            <div style={{fontSize:10,color:"var(--col-text-3)",marginTop:4}}>{window.t("review.studyBlocksNote")}</div>
          </div>
        )}
        <button onClick={onClose} style={{width:"100%",padding:"8px",fontSize:12,borderRadius:10,border:"1px solid var(--col-border)",color:"var(--col-text-sec)"}}>{window.t("review.close")}</button>
      </div>
    </div>
  );
}

// ── CalendarWeekView ─────────────────────────────────────────────────
function CalendarWeekView({ todos, exams, events, categories = [], dayPlan = null, onTodoDropOnDay = null }){
  const [offset, setOffset] = useState(0);
  const [mode, setMode] = useState("woche"); // 'agenda' | 'woche' | 'monat'
  const [dragOverIso, setDragOverIso] = useState(null);
  const today = todayISO();
  const activeTodos = todos.filter(t => !t.done && !t.deletedAt);
  // Alle nicht-gelöschten Todos (inkl. erledigte) — für Template-Duplikat-Check
  const allNonDeleted = todos.filter(t => !t.deletedAt);
  const studyBlockIds = new Set((exams||[]).flatMap(e=>(e.studyBlocks||[]).map(b=>b.todoId)).filter(Boolean));

  // Returns true if todo belongs on the given iso day
  const matchesDay = (t, iso) => {
    // Recurring templates: use recurring logic only (ignore their own plannedDay to avoid duplication)
    if (t.recurring && !t._fromTemplate) {
      const r = t.recurring;
      if (iso < today) return false; // nie in der Vergangenheit
      if (t.plannedDay && iso < t.plannedDay) return false; // nie vor Startdatum
      if (r.endDate && iso > r.endDate) return false;
      if (r.freq === "daily") {
        // Auch erledigte Instanzen berücksichtigen — sonst zeigt Template doppelt neben erledigter Instanz
        if (allNonDeleted.some(x => x._fromTemplate === t.id && x.plannedDay === iso)) return false;
        return true;
      }
      if (r.freq === "weekly" && Array.isArray(r.days)) {
        const dow = (new Date(iso + "T12:00:00").getDay()) || 7;
        // Show on recurring day (if no instance already exists)
        if (r.days.includes(dow)) {
          if (allNonDeleted.some(x => x._fromTemplate === t.id && x.plannedDay === iso)) return false;
          return true;
        }
        // Also show on deadline-offset day (e.g. +2 days after Saturday = Monday)
        if ((r.deadlineDays || 0) > 0) {
          const base = new Date(iso + "T12:00:00");
          base.setDate(base.getDate() - r.deadlineDays);
          const baseDow = base.getDay() || 7;
          if (r.days.includes(baseDow)) return true;
        }
      }
      return false;
    }
    // Normal todos and instances: match by plannedDay or deadline
    return t.plannedDay === iso || t.deadline === iso;
  };

  // True when a todo should be styled as a deadline on the given day
  const isDeadlineForDay = (t, iso) => {
    if (t.deadline === iso && t.plannedDay !== iso) return true;
    if (t.recurring && !t._fromTemplate && (t.recurring.deadlineDays || 0) > 0) {
      const r = t.recurring;
      const base = new Date(iso + "T12:00:00");
      base.setDate(base.getDate() - r.deadlineDays);
      const baseISO = localISO(base);
      if (baseISO >= today && (!r.endDate || baseISO <= r.endDate)) {
        const baseDow = base.getDay() || 7;
        if (r.freq === "daily") return true;
        if (r.freq === "weekly" && Array.isArray(r.days) && r.days.includes(baseDow)) return true;
      }
    }
    return false;
  };

  // Drop-handlers für Tageszellen
  const dropProps = (iso) => onTodoDropOnDay ? {
    onDragOver: (e) => { e.preventDefault(); e.dataTransfer.dropEffect='move'; if(dragOverIso!==iso) setDragOverIso(iso); },
    onDragLeave: (e) => { if(dragOverIso===iso) setDragOverIso(null); },
    onDrop: (e) => {
      e.preventDefault();
      const id = e.dataTransfer.getData('text/todo-id');
      setDragOverIso(null);
      if (id) onTodoDropOnDay(id, iso);
    }
  } : {};

  const ChevL = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M15 6l-6 6 6 6"/></svg>;
  const ChevR = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M9 6l6 6-6 6"/></svg>;
  const navBtn = {padding:"5px 10px",borderRadius:20,border:"1px solid var(--col-border)",color:"var(--col-text-sec)",fontSize:11,fontFamily:"var(--mono)",letterSpacing:"0.04em",display:"inline-flex",alignItems:"center",gap:5,background:"transparent"};

  const ModeToggle = () => (
    <div style={{display:"inline-flex",border:"1px solid var(--col-border)",borderRadius:20,padding:2,background:"var(--col-bg)"}}>
      {[{k:"agenda",l:t("cal.agenda")},{k:"woche",l:t("cal.woche")},{k:"monat",l:t("cal.monat")}].map(o=>{
        const a = mode === o.k;
        return <button key={o.k} onClick={()=>{setMode(o.k);setOffset(0);}} style={{padding:"4px 12px",borderRadius:20,fontSize:11,fontFamily:"var(--mono)",letterSpacing:"0.06em",background:a?"var(--col-accent)":"transparent",color:a?"var(--col-bg)":"var(--col-text-sec)",fontWeight:a?500:400,border:"none"}}>{o.l}</button>;
      })}
    </div>
  );

  // ── AGENDA ──
  if (mode === "agenda") {
    const start = new Date(); start.setDate(start.getDate() + offset*14);
    const days = Array.from({length:14}, (_, i) => {
      const d = new Date(start); d.setDate(d.getDate() + i);
      const iso = localISO(d);
      const dTodos = activeTodos.filter(t => matchesDay(t, iso));
      const dEvs = events.filter(e => e.start?.dateTime?.slice(0,10) === iso).sort((a,b)=>(a.start?.dateTime||"").localeCompare(b.start?.dateTime||""));
      const dExams = (exams||[]).filter(e => e.date === iso);
      return { d, iso, dTodos, dEvs, dExams, total: dTodos.length + dEvs.length + dExams.length };
    });
    const _loc = window.currentLang==="en"?"en-GB":"de-CH";
    const startLabel = days[0].d.toLocaleDateString(_loc,{day:"numeric",month:"short"});
    const endLabel   = days[13].d.toLocaleDateString(_loc,{day:"numeric",month:"short",year:"numeric"});
    return (
      <div>
        <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:14,flexWrap:"wrap",gap:8}}>
          <ModeToggle/>
          <div style={{display:"flex",alignItems:"center",gap:8}}>
            <button onClick={()=>setOffset(x=>x-1)} style={navBtn}><ChevL/> {t("cal.back")}</button>
            <span className="cap" style={{minWidth:120,textAlign:"center"}}>{startLabel} – {endLabel}</span>
            <button onClick={()=>setOffset(x=>x+1)} style={navBtn}>{t("cal.forward")} <ChevR/></button>
          </div>
        </div>
        <div>
          {days.filter(x=>x.total>0).length===0 && <div style={{fontSize:13,color:"var(--col-text-sec)",fontStyle:"italic",padding:"24px 0",textAlign:"center"}}>{t("cal.nothingInRange")}</div>}
          {days.filter(x=>x.total>0).map(({d,iso,dTodos,dEvs,dExams})=>{
            const wd = ["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"][d.getDay()];
            const isToday = iso === today;
            return (
              <div key={iso} {...dropProps(iso)} style={{display:"grid",gridTemplateColumns:"90px 1fr",gap:18,padding:"14px 0",borderBottom:"1px solid var(--col-border-soft)",background:dragOverIso===iso?"var(--col-bg-sec)":"transparent",outline:dragOverIso===iso?"1.5px dashed var(--col-accent)":"none",outlineOffset:-2,borderRadius:dragOverIso===iso?6:0,transition:"background 0.12s"}}>
                <div style={{textAlign:"left",borderRight:isToday?"2px solid var(--col-accent)":"none",paddingRight:isToday?6:8}}>
                  <div className="cap" style={{color:isToday?"var(--col-accent)":"var(--col-text-3)",marginBottom:2}}>{wd.slice(0,3)}</div>
                  <div className="serif" style={{fontSize:28,fontStyle:"italic",lineHeight:1,color:isToday?"var(--col-accent)":"var(--col-text)"}}>{d.getDate()}</div>
                  <div className="mono" style={{fontSize:10,color:"var(--col-text-3)",marginTop:3,letterSpacing:"0.04em"}}>{d.toLocaleDateString(window.currentLang==="en"?"en-GB":"de-CH",{month:"short"})}</div>
                </div>
                <div style={{display:"flex",flexDirection:"column",gap:5,minWidth:0}}>
                  {dEvs.map((ev,i)=>{
                    const t1 = ev.start?.dateTime?.slice(11,16);
                    const t2 = ev.end?.dateTime?.slice(11,16);
                    const isAllDay = !ev.start?.dateTime || (t1==="00:00"&&t2==="00:00"&&ev.start?.dateTime?.slice(0,10)!==ev.end?.dateTime?.slice(0,10)) || !!ev.start?.date;
                    return (
                      <div key={"e"+i} style={{display:"flex",gap:10,alignItems:"baseline",minWidth:0}}>
                        <span className="mono" style={{fontSize:11,color:"var(--col-text-sec)",letterSpacing:"0.02em",flexShrink:0,minWidth:88}}>{isAllDay?window.t("cal.allday"):`${t1}${t2?`–${t2}`:""}`}</span>
                        <span style={{fontSize:13,color:"var(--col-text)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:0}}>{ev.subject}</span>
                      </div>
                    );
                  })}
                  {iso===today && dayPlan?.slots?.filter(sl=>{
                    const evTitles = new Set(dEvs.map(e => (e.subject||"").trim().toLowerCase()));
                    return sl.time && !evTitles.has((sl.task||"").trim().toLowerCase());
                  }).map((sl,i)=>{
                    const dur = parseInt(sl.duration) || 30;
                    const [hh,mm] = sl.time.split(":").map(Number);
                    const eh = Math.floor((hh*60+mm+dur)/60), em = (hh*60+mm+dur)%60;
                    const t2 = `${String(eh).padStart(2,"0")}:${String(em).padStart(2,"0")}`;
                    return (
                      <div key={"p"+i} style={{display:"flex",gap:10,alignItems:"baseline",minWidth:0}}>
                        <span className="mono" style={{fontSize:11,color:"var(--col-accent)",letterSpacing:"0.02em",flexShrink:0,minWidth:88}}>{sl.time}–{t2}</span>
                        <span className="serif" style={{fontSize:14,fontStyle:"italic",color:"var(--col-text)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:0}}>✦ {sl.task}</span>
                      </div>
                    );
                  })}
                  {dTodos.filter(t=>{
                    if (iso !== today) return true;
                    const planTitles = new Set((dayPlan?.slots||[]).map(s => (s.task||"").trim().toLowerCase()));
                    return !planTitles.has((t.text||"").trim().toLowerCase());
                  }).map(t=>{
                    const isStudy = studyBlockIds.has(t.id);
                    return(
                      <div key={"t"+t.id} style={{display:"flex",gap:10,alignItems:"baseline",minWidth:0}}>
                        <span className="mono" style={{fontSize:11,color:isStudy?"var(--col-text-sec)":"var(--col-accent)",letterSpacing:"0.02em",flexShrink:0,minWidth:88}}>{isStudy?window.t("cal.studyBlock"):window.t("cal.task")}</span>
                        <span className="serif" style={{fontSize:14,fontStyle:"italic",color:isStudy?"var(--col-text-sec)":"var(--col-text)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:0}}>{isStudy?t.text.replace(/^Lernen:\s*/,""):t.text}</span>
                      </div>
                    );
                  })}
                  {dExams.map((ex,i)=>(
                    <div key={"ex"+i} style={{display:"flex",gap:10,alignItems:"baseline",minWidth:0}}>
                      <span className="mono" style={{fontSize:11,color:"#dc2626",letterSpacing:"0.02em",flexShrink:0,minWidth:88,fontWeight:600}}>{t("cal.exam")}</span>
                      <span className="serif" style={{fontSize:14,fontStyle:"italic",color:"#dc2626",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:0,fontWeight:600}}>{ex.name}</span>
                    </div>
                  ))}
                </div>
              </div>
            );
          })}
        </div>
      </div>
    );
  }

  // ── MONAT ──
  if (mode === "monat") {
    const base = new Date(); base.setMonth(base.getMonth()+offset); base.setDate(1);
    const monthLabel = base.toLocaleDateString(window.currentLang==="en"?"en-GB":"de-CH",{month:"long",year:"numeric"});
    const firstDow = (base.getDay()||7)-1;
    const gridStart = new Date(base); gridStart.setDate(1-firstDow);
    const cells = Array.from({length:42},(_,i)=>{
      const d = new Date(gridStart); d.setDate(gridStart.getDate()+i);
      const iso = localISO(d);
      const dTodos = activeTodos.filter(t => matchesDay(t, iso));
      const dEvs = events.filter(e => e.start?.dateTime?.slice(0,10) === iso);
      return { d, iso, inMonth: d.getMonth()===base.getMonth(), dTodos, dEvs };
    });
    return (
      <div>
        <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:14,flexWrap:"wrap",gap:8}}>
          <ModeToggle/>
          <div style={{display:"flex",alignItems:"center",gap:8}}>
            <button onClick={()=>setOffset(x=>x-1)} style={navBtn}><ChevL/></button>
            <span className="serif" style={{fontSize:18,fontStyle:"italic",minWidth:160,textAlign:"center"}}>{monthLabel}</span>
            <button onClick={()=>setOffset(x=>x+1)} style={navBtn}><ChevR/></button>
          </div>
        </div>
        <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:1,background:"var(--col-border-soft)",border:"1px solid var(--col-border-soft)"}}>
          {["Mo","Di","Mi","Do","Fr","Sa","So"].map(l=>(
            <div key={l} className="cap" style={{padding:"8px 6px",background:"var(--col-bg)",textAlign:"left"}}>{l}</div>
          ))}
          {cells.map(({d,iso,inMonth,dTodos,dEvs})=>{
            const isT = iso === today;
            const total = dTodos.length + dEvs.length;
            return (
              <div key={iso} {...dropProps(iso)} style={{background:dragOverIso===iso?"var(--col-accent-soft, var(--col-bg-sec))":"var(--col-bg)",padding:"6px 8px",minHeight:84,display:"flex",flexDirection:"column",gap:3,opacity:inMonth?1:0.35,position:"relative",outline:dragOverIso===iso?"2px solid var(--col-accent)":"none",outlineOffset:-2,transition:"background 0.12s"}}>
                <div style={{display:"flex",alignItems:"baseline",justifyContent:"space-between",gap:4}}>
                  <span className="serif" style={{fontSize:isT?17:14,fontStyle:isT?"italic":"normal",color:isT?"var(--col-accent)":"var(--col-text)",lineHeight:1,fontWeight:isT?500:400}}>{d.getDate()}</span>
                  {total>0 && <span className="mono" style={{fontSize:9.5,color:"var(--col-text-3)",letterSpacing:"0.04em"}}>{total}</span>}
                </div>
                <div style={{display:"flex",flexDirection:"column",gap:2,marginTop:2,minWidth:0}}>
                  {dEvs.slice(0,2).map((ev,i)=>(
                    <div key={"e"+i} style={{fontSize:10,color:"var(--col-text-sec)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",borderLeft:"2px solid var(--col-text-3)",paddingLeft:5}}>{ev.subject}</div>
                  ))}
                  {dTodos.slice(0,Math.max(0,3-Math.min(2,dEvs.length))).map(t=>{
                    const isDl = isDeadlineForDay(t, iso);
                    return (
                      <div key={"t"+t.id} style={{fontSize:10,color:isDl?"#dc2626":"var(--col-accent)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",borderLeft:`2px solid ${isDl?"#dc2626":"var(--col-accent)"}`,paddingLeft:5,fontStyle:"italic",fontWeight:isDl?500:400}}>{isDl?"! ":""}{t.text}</div>
                    );
                  })}
                  {total>3 && <div className="mono" style={{fontSize:9,color:"var(--col-text-3)",letterSpacing:"0.04em"}}>+{total-3}</div>}
                </div>
              </div>
            );
          })}
        </div>
      </div>
    );
  }

  // ── WOCHE ──
  const days = Array.from({length:7},(_,i)=>{
    const d = new Date(); const dow = d.getDay()||7;
    d.setDate(d.getDate()-dow+1+offset*7+i);
    const iso = localISO(d);
    return { d, iso, label:["Mo","Di","Mi","Do","Fr","Sa","So"][i], date:d.getDate(), isToday: iso===today, isWeekend: i>=5 };
  });
  const wkLabel = `${days[0].d.toLocaleDateString(window.currentLang==="en"?"en-GB":"de-CH",{day:"numeric",month:"short"})} – ${days[6].d.toLocaleDateString(window.currentLang==="en"?"en-GB":"de-CH",{day:"numeric",month:"short"})}`;
  const HOUR_START = 7, HOUR_END = 21, HOUR_PX = 48;
  const totalH = (HOUR_END - HOUR_START) * HOUR_PX;
  const hours = Array.from({length: HOUR_END-HOUR_START+1}, (_,i)=>HOUR_START+i);
  const toY = (hh,mm) => Math.max(0, Math.min(totalH-22, ((hh-HOUR_START)*60+mm)*HOUR_PX/60));
  const isMobile = window.innerWidth < 768;

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:14,flexWrap:"wrap",gap:8}}>
        <ModeToggle/>
        <div style={{display:"flex",alignItems:"center",gap:8}}>
          <button onClick={()=>setOffset(x=>x-1)} style={navBtn}><ChevL/> {t("cal.prevWeek")}</button>
          <span className="cap" style={{minWidth:120,textAlign:"center"}}>{wkLabel}</span>
          <button onClick={()=>setOffset(x=>x+1)} style={navBtn}>{t("cal.nextWeek")} <ChevR/></button>
        </div>
      </div>
      {isMobile ? (
        <div style={{display:"grid",gridTemplateColumns:"repeat(2,1fr)",gap:6}}>
          {days.map(d=>{
            const dTodos = activeTodos.filter(t => matchesDay(t, d.iso));
            const dEvs   = events.filter(e => e.start?.dateTime?.slice(0,10) === d.iso);
            return (
              <div key={d.iso} {...dropProps(d.iso)} style={{background:dragOverIso===d.iso?"var(--col-bg-sec)":"var(--col-bg)",border:dragOverIso===d.iso?"1.5px dashed var(--col-accent)":d.isToday?"1.5px solid var(--col-accent)":"1px solid var(--col-border-soft)",borderRadius:6,padding:"8px 9px",minHeight:90,transition:"background 0.12s, border-color 0.12s"}}>
                <div style={{display:"flex",alignItems:"baseline",justifyContent:"space-between",marginBottom:4}}>
                  <div className="cap" style={{color:d.isToday?"var(--col-accent)":"var(--col-text-3)"}}>{d.label}</div>
                  <div className="serif" style={{fontSize:16,fontWeight:500,color:d.isToday?"var(--col-accent)":"var(--col-text)"}}>{d.date}</div>
                </div>
                {dEvs.slice(0,2).map((ev,i)=>(<div key={"e"+i} style={{fontSize:10.5,color:"var(--col-text-sec)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{ev.start?.dateTime?.slice(11,16)} {ev.subject}</div>))}
                {dTodos.slice(0,2).map(t=>(<div key={"t"+t.id} className="serif" style={{fontSize:11,fontStyle:"italic",color:"var(--col-accent)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{t.text}</div>))}
              </div>
            );
          })}
        </div>
      ) : (
        <div style={{border:"1px solid var(--col-border-soft)",borderRadius:6,overflow:"hidden",background:"var(--col-bg)"}}>
          {(() => {
            const perDay = days.map(d=>{
              const dTodos = activeTodos.filter(t => matchesDay(t, d.iso));
              const dEvs   = events.filter(e => e.start?.dateTime?.slice(0,10) === d.iso);
              const timed = []; const untimed = [];
              dEvs.forEach(ev=>{
                const sd = ev.start?.dateTime, ed = ev.end?.dateTime;
                if (!sd) return;
                const [sh,sm] = sd.slice(11,16).split(":").map(Number);
                const [eh,em] = (ed||sd).slice(11,16).split(":").map(Number);
                const top = toY(sh,sm); const bottom = toY(eh,em);
                timed.push({type:"ev", top, h:Math.max(22,bottom-top), title:ev.subject, time:sd.slice(11,16)});
              });
              dTodos.forEach(t=>{
                const isDeadline = isDeadlineForDay(t, d.iso);
                const m = (t.text||"").match(/^(\d{1,2}):(\d{2})/);
                if (m) {
                  const hh = +m[1], mm = +m[2];
                  timed.push({type: isDeadline?"dl":"todo", top:toY(hh,mm), h:Math.max(28,(t.duration||60)*HOUR_PX/60), title:t.text, prio:t.priority||"mittel", cat:t.category, time:`${String(hh).padStart(2,"0")}:${String(mm).padStart(2,"0")}`});
                } else {
                  untimed.push({type: isDeadline?"dl":"todo", title:t.text, prio:t.priority||"mittel", cat:t.category});
                }
              });
              // Erledigte Todos des Tages mit grünem Haken
              todos.filter(t=>t.done&&!t.deletedAt&&(t.plannedDay===d.iso||(t.doneAt&&localISO(new Date(t.doneAt))===d.iso))).forEach(t=>{
                untimed.push({type:"done", title:t.text, prio:t.priority||"mittel", cat:t.category});
              });
              if (d.iso === today && dayPlan?.slots?.length) {
                const evTitles = new Set(dEvs.map(e => (e.subject||"").trim().toLowerCase()));
                dayPlan.slots.forEach(sl=>{
                  if (!sl.time) return;
                  if (evTitles.has((sl.task||"").trim().toLowerCase())) return;
                  const [hh,mm] = sl.time.split(":").map(Number);
                  if (isNaN(hh)) return;
                  const dur = parseInt(sl.duration) || 30;
                  const matchedTodo = activeTodos.find(t => t.text === sl.task);
                  timed.push({type:"plan", top:toY(hh,mm), h:Math.max(22,dur*HOUR_PX/60), title:sl.task, time:sl.time, prio:matchedTodo?.priority||"mittel", cat:matchedTodo?.category});
                  const ix = untimed.findIndex(u => u.title === sl.task);
                  if (ix >= 0) untimed.splice(ix,1);
                });
              }
              return { ...d, timed, untimed };
            });
            const maxUntimed = Math.max(0, ...perDay.map(x => x.untimed.length));
            const ALLDAY_ROW = 22;
            const allDayH = maxUntimed === 0 ? 0 : 8 + maxUntimed*ALLDAY_ROW + 6;
            return (
              <>
                <div style={{display:"grid",gridTemplateColumns:"56px repeat(7,1fr)",borderBottom:"1px solid var(--col-border-soft)"}}>
                  <div/>
                  {days.map(d=>(
                    <div key={d.iso} style={{padding:"8px 6px",textAlign:"center",borderLeft:"1px solid var(--col-border-soft)",background:d.isToday?"var(--col-accent-wash)":d.isWeekend?"var(--col-bg-sec)":"transparent"}}>
                      <div className="mono" style={{fontSize:10,color:d.isToday?"var(--col-accent)":d.isWeekend?"var(--col-text-3)":"var(--col-text-sec)",fontWeight:600,letterSpacing:"0.06em"}}>{d.label.toUpperCase()}</div>
                      <div className="serif" style={{fontSize:18,color:d.isToday?"var(--col-accent)":d.isWeekend?"var(--col-text-3)":"var(--col-text)",fontWeight:500,fontStyle:d.isToday?"italic":"normal"}}>{d.date}</div>
                    </div>
                  ))}
                </div>
                {maxUntimed>0 && (
                  <div style={{display:"grid",gridTemplateColumns:"56px repeat(7,1fr)",borderBottom:"1px solid var(--col-border-soft)",background:"var(--col-bg-sec)",minHeight:allDayH}}>
                    <div style={{padding:"4px 6px",textAlign:"right"}}>
                      <span className="mono" style={{fontSize:9,color:"var(--col-text-3)",letterSpacing:"0.06em",textTransform:"uppercase"}}>{t("cal.ganztags")}</span>
                    </div>
                    {perDay.map(d=>(
                      <div key={d.iso} style={{padding:"4px 3px",borderLeft:"1px solid var(--col-border-soft)",background:d.isToday?"var(--col-accent-wash)":d.isWeekend?"var(--col-bg-sec)":"transparent",display:"flex",flexDirection:"column",gap:2,overflow:"hidden",minWidth:0}}>
                        {d.untimed.map((it,i)=>{
                          const catCol = it.cat ? (getCatColor(categories,it.cat).col) : prioCol[it.prio]||"var(--col-text-3)";
                          const isDl = it.type === "dl";
                          const isDone = it.type === "done";
                          return (
                            <div key={i} title={it.title} style={{
                              fontSize:10.5,padding:"2px 6px",borderRadius:3,
                              background: isDone ? "rgba(22,101,52,0.06)" : isDl ? hexToRgba("#dc2626",0.08) : "var(--col-bg)",
                              borderLeft:`2px solid ${isDone?"#166534":isDl?"#dc2626":catCol}`,
                              border:"1px solid var(--col-border)",
                              color: isDone ? "var(--col-text-3)" : "var(--col-text)",
                              fontWeight:500,textDecoration:isDone?"line-through":"none",
                              whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",lineHeight:1.4
                            }}>
                              <span style={{color:isDone?"#166534":isDl?"#dc2626":"var(--col-accent)",marginRight:3}}>{isDone?"✓":isDl?"!":"○"}</span>{it.title}{isDl?<span className="mono" style={{fontSize:8.5,color:"#dc2626",marginLeft:5,letterSpacing:"0.06em"}}>DL</span>:null}
                            </div>
                          );
                        })}
                      </div>
                    ))}
                  </div>
                )}
                <div style={{display:"grid",gridTemplateColumns:"56px repeat(7,1fr)",height:totalH,position:"relative"}}>
                  <div style={{position:"relative"}}>
                    {hours.map(h=>(
                      <div key={h} style={{position:"absolute",top:(h-HOUR_START)*HOUR_PX,right:6,fontSize:10,color:"var(--col-text-3)",fontFamily:"var(--mono)",letterSpacing:"0.04em"}}>{String(h).padStart(2,"0")}:00</div>
                    ))}
                  </div>
                  {perDay.map(d=>(
                    <div key={d.iso} {...dropProps(d.iso)} style={{position:"relative",borderLeft:"1px solid var(--col-border-soft)",background:dragOverIso===d.iso?"var(--col-accent-wash)":d.isToday?"var(--col-accent-wash)":d.isWeekend?"var(--col-bg-sec)":"transparent",outline:dragOverIso===d.iso?"2px dashed var(--col-accent)":"none",outlineOffset:-2,transition:"background 0.12s"}}>
                      {hours.map(h=>(
                        <div key={h} style={{position:"absolute",left:0,right:0,top:(h-HOUR_START)*HOUR_PX,height:1,background:"var(--col-border-soft)"}}/>
                      ))}
                      {d.timed.map((it,i)=>{
                        const catCol = it.cat ? (getCatColor(categories,it.cat).col) : prioCol[it.prio]||"var(--col-text-3)";
                        const isEv = it.type === "ev";
                        const isDl = it.type === "dl";
                        const isPlan = it.type === "plan";
                        return (
                          <div key={i} title={it.title} style={{
                            position:"absolute",left:3,right:3,top:it.top+1,height:it.h-2,
                            background: isEv ? "var(--col-bg-sec)" : isDl ? hexToRgba("#dc2626",0.06) : isPlan ? "var(--col-accent-wash)" : "var(--col-bg)",
                            border: isPlan ? "1px dashed var(--col-accent)" : "1px solid var(--col-border)",
                            borderLeft: `2px solid ${isDl?"#dc2626":isEv?"var(--col-text-3)":catCol}`,
                            borderRadius:3,padding:"3px 6px",overflow:"hidden",
                            boxShadow: isEv||isPlan ? "none" : "0 1px 2px rgba(0,0,0,0.03)"
                          }}>
                            {it.time && <div className="mono" style={{fontSize:9,color:isPlan?"var(--col-accent)":"var(--col-text-3)",letterSpacing:"0.04em",marginBottom:1}}>{it.time}{isPlan?t("cal.plan"):""}</div>}
                            <div style={{fontSize:10.5,fontWeight:500,color:"var(--col-text)",lineHeight:1.25,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}}>
                              {!isEv && <span style={{color:isDl?"#dc2626":"var(--col-accent)",marginRight:3}}>{isPlan?"✦":"○"}</span>}{it.title}
                            </div>
                            {isDl && <div className="mono" style={{fontSize:8.5,color:"#dc2626",letterSpacing:"0.06em",marginTop:1}}>DEADLINE</div>}
                          </div>
                        );
                      })}
                    </div>
                  ))}
                </div>
              </>
            );
          })()}
          <div style={{display:"flex",alignItems:"center",gap:14,padding:"8px 12px",borderTop:"1px solid var(--col-border-soft)",background:"var(--col-bg-sec)"}}>
            <span style={{display:"inline-flex",alignItems:"center",gap:5,fontSize:10.5,color:"var(--col-text-sec)"}}><span style={{width:10,height:10,background:"var(--col-bg-sec)",border:"1px solid var(--col-border)",borderLeft:"2px solid var(--col-text-3)"}}/>{t("cal.appointment")}</span>
            <span style={{display:"inline-flex",alignItems:"center",gap:5,fontSize:10.5,color:"var(--col-text-sec)"}}><span style={{width:10,height:10,background:"var(--col-bg)",border:"1px solid var(--col-border)",borderLeft:"2px solid var(--col-accent)"}}/>{t("cal.task")}</span>
            <span style={{display:"inline-flex",alignItems:"center",gap:5,fontSize:10.5,color:"#dc2626"}}><span style={{width:10,height:10,background:hexToRgba("#dc2626",0.06),border:"1px solid var(--col-border)",borderLeft:"2px solid #dc2626"}}/>{t("cal.deadline")}</span>
          </div>
        </div>
      )}
    </div>
  );
}

// ── ICS ──────────────────────────────────────────────────────────────
function downloadICS(slots, date){
  const pad = n => String(n).padStart(2,"0");
  const ds = localISO(date).replace(/-/g,"");
  const lines = ["BEGIN:VCALENDAR","VERSION:2.0","PRODID:-//Planer//DE","CALSCALE:GREGORIAN"];
  slots.forEach((s,i)=>{
    if (!s.time) return;
    const [h,m] = s.time.split(":").map(Number), dur = parseInt(s.duration)||30;
    const eH = h+Math.floor((m+dur)/60), eM = (m+dur)%60;
    lines.push("BEGIN:VEVENT", `UID:${ds}-${i}@planer`, `DTSTART:${ds}T${pad(h)}${pad(m)}00`, `DTEND:${ds}T${pad(eH)}${pad(eM)}00`, `SUMMARY:${s.task}`, `DESCRIPTION:${s.tip||""}`, "END:VEVENT");
  });
  lines.push("END:VCALENDAR");
  const url = URL.createObjectURL(new Blob([lines.join("\r\n")],{type:"text/calendar;charset=utf-8"}));
  const a = document.createElement("a"); a.href = url; a.download = "tagesplan.ics"; a.click();
  setTimeout(()=>URL.revokeObjectURL(url), 1000);
}

// ── SlotAdder ────────────────────────────────────────────────────────
function SlotAdder({ todos, onAdd, onCancel }){
  const now = new Date();
  const rm = Math.ceil(now.getMinutes()/15)*15;
  const defH = (now.getHours()+Math.floor(rm/60))%24, defM = rm%60;
  const [time, setTime] = useState(`${String(defH).padStart(2,"0")}:${String(defM).padStart(2,"0")}`);
  const [task, setTask] = useState("");
  const [dur, setDur]   = useState(30);
  function submit(){
    if (!task.trim()) return;
    onAdd({ time, task: task.trim(), duration: `${dur} Min`, tip: "" });
  }
  return (
    <div style={{background:"var(--col-bg-sec)",borderRadius:8,padding:"8px",border:"1px solid var(--col-border)"}}>
      <div style={{fontSize:11,fontWeight:600,color:"var(--col-text-sec)",marginBottom:6}}>{window.t("slot.new")}</div>
      <div style={{display:"flex",gap:6,marginBottom:6}}>
        <div style={{flex:1}}><div style={{fontSize:10,color:"var(--col-text-sec)",marginBottom:2}}>{window.t("slot.time")}</div><input type="time" value={time} onChange={e=>setTime(e.target.value)} style={{width:"100%",fontSize:12}}/></div>
        <div style={{flex:1}}><div style={{fontSize:10,color:"var(--col-text-sec)",marginBottom:2}}>{window.t("slot.duration")}</div><input type="number" min="5" max="480" step="5" value={dur} onChange={e=>setDur(Number(e.target.value))} style={{width:"100%",fontSize:12}}/></div>
      </div>
      <input list="slot-todo-list" placeholder={window.t("slot.placeholder")} value={task} onChange={e=>setTask(e.target.value)} onKeyDown={e=>e.key==="Enter"&&submit()} style={{width:"100%",fontSize:12,marginBottom:6}}/>
      <datalist id="slot-todo-list">{todos.filter(t=>!t.done).map(t=><option key={t.id} value={t.text}/>)}</datalist>
      <div style={{display:"flex",gap:5}}>
        <button onClick={submit} disabled={!task.trim()} style={{flex:1,padding:"5px",fontSize:11,borderRadius:6,background:"var(--col-accent)",color:"var(--col-bg)",fontWeight:500}}>{window.t("slot.add")}</button>
        <button onClick={onCancel} style={{padding:"5px 10px",fontSize:11,borderRadius:6,border:"1px solid var(--col-border)",color:"var(--col-text-sec)"}}>{window.t("slot.cancel")}</button>
      </div>
    </div>
  );
}

// ── PruefungsplanView ────────────────────────────────────────────────
// Cat-ink palette aus tokens.css — passt zu Paper/Ink-Theme
const EXAM_COLORS = [
  "#6B4E2E","#7A3B33","#4D6B3F","#7A6024","#5C4762","#4A5560",
  "#8A6040","#9A4B42","#3D5530","#8A7030","#704878","#3A4A58"
];
function buildExamColorMap(exams){
  const sorted=[...(exams||[])].sort((a,b)=>(a.date||'')<(b.date||'')?-1:1);
  const m={};sorted.forEach((e,i)=>{m[String(e.id)]=EXAM_COLORS[i%EXAM_COLORS.length];});
  return m;
}
// Kept for backward compat / fallback (timer bar uses examId lookup instead)
function subjectColor(exam,colorMap){
  if(colorMap&&exam?.id)return colorMap[String(exam.id)]||EXAM_COLORS[0];
  const key=((exam&&(exam.subject||exam.name))||"").toLowerCase().trim();
  if(!key)return EXAM_COLORS[0];
  let h=0;for(let i=0;i<key.length;i++)h=(h*31+key.charCodeAt(i))&0x7fffffff;
  return EXAM_COLORS[h%EXAM_COLORS.length];
}

function PruefungsplanView({ exams, todos, isMobile, calEvents, outlookConnected, onRefreshOutlook, lectures, onAddLecture, onUpdateLecture, onDeleteLecture, onAddExam, onUpdateExam, onDeleteExam, onAddTodo, onDeleteTodo, onUpdateTodo, studyTimer, startStudyTimer, pauseStudyTimer, resumeStudyTimer, stopStudyTimer, fmtMs, clock, onOpenPip }){
  const { useState: useS } = React;
  const DatePicker = window.DatePicker;
  const today = todayISO();
  const t = window.t;
  const WDAY = window.currentLang==="en" ? ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"] : ["So","Mo","Di","Mi","Do","Fr","Sa"];
  const [monthOffset, setMonthOffset] = useS(0);
  const [selectedExam, setSelectedExam] = useS(null);
  const [showAddExam, setShowAddExam] = useS(false);
  const [newExam, setNewExam] = useS({ name:"", date:today, subject:"" });
  const [showAddBlock, setShowAddBlock] = useS(false);
  const [newBlock, setNewBlock] = useS({ date:today, hours:2 });
  const [editingBlockId, setEditingBlockId] = useS(null);
  const [editBlock, setEditBlock] = useS({ date:today, hours:2 });
  const [editingExamName, setEditingExamName] = useS(false);
  const [editExamNameValue, setEditExamNameValue] = useS("");
  const [confirmDelete, setConfirmDelete] = useS(false);
  const [dragOverDate, setDragOverDate] = useS(null);
  const [showLecturePicker, setShowLecturePicker] = useS(false);
  const [pickedEvent, setPickedEvent] = useS(null);
  const [lectureHours, setLectureHours] = useS(1.5);
  const [showLectures, setShowLectures] = useS(()=>{
    try{return localStorage.getItem("planer_collapse_vorlesungen_"+(getAuthUsername()||""))!=="closed";}catch{return true;}
  });
  const [showExams, setShowExams] = useS(()=>{
    try{return localStorage.getItem("planer_collapse_pruefungen_"+(getAuthUsername()||""))!=="closed";}catch{return true;}
  });
  function toggleLectures(){setShowLectures(x=>{const n=!x;try{localStorage.setItem("planer_collapse_vorlesungen_"+(getAuthUsername()||""),n?"open":"closed");}catch{}return n;});}
  function toggleExams(){setShowExams(x=>{const n=!x;try{localStorage.setItem("planer_collapse_pruefungen_"+(getAuthUsername()||""),n?"open":"closed");}catch{}return n;});}

  // Reset edit/confirm state when exam selection changes
  const skipBlockResetRef = React.useRef(false);
  React.useEffect(()=>{
    setEditingExamName(false);setConfirmDelete(false);
    if(skipBlockResetRef.current){skipBlockResetRef.current=false;return;}
    setEditingBlockId(null);
  },[selectedExam?.id]);

  // Month calendar
  const base = new Date(); base.setDate(1); base.setMonth(base.getMonth() + monthOffset);
  const y = base.getFullYear(), mo = base.getMonth();
  const firstDow = (base.getDay() + 6) % 7;
  const daysInMonth = new Date(y, mo + 1, 0).getDate();
  const monthLabel = base.toLocaleDateString(window.currentLang==="en"?"en-GB":"de-CH", {month:"long", year:"numeric"});
  const cells = [];
  for (let i = 0; i < firstDow; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(y, mo, d));
  while (cells.length % 7 !== 0) cells.push(null);

  // Index by date
  const examsByDate = {};
  (exams||[]).forEach(e => { if(!examsByDate[e.date]) examsByDate[e.date]=[]; examsByDate[e.date].push(e); });
  const blocksByDate = {};
  (exams||[]).forEach(e => {
    (e.studyBlocks||[]).forEach(b => {
      if(!blocksByDate[b.date]) blocksByDate[b.date]=[];
      blocksByDate[b.date].push({...b, examName:e.name, examId:e.id, exam:e});
    });
  });

  // Vorlesungstage im aktuellen Monat indexieren
  const lecturesByDate={};
  (lectures||[]).filter(l=>!l.deletedAt).forEach(lec=>{
    cells.forEach(d=>{if(!d)return;if(d.getDay()===lec.weekday){const iso=localISO(d);lecturesByDate[iso]=(lecturesByDate[iso]||0)+1;}});
  });

  // Keep selectedExam in sync with exams array
  const syncedSelected = selectedExam ? (exams||[]).find(e=>e.id===selectedExam.id) || null : null;

  function addExam(){
    if(!newExam.name.trim()||!newExam.date)return;
    onAddExam({id:Date.now(),name:newExam.name.trim(),date:newExam.date,subject:newExam.subject.trim()||null,studyBlocks:[],createdAt:Date.now()});
    setNewExam({name:"",date:today,subject:""});
    setShowAddExam(false);
  }

  function addStudyBlock(){
    if(!syncedSelected||!newBlock.date||!newBlock.hours)return;
    const blockId=Date.now();
    const todoId=blockId+Math.floor(Math.random()*900000)+100000;
    const hours=parseFloat(newBlock.hours)||1;
    const todoText=`Lernen: ${syncedSelected.name} · ${hours}h`;
    const todo={id:todoId,createdAt:Date.now(),updatedAt:Date.now(),text:todoText,done:false,priority:"hoch",plannedDay:newBlock.date,deadline:null,category:null,subcategory:null,subtasks:[],comments:[],duration:Math.round(hours*60),recurring:null};
    onAddTodo(todo);
    const block={id:blockId,date:newBlock.date,hours,todoId};
    const updated={...syncedSelected,studyBlocks:[...(syncedSelected.studyBlocks||[]),block]};
    onUpdateExam(updated);
    setSelectedExam(updated);
    setNewBlock({date:today,hours:2});
    setShowAddBlock(false);
  }

  function updateStudyBlock(block, newDate, newHours){
    if(!syncedSelected)return;
    const hours=parseFloat(newHours)||block.hours;
    const date=newDate||block.date;
    const updatedBlocks=(syncedSelected.studyBlocks||[]).map(b=>b.id===block.id?{...b,date,hours}:b);
    const updated={...syncedSelected,studyBlocks:updatedBlocks};
    onUpdateExam(updated);
    setSelectedExam(updated);
    if(block.todoId&&onUpdateTodo){
      const linked=todos.find(t=>t.id===block.todoId);
      if(linked)onUpdateTodo({...linked,plannedDay:date,duration:Math.round(hours*60),text:`Lernen: ${syncedSelected.name} · ${hours}h`});
    }
    setEditingBlockId(null);
  }

  function deleteStudyBlock(block){
    if(block.todoId)onDeleteTodo(block.todoId);
    const updated={...syncedSelected,studyBlocks:(syncedSelected.studyBlocks||[]).filter(b=>b.id!==block.id)};
    onUpdateExam(updated);
    setSelectedExam(updated);
  }

  function moveStudyBlockToDate(examId, blockId, newDate){
    const exam=(exams||[]).find(e=>e.id===examId);
    if(!exam)return;
    const block=(exam.studyBlocks||[]).find(b=>b.id===blockId);
    if(!block||block.date===newDate)return;
    const updatedBlocks=(exam.studyBlocks).map(b=>b.id===blockId?{...b,date:newDate}:b);
    const updatedExam={...exam,studyBlocks:updatedBlocks,updatedAt:Date.now()};
    onUpdateExam(updatedExam);
    if(syncedSelected?.id===examId)setSelectedExam(updatedExam);
    if(block.todoId&&onUpdateTodo){
      const linked=todos.find(t=>t.id===block.todoId);
      if(linked)onUpdateTodo({...linked,plannedDay:newDate,updatedAt:Date.now()});
    }
  }

  function deleteExam(id){
    const ex=(exams||[]).find(e=>e.id===id);
    if(ex)(ex.studyBlocks||[]).forEach(b=>{if(b.todoId)onDeleteTodo(b.todoId);});
    onDeleteExam(id);
    if(syncedSelected?.id===id)setSelectedExam(null);
  }

  function addLectureFromOutlook(){
    if(!pickedEvent)return;
    const wd=new Date(pickedEvent.start.dateTime).getDay();
    onAddLecture({id:Date.now(),weekday:wd,hoursAfter:parseFloat(lectureHours)||1.5,
      label:pickedEvent.subject+" Nacharbeitung",startDate:today,
      fromOutlook:pickedEvent.subject,examId:null,intervalDays:7,noAutoCleanup:false,
      deletedAt:null,updatedAt:Date.now()});
    setShowLecturePicker(false);setPickedEvent(null);setLectureHours(1.5);
  }
  function toggleLectureNoCleanup(lec){onUpdateLecture({...lec,noAutoCleanup:!lec.noAutoCleanup,updatedAt:Date.now()});}
  function linkLectureToExam(lec,examId){onUpdateLecture({...lec,examId:examId||null,updatedAt:Date.now()});}

  const examColorMap = buildExamColorMap(exams);
  const examColor = e => e ? (examColorMap[String(e.id)] || EXAM_COLORS[0]) : EXAM_COLORS[0];
  const sel = syncedSelected || selectedExam;
  const totalH = sel ? (sel.studyBlocks||[]).reduce((s,b)=>s+(b.hours||0),0) : 0;
  const daysLeft = sel ? Math.round((new Date(sel.date+"T12:00:00")-new Date(today+"T12:00:00"))/86400000) : 0;
  const selColor = sel ? examColor(sel) : "var(--col-accent)";

  const navBtn={padding:"4px 10px",fontSize:14,border:"1px solid var(--col-border)",borderRadius:6,color:"var(--col-text-sec)",background:"transparent",cursor:"pointer",lineHeight:1,display:"inline-flex",alignItems:"center"};
  const ChevL=()=><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M15 6l-6 6 6 6"/></svg>;
  const ChevR=()=><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M9 6l6 6-6 6"/></svg>;

  return (
    <div>
      {/* Month calendar */}
      <div style={{background:"var(--col-bg)",border:"1px solid var(--col-border-soft)",borderRadius:8,padding:"14px",marginBottom:16}}>
        <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:12}}>
          <button onClick={()=>setMonthOffset(x=>x-1)} style={navBtn}><ChevL/></button>
          <div style={{display:"flex",alignItems:"center",gap:8}}>
            <span className="serif" style={{fontSize:20,fontStyle:"italic",fontWeight:500,color:"var(--col-text)"}}>{monthLabel}</span>
            {monthOffset!==0&&<button onClick={()=>setMonthOffset(0)} style={{fontSize:10,padding:"2px 8px",borderRadius:10,border:"1px solid var(--col-border)",background:"var(--col-bg-sec)",color:"var(--col-text-sec)",cursor:"pointer"}}>{t("pruef.today")}</button>}
          </div>
          <button onClick={()=>setMonthOffset(x=>x+1)} style={navBtn}><ChevR/></button>
        </div>
        <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:1,background:"var(--col-border-soft)",border:"1px solid var(--col-border-soft)",borderRadius:6,overflow:"hidden"}}>
          {(window.currentLang==="en"?["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]:["Mo","Di","Mi","Do","Fr","Sa","So"]).map(l=>(
            <div key={l} className="cap" style={{padding:"5px 6px",background:"var(--col-bg-sec)",fontSize:10,letterSpacing:"0.06em",color:"var(--col-text-sec)"}}>{l}</div>
          ))}
          {cells.map((d,i)=>{
            if(!d)return <div key={i} style={{background:"var(--col-bg-sec)",minHeight:72,opacity:0.3}}/>;
            const iso=localISO(d);
            const isT=iso===today;
            const isWknd=d.getDay()===0||d.getDay()===6;
            const dayExams=examsByDate[iso]||[];
            const dayBlocks=blocksByDate[iso]||[];
            const hasItems=dayExams.length>0||dayBlocks.length>0;
            return(
              <div key={i}
                onClick={()=>dayExams.length>0&&setSelectedExam(dayExams[0])}
                onDragOver={e=>{e.preventDefault();setDragOverDate(iso);}}
                onDragLeave={e=>{if(!e.currentTarget.contains(e.relatedTarget))setDragOverDate(null);}}
                onDrop={e=>{e.preventDefault();setDragOverDate(null);const raw=e.dataTransfer.getData("studyBlock");if(!raw)return;try{const{blockId,examId}=JSON.parse(raw);moveStudyBlockToDate(examId,blockId,iso);}catch{}}}
                style={{background:dragOverDate===iso?"var(--col-accent-wash)":"var(--col-bg)",minHeight:72,padding:"5px 6px",cursor:dayExams.length>0?"pointer":"default",opacity:isWknd?0.85:1,transition:"background 0.1s"}}>
                <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:3}}>
                  <span style={{fontSize:11,fontWeight:isT?700:400,color:isT?"var(--col-bg)":"var(--col-text)",background:isT?"var(--col-accent)":"transparent",borderRadius:"50%",width:isT?18:"auto",height:isT?18:"auto",display:"inline-flex",alignItems:"center",justifyContent:"center",minWidth:isT?18:"auto",flexShrink:0}}>{d.getDate()}</span>
                  {hasItems&&<span className="mono" style={{fontSize:9,color:"var(--col-text-3)"}}>{dayExams.length+dayBlocks.length}</span>}
                </div>
                <div style={{display:"flex",flexDirection:"column",gap:2}}>
                  {dayExams.slice(0,4).map((e,j)=>{
                    const c=examColor(e);
                    return(
                      <div key={j} style={{fontSize:9.5,color:c,background:hexToRgba(c,0.10),border:`1px solid ${hexToRgba(c,0.35)}`,borderLeft:`2px solid ${c}`,borderRadius:3,padding:"1px 4px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",fontWeight:600}}>{e.name}</div>
                    );
                  })}
                  {dayBlocks.slice(0,4).map((b,j)=>{
                    const c=examColor(b.exam);
                    return(
                      <div key={j} draggable onDragStart={ev=>{ev.dataTransfer.setData("studyBlock",JSON.stringify({blockId:b.id,examId:b.exam.id}));ev.dataTransfer.effectAllowed="move";}}
                        onClick={ev=>{
                          ev.stopPropagation();
                          const exam=(exams||[]).find(e=>String(e.id)===String(b.examId));
                          if(!exam)return;
                          skipBlockResetRef.current=true;
                          setSelectedExam(exam);
                          const block=(exam.studyBlocks||[]).find(bl=>String(bl.id)===String(b.id));
                          if(block){setEditingBlockId(block.id);setEditBlock({date:block.date,hours:block.hours});}
                        }}
                        onMouseDown={e=>e.preventDefault()} style={{fontSize:9.5,color:c,background:hexToRgba(c,0.06),borderLeft:`2px solid ${c}`,borderRadius:3,padding:"1px 4px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",opacity:0.85,cursor:"grab",userSelect:"none",WebkitUserSelect:"none"}}>{b.examName} {b.hours}h</div>
                    );
                  })}
                  {dayExams.length+dayBlocks.length>4&&<div className="mono" style={{fontSize:8,color:"var(--col-text-3)"}}>+{dayExams.length+dayBlocks.length-4}</div>}
                  {lecturesByDate[iso]>0&&<div style={{fontSize:9,color:"var(--col-accent)",opacity:0.6,marginTop:1}}>VL</div>}
                </div>
              </div>
            );
          })}
        </div>
        <div style={{display:"flex",gap:14,marginTop:8,fontSize:9.5,flexWrap:"wrap",alignItems:"center"}} className="mono">
          <span style={{display:"inline-flex",alignItems:"center",gap:5}}><span style={{width:10,height:10,borderRadius:2,background:hexToRgba(EXAM_COLORS[0],0.10),borderLeft:`2px solid ${EXAM_COLORS[0]}`}}/>{t("pruef.legendExam")}</span>
          <span style={{display:"inline-flex",alignItems:"center",gap:5}}><span style={{width:10,height:10,borderRadius:2,background:hexToRgba(EXAM_COLORS[2],0.06),borderLeft:`2px solid ${EXAM_COLORS[2]}`}}/>{t("pruef.legendBlock")}</span>
          <span style={{display:"inline-flex",alignItems:"center",gap:5}}><span style={{width:10,height:10,borderRadius:2,background:hexToRgba(EXAM_COLORS[3],0.08),borderLeft:`2px solid var(--col-accent)`}}/>{t("pruef.legendLecture")}</span>
          <span style={{fontSize:9,color:"var(--col-text-3)",opacity:0.7}}>{t("pruef.legendColor")}</span>
        </div>
      </div>

      {/* Content grid */}
      <div style={{display:"grid",gridTemplateColumns:isMobile?"1fr":sel?"1fr 340px":"1fr",gap:14,alignItems:"start"}}>
        {/* Vorlesungsplan — eigenständig, oberhalb Exam-Liste */}
        <div>
          <div style={{marginBottom:14,background:"var(--col-bg)",border:"1px solid var(--col-border-soft)",borderRadius:8,padding:"12px 14px"}}>
            <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:showLectures?8:0}}>
              <button onClick={toggleLectures} style={{display:"flex",alignItems:"center",gap:5,background:"none",border:"none",padding:0,cursor:"pointer",fontSize:12,fontWeight:600,color:"var(--col-text-sec)"}}>
                <span style={{display:"inline-block",transform:showLectures?"rotate(90deg)":"none",transition:"transform 0.15s"}}>▶</span> {t("pruef.lecturePlan")}
              </button>
              {showLectures&&(
                <button onClick={()=>{const opening=!showLecturePicker;setShowLecturePicker(x=>!x);setPickedEvent(null);if(opening&&onRefreshOutlook)onRefreshOutlook();}}
                  style={{fontSize:11,padding:"3px 8px",borderRadius:5,border:"1px solid var(--col-border)",background:showLecturePicker?"var(--col-bg-sec)":"transparent",color:"var(--col-text-sec)",cursor:"pointer"}}>
                  {showLecturePicker?t("pruef.cancel"):t("pruef.fromOutlook")}
                </button>
              )}
            </div>

            {showLectures&&<>
            {/* Outlook-Picker */}
            {showLecturePicker&&(
              <div style={{background:"var(--col-bg-sec)",borderRadius:8,padding:10,border:"1px solid var(--col-border)",marginBottom:8}}>
                <div style={{fontSize:11,fontWeight:600,marginBottom:6,color:"var(--col-text-sec)"}}>{t("pruef.pickOutlookEvent")}</div>
                <div style={{maxHeight:160,overflowY:"auto",marginBottom:8}}>
                  {!(calEvents||[]).length
                    ?<div style={{fontSize:11,color:"var(--col-text-3)"}}>{outlookConnected?t("pruef.outlookLoading"):t("pruef.outlookNotConnected")}</div>
                    :[...new Map((calEvents||[]).map(e=>[e.subject+"-"+new Date(e.start.dateTime).getDay(),e])).values()]
                        .map(e=>(
                          <div key={e.id} onClick={()=>setPickedEvent(ev=>ev?.id===e.id?null:e)}
                            style={{padding:"5px 8px",borderRadius:5,marginBottom:3,cursor:"pointer",fontSize:11,
                              background:pickedEvent?.id===e.id?"var(--col-accent-wash)":"transparent",
                              border:pickedEvent?.id===e.id?"1px solid var(--col-accent)":"1px solid transparent"}}>
                            <b>{e.subject}</b>
                            <span style={{color:"var(--col-text-3)",marginLeft:8}}>{WDAY[new Date(e.start.dateTime).getDay()]} {e.start.dateTime.slice(11,16)}</span>
                          </div>
                        ))
                  }
                </div>
                {pickedEvent&&(
                  <div style={{marginBottom:8}}>
                    <label style={{fontSize:11,color:"var(--col-text-sec)"}}>{t("pruef.followupHours")}</label>
                    <input type="number" min="0.5" max="8" step="0.5" value={lectureHours}
                      onChange={e=>setLectureHours(parseFloat(e.target.value)||1.5)}
                      style={{width:"100%",fontSize:12,marginTop:3}}/>
                  </div>
                )}
                <button onClick={addLectureFromOutlook} disabled={!pickedEvent}
                  style={{width:"100%",padding:"6px",fontSize:11,borderRadius:6,background:"var(--col-accent)",color:"var(--col-bg)",fontWeight:500,cursor:pickedEvent?"pointer":"default",opacity:pickedEvent?1:0.4}}>
                  {t("pruef.link")}
                </button>
              </div>
            )}

            {/* Gespeicherte Regeln */}
            {(lectures||[]).filter(l=>!l.deletedAt).length===0&&!showLecturePicker&&(
              <div style={{fontSize:11,color:"var(--col-text-3)",textAlign:"center",padding:"6px 0"}}>
                {t("pruef.noLectures")}
              </div>
            )}
            {(lectures||[]).filter(l=>!l.deletedAt).map(lec=>{
              const linkedExam=(exams||[]).find(e=>String(e.id)===String(lec.examId));
              return(
                <div key={lec.id} style={{background:"var(--col-bg-sec)",borderRadius:6,marginBottom:4,padding:"6px 8px",border:"1px solid var(--col-border-soft)"}}>
                  <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",fontSize:11}}>
                    <span style={{fontWeight:500}}>{lec.fromOutlook||lec.label} · {WDAY[lec.weekday]} · {lec.hoursAfter}h</span>
                    <button onClick={()=>onDeleteLecture(lec.id)} style={{background:"none",border:"none",cursor:"pointer",color:"var(--col-text-3)",fontSize:14,padding:"0 2px"}}>×</button>
                  </div>
                  <div style={{marginTop:4,display:"flex",alignItems:"center",gap:6}}>
                    <span style={{fontSize:10,color:"var(--col-text-3)"}}>{t("pruef.examLabel")}</span>
                    <select value={lec.examId||""} onChange={e=>linkLectureToExam(lec,e.target.value||null)}
                      style={{fontSize:10,border:"1px solid var(--col-border)",borderRadius:4,padding:"1px 4px",background:"var(--col-bg)",color:"var(--col-text)"}}>
                      <option value="">{t("pruef.none")}</option>
                      {(exams||[]).map(e=><option key={e.id} value={e.id}>{e.name}</option>)}
                    </select>
                  </div>
                  <div style={{marginTop:3,display:"flex",alignItems:"center",gap:6}}>
                    <input type="checkbox" id={"nc"+lec.id} checked={!!lec.noAutoCleanup} onChange={()=>toggleLectureNoCleanup(lec)} style={{cursor:"pointer"}}/>
                    <label htmlFor={"nc"+lec.id} style={{fontSize:10,color:"var(--col-text-3)",cursor:"pointer"}}>{t("pruef.noAutoDelete")}</label>
                    {lec.intervalDays&&<span style={{fontSize:10,color:"var(--col-text-3)",marginLeft:"auto"}}>∿{lec.intervalDays}d</span>}
                  </div>
                </div>
              );
            })}
            </>}
          </div>

          {/* Exam list */}
          <div style={{marginBottom:14,background:"var(--col-bg)",border:"1px solid var(--col-border-soft)",borderRadius:8,padding:"12px 14px"}}>
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:showExams?10:0}}>
            <button onClick={toggleExams} style={{display:"flex",alignItems:"center",gap:5,background:"none",border:"none",padding:0,cursor:"pointer"}}>
              <span style={{display:"inline-block",transform:showExams?"rotate(90deg)":"none",transition:"transform 0.15s"}}>▶</span>
              <span className="cap" style={{color:"var(--col-text-3)"}}>{t("pruef.exams",{n:(exams||[]).length})}</span>
            </button>
            {showExams&&<button onClick={()=>setShowAddExam(x=>!x)} style={{padding:"5px 12px",fontSize:11,borderRadius:20,background:showAddExam?"var(--col-bg-sec)":"var(--col-accent)",color:showAddExam?"var(--col-text-sec)":"var(--col-bg)",border:showAddExam?"1px solid var(--col-border)":"none",fontWeight:500,cursor:"pointer"}}>{showAddExam?t("pruef.cancel"):t("pruef.addExam")}</button>}
          </div>

          {showExams&&<>
          {showAddExam&&(
            <div style={{background:"var(--col-bg-sec)",borderRadius:8,padding:"12px",marginBottom:12,border:"1px solid var(--col-border)"}}>
              <div style={{fontSize:11,fontWeight:600,color:"var(--col-text-sec)",marginBottom:8}}>{t("pruef.newExam")}</div>
              <input placeholder={t("pruef.examNamePlaceholder")} value={newExam.name} onChange={e=>setNewExam(x=>({...x,name:e.target.value}))} onKeyDown={e=>{if(e.key==="Enter")addExam();if(e.key==="Escape")setShowAddExam(false);}} style={{width:"100%",boxSizing:"border-box",fontSize:12,marginBottom:6}} autoFocus/>
              <input placeholder={t("pruef.subjectPlaceholder")} value={newExam.subject} onChange={e=>setNewExam(x=>({...x,subject:e.target.value}))} style={{width:"100%",boxSizing:"border-box",fontSize:12,marginBottom:8}}/>
              <DatePicker value={newExam.date} onChange={d=>setNewExam(x=>({...x,date:d||today}))} label={t("pruef.examDate")}/>
              <div style={{display:"flex",gap:6,marginTop:10}}>
                <button onClick={addExam} disabled={!newExam.name.trim()} style={{flex:1,padding:"7px",fontSize:12,borderRadius:6,background:"var(--col-accent)",color:"var(--col-bg)",fontWeight:500,cursor:"pointer"}}>{t("pruef.save")}</button>
                <button onClick={()=>setShowAddExam(false)} style={{padding:"7px 12px",fontSize:12,borderRadius:6,border:"1px solid var(--col-border)",color:"var(--col-text-sec)",cursor:"pointer"}}>{t("pruef.cancel")}</button>
              </div>
            </div>
          )}

          {(exams||[]).length===0&&!showAddExam&&(
            <div style={{padding:"32px 0",textAlign:"center"}}>
              <p className="serif" style={{fontSize:15,color:"var(--col-text-sec)",fontStyle:"italic",marginBottom:6}}>{t("pruef.noExams")}</p>
              <p style={{fontSize:12,color:"var(--col-text-3)"}}>{t("pruef.noExamsHint")}</p>
            </div>
          )}

          <div style={{display:"flex",flexDirection:"column",gap:6}}>
            {[...(exams||[])].filter(e=>e.date>=today).sort((a,b)=>a.date>b.date?1:-1).map(e=>{
              const dL=Math.round((new Date(e.date+"T12:00:00")-new Date(today+"T12:00:00"))/86400000);
              const isSel=sel?.id===e.id;
              const totalBlH=(e.studyBlocks||[]).reduce((s,b)=>s+(b.hours||0),0);
              const doneBlocks=(e.studyBlocks||[]).filter(b=>todos.some(t=>t.id===b.todoId&&t.done)).length;
              const studiedMs=(e.studyBlocks||[]).reduce((sum,b)=>(b.sessions||[]).reduce((s,ss)=>s+ss.ms,0)+sum,0);
              const blProg=totalBlH>0?Math.min(1,studiedMs/(totalBlH*3600000)):0;
              const eColor=examColor(e);
              return(
                <div key={e.id} onClick={()=>setSelectedExam(isSel?null:e)}
                  style={{padding:"10px 12px",borderRadius:8,cursor:"pointer",
                    background:isSel?"var(--col-accent-wash)":"var(--col-bg)",
                    border:isSel?"1.5px solid var(--col-accent)":"1px solid var(--col-border-soft)",
                    borderLeft:`4px solid ${eColor}`,
                    transition:"border-color 0.12s,background 0.12s"}}>
                  <div style={{display:"flex",justifyContent:"space-between",alignItems:"baseline",gap:8}}>
                    <span style={{fontSize:13,fontWeight:500,color:isSel?"var(--col-accent)":"var(--col-text)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{e.name}</span>
                    <span className="mono" style={{fontSize:10,color:dL<0?"#b91c1c":dL<=3?"#92400e":"var(--col-text-3)",flexShrink:0,letterSpacing:"0.04em"}}>{dL<0?t("pruef.daysAgo",{n:-dL}):dL===0?t("pruef.todayBang"):dL===1?t("pruef.tomorrow"):t("pruef.daysLeft",{n:dL})}</span>
                  </div>
                  <div style={{display:"flex",gap:10,marginTop:3,flexWrap:"wrap"}}>
                    <span className="mono" style={{fontSize:10,color:"var(--col-text-sec)"}}>{fmtDate(e.date)}</span>
                    {e.subject&&<span style={{fontSize:10,color:eColor,fontWeight:600}}>{e.subject}</span>}
                    {totalBlH>0&&<span className="mono" style={{fontSize:10,color:"var(--col-accent)"}}>{t("pruef.hoursPlanned",{n:totalBlH})}</span>}
                    {(e.studyBlocks||[]).length>0&&<span className="mono" style={{fontSize:10,color:doneBlocks===(e.studyBlocks||[]).length?"#166534":"var(--col-text-3)"}}>{t("pruef.doneOfTotal",{done:doneBlocks,total:(e.studyBlocks||[]).length})}</span>}
                  </div>
                  {totalBlH>0&&<div style={{marginTop:6,height:3,background:"var(--col-bg-sec)",borderRadius:3,overflow:"hidden"}}><div style={{height:"100%",width:`${blProg*100}%`,background:eColor,borderRadius:3,transition:"width 0.4s"}}/></div>}
                </div>
              );
            })}
          </div>

          {(()=>{
            const pastExams=[...(exams||[])].filter(e=>e.date<today).sort((a,b)=>a.date<b.date?1:-1);
            if(pastExams.length===0)return null;
            return(
              <div style={{marginTop:14,paddingTop:10,borderTop:"1px solid var(--col-border-soft)",display:"flex",flexDirection:"column",gap:3}}>
                {pastExams.map(e=>(
                  <div key={e.id} onClick={()=>setSelectedExam(sel?.id===e.id?null:e)}
                    style={{display:"flex",alignItems:"center",gap:6,cursor:"pointer",opacity:0.55,overflow:"hidden"}}>
                    <span style={{fontSize:11,color:"#16a34a",flexShrink:0}}>✓</span>
                    <span style={{fontSize:11,color:"var(--col-text-sec)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{e.name}</span>
                    <span className="mono" style={{fontSize:10,color:"var(--col-text-3)",flexShrink:0,marginLeft:"auto"}}>{fmtDate(e.date)}</span>
                  </div>
                ))}
              </div>
            );
          })()}
          </>}
          </div>
        </div>

        {/* Exam detail */}
        {sel&&isMobile&&<div onClick={()=>setSelectedExam(null)} style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.35)",zIndex:300}}/>}
        {sel&&(
          <div style={isMobile?{position:"fixed",bottom:0,left:0,right:0,zIndex:301,background:"var(--col-bg)",borderRadius:"16px 16px 0 0",borderTop:`4px solid ${selColor}`,padding:"16px 14px",paddingBottom:"calc(70px + env(safe-area-inset-bottom,0px))",maxHeight:"88vh",overflowY:"auto",boxShadow:"0 -8px 32px rgba(0,0,0,0.18)"}:{background:"var(--col-bg)",border:"1px solid var(--col-border-soft)",borderLeft:`4px solid ${selColor}`,borderRadius:8,padding:"14px",position:"sticky",top:24}}>
            {isMobile&&<div style={{width:36,height:4,background:"var(--col-border)",borderRadius:2,margin:"0 auto 14px"}}/>}
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:10,gap:8}}>
              <div style={{minWidth:0,flex:1}}>
                {editingExamName?(
                  <input autoFocus value={editExamNameValue}
                    onChange={e=>setEditExamNameValue(e.target.value)}
                    onKeyDown={e=>{if(e.key==='Enter'&&editExamNameValue.trim()){onUpdateExam({...sel,name:editExamNameValue.trim(),updatedAt:Date.now()});setEditingExamName(false);}if(e.key==='Escape')setEditingExamName(false);}}
                    onBlur={()=>{if(editExamNameValue.trim())onUpdateExam({...sel,name:editExamNameValue.trim(),updatedAt:Date.now()});setEditingExamName(false);}}
                    style={{fontSize:14,fontWeight:600,width:"100%",border:"none",borderBottom:`1.5px solid ${selColor}`,background:"transparent",outline:"none",color:"var(--col-text)",padding:"0 0 2px",boxSizing:"border-box"}}/>
                ):(
                  <div onClick={()=>{setEditingExamName(true);setEditExamNameValue(sel.name);}} title={t("pruef.clickToRename")}
                    style={{fontSize:14,fontWeight:600,color:"var(--col-text)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",cursor:"text",display:"flex",alignItems:"center",gap:4}}>
                    <span style={{flex:1,overflow:"hidden",textOverflow:"ellipsis"}}>{sel.name}</span>
                    <span style={{fontSize:10,color:"var(--col-text-3)",opacity:0.5,flexShrink:0}}>✎</span>
                  </div>
                )}
                <div className="mono" style={{fontSize:10.5,color:"var(--col-text-sec)",marginTop:2}}>{fmtDate(sel.date)}{daysLeft>0?t("pruef.inDays",{n:daysLeft}):daysLeft===0?t("pruef.dueToday"):t("pruef.daysAgoSuffix",{n:-daysLeft})}</div>
                {sel.subject&&<div style={{fontSize:11,color:selColor,fontWeight:600,marginTop:1}}>{sel.subject}</div>}
              </div>
              <div style={{display:"flex",gap:4,flexShrink:0,alignItems:"flex-start"}}>
                {confirmDelete?(
                  <>
                    <button onClick={()=>{deleteExam(sel.id);setConfirmDelete(false);setSelectedExam(null);}} style={{padding:"3px 8px",fontSize:10,borderRadius:6,background:"#b91c1c",color:"#fff",border:"none",cursor:"pointer",fontWeight:600}}>{t("pruef.confirmDelete")}</button>
                    <button onClick={()=>setConfirmDelete(false)} style={{padding:"3px 7px",fontSize:10,borderRadius:6,border:"1px solid var(--col-border)",color:"var(--col-text-sec)",cursor:"pointer"}}>{t("pruef.cancel")}</button>
                  </>
                ):(
                  <button onClick={()=>setConfirmDelete(true)} style={{padding:"3px 8px",fontSize:10,borderRadius:6,border:"1px solid #fca5a5",color:"#b91c1c",cursor:"pointer"}}>{t("pruef.delete")}</button>
                )}
                <button onClick={()=>setSelectedExam(null)} style={{padding:"3px 7px",fontSize:12,borderRadius:6,border:"1px solid var(--col-border)",color:"var(--col-text-sec)",cursor:"pointer"}}>×</button>
              </div>
            </div>

            {totalH>0&&(()=>{
              const studiedMs=(sel.studyBlocks||[]).reduce((sum,b)=>(b.sessions||[]).reduce((s,ss)=>s+ss.ms,0)+sum,0);
              const studiedH=(studiedMs/3600000).toFixed(1);
              const prog=totalH>0?Math.min(1,studiedMs/(totalH*3600000)):0;
              return(
                <div style={{background:"var(--col-accent-wash)",borderRadius:6,padding:"8px 10px",marginBottom:12}}>
                  <div style={{display:"flex",gap:20,marginBottom:studiedMs>0?8:0}}>
                    <div><div className="serif" style={{fontSize:22,fontStyle:"italic",color:selColor,lineHeight:1}}>{totalH}h</div><div className="mono" style={{fontSize:9,color:"var(--col-text-3)",textTransform:"uppercase",letterSpacing:"0.06em",marginTop:2}}>{t("pruef.statPlanned")}</div></div>
                    <div><div className="serif" style={{fontSize:22,fontStyle:"italic",color:"var(--col-text)",lineHeight:1}}>{(sel.studyBlocks||[]).length}</div><div className="mono" style={{fontSize:9,color:"var(--col-text-3)",textTransform:"uppercase",letterSpacing:"0.06em",marginTop:2}}>{t("pruef.statBlocks")}</div></div>
                    <div><div className="serif" style={{fontSize:22,fontStyle:"italic",color:"#166534",lineHeight:1}}>{(sel.studyBlocks||[]).filter(b=>todos.some(t=>t.id===b.todoId&&t.done)).length}</div><div className="mono" style={{fontSize:9,color:"#166534",textTransform:"uppercase",letterSpacing:"0.06em",marginTop:2}}>{t("pruef.statDone")}</div></div>
                    {studiedMs>0&&<div><div className="serif" style={{fontSize:22,fontStyle:"italic",color:"#3a6bc7",lineHeight:1}}>{studiedH}h</div><div className="mono" style={{fontSize:9,color:"#3a6bc7",textTransform:"uppercase",letterSpacing:"0.06em",marginTop:2}}>{t("pruef.statStudied")}</div></div>}
                  </div>
                  {studiedMs>0&&<div style={{height:4,background:"rgba(0,0,0,0.08)",borderRadius:4,overflow:"hidden"}}><div style={{height:"100%",width:`${prog*100}%`,background:selColor,borderRadius:4,transition:"width 0.4s"}}/></div>}
                </div>
              );
            })()}

            {startStudyTimer&&studyTimer&&String(studyTimer.examId)===String(sel.id)&&(()=>{
              const elapsed=studyTimer.elapsed+(studyTimer.running?(clock?clock.getTime():Date.now())-studyTimer.startTs:0);
              return(
                <div style={{background:"var(--col-accent-wash)",border:"1px solid var(--col-accent)",borderRadius:8,padding:"8px 12px",marginBottom:10,display:"flex",alignItems:"center",gap:10}}>
                  <span className="serif" style={{fontSize:18,fontStyle:"italic",color:"var(--col-accent)",minWidth:55}}>{fmtMs(elapsed)}</span>
                  <span style={{flex:1,fontSize:11,color:"var(--col-text-sec)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{studyTimer.subject||studyTimer.examName}</span>
                  <button onClick={studyTimer.running?pauseStudyTimer:resumeStudyTimer}
                    style={{padding:"4px 10px",fontSize:11,borderRadius:6,background:studyTimer.running?"transparent":selColor,color:studyTimer.running?selColor:"#fff",border:`1px solid ${selColor}`,cursor:"pointer",fontWeight:600,flexShrink:0}}>
                    {studyTimer.running?t("pruef.pause"):t("pruef.resume")}
                  </button>
                  <button onClick={stopStudyTimer}
                    style={{padding:"4px 8px",fontSize:11,borderRadius:6,border:"1px solid var(--col-border)",color:"var(--col-text-sec)",background:"transparent",cursor:"pointer",flexShrink:0}}>{t("pruef.stop")}</button>
                  {onOpenPip&&<button onClick={onOpenPip} title={t("pruef.miniWindow")}
                    style={{padding:"4px 8px",fontSize:11,borderRadius:6,border:"1px solid var(--col-border)",color:"var(--col-text-sec)",background:"transparent",cursor:"pointer",flexShrink:0}}>⧉</button>}
                </div>
              );
            })()}
            <div className="cap" style={{color:"var(--col-text-3)",marginBottom:6}}>{t("pruef.studyBlocks")} <span style={{fontSize:9,fontWeight:400,opacity:0.7,textTransform:"none"}}>{t("pruef.tapToEdit")}</span></div>

            {(sel.studyBlocks||[]).length===0&&!showAddBlock&&(
              <p style={{fontSize:12,color:"var(--col-text-sec)",fontStyle:"italic",marginBottom:8}}>{t("pruef.noBlocks")}</p>
            )}

            <div style={{display:"flex",flexDirection:"column",gap:0,marginBottom:6}}>
              {[...(sel.studyBlocks||[])].sort((a,b)=>a.date>b.date?1:-1).map(b=>{
                const linked=todos.find(t=>t.id===b.todoId);
                const isDone=linked?.done||false;
                const isEditing=editingBlockId===b.id;

                if(isEditing){
                  const editDateAfterExam=editBlock.date&&sel.date&&editBlock.date>sel.date;
                  return(
                    <div key={b.id} onKeyDown={e=>{if(e.key==='Escape')setEditingBlockId(null);}}
                      style={{padding:"8px",borderBottom:"1px solid var(--col-border-soft)",background:"var(--col-bg-sec)",borderRadius:6,marginBottom:4}}>
                      <div style={{marginBottom:6}}>
                        <DatePicker value={editBlock.date} onChange={d=>setEditBlock(x=>({...x,date:d||today}))} label={t("pruef.date")}/>
                      </div>
                      {editDateAfterExam&&<div style={{fontSize:10,color:"#92400e",background:"#fef3c7",borderRadius:4,padding:"3px 6px",marginBottom:6}}>{t("pruef.afterExamWarning",{date:fmtDate(sel.date)})}</div>}
                      <label style={{fontSize:11,color:"var(--col-text-sec)",display:"block",marginBottom:3}}>{t("pruef.hours")}</label>
                      <input type="number" min="0.5" max="12" step="0.5" value={editBlock.hours}
                        onChange={e=>setEditBlock(x=>({...x,hours:parseFloat(e.target.value)||1}))}
                        style={{width:"100%",fontSize:12,marginBottom:6}}/>
                      <div style={{display:"flex",gap:5}}>
                        <button onClick={()=>updateStudyBlock(b,editBlock.date,editBlock.hours)}
                          style={{flex:1,padding:"5px",fontSize:11,borderRadius:6,background:selColor,color:"#fff",fontWeight:500,cursor:"pointer"}}>{t("pruef.save")}</button>
                        <button onClick={()=>setEditingBlockId(null)}
                          style={{padding:"5px 10px",fontSize:11,borderRadius:6,border:"1px solid var(--col-border)",color:"var(--col-text-sec)",cursor:"pointer"}}>{t("pruef.cancel")}</button>
                      </div>
                    </div>
                  );
                }

                const sessionMs=(b.sessions||[]).reduce((s,ss)=>s+ss.ms,0);
                const sessionLabel=sessionMs>60000?t("pruef.hoursStudied",{n:(sessionMs/3600000).toFixed(1)}):"";
                return(
                  <div key={b.id}
                    onClick={()=>{setEditingBlockId(b.id);setEditBlock({date:b.date,hours:b.hours});}}
                    style={{display:"flex",alignItems:"center",gap:8,padding:"7px 4px",borderBottom:"1px solid var(--col-border-soft)",cursor:"pointer",borderRadius:4,transition:"background 0.1s"}}
                    onMouseEnter={e=>e.currentTarget.style.background="var(--col-bg-sec)"}
                    onMouseLeave={e=>e.currentTarget.style.background="transparent"}>
                    <span style={{width:8,height:8,borderRadius:2,background:isDone?"#166534":selColor,flexShrink:0}}/>
                    <span className="mono" style={{fontSize:11,color:"var(--col-text-sec)",minWidth:52}}>{fmtDate(b.date)}</span>
                    <span style={{flex:1,fontSize:12,color:isDone?"var(--col-text-3)":"var(--col-text)",textDecoration:isDone?"line-through":"none"}}>{t("pruef.hoursStudy",{n:b.hours})}{sessionLabel&&<span style={{fontSize:10,color:"#3a6bc7"}}>{sessionLabel}</span>}</span>
                    {isDone&&<span style={{fontSize:9,color:"#166534"}}>✓</span>}
                    <span style={{fontSize:11,color:"var(--col-text-3)",opacity:0.5}}>✎</span>
                    {startStudyTimer&&!isDone&&(
                      <button onClick={e=>{e.stopPropagation();startStudyTimer(b,sel);}}
                        title={t("pruef.startTimer")}
                        style={{background:"none",border:"none",color:studyTimer&&String(studyTimer.blockId)===String(b.id)?selColor:selColor,fontSize:12,cursor:"pointer",padding:"0 3px",opacity:studyTimer&&String(studyTimer.blockId)===String(b.id)?1:0.45,fontWeight:600}}>
                        {studyTimer&&String(studyTimer.blockId)===String(b.id)?(studyTimer.running?"●":"▶"):"▶"}
                      </button>
                    )}
                    <button onClick={e=>{e.stopPropagation();deleteStudyBlock(b);}} style={{background:"none",border:"none",color:"var(--col-text-sec)",fontSize:14,cursor:"pointer",padding:"0 2px"}}>×</button>
                  </div>
                );
              })}
            </div>

            {showAddBlock?(
              <div style={{background:"var(--col-bg-sec)",borderRadius:8,padding:"10px",border:"1px solid var(--col-border)",marginBottom:6}} onKeyDown={e=>{if(e.key==='Escape')setShowAddBlock(false);}}>
                <div style={{fontSize:11,fontWeight:600,color:"var(--col-text-sec)",marginBottom:8}}>{t("pruef.newBlock")}</div>
                <div style={{marginBottom:8}}>
                  <DatePicker value={newBlock.date} onChange={d=>setNewBlock(x=>({...x,date:d||today}))} label={t("pruef.date")}/>
                </div>
                {newBlock.date&&sel.date&&newBlock.date>sel.date&&<div style={{fontSize:10,color:"#92400e",background:"#fef3c7",borderRadius:4,padding:"3px 6px",marginBottom:6}}>{t("pruef.afterExamWarning",{date:fmtDate(sel.date)})}</div>}
                <label style={{fontSize:11,color:"var(--col-text-sec)",display:"block",marginBottom:4}}>{t("pruef.hours")}</label>
                <input type="number" min="0.5" max="12" step="0.5" value={newBlock.hours}
                  onChange={e=>setNewBlock(x=>({...x,hours:parseFloat(e.target.value)||1}))}
                  style={{width:"100%",fontSize:12,marginBottom:8}}/>
                <div style={{display:"flex",gap:5}}>
                  <button onClick={addStudyBlock} style={{flex:1,padding:"6px",fontSize:11,borderRadius:6,background:selColor,color:"#fff",fontWeight:500,cursor:"pointer"}}>{t("pruef.add")}</button>
                  <button onClick={()=>setShowAddBlock(false)} style={{padding:"6px 10px",fontSize:11,borderRadius:6,border:"1px solid var(--col-border)",color:"var(--col-text-sec)",cursor:"pointer"}}>{t("pruef.cancel")}</button>
                </div>
              </div>
            ):(
              <button onClick={()=>setShowAddBlock(true)} style={{width:"100%",padding:"6px",fontSize:11,borderRadius:6,border:"1px dashed var(--col-border)",color:"var(--col-text-sec)",background:"transparent",cursor:"pointer"}}>{t("pruef.addBlock")}</button>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { SettingsPanel, ReviewModal, CalendarWeekView, SlotAdder, downloadICS, PruefungsplanView, subjectColor, buildExamColorMap, EXAM_COLORS });

})();
