:root{--bg:#efefef;--card:#f8f8f8;--muted:#a5a5a5;--text:#111;--accent:#ff3f49;--shadow:0 10px 24px rgba(0,0,0,.08);--shadow-soft:0 8px 20px rgba(0,0,0,.06);--radius:34px;--radius-sm:26px;--line:#ececec}*{box-sizing:border-box}html,body{margin:0;padding:0;font-family:Inter,Arial,Helvetica,sans-serif;background:linear-gradient(135deg,#f6f6f6,#e8e8e8);color:var(--text);min-height:100%}body.theme-dark{--bg:#171717;--card:#202020;--muted:#8f8f8f;--text:#f6f6f6;--accent:#ff4a53;--line:#2c2c2c;background:linear-gradient(135deg,#111,#1a1a1a)}a{text-decoration:none;color:inherit}img{max-width:100%}button,input,select,textarea{font:inherit}button{cursor:pointer;border:none}.desktop-shell{max-width:430px;min-height:100vh;margin:0 auto;position:relative;background:var(--bg);box-shadow:0 0 0 1px rgba(0,0,0,.03),0 24px 80px rgba(0,0,0,.12);overflow:hidden}.page{min-height:100vh;padding-bottom:110px}.top-hero{height:255px;background:var(--accent);padding:44px 28px 24px;color:#fff;position:relative}.top-hero .user-row{display:flex;align-items:center;gap:18px;margin-top:42px}.avatar{width:100px;height:100px;border-radius:50%;object-fit:cover;background:#fff;border:6px solid rgba(255,255,255,.16)}.hero-name{font-size:22px;font-weight:800;line-height:1.1}.hero-role{margin-top:8px;font-size:12px;opacity:.9}.curve-body{margin-top:-18px;background:var(--bg);border-top-left-radius:42px;border-top-right-radius:42px;padding:34px 22px 18px;min-height:calc(100vh - 237px)}.greet-grid{display:grid;grid-template-columns:1.06fr 1fr;gap:18px;align-items:start}.greet-title{font-size:17px;font-weight:800;margin:8px 0 6px}.greet-sub{font-size:14px;color:var(--muted);line-height:1.45;font-weight:700;max-width:140px}.sun-icon{width:36px;height:36px;color:var(--accent)}.menu-card{background:var(--card);border-radius:34px;box-shadow:var(--shadow-soft);padding:24px 16px;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:158px;border:1px solid rgba(255,255,255,.35)}.menu-card .ic{width:70px;height:70px;color:var(--accent);margin-bottom:16px}.menu-card .label{font-size:15px;font-weight:800;color:var(--accent);text-align:center;line-height:1.25}.menu-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:18px}.quick-status,.panel,.list-card,.form-card,.stat-card{background:var(--card);border-radius:28px;box-shadow:var(--shadow-soft);padding:18px;border:1px solid rgba(255,255,255,.35)}.quick-status{margin-top:18px}.section-title{font-size:15px;font-weight:800;margin:0 0 12px}.muted{color:var(--muted)}.row{display:flex;align-items:center;justify-content:space-between;gap:12px}.tiny{font-size:12px}.pill{display:inline-flex;align-items:center;gap:8px;padding:8px 12px;border-radius:999px;background:rgba(255,63,73,.1);color:var(--accent);font-size:12px;font-weight:700}.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;background:var(--accent);color:#fff;padding:13px 16px;border-radius:18px;font-weight:800;box-shadow:0 12px 22px rgba(255,63,73,.22)}.btn.secondary{background:transparent;color:var(--text);border:1px solid var(--line);box-shadow:none}.btn.ghost{background:#fff;color:var(--accent);border:1px solid rgba(255,63,73,.2);box-shadow:none}.btn.full{width:100%}.btn:disabled{opacity:.55;cursor:not-allowed}.bottom-nav{position:fixed;left:50%;transform:translateX(-50%);bottom:14px;width:min(390px,calc(100vw - 28px));background:rgba(255,255,255,.92);backdrop-filter:blur(12px);border-radius:999px;box-shadow:0 14px 35px rgba(0,0,0,.12);padding:12px 8px;display:grid;grid-template-columns:repeat(3,1fr);z-index:99}.theme-dark .bottom-nav{background:rgba(26,26,26,.92)}.nav-item{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;color:#c6c6c6;font-size:11px;font-weight:700;padding:4px 2px}.nav-item svg{width:26px;height:26px}.nav-item.active{color:var(--accent)}.topbar{padding:18px 18px 10px;display:flex;align-items:center;gap:12px;position:sticky;top:0;background:linear-gradient(180deg,var(--bg),rgba(255,255,255,0));z-index:10}.back-btn,.icon-btn{width:40px;height:40px;border-radius:14px;background:var(--card);box-shadow:var(--shadow-soft);display:flex;align-items:center;justify-content:center}.topbar-title{font-size:18px;font-weight:800}.content{padding:12px 18px 120px}.field{display:flex;flex-direction:column;gap:7px;margin-bottom:14px}.field label{font-size:13px;font-weight:700}.field input,.field select,.field textarea{background:var(--card);border:1px solid var(--line);min-height:48px;padding:12px 14px;border-radius:18px;color:var(--text);outline:none}.field textarea{min-height:102px;resize:vertical}.stats-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}.stat-card .num{font-size:28px;font-weight:900;color:var(--accent)}.list{display:flex;flex-direction:column;gap:12px}.list-item{padding:14px 16px;border-radius:22px;background:var(--card);box-shadow:var(--shadow-soft);display:flex;flex-direction:column;gap:8px;border:1px solid rgba(255,255,255,.35)}.status{display:inline-flex;padding:7px 10px;border-radius:999px;font-size:11px;font-weight:800}.s-ok{background:rgba(10,168,104,.12);color:#0d9b63}.s-wait{background:rgba(255,168,0,.14);color:#c78000}.s-bad{background:rgba(255,63,73,.12);color:var(--accent)}.s-info{background:rgba(0,120,255,.12);color:#0073e6}.login-wrap,.landing-wrap{min-height:100vh;background:var(--bg)}.landing-hero{min-height:100vh;display:flex;flex-direction:column;justify-content:flex-end;position:relative;overflow:hidden}.landing-photo{position:absolute;inset:0;background:linear-gradient(0deg,rgba(0,0,0,.55),rgba(0,0,0,.18)),url('https://images.unsplash.com/photo-1521791136064-7986c2920216?auto=format&fit=crop&w=1200&q=80') center/cover no-repeat}.landing-card{position:relative;z-index:2;margin:0 18px 22px;background:rgba(255,255,255,.9);backdrop-filter:blur(10px);border-radius:34px;padding:22px;box-shadow:0 20px 40px rgba(0,0,0,.18)}.landing-card h1{margin:0 0 8px;font-size:31px;line-height:1.08}.landing-card p{margin:0 0 18px;color:#595959;line-height:1.5;font-size:14px}.stack{display:flex;flex-direction:column;gap:12px}.split{display:grid;grid-template-columns:1fr 1fr;gap:12px}.logo-dot{width:52px;height:52px;border-radius:18px;background:var(--accent);display:flex;align-items:center;justify-content:center;color:#fff;margin-bottom:14px;box-shadow:0 14px 28px rgba(255,63,73,.28)}.login-card{margin:22px 18px 18px;background:var(--card);padding:22px;border-radius:32px;box-shadow:var(--shadow-soft)}.login-head{background:var(--accent);padding:40px 22px 90px;border-bottom-left-radius:36px;border-bottom-right-radius:36px;color:#fff}.watermark{position:fixed;right:10px;bottom:92px;font-size:10px;color:rgba(0,0,0,.42);transform:rotate(-90deg);transform-origin:right bottom;z-index:100}.theme-dark .watermark{color:rgba(255,255,255,.3)}.chip-lock{display:inline-flex;align-items:center;gap:8px;background:rgba(0,0,0,.06);padding:9px 12px;border-radius:999px;font-size:12px;font-weight:800}.theme-dark .chip-lock{background:rgba(255,255,255,.08)}.table-lite{width:100%;border-collapse:collapse}.table-lite th,.table-lite td{text-align:left;padding:12px 8px;border-bottom:1px solid var(--line);font-size:13px}.table-lite th{font-size:12px;color:var(--muted)}.hidden{display:none!important}.center{text-align:center}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}.mb-18{margin-bottom:18px}.mb-24{margin-bottom:24px}.mt-10{margin-top:10px}.mt-14{margin-top:14px}.mt-18{margin-top:18px}.photo-sm{width:72px;height:72px;border-radius:50%;object-fit:cover}.separator{height:1px;background:var(--line);margin:14px 0}.notice{padding:12px 14px;border-radius:18px;background:rgba(255,63,73,.08);font-size:12px;color:var(--accent);font-weight:700}.okbox{padding:12px 14px;border-radius:18px;background:rgba(12,162,94,.1);font-size:12px;color:#0c9f5d;font-weight:700}.admin-nav{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}.admin-shortcut{padding:16px;border-radius:24px;background:var(--card);box-shadow:var(--shadow-soft)}.admin-shortcut svg{width:28px;height:28px;color:var(--accent);margin-bottom:10px}.admin-shortcut strong{display:block;font-size:14px}.banner-mini{border-radius:28px;padding:16px;background:linear-gradient(135deg,var(--accent),#ff6c73);color:#fff;box-shadow:0 16px 34px rgba(255,63,73,.24)}.toggle{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 14px;border-radius:20px;background:var(--card);box-shadow:var(--shadow-soft)}.switch{width:52px;height:32px;border-radius:999px;background:#ddd;position:relative}.switch:after{content:'';position:absolute;top:4px;left:4px;width:24px;height:24px;border-radius:50%;background:#fff;transition:.25s}.switch.on{background:var(--accent)}.switch.on:after{left:24px}@media (min-width:768px){body{padding:24px}.desktop-shell{border-radius:42px;min-height:calc(100vh - 48px)}.bottom-nav{bottom:38px}}EOF

cat > /mnt/data/absensi_sederhana/script.js <<'EOF'
const A=(()=>{const S={user:null,settings:{theme:localStorage.getItem('theme')||'light'}};const icon=(n)=>`<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.9">${n}</svg>`;const I={sun:icon('<circle cx="12" cy="12" r="4"/><path stroke-linecap="round" d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/>'),home:icon('<path stroke-linecap="round" stroke-linejoin="round" d="M3 11.5 12 4l9 7.5"/><path stroke-linecap="round" stroke-linejoin="round" d="M5 10.5V20h14v-9.5"/>'),file:icon('<path stroke-linecap="round" stroke-linejoin="round" d="M8 3h6l5 5v13H8a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2Z"/><path stroke-linecap="round" stroke-linejoin="round" d="M14 3v5h5"/><circle cx="11" cy="14" r="2.2"/><path stroke-linecap="round" d="M8.8 19c.6-1.8 2-3 4.2-3s3.6 1.2 4.2 3"/>'),user:icon('<circle cx="12" cy="8" r="3.2"/><path stroke-linecap="round" d="M5 20c1.8-3.6 4.2-5 7-5s5.2 1.4 7 5"/>'),checkin:icon('<circle cx="8" cy="8" r="3"/><path d="M5 16c1.1-2.4 2.8-3.5 5-3.5 1.2 0 2.2.3 3.1.9"/><path stroke-linecap="round" stroke-linejoin="round" d="m14 15 2.5 2.5L21 13"/>'),mail:icon('<path stroke-linecap="round" stroke-linejoin="round" d="M3.5 6.5h17v11h-17z"/><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 8 7.5 5 7.5-5"/><path stroke-linecap="round" stroke-linejoin="round" d="M15 17.5h5"/><path stroke-linecap="round" stroke-linejoin="round" d="M18 14.5v6"/>'),history:icon('<path stroke-linecap="round" stroke-linejoin="round" d="M3 12a9 9 0 1 0 3-6.7"/><path stroke-linecap="round" stroke-linejoin="round" d="M3 4v5h5"/><circle cx="12" cy="12" r="2.5"/>'),map:icon('<path stroke-linecap="round" stroke-linejoin="round" d="M12 21s6-4.5 6-10a6 6 0 1 0-12 0c0 5.5 6 10 6 10Z"/><circle cx="12" cy="11" r="2.5"/>'),logout:icon('<path stroke-linecap="round" stroke-linejoin="round" d="M10 6H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h4"/><path stroke-linecap="round" stroke-linejoin="round" d="m14 16 4-4-4-4"/><path stroke-linecap="round" d="M18 12H9"/>'),lock:icon('<rect x="5" y="10" width="14" height="10" rx="2"/><path d="M8 10V8a4 4 0 0 1 8 0v2"/>'),settings:icon('<path stroke-linecap="round" stroke-linejoin="round" d="M12 8.5A3.5 3.5 0 1 0 12 15.5A3.5 3.5 0 1 0 12 8.5Z"/><path stroke-linecap="round" stroke-linejoin="round" d="M19.4 15a1 1 0 0 0 .2 1.1l.1.1a2 2 0 0 1-2.8 2.8l-.1-.1a1 1 0 0 0-1.1-.2 1 1 0 0 0-.6.9V20a2 2 0 0 1-4 0v-.1a1 1 0 0 0-.6-.9 1 1 0 0 0-1.1.2l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1 1 0 0 0 .2-1.1 1 1 0 0 0-.9-.6H4a2 2 0 0 1 0-4h.1a1 1 0 0 0 .9-.6 1 1 0 0 0-.2-1.1l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1 1 0 0 0 1.1.2 1 1 0 0 0 .6-.9V4a2 2 0 0 1 4 0v.1a1 1 0 0 0 .6.9 1 1 0 0 0 1.1-.2l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1 1 0 0 0-.2 1.1 1 1 0 0 0 .9.6H20a2 2 0 0 1 0 4h-.1a1 1 0 0 0-.9.6Z"/>'),chart:icon('<path stroke-linecap="round" stroke-linejoin="round" d="M4 19h16"/><path stroke-linecap="round" stroke-linejoin="round" d="M7 16V9"/><path stroke-linecap="round" stroke-linejoin="round" d="M12 16V5"/><path stroke-linecap="round" stroke-linejoin="round" d="M17 16v-3"/>'),users:icon('<circle cx="9" cy="8" r="2.7"/><circle cx="17" cy="9.5" r="2.2"/><path stroke-linecap="round" d="M4.5 18c1.4-2.7 3.3-3.8 5.9-3.8S15 15.3 16.3 18"/><path stroke-linecap="round" d="M15 17.7c.7-1.9 2-2.9 4-2.9 1.1 0 2 .3 2.8 1"/>'),download:icon('<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v11"/><path stroke-linecap="round" stroke-linejoin="round" d="m8 11 4 4 4-4"/><path stroke-linecap="round" stroke-linejoin="round" d="M4 20h16"/>')};const qs=s=>document.querySelector(s),qsa=s=>[...document.querySelectorAll(s)];const jfetch=(u,o={})=>fetch(u,o).then(r=>r.json());const toast=(m,ok=1)=>alert(m);const applyTheme=()=>document.body.classList.toggle('theme-dark',S.settings.theme==='dark');const setTheme=t=>{S.settings.theme=t;localStorage.setItem('theme',t);applyTheme()};const page=()=>document.body.dataset.page||'';const auth=async()=>{const t=localStorage.getItem('absen_token');if(!t)return null;const d=await jfetch('api.php?action=me&token='+encodeURIComponent(t));if(d.ok){S.user=d.user;return d.user}localStorage.removeItem('absen_token');return null};const requireAuth=async(role)=>{const u=await auth();if(!u){location.href='login.html';return null}if(role&&u.role!==role){location.href=u.role==='admin'?'dashboard-admin.html':'home.html';return null}return u};const fillIcons=()=>qsa('[data-ic]').forEach(e=>e.innerHTML=I[e.dataset.ic]||'');const nav=(active)=>`<nav class="bottom-nav"><a class="nav-item ${active==='home'?'active':''}" href="home.html">${I.home}<span>Home</span></a><a class="nav-item ${active==='izin'?'active':''}" href="status-izin.html">${I.file}<span>Status Izin</span></a><a class="nav-item ${active==='profile'?'active':''}" href="profile.html">${I.user}<span>Profile</span></a></nav>`;const back=(title,tools='')=>`<div class="topbar"><a href="javascript:history.back()" class="back-btn">${icon('<path stroke-linecap="round" stroke-linejoin="round" d="m15 18-6-6 6-6"/>')}</a><div class="topbar-title">${title}</div><div style="margin-left:auto;display:flex;gap:10px">${tools}</div></div>`;const fmtDate=s=>{const d=new Date(s);return d.toLocaleDateString('id-ID',{day:'2-digit',month:'short',year:'numeric'})};const fmtTime=s=>s?new Date(s).toLocaleTimeString('id-ID',{hour:'2-digit',minute:'2-digit'}):'-';const getLocation=()=>new Promise((resolve,reject)=>{if(!navigator.geolocation)return reject('Browser tidak mendukung GPS');navigator.geolocation.getCurrentPosition(p=>resolve({lat:p.coords.latitude,lng:p.coords.longitude,acc:p.coords.accuracy}),e=>reject('GPS belum diizinkan atau gagal dibaca'),{enableHighAccuracy:true,timeout:10000,maximumAge:0})});const uploadFileAsBase64=f=>new Promise(res=>{if(!f)return res('');const r=new FileReader();r.onload=()=>res(r.result.split(',')[1]||'');r.readAsDataURL(f)});const initLanding=()=>{qs('#year')&&(qs('#year').textContent=new Date().getFullYear())};const initLogin=()=>{const form=qs('#loginForm');qs('#fillAdmin').onclick=()=>{qs('[name=username]').value='admin';qs('[name=password]').value='admin123'};qs('#fillPegawai').onclick=()=>{qs('[name=username]').value='pegawai';qs('[name=password]').value='pegawai123'};qs('#demoAdmin').onclick=()=>{qs('[name=username]').value='admin';qs('[name=password]').value='admin123';form.requestSubmit()};form.onsubmit=async e=>{e.preventDefault();const fd=new FormData(form);const r=await jfetch('api.php?action=login',{method:'POST',body:fd});if(!r.ok)return toast(r.message||'Login gagal',0);localStorage.setItem('absen_token',r.token);location.href=r.user.role==='admin'?'dashboard-admin.html':'home.html'}};const initHome=async()=>{const u=await requireAuth('pegawai');if(!u)return;qs('#navMount').innerHTML=nav('home');const r=await jfetch('api.php?action=employee_home&token='+localStorage.getItem('absen_token'));qs('#heroName').textContent='Hi, '+u.name.split(' ')[0];qs('#heroRole').textContent=u.position||'Pegawai';qs('#empPhoto').src=u.photo||'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?auto=format&fit=crop&w=300&q=80';qs('#todayStatus').innerHTML=`<div class="row"><div><div class="tiny muted">Status hari ini</div><div class="section-title">${r.today.checked_in?'Sudah absen masuk':'Belum absen masuk'}</div></div><span class="pill">${r.gps.valid?'Lokasi valid':'GPS belum valid'}</span></div><div class="separator"></div><div class="row tiny"><span>Masuk</span><strong>${r.today.checkin_time||'-'}</strong></div><div class="row tiny"><span>Keluar</span><strong>${r.today.checkout_time||'-'}</strong></div><div class="row tiny"><span>Radius</span><strong>${r.gps.radius} meter</strong></div><div class="row mt-14"><a class="btn" href="absen.html">Absen Cepat</a><a class="btn secondary" href="pengajuan.html">Ajukan Izin</a></div>`;qs('#gpsBadge').textContent=r.gps.valid?'Lokasi valid':'Di luar radius';qs('#gpsBadge').className=r.gps.valid?'pill':'pill';qs('#selfieStatus').innerHTML='<span class="chip-lock">'+I.lock+' Absen Selfie Terkunci</span>'};const initAbsen=async()=>{const u=await requireAuth('pegawai');if(!u)return;qs('#head').innerHTML=back('Absensi',`<a href="home.html" class="icon-btn">${I.home}</a>`);const token=localStorage.getItem('absen_token');const statusBox=qs('#statusBox');const refresh=async()=>{const r=await jfetch('api.php?action=employee_home&token='+token);statusBox.innerHTML=`<div class="row"><div><div class="tiny muted">Status GPS</div><div class="section-title">${r.gps.valid?'Lokasi valid':'Lokasi belum valid'}</div></div><span class="status ${r.gps.valid?'s-ok':'s-bad'}">${r.gps.distance} m</span></div><div class="separator"></div><div class="row tiny"><span>Masuk hari ini</span><strong>${r.today.checkin_time||'-'}</strong></div><div class="row tiny"><span>Keluar hari ini</span><strong>${r.today.checkout_time||'-'}</strong></div><div class="row tiny"><span>Koordinat kantor</span><strong>${r.gps.office_lat}, ${r.gps.office_lng}</strong></div>`};await refresh();const act=async(type)=>{try{qs('#geoMsg').textContent='Membaca GPS...';const p=await getLocation();qs('#geoMsg').textContent=`GPS terbaca ${p.lat.toFixed(5)}, ${p.lng.toFixed(5)}`;const fd=new FormData();fd.append('token',token);fd.append('type',type);fd.append('lat',p.lat);fd.append('lng',p.lng);fd.append('accuracy',p.acc);const r=await jfetch('api.php?action=attendance_action',{method:'POST',body:fd});toast(r.message,r.ok?1:0);await refresh()}catch(e){toast(String(e),0)}};qs('#btnIn').onclick=()=>act('in');qs('#btnOut').onclick=()=>act('out');qs('#btnCheckGps').onclick=async()=>{try{const p=await getLocation();const fd=new FormData();fd.append('token',token);fd.append('lat',p.lat);fd.append('lng',p.lng);const r=await jfetch('api.php?action=gps_check',{method:'POST',body:fd});qs('#geoMsg').textContent=r.message}catch(e){toast(String(e),0)}}};const initPengajuan=async()=>{await requireAuth('pegawai');qs('#head').innerHTML=back('Pengajuan Absen');qs('#leaveForm').onsubmit=async e=>{e.preventDefault();const fd=new FormData(qs('#leaveForm'));fd.append('token',localStorage.getItem('absen_token'));const f=qs('#lampiran').files[0];if(f)fd.append('attachment_b64',await uploadFileAsBase64(f));const r=await jfetch('api.php?action=create_leave',{method:'POST',body:fd});toast(r.message,r.ok?1:0);if(r.ok)e.target.reset()}};const initRiwayat=async()=>{await requireAuth('pegawai');qs('#head').innerHTML=back('Riwayat Absensi');const token=localStorage.getItem('absen_token');const load=async()=>{const d=qs('#fdate').value;const r=await jfetch('api.php?action=attendance_history&token='+token+'&date='+encodeURIComponent(d||''));qs('#list').innerHTML=r.items.map(x=>`<div class="list-item"><div class="row"><strong>${fmtDate(x.work_date)}</strong><span class="status s-info">${x.status}</span></div><div class="row tiny"><span>Masuk</span><strong>${x.checkin_time||'-'}</strong></div><div class="row tiny"><span>Keluar</span><strong>${x.checkout_time||'-'}</strong></div><div class="row tiny"><span>Lokasi</span><strong>${x.checkin_lat?x.checkin_lat+', '+x.checkin_lng:'-'}</strong></div></div>`).join('')||'<div class="notice">Belum ada riwayat untuk filter ini.</div>'};qs('#fdate').onchange=load;load()};const initStatusIzin=async()=>{await requireAuth('pegawai');qs('#navMount').innerHTML=nav('izin');const r=await jfetch('api.php?action=leave_history&token='+localStorage.getItem('absen_token'));qs('#leaveList').innerHTML=r.items.map(x=>`<div class="list-item"><div class="row"><strong>${x.leave_type.toUpperCase()}</strong><span class="status ${x.status==='disetujui'?'s-ok':x.status==='ditolak'?'s-bad':'s-wait'}">${x.status}</span></div><div class="tiny muted">${fmtDate(x.leave_date)}</div><div>${x.reason}</div></div>`).join('')||'<div class="notice">Belum ada pengajuan.</div>'};const initProfile=async()=>{const u=await requireAuth();if(!u)return;qs('#navMount').innerHTML=nav('profile');qs('#pfPhoto').src=u.photo;qs('#pfName').textContent=u.name;qs('#pfRole').textContent=u.position||u.role;qs('#pfPhone').textContent=u.phone||'-';qs('#pfUnit').textContent=u.unit||'-';qs('#logoutBtn').onclick=()=>{localStorage.removeItem('absen_token');location.href='login.html'};qs('#passForm').onsubmit=async e=>{e.preventDefault();const fd=new FormData(e.target);fd.append('token',localStorage.getItem('absen_token'));const r=await jfetch('api.php?action=change_password',{method:'POST',body:fd});toast(r.message,r.ok?1:0);if(r.ok)e.target.reset()};qs('#themeSwitch').classList.toggle('on',S.settings.theme==='dark');qs('#themeSwitch').onclick=()=>{setTheme(S.settings.theme==='dark'?'light':'dark');qs('#themeSwitch').classList.toggle('on',S.settings.theme==='dark')}};const initAdminDash=async()=>{const u=await requireAuth('admin');if(!u)return;qs('#head').innerHTML=back('Dashboard Admin',`<a href="settings.html" class="icon-btn">${I.settings}</a>`);const r=await jfetch('api.php?action=admin_dashboard&token='+localStorage.getItem('absen_token'));qs('#statWrap').innerHTML=`<div class="stat-card"><div class="tiny muted">Total Pegawai</div><div class="num">${r.stats.employees}</div></div><div class="stat-card"><div class="tiny muted">Masuk Hari Ini</div><div class="num">${r.stats.checkins}</div></div><div class="stat-card"><div class="tiny muted">Keluar Hari Ini</div><div class="num">${r.stats.checkouts}</div></div><div class="stat-card"><div class="tiny muted">Izin Aktif</div><div class="num">${r.stats.leaves}</div></div>`;qs('#latest').innerHTML=r.latest.map(x=>`<div class="list-item"><div class="row"><strong>${x.actor_name}</strong><span class="tiny muted">${x.created_at}</span></div><div>${x.action}</div></div>`).join('');};const initPegawaiAdmin=async()=>{await requireAuth('admin');qs('#head').innerHTML=back('Data Pegawai');const r=await jfetch('api.php?action=employees&token='+localStorage.getItem('absen_token'));qs('#items').innerHTML=r.items.map(x=>`<div class="list-item"><div class="row"><div><strong>${x.name}</strong><div class="tiny muted">${x.position}</div></div><span class="status s-info">${x.unit||'Unit'}</span></div><div class="tiny muted">${x.phone||'-'}</div></div>`).join('')};const initAbsensiAdmin=async()=>{await requireAuth('admin');qs('#head').innerHTML=back('Data Absensi');const load=async()=>{const d=qs('#fdate').value;const r=await jfetch('api.php?action=admin_attendance&token='+localStorage.getItem('absen_token')+'&date='+encodeURIComponent(d||''));qs('#tbl').innerHTML=r.items.map(x=>`<tr><td>${x.name}</td><td>${x.work_date}</td><td>${x.checkin_time||'-'}</td><td>${x.checkout_time||'-'}</td><td>${x.distance_m||'-'} m</td></tr>`).join('')};qs('#fdate').onchange=load;load()};const initGps=async()=>{await requireAuth('admin');qs('#head').innerHTML=back('Pengaturan GPS');const token=localStorage.getItem('absen_token');const r=await jfetch('api.php?action=gps_settings&token='+token);['office_lat','office_lng','radius_m'].forEach(k=>qs('[name='+k+']').value=r.item[k]);qs('#gpsForm').onsubmit=async e=>{e.preventDefault();const fd=new FormData(e.target);fd.append('token',token);const x=await jfetch('api.php?action=save_gps',{method:'POST',body:fd});toast(x.message,x.ok?1:0)}};const initLaporan=async()=>{await requireAuth('admin');qs('#head').innerHTML=back('Laporan');qs('#btnBackup').onclick=async()=>{const r=await jfetch('api.php?action=backup&token='+localStorage.getItem('absen_token'));const a=document.createElement('a');a.href='data:application/json;base64,'+r.payload;a.download='backup-absensi.json';a.click()};qs('#restoreForm').onsubmit=async e=>{e.preventDefault();const f=qs('#backupFile').files[0];if(!f)return toast('Pilih file backup dulu',0);const txt=await f.text();const fd=new FormData();fd.append('token',localStorage.getItem('absen_token'));fd.append('payload',btoa(unescape(encodeURIComponent(txt))));const r=await jfetch('api.php?action=restore',{method:'POST',body:fd});toast(r.message,r.ok?1:0)}};const initSettings=async()=>{await requireAuth('admin');qs('#head').innerHTML=back('Settings');const sw=qs('#themeSwitch');sw.classList.toggle('on',S.settings.theme==='dark');sw.onclick=()=>{setTheme(S.settings.theme==='dark'?'light':'dark');sw.classList.toggle('on',S.settings.theme==='dark')}};const initAdminRoot=async()=>{const u=await requireAuth('admin');if(!u)return;location.href='dashboard-admin.html'};const initAll=()=>{applyTheme();fillIcons();const p=page();({'landing':initLanding,'login':initLogin,'home':initHome,'absen':initAbsen,'pengajuan':initPengajuan,'riwayat':initRiwayat,'statusizin':initStatusIzin,'profile':initProfile,'adminroot':initAdminRoot,'admindash':initAdminDash,'pegawaiadmin':initPegawaiAdmin,'absensiadm':initAbsensiAdmin,'gps':initGps,'laporan':initLaporan,'settings':initSettings}[p]||(()=>{}))()};return{initAll,icon:I,setTheme}})();document.addEventListener('DOMContentLoaded',A.initAll);
