from pathlib import Path


html = r'''<!DOCTYPE html>

<html lang="th">

<head>

  <meta charset="UTF-8" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />

  <meta name="theme-color" content="#FFD91E" />

  <title>Fieldmate — แพลตฟอร์มข้อมูลภาคสนาม</title>


  <!-- Leaflet: แผนที่ OpenStreetMap แบบไม่ต้องใช้ API Key -->

  <link

    rel="stylesheet"

    href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"

    integrity="sha256-p4NxAoJBhIINfQ3ynh1Z7ZtY1t0zT0kG2x9w4V0aA6M="

    crossorigin=""

  />

  <script

    src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"

    integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="

    crossorigin=""

  ></script>


  <style>

    :root{

      --yellow:#FFD91E;

      --yellow-soft:#FFF7C2;

      --ink:#241918;

      --ink-2:#443A38;

      --bg:#F5F6F7;

      --card:#FFFFFF;

      --line:#E7E3E1;

      --muted:#746D6A;

      --success:#20865A;

      --danger:#C73B32;

      --warning:#E67E22;

      --info:#2D6CDF;

      --shadow:0 12px 32px rgba(36,25,24,.08);

      --radius:20px;

      --sidebar:250px;

    }


    *{box-sizing:border-box}

    html{scroll-behavior:smooth}

    body{

      margin:0;

      font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans Thai",Tahoma,sans-serif;

      color:var(--ink);

      background:var(--bg);

      min-height:100vh;

    }

    button,input,select,textarea{font:inherit}

    button{cursor:pointer}

    a{color:inherit;text-decoration:none}

    .hidden{display:none!important}

    .muted{color:var(--muted)}

    .tiny{font-size:12px}

    .small{font-size:14px}

    .stack{display:flex;flex-direction:column;gap:12px}

    .row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}

    .spread{display:flex;justify-content:space-between;align-items:center;gap:12px}

    .nowrap{white-space:nowrap}

    .danger-text{color:var(--danger)}

    .success-text{color:var(--success)}

    .warning-text{color:var(--warning)}

    .info-text{color:var(--info)}

    .full{width:100%}


    .app-shell{

      display:grid;

      grid-template-columns:var(--sidebar) 1fr;

      min-height:100vh;

    }


    .sidebar{

      position:fixed;

      inset:0 auto 0 0;

      width:var(--sidebar);

      padding:20px 14px;

      background:var(--ink);

      color:#fff;

      z-index:50;

      display:flex;

      flex-direction:column;

      gap:20px;

    }


    .brand{

      display:flex;

      gap:12px;

      align-items:center;

      padding:6px 8px 16px;

      border-bottom:1px solid rgba(255,255,255,.12);

    }


    .brand-mark{

      width:42px;height:42px;border-radius:14px;

      background:var(--yellow);

      color:var(--ink);

      display:grid;place-items:center;

      font-size:24px;font-weight:900;

      box-shadow:inset 0 -4px 0 rgba(0,0,0,.08);

    }


    .brand h1{font-size:20px;margin:0}

    .brand p{margin:2px 0 0;color:#BFB7B5;font-size:12px}


    .nav{display:flex;flex-direction:column;gap:5px;overflow:auto}

    .nav button{

      border:0;background:transparent;color:#DDD6D3;

      display:flex;align-items:center;gap:12px;

      padding:12px 14px;border-radius:14px;text-align:left;

      transition:.2s;

    }

    .nav button:hover,.nav button.active{

      background:var(--yellow);color:var(--ink);font-weight:700;

    }

    .nav .icon{width:24px;text-align:center;font-size:18px}

    .sidebar-footer{

      margin-top:auto;

      background:rgba(255,255,255,.08);

      border:1px solid rgba(255,255,255,.1);

      padding:12px;border-radius:16px;

      font-size:13px;color:#D8D0CE;

    }


    main{

      grid-column:2;

      min-width:0;

      padding:24px 28px 100px;

    }


    .topbar{

      position:sticky;top:0;z-index:35;

      background:rgba(245,246,247,.88);

      backdrop-filter:blur(14px);

      display:flex;justify-content:space-between;align-items:center;

      padding:8px 0 18px;

      margin-bottom:8px;

    }


    .page-title h2{margin:0;font-size:28px;line-height:1.2}

    .page-title p{margin:6px 0 0;color:var(--muted)}

    .top-actions{display:flex;align-items:center;gap:10px}

    .avatar{

      width:42px;height:42px;border-radius:50%;

      display:grid;place-items:center;background:var(--ink);color:#fff;font-weight:800;

    }


    .btn{

      border:1px solid var(--line);

      background:#fff;color:var(--ink);

      border-radius:14px;padding:11px 16px;

      display:inline-flex;align-items:center;justify-content:center;

      gap:8px;font-weight:700;min-height:44px;

      transition:.18s ease;

    }

    .btn:hover{transform:translateY(-1px);box-shadow:0 6px 14px rgba(36,25,24,.08)}

    .btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none}

    .btn-primary{background:var(--yellow);border-color:var(--yellow)}

    .btn-dark{background:var(--ink);border-color:var(--ink);color:#fff}

    .btn-danger{background:var(--danger);border-color:var(--danger);color:#fff}

    .btn-soft{background:var(--yellow-soft);border-color:#F4ECA5}

    .btn-ghost{background:transparent}

    .btn-sm{padding:8px 11px;min-height:36px;border-radius:11px;font-size:13px}

    .icon-btn{

      width:44px;height:44px;border-radius:14px;

      border:1px solid var(--line);background:#fff;

      display:grid;place-items:center;

    }


    .page{display:none;animation:fade .22s ease}

    .page.active{display:block}

    @keyframes fade{from{opacity:.3;transform:translateY(4px)}to{opacity:1;transform:none}}


    .grid{display:grid;gap:16px}

    .grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}

    .grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}

    .grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}

    .grid-6{grid-template-columns:repeat(6,minmax(0,1fr))}

    .dashboard-grid{grid-template-columns:1.4fr .8fr}

    .content-sidebar{grid-template-columns:minmax(0,1fr) 380px}


    .card{

      background:var(--card);

      border:1px solid var(--line);

      border-radius:var(--radius);

      box-shadow:var(--shadow);

      padding:18px;

      min-width:0;

    }

    .card.flat{box-shadow:none}

    .card h3{margin:0 0 4px;font-size:18px}

    .card-title{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:14px}


    .hero{

      background:var(--ink);

      color:#fff;

      padding:26px;

      border-radius:26px;

      position:relative;

      overflow:hidden;

    }

    .hero:after{

      content:"";

      position:absolute;right:-40px;top:-70px;

      width:220px;height:220px;border-radius:50%;

      background:var(--yellow);opacity:.16;

    }

    .hero h2{font-size:28px;margin:0 0 8px}

    .hero p{color:#D7CFCD;max-width:650px;margin:0 0 20px}

    .hero .btn{position:relative;z-index:2}


    .stat-card{padding:16px;box-shadow:none}

    .stat-card .label{font-size:13px;color:var(--muted)}

    .stat-card .value{font-size:28px;font-weight:850;margin:7px 0 3px}

    .stat-card .delta{font-size:12px}

    .stat-card.warning{border-left:5px solid var(--warning)}

    .stat-card.success{border-left:5px solid var(--success)}

    .stat-card.info{border-left:5px solid var(--info)}

    .stat-card.yellow{border-left:5px solid var(--yellow)}


    .quick-actions{

      display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;

    }

    .quick{

      border:1px solid var(--line);

      background:#fff;border-radius:16px;

      padding:15px;text-align:left;

      min-height:90px;

    }

    .quick:hover{border-color:var(--yellow);background:#FFFDF2}

    .quick .qicon{font-size:24px;margin-bottom:10px}

    .quick strong{display:block}

    .quick span{color:var(--muted);font-size:12px}


    .map{

      width:100%;

      min-height:460px;

      border-radius:18px;

      overflow:hidden;

      background:

        linear-gradient(135deg,#EBECEE 25%,transparent 25%) -20px 0/40px 40px,

        linear-gradient(225deg,#EBECEE 25%,transparent 25%) -20px 0/40px 40px,

        linear-gradient(315deg,#EBECEE 25%,transparent 25%) 0 0/40px 40px,

        linear-gradient(45deg,#EBECEE 25%,#F7F7F7 25%) 0 0/40px 40px;

    }

    .map.small{min-height:300px}

    .map-fallback{

      min-height:300px;display:grid;place-items:center;text-align:center;padding:24px;color:var(--muted);

    }


    .toolbar{

      display:flex;gap:10px;flex-wrap:wrap;margin-bottom:14px;

    }

    .input,.select,.textarea{

      width:100%;border:1px solid var(--line);background:#fff;

      border-radius:13px;padding:12px 13px;color:var(--ink);

      outline:none;min-height:44px;

    }

    .input:focus,.select:focus,.textarea:focus{border-color:#B6A100;box-shadow:0 0 0 3px rgba(255,217,30,.2)}

    .textarea{min-height:100px;resize:vertical}

    .field label{display:block;font-size:13px;font-weight:700;margin:0 0 7px}

    .field small{display:block;color:var(--muted);margin-top:5px}

    .field-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}

    .field-grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}


    .searchbox{position:relative;flex:1;min-width:240px}

    .searchbox input{padding-left:42px}

    .searchbox:before{content:"⌕";position:absolute;left:15px;top:10px;font-size:22px;color:var(--muted)}


    .chip{

      display:inline-flex;align-items:center;gap:6px;

      border-radius:999px;padding:6px 10px;font-size:12px;font-weight:700;

      background:#F0EFEE;color:var(--ink-2);

    }

    .chip.green{background:#E6F5EE;color:var(--success)}

    .chip.red{background:#FBE9E7;color:var(--danger)}

    .chip.orange{background:#FFF0DF;color:#A75400}

    .chip.blue{background:#E9F0FF;color:var(--info)}

    .chip.yellow{background:var(--yellow-soft);color:#6B5E00}


    .list{display:flex;flex-direction:column;gap:10px}

    .list-item{

      border:1px solid var(--line);border-radius:16px;padding:14px;

      background:#fff;

    }

    .list-item:hover{border-color:#D8CB66}

    .record-card{

      display:grid;grid-template-columns:88px 1fr auto;gap:14px;align-items:center;

    }

    .thumb{

      width:88px;height:72px;border-radius:12px;object-fit:cover;background:#ECE8E6;

    }

    .record-card h4{margin:0 0 5px}

    .record-card p{margin:3px 0;color:var(--muted);font-size:13px}

    .meta{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}


    table{width:100%;border-collapse:collapse}

    th,td{text-align:left;padding:13px 10px;border-bottom:1px solid var(--line);font-size:14px;vertical-align:top}

    th{color:var(--muted);font-size:12px;text-transform:none}

    tr:hover td{background:#FFFDF3}


    .stepper{display:flex;gap:8px;overflow:auto;padding:2px 2px 14px}

    .step{

      min-width:135px;padding:10px 12px;border-radius:12px;border:1px solid var(--line);

      background:#fff;color:var(--muted);font-size:12px;font-weight:700;

    }

    .step.active{background:var(--yellow);color:var(--ink);border-color:var(--yellow)}

    .step.done{background:#EAF7F0;color:var(--success);border-color:#BFE3D0}

    .step-panel{display:none}

    .step-panel.active{display:block}

    .step-actions{display:flex;justify-content:space-between;gap:10px;margin-top:20px}


    .camera-box{

      background:#121212;border-radius:18px;overflow:hidden;min-height:320px;

      position:relative;display:grid;place-items:center;color:#fff;

    }

    video{width:100%;max-height:500px;object-fit:cover}

    .camera-active{

      position:absolute;top:12px;left:12px;

      background:rgba(199,59,50,.92);padding:7px 10px;border-radius:999px;font-size:12px;

    }

    .photo-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}

    .photo-item{position:relative;border-radius:14px;overflow:hidden;border:1px solid var(--line);background:#eee}

    .photo-item img{width:100%;height:110px;object-fit:cover;display:block}

    .photo-item button{position:absolute;top:6px;right:6px;border:0;background:rgba(0,0,0,.65);color:#fff;border-radius:50%;width:28px;height:28px}

    .photo-item .cover{position:absolute;bottom:6px;left:6px;background:var(--yellow);padding:4px 7px;border-radius:999px;font-size:11px;font-weight:800}


    .warning-card{border-left:5px solid var(--warning)}

    .warning-card.high{border-left-color:var(--danger)}

    .warning-card.normal{border-left-color:var(--info)}


    .progress{height:8px;border-radius:999px;background:#E9E7E5;overflow:hidden}

    .progress span{display:block;height:100%;background:var(--yellow)}


    .storage-visual{

      border-radius:24px;

      padding:24px;

      background:linear-gradient(180deg,#2E2523,#241918);

      color:#fff;position:relative;overflow:hidden;

    }

    .storage-visual:after{

      content:"";

      position:absolute;inset:auto -20px -60px auto;

      width:200px;height:200px;border-radius:50%;

      background:var(--yellow);opacity:.13;

    }

    .storage-meter{

      height:18px;border-radius:999px;background:rgba(255,255,255,.14);overflow:hidden;margin:16px 0 8px

    }

    .storage-meter span{display:block;height:100%;width:63%;background:var(--yellow)}

    .folder-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}

    .folder{

      border:1px solid var(--line);background:#fff;border-radius:17px;padding:16px;

    }

    .folder .folder-icon{font-size:28px}

    .folder strong{display:block;margin:8px 0 4px}

    .folder small{color:var(--muted)}


    .bottom-nav{

      display:none;

      position:fixed;bottom:0;left:0;right:0;z-index:60;

      background:#fff;border-top:1px solid var(--line);

      padding:8px 8px calc(8px + env(safe-area-inset-bottom));

      grid-template-columns:repeat(5,1fr);

      box-shadow:0 -8px 24px rgba(36,25,24,.08);

    }

    .bottom-nav button{

      border:0;background:transparent;color:var(--muted);

      font-size:11px;display:flex;flex-direction:column;align-items:center;gap:4px;

      padding:5px;

    }

    .bottom-nav button.active{color:var(--ink);font-weight:800}

    .bottom-nav .add-mobile{

      width:52px;height:52px;border-radius:18px;background:var(--yellow);

      color:var(--ink);font-size:24px;margin-top:-22px;box-shadow:0 8px 18px rgba(0,0,0,.18);

    }


    .modal{

      position:fixed;inset:0;background:rgba(24,18,17,.62);

      z-index:100;display:none;align-items:center;justify-content:center;padding:18px;

    }

    .modal.open{display:flex}

    .modal-card{

      width:min(720px,100%);max-height:92vh;overflow:auto;

      background:#fff;border-radius:24px;padding:20px;box-shadow:0 30px 80px rgba(0,0,0,.28);

    }

    .modal-card.wide{width:min(1000px,100%)}

    .modal-header{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:16px}

    .modal-header h3{margin:0}


    .toast{

      position:fixed;right:22px;bottom:24px;z-index:200;

      padding:13px 16px;background:var(--ink);color:#fff;

      border-radius:14px;box-shadow:var(--shadow);display:none;max-width:360px;

    }

    .toast.show{display:block;animation:toastIn .2s ease}

    @keyframes toastIn{from{transform:translateY(14px);opacity:0}to{transform:none;opacity:1}}


    .offline-banner{

      display:none;background:#FFF0DF;color:#884600;border:1px solid #F3C89B;

      padding:10px 14px;border-radius:14px;margin-bottom:14px;

    }

    .offline-banner.show{display:block}


    .alert{

      padding:13px 14px;border-radius:14px;border:1px solid;

      background:#fff;margin:10px 0;

    }

    .alert.warning{border-color:#F0C48B;background:#FFF8EF}

    .alert.danger{border-color:#EDB5B0;background:#FFF2F1}

    .alert.success{border-color:#BCE0CD;background:#EFFAF4}

    .alert.info{border-color:#BFD0F3;background:#F3F7FF}


    @media(max-width:1180px){

      .grid-6{grid-template-columns:repeat(3,1fr)}

      .grid-4{grid-template-columns:repeat(2,1fr)}

      .dashboard-grid,.content-sidebar{grid-template-columns:1fr}

      .folder-grid{grid-template-columns:repeat(2,1fr)}

    }


    @media(max-width:820px){

      :root{--sidebar:0px}

      .app-shell{display:block}

      .sidebar{display:none}

      main{padding:16px 14px 105px}

      .topbar{padding:8px 0 14px}

      .topbar .page-title p{display:none}

      .top-actions .btn{display:none}

      .page-title h2{font-size:22px}

      .bottom-nav{display:grid}

      .grid-2,.grid-3,.grid-4,.grid-6{grid-template-columns:1fr}

      .quick-actions{grid-template-columns:repeat(2,1fr)}

      .field-grid,.field-grid-3{grid-template-columns:1fr}

      .record-card{grid-template-columns:72px 1fr}

      .record-card .record-actions{grid-column:1/-1;display:flex;gap:8px}

      .thumb{width:72px;height:64px}

      .photo-grid{grid-template-columns:repeat(2,1fr)}

      .folder-grid{grid-template-columns:repeat(2,1fr)}

      .hero{padding:22px}

      .hero h2{font-size:24px}

      table{display:block;overflow:auto}

      .map{min-height:380px}

    }


    @media(max-width:470px){

      .quick-actions{grid-template-columns:1fr 1fr}

      .folder-grid{grid-template-columns:1fr 1fr}

      .card{padding:14px;border-radius:17px}

      .btn{padding:10px 12px}

    }

  </style>

</head>


<body>

<div class="app-shell">

  <aside class="sidebar">

    <div class="brand">

      <div class="brand-mark">F</div>

      <div>

        <h1>Fieldmate</h1>

        <p>Central Field Data Platform</p>

      </div>

    </div>


    <nav class="nav" id="desktopNav">

      <button class="active" data-page="dashboard"><span class="icon">⌂</span>ภาพรวม</button>

      <button data-page="map"><span class="icon">⌖</span>แผนที่ข้อมูล</button>

      <button data-page="search"><span class="icon">⌕</span>ค้นหาข้อมูล</button>

      <button data-page="add"><span class="icon">+</span>เพิ่มข้อมูล</button>

      <button data-page="storage"><span class="icon">▣</span>คลังข้อมูลกลาง</button>

      <button data-page="team"><span class="icon">♙</span>งานของทีม</button>

      <button data-page="safety"><span class="icon">⚠</span>แจ้งเตือนพื้นที่</button>

      <button data-page="nearby"><span class="icon">☕</span>พักไหนดีใกล้ฉัน</button>

      <button data-page="reports"><span class="icon">▥</span>รายงาน</button>

    </nav>


    <div class="sidebar-footer">

      <strong>สถานะระบบ</strong>

      <div class="row" style="margin-top:8px">

        <span style="width:9px;height:9px;border-radius:50%;background:#5DD39E"></span>

        <span id="syncStatusSidebar">เชื่อมต่อและ Sync แล้ว</span>

      </div>

    </div>

  </aside>


  <main>

    <div id="offlineBanner" class="offline-banner">

      คุณกำลังใช้งานแบบ Offline ข้อมูลใหม่จะถูกเก็บในอุปกรณ์และ Sync เมื่อกลับมาออนไลน์

    </div>


    <header class="topbar">

      <div class="page-title">

        <h2 id="topPageTitle">ภาพรวม</h2>

        <p id="topPageSubtitle">ข้อมูลภาคสนามของทีมในที่เดียว</p>

      </div>

      <div class="top-actions">

        <button class="btn btn-primary" onclick="openPage('add')">+ เพิ่มข้อมูลภาคสนาม</button>

        <button class="icon-btn" title="แจ้งเตือน">🔔</button>

        <div class="avatar">ปอ</div>

      </div>

    </header>


    <!-- DASHBOARD -->

    <section class="page active" id="page-dashboard">

      <div class="hero">

        <h2>สวัสดี คุณปอ 👋</h2>

        <p id="todayText">พร้อมออกสำรวจวันนี้หรือยัง ตรวจสอบข้อมูลเดิม จุดที่ต้องระวัง และงานที่ได้รับมอบหมายก่อนเดินทาง</p>

        <div class="row">

          <button class="btn btn-primary" onclick="openPage('add')">+ เพิ่มข้อมูลภาคสนาม</button>

          <button class="btn btn-ghost" style="color:#fff;border-color:rgba(255,255,255,.25)" onclick="requestLocationWithExplanation()">⌖ ใช้ตำแหน่งปัจจุบัน</button>

        </div>

      </div>


      <div class="grid grid-6" style="margin-top:16px">

        <div class="card stat-card yellow"><div class="label">ข้อมูลภาคสนามทั้งหมด</div><div class="value" id="statAll">248</div><div class="delta">รายการในคลังกลาง</div></div>

        <div class="card stat-card success"><div class="label">เพิ่มใหม่เดือนนี้</div><div class="value">32</div><div class="delta success-text">+12% จากเดือนก่อน</div></div>

        <div class="card stat-card warning"><div class="label">ข้อมูลที่อาจซ้ำ</div><div class="value">6</div><div class="delta warning-text">รอตรวจสอบ</div></div>

        <div class="card stat-card info"><div class="label">ควรสำรวจซ้ำ</div><div class="value">18</div><div class="delta info-text">เกิน 6 เดือน</div></div>

        <div class="card stat-card warning"><div class="label">จุดที่ต้องระวัง</div><div class="value">12</div><div class="delta danger-text">3 จุดเสี่ยงสูง</div></div>

        <div class="card stat-card success"><div class="label">ป้องกันการลงพื้นที่ซ้ำ</div><div class="value">24</div><div class="delta success-text">ครั้ง</div></div>

      </div>


      <div class="card" style="margin-top:16px">

        <div class="card-title"><div><h3>ทางลัดสำหรับงานภาคสนาม</h3><div class="muted small">กดใช้งานได้ทันที</div></div></div>

        <div class="quick-actions">

          <button class="quick" onclick="openCameraPermissionModal()"><div class="qicon">📷</div><strong>ถ่ายรูปป้าย</strong><span>เปิดกล้องของอุปกรณ์</span></button>

          <button class="quick" onclick="requestLocationWithExplanation()"><div class="qicon">📍</div><strong>ใช้ตำแหน่งปัจจุบัน</strong><span>ค้นหาข้อมูลรอบตัว</span></button>

          <button class="quick" onclick="searchNearMe()"><div class="qicon">🔎</div><strong>ค้นหาข้อมูลใกล้ฉัน</strong><span>ภายใน 250 เมตร</span></button>

          <button class="quick" onclick="openPage('safety')"><div class="qicon">⚠️</div><strong>ดูจุดที่ต้องระวัง</strong><span>ตรวจสอบก่อนเดินทาง</span></button>

          <button class="quick" onclick="openPage('team')"><div class="qicon">✅</div><strong>ดูงานที่ได้รับมอบหมาย</strong><span>3 งานวันนี้</span></button>

          <button class="quick" onclick="openPage('nearby')"><div class="qicon">🍜</div><strong>ดูร้านอาหารใกล้เคียง</strong><span>สำหรับพักระหว่างงาน</span></button>

        </div>

      </div>


      <div class="grid dashboard-grid" style="margin-top:16px">

        <div class="card">

          <div class="card-title">

            <div><h3>ข้อมูลรอบพื้นที่</h3><div class="muted small" id="locationSummary">ยังไม่ได้ใช้ตำแหน่งปัจจุบัน</div></div>

            <button class="btn btn-sm" onclick="openPage('map')">เปิด Smart Map</button>

          </div>

          <div id="dashboardMap" class="map small"></div>

        </div>

        <div class="stack">

          <div class="card">

            <div class="card-title"><h3>งานที่ครบกำหนดวันนี้</h3><span class="chip red">3 งาน</span></div>

            <div class="list" id="dashboardTasks"></div>

          </div>

          <div class="card">

            <div class="card-title"><h3>จุดเตือนล่าสุด</h3><button class="btn btn-sm" onclick="openPage('safety')">ดูทั้งหมด</button></div>

            <div class="list" id="dashboardWarnings"></div>

          </div>

        </div>

      </div>


      <div class="grid grid-2" style="margin-top:16px">

        <div class="card">

          <div class="card-title"><h3>กิจกรรมล่าสุดของทีม</h3></div>

          <div class="list" id="teamActivity"></div>

        </div>

        <div class="card">

          <div class="card-title">

            <div><h3>คลังข้อมูลกลาง</h3><div class="muted small">สถานะพื้นที่จัดเก็บและ Sync</div></div>

            <button class="btn btn-sm btn-soft" onclick="openPage('storage')">เปิดคลัง</button>

          </div>

          <div class="spread"><span>พื้นที่ใช้งาน</span><strong>63%</strong></div>

          <div class="progress" style="margin:10px 0 14px"><span style="width:63%"></span></div>

          <div class="grid grid-3">

            <div><strong>2,184</strong><div class="tiny muted">รูปภาพ</div></div>

            <div><strong>164</strong><div class="tiny muted">เอกสาร</div></div>

            <div><strong id="pendingSyncCount">0</strong><div class="tiny muted">รอ Sync</div></div>

          </div>

        </div>

      </div>

    </section>


    <!-- MAP -->

    <section class="page" id="page-map">

      <div class="card">

        <div class="toolbar">

          <div class="searchbox"><input id="mapSearchInput" class="input" placeholder="ค้นหาสถานที่ เลขที่โฉนด เบอร์โทร ชื่อโครงการ หรือรหัสรายการ"></div>

          <button class="btn btn-primary" onclick="filterMapRecords()">ค้นหา</button>

          <button class="btn" onclick="recenterMap()">⌖ ตำแหน่งฉัน</button>

          <button class="btn" id="trackingBtn" onclick="toggleTracking()">▶ เริ่มติดตาม</button>

          <button class="btn" onclick="fitAllMarkers()">ขยายให้เห็นทั้งหมด</button>

        </div>


        <div class="grid grid-4" style="margin-bottom:14px">

          <select class="select" id="mapPropertyFilter" onchange="filterMapRecords()">

            <option value="">ทุกประเภททรัพย์</option>

            <option>บ้านเดี่ยว</option><option>ทาวน์โฮม</option><option>คอนโดมิเนียม</option>

            <option>ที่ดินเปล่า</option><option>อาคารพาณิชย์</option><option>โรงงาน</option>

          </select>

          <select class="select" id="mapStatusFilter" onchange="filterMapRecords()">

            <option value="">ทุกสถานะ</option>

            <option>ข้อมูลใหม่</option><option>ยืนยันแล้ว</option><option>ควรสำรวจซ้ำ</option><option>อาจซ้ำ</option><option>ฉบับร่าง</option>

          </select>

          <select class="select" id="mapWarningFilter" onchange="filterMapRecords()">

            <option value="">จุดเตือนทุกประเภท</option>

            <option>สุนัขดุ</option><option>ทางเข้าแคบ</option><option>น้ำท่วม</option><option>ถนนชำรุด</option>

          </select>

          <select class="select" id="mapPlaceFilter" onchange="renderMapMarkers()">

            <option value="">ไม่แสดงสถานที่ใกล้เคียง</option>

            <option>ร้านอาหาร</option><option>ร้านกาแฟ</option><option>ร้านสะดวกซื้อ</option>

            <option>ห้องน้ำ</option><option>ปั๊มน้ำมัน</option><option>ATM</option>

          </select>

        </div>


        <div class="row" style="margin-bottom:10px">

          <span class="chip blue" id="gpsChip">GPS: ยังไม่เชื่อมต่อ</span>

          <span class="chip" id="accuracyChip">ความแม่นยำ: —</span>

          <span class="chip" id="updateChip">อัปเดตล่าสุด: —</span>

        </div>


        <div class="grid content-sidebar">

          <div id="mainMap" class="map"></div>

          <aside class="card flat" id="mapSidePanel">

            <h3>เลือกหมุดบนแผนที่</h3>

            <p class="muted">คลิกหมุดข้อมูล จุดเตือน หรือสถานที่ใกล้เคียงเพื่อดูรายละเอียด</p>

          </aside>

        </div>

      </div>

    </section>


    <!-- SEARCH -->

    <section class="page" id="page-search">

      <div class="card">

        <div class="toolbar">

          <div class="searchbox"><input id="centralSearchInput" class="input" placeholder="ค้นหาที่อยู่ รหัสรายการ โฉนด เบอร์โทร โครงการ เจ้าหน้าที่ หรือหมายเหตุ" oninput="renderSearchResults()"></div>

          <select class="select" style="max-width:200px" id="searchSort" onchange="renderSearchResults()">

            <option value="latest">ล่าสุด</option>

            <option value="nearest">ใกล้ที่สุด</option>

            <option value="oldest">อัปเดตเก่าสุด</option>

          </select>

          <button class="btn" onclick="exportRecords()">⇩ Export CSV</button>

        </div>


        <div class="grid grid-4" style="margin-bottom:15px">

          <select class="select" id="searchType" onchange="renderSearchResults()">

            <option value="">ทุกประเภททรัพย์</option>

            <option>บ้านเดี่ยว</option><option>ทาวน์โฮม</option><option>คอนโดมิเนียม</option><option>ที่ดินเปล่า</option>

          </select>

          <select class="select" id="searchArea" onchange="renderSearchResults()">

            <option value="">ทุกพื้นที่</option>

            <option>บางนา</option><option>ศรีนครินทร์</option><option>ลาดกระบัง</option><option>บางพลี</option><option>สมุทรปราการ</option><option>พระโขนง</option>

          </select>

          <select class="select" id="searchStatus" onchange="renderSearchResults()">

            <option value="">ทุกสถานะ</option>

            <option>ข้อมูลใหม่</option><option>ยืนยันแล้ว</option><option>ควรสำรวจซ้ำ</option><option>อาจซ้ำ</option><option>ฉบับร่าง</option>

          </select>

          <select class="select" id="searchOfficer" onchange="renderSearchResults()">

            <option value="">ผู้บันทึกทุกคน</option>

            <option>คุณปอ</option><option>คุณเมย์</option><option>คุณต้น</option><option>คุณฝน</option>

          </select>

        </div>


        <div class="spread" style="margin-bottom:12px">

          <div><strong id="searchResultCount">0</strong> รายการ</div>

          <div class="muted small">แสดงเบอร์โทรแบบปกปิดในหน้ารายการ</div>

        </div>

        <div id="searchLoading" class="alert info hidden">กำลังค้นหาข้อมูล...</div>

        <div id="searchResults" class="list"></div>

        <div class="row" style="justify-content:center;margin-top:18px">

          <button class="btn btn-sm" onclick="changePage(-1)">ก่อนหน้า</button>

          <span class="chip" id="paginationLabel">หน้า 1</span>

          <button class="btn btn-sm" onclick="changePage(1)">ถัดไป</button>

        </div>

      </div>

    </section>


    <!-- ADD RECORD -->

    <section class="page" id="page-add">

      <div class="stepper" id="stepper">

        <button class="step active" data-step="1">1 ตรวจสอบข้อมูลเดิม</button>

        <button class="step" data-step="2">2 ตำแหน่ง</button>

        <button class="step" data-step="3">3 กล้องและรูป</button>

        <button class="step" data-step="4">4 ข้อมูลทรัพย์</button>

        <button class="step" data-step="5">5 Field Safety</button>

        <button class="step" data-step="6">6 ตรวจข้อมูลซ้ำ</button>

        <button class="step" data-step="7">7 ตรวจสอบและบันทึก</button>

      </div>


      <div class="card">

        <div class="step-panel active" data-step-panel="1">

          <div class="card-title"><div><h3>ตรวจสอบข้อมูลเดิมก่อนลงพื้นที่</h3><div class="muted small">ลดการลงพื้นที่ซ้ำและนำข้อมูลเดิมกลับมาใช้</div></div></div>

          <div class="grid grid-3">

            <div class="field"><label>ระยะค้นหา</label><select id="nearbyDistance" class="select"><option value="50">50 เมตร</option><option value="100">100 เมตร</option><option value="250" selected>250 เมตร</option><option value="500">500 เมตร</option></select></div>

            <div class="field"><label>ค้นหาจากข้อมูล</label><input id="duplicateSearchTerm" class="input" placeholder="เบอร์โทร โฉนด ที่อยู่ หรือชื่อโครงการ"></div>

            <div class="field"><label>&nbsp;</label><button class="btn btn-primary full" onclick="checkExistingRecords()">ค้นหาข้อมูลเดิม</button></div>

          </div>

          <div id="existingCheckInfo" class="alert info">ใช้ตำแหน่งปัจจุบันหรือกรอกข้อมูลเพื่อค้นหารายการเดิม</div>

          <div id="existingRecordResults" class="list"></div>

          <div class="step-actions"><span></span><button class="btn btn-primary" onclick="nextStep()">ยืนยันว่าเป็นจุดใหม่ →</button></div>

        </div>


        <div class="step-panel" data-step-panel="2">

          <div class="card-title"><div><h3>ตำแหน่งสำรวจ</h3><div class="muted small">ตำแหน่งจะถูกบันทึกเมื่อผู้ใช้กดยืนยันเท่านั้น</div></div></div>

          <div class="toolbar">

            <button class="btn btn-primary" onclick="requestLocationWithExplanation()">⌖ ใช้ตำแหน่งปัจจุบัน</button>

            <button class="btn" onclick="toggleTracking()">▶ เริ่มติดตามตำแหน่ง</button>

            <button class="btn" onclick="enableManualPin()">📌 ปักหมุดด้วยตนเอง</button>

          </div>

          <div class="grid grid-3">

            <div class="field"><label>Latitude</label><input id="formLat" class="input" type="number" step="any" value="13.6678"></div>

            <div class="field"><label>Longitude</label><input id="formLng" class="input" type="number" step="any" value="100.6351"></div>

            <div class="field"><label>ความแม่นยำ GPS</label><input id="formAccuracy" class="input" value="ยังไม่มีข้อมูล" readonly></div>

          </div>

          <div id="formMap" class="map small" style="margin-top:14px"></div>

          <div class="field-grid" style="margin-top:14px">

            <div class="field"><label>ที่อยู่</label><input id="formAddress" class="input" placeholder="เลขที่ ซอย ถนน"></div>

            <div class="field"><label>จุดสังเกต</label><input id="formLandmark" class="input" placeholder="เช่น ตรงข้ามปั๊มน้ำมัน"></div>

            <div class="field"><label>จังหวัด</label><input id="formProvince" class="input" value="กรุงเทพมหานคร"></div>

            <div class="field"><label>เขต/อำเภอ</label><input id="formDistrict" class="input" value="บางนา"></div>

            <div class="field"><label>แขวง/ตำบล</label><input id="formSubdistrict" class="input" value="บางนาเหนือ"></div>

            <div class="field"><label>ถนน</label><input id="formRoad" class="input" placeholder="ชื่อถนน"></div>

          </div>

          <div class="field" style="margin-top:14px"><label>หมายเหตุตำแหน่ง</label><textarea id="formLocationNote" class="textarea" placeholder="รายละเอียดทางเข้า จุดสังเกต หรือวิธีเข้าพื้นที่"></textarea></div>

          <div class="step-actions"><button class="btn" onclick="prevStep()">← ย้อนกลับ</button><button class="btn btn-primary" onclick="nextStep()">ใช้ตำแหน่งนี้ →</button></div>

        </div>


        <div class="step-panel" data-step-panel="3">

          <div class="card-title"><div><h3>กล้องและรูปภาพ</h3><div class="muted small">บันทึกป้ายประกาศ สภาพทรัพย์ ทางเข้า ถนน และจุดเสี่ยง</div></div></div>

          <div class="toolbar">

            <button class="btn btn-primary" onclick="openCameraPermissionModal()">📷 เปิดกล้อง</button>

            <label class="btn">🖼 อัปโหลดจากเครื่อง<input id="galleryInput" type="file" accept="image/*" capture="environment" multiple hidden onchange="handleGalleryUpload(event)"></label>

            <select id="photoCategory" class="select" style="max-width:220px">

              <option>ป้ายประกาศ</option><option>ด้านหน้าทรัพย์</option><option>ทางเข้า</option><option>ถนน</option>

              <option>สภาพแวดล้อม</option><option>จุดจอดรถ</option><option>จุดที่ต้องระวัง</option><option>เอกสาร</option><option>อื่น ๆ</option>

            </select>

          </div>

          <div id="photoGrid" class="photo-grid"></div>


          <div class="card flat" style="margin-top:18px;background:#FAFAFA">

            <div class="card-title"><div><h3>OCR จากป้าย — Prototype</h3><div class="muted small">ข้อมูลตัวอย่าง ต้องตรวจสอบและยืนยันก่อนบันทึก</div></div><button class="btn btn-sm" onclick="runMockOCR()">อ่านข้อมูลจากภาพ</button></div>

            <div id="ocrFields" class="field-grid hidden">

              <div class="field"><label>เบอร์โทร <span class="chip yellow">อ่านจากภาพ</span></label><input id="ocrPhone" class="input"></div>

              <div class="field"><label>ราคาที่ประกาศ <span class="chip yellow">อ่านจากภาพ</span></label><input id="ocrPrice" class="input"></div>

              <div class="field"><label>พื้นที่ <span class="chip yellow">อ่านจากภาพ</span></label><input id="ocrArea" class="input"></div>

              <div class="field"><label>ชื่อผู้ติดต่อ <span class="chip yellow">อ่านจากภาพ</span></label><input id="ocrContact" class="input"></div>

            </div>

          </div>

          <div class="step-actions"><button class="btn" onclick="prevStep()">← ย้อนกลับ</button><button class="btn btn-primary" onclick="nextStep()">ถัดไป →</button></div>

        </div>


        <div class="step-panel" data-step-panel="4">

          <div class="card-title"><div><h3>ข้อมูลทรัพย์และข้อมูลภาคสนาม</h3><div class="muted small">ไม่มีการวิเคราะห์หรือประเมินราคาตลาด</div></div></div>

          <div class="field-grid">

            <div class="field"><label>ประเภททรัพย์</label><select id="propertyType" class="select"><option>ที่ดินเปล่า</option><option>บ้านเดี่ยว</option><option>ทาวน์โฮม</option><option>อาคารพาณิชย์</option><option>คอนโดมิเนียม</option><option>โรงงาน</option><option>โกดัง</option><option>อาคารสำนักงาน</option><option>อื่น ๆ</option></select></div>

            <div class="field"><label>เลขที่โฉนด</label><input id="titleDeed" class="input"></div>

            <div class="field"><label>ชื่อโครงการ</label><input id="projectName" class="input"></div>

            <div class="field"><label>พื้นที่ดิน</label><input id="landArea" class="input" placeholder="เช่น 52 ตร.ว."></div>

            <div class="field"><label>พื้นที่ใช้สอย</label><input id="usableArea" class="input" placeholder="เช่น 180 ตร.ม."></div>

            <div class="field"><label>จำนวนชั้น</label><input id="floors" class="input" type="number"></div>

            <div class="field"><label>ห้องนอน</label><input id="bedrooms" class="input" type="number"></div>

            <div class="field"><label>ห้องน้ำ</label><input id="bathrooms" class="input" type="number"></div>

            <div class="field"><label>ราคาที่ประกาศ (ถ้ามี)</label><input id="advertisedPrice" class="input" placeholder="บันทึกตามป้ายหรือผู้ติดต่อเท่านั้น"></div>

            <div class="field"><label>ชื่อผู้ติดต่อ</label><input id="contactName" class="input"></div>

            <div class="field"><label>เบอร์โทร</label><input id="contactPhone" class="input"></div>

            <div class="field"><label>วันที่พบข้อมูล</label><input id="foundDate" class="input" type="date"></div>

            <div class="field"><label>สภาพทรัพย์</label><select id="condition" class="select"><option>สภาพดี</option><option>ใช้งานได้</option><option>ต้องปรับปรุง</option><option>อยู่ระหว่างก่อสร้าง</option><option>ไม่สามารถเข้าตรวจสอบได้</option></select></div>

            <div class="field"><label>สภาพการเข้าถึง</label><select id="accessCondition" class="select"><option>รถยนต์เข้าได้</option><option>ทางเข้าแคบ</option><option>ต้องเดินเข้า</option><option>รถเข้าไม่ได้</option></select></div>

            <div class="field"><label>สภาพถนน</label><select id="roadCondition" class="select"><option>ถนนลาดยาง</option><option>ถนนคอนกรีต</option><option>ถนนลูกรัง</option><option>ถนนชำรุด</option></select></div>

            <div class="field"><label>ที่จอดรถ</label><select id="parking" class="select"><option>มีที่จอด</option><option>จอดริมถนน</option><option>จำกัด</option><option>ไม่มีที่จอด</option></select></div>

            <div class="field"><label>สัญญาณโทรศัพท์</label><select id="mobileSignal" class="select"><option>ดี</option><option>ปานกลาง</option><option>อ่อน</option><option>ไม่มีสัญญาณ</option></select></div>

          </div>

          <div class="field" style="margin-top:14px"><label>หมายเหตุทั่วไป</label><textarea id="generalNotes" class="textarea"></textarea></div>

          <div class="step-actions"><button class="btn" onclick="prevStep()">← ย้อนกลับ</button><button class="btn btn-primary" onclick="nextStep()">ถัดไป →</button></div>

        </div>


        <div class="step-panel" data-step-panel="5">

          <div class="card-title"><div><h3>Field Safety</h3><div class="muted small">บันทึกจุดเสี่ยงและข้อควรระวังให้ทีม</div></div></div>

          <div class="row" id="quickWarnings">

            <button class="btn btn-sm" onclick="setWarning('สุนัขดุ')">🐕 พบสุนัขดุ</button>

            <button class="btn btn-sm" onclick="setWarning('ทางเข้าแคบ')">↔ ทางเข้าแคบ</button>

            <button class="btn btn-sm" onclick="setWarning('ถนนชำรุด')">🚧 ถนนชำรุด</button>

            <button class="btn btn-sm" onclick="setWarning('รถเข้าไม่ได้')">🚫 รถเข้าไม่ได้</button>

            <button class="btn btn-sm" onclick="setWarning('น้ำท่วม')">🌊 น้ำท่วม</button>

            <button class="btn btn-sm" onclick="setWarning('พื้นที่เปลี่ยว')">🌙 พื้นที่เปลี่ยว</button>

            <button class="btn btn-sm" onclick="setWarning('ไม่มีสัญญาณ')">📵 ไม่มีสัญญาณ</button>

            <button class="btn btn-sm" onclick="setWarning('ไม่มีที่จอดรถ')">🅿️ ไม่มีที่จอดรถ</button>

          </div>

          <div class="field-grid" style="margin-top:16px">

            <div class="field"><label>ประเภทจุดเตือน</label><select id="warningType" class="select" onchange="toggleDogFields()"><option value="">ไม่มีจุดเตือน</option><option>สุนัขดุ</option><option>พื้นที่เปลี่ยว</option><option>ทางเข้าแคบ</option><option>ถนนชำรุด</option><option>ถนนลูกรัง</option><option>รถยนต์เข้าไม่ได้</option><option>น้ำท่วม</option><option>พื้นที่ก่อสร้าง</option><option>เสี่ยงอุบัติเหตุ</option><option>ไม่มีสัญญาณโทรศัพท์</option><option>ที่จอดรถจำกัด</option><option>พื้นที่ห้ามเข้า</option><option>อื่น ๆ</option></select></div>

            <div class="field"><label>ระดับความรุนแรง</label><select id="warningSeverity" class="select"><option>ข้อมูลทั่วไป</option><option>ควรระวัง</option><option>เสี่ยงสูง</option></select></div>

            <div class="field"><label>ใช้งานถึงวันที่</label><input id="warningActiveUntil" class="input" type="date"></div>

            <div class="field"><label>การมองเห็น</label><select id="warningVisibility" class="select"><option>เห็นได้ทั้งทีม</option><option>เฉพาะทีมของฉัน</option></select></div>

          </div>

          <div class="field" style="margin-top:14px"><label>รายละเอียด</label><textarea id="warningDescription" class="textarea" placeholder="อธิบายจุดที่พบ เวลา และคำแนะนำ"></textarea></div>

          <div id="dogFields" class="card flat hidden" style="margin-top:14px;background:#FFF8EF">

            <h3>รายละเอียดสุนัขดุ</h3>

            <div class="field-grid" style="margin-top:12px">

              <div class="field"><label>จำนวนสุนัข</label><input id="dogCount" class="input" type="number" min="1"></div>

              <div class="field"><label>สถานะ</label><select id="dogChain" class="select"><option>ไม่ได้ล่าม</option><option>ล่ามอยู่</option><option>ไม่แน่ใจ</option></select></div>

              <div class="field"><label>จุดที่พบ</label><input id="dogLocation" class="input" placeholder="เช่น หน้าประตูรั้ว"></div>

              <div class="field"><label>ช่วงเวลาที่พบ</label><input id="dogTime" class="input" type="time"></div>

            </div>

          </div>

          <div class="step-actions"><button class="btn" onclick="prevStep()">← ย้อนกลับ</button><button class="btn btn-primary" onclick="nextStep()">ตรวจข้อมูลซ้ำ →</button></div>

        </div>


        <div class="step-panel" data-step-panel="6">

          <div class="card-title"><div><h3>ตรวจสอบข้อมูลที่อาจซ้ำ</h3><div class="muted small">ตรวจจาก GPS เบอร์โทร โฉนด ที่อยู่ โครงการ และข้อมูลใกล้เคียง</div></div><button class="btn btn-primary" onclick="runDuplicateDetection()">ตรวจสอบอีกครั้ง</button></div>

          <div id="duplicateDetectionSummary" class="alert info">กด “ตรวจสอบอีกครั้ง” เพื่อค้นหารายการที่อาจเป็นรายการเดียวกัน</div>

          <div id="duplicateMatches" class="list"></div>

          <div class="step-actions"><button class="btn" onclick="prevStep()">← ย้อนกลับ</button><button class="btn btn-primary" onclick="nextStep()">ยืนยันและตรวจทาน →</button></div>

        </div>


        <div class="step-panel" data-step-panel="7">

          <div class="card-title"><div><h3>ตรวจสอบและบันทึก</h3><div class="muted small">ข้อมูลจะเข้าสู่คลังกลางเมื่อคุณกดยืนยัน</div></div></div>

          <div id="reviewSummary"></div>

          <div class="row" style="justify-content:flex-end;margin-top:20px">

            <button class="btn" onclick="saveDraft()">บันทึกเป็นฉบับร่าง</button>

            <button class="btn btn-danger" onclick="resetForm()">ยกเลิก</button>

            <button class="btn btn-primary" onclick="saveRecord()">บันทึกข้อมูล</button>

          </div>

        </div>

      </div>

    </section>


    <!-- STORAGE -->

    <section class="page" id="page-storage">

      <div class="grid grid-2">

        <div class="storage-visual">

          <div class="chip yellow">Central Repository</div>

          <h2 style="margin:14px 0 6px">คลังข้อมูลกลางของทีม</h2>

          <p style="color:#D4CCCA;margin:0">Single Source of Truth สำหรับข้อมูลทรัพย์ รูปภาพ เอกสาร GPS ประวัติสำรวจ งาน และจุดเตือน</p>

          <div class="storage-meter"><span></span></div>

          <div class="spread"><span>ใช้แล้ว 63 GB จาก 100 GB</span><strong>63%</strong></div>

        </div>

        <div class="card">

          <div class="card-title"><h3>สถานะข้อมูล</h3><span class="chip green" id="storageSyncChip">Sync แล้ว</span></div>

          <div class="grid grid-3">

            <div class="stat-card card"><div class="label">รายการข้อมูล</div><div class="value" id="storageRecordCount">248</div></div>

            <div class="stat-card card"><div class="label">รูปภาพ</div><div class="value">2,184</div></div>

            <div class="stat-card card"><div class="label">เอกสาร</div><div class="value">164</div></div>

          </div>

          <div class="alert info" style="margin-top:14px">Prototype นี้จัดเก็บ Draft และรายการที่รอ Sync ใน Local Storage ของ Browser</div>

        </div>

      </div>


      <div class="card" style="margin-top:16px">

        <div class="card-title">

          <div><h3>ถังเก็บข้อมูล</h3><div class="muted small">จัดหมวดข้อมูลเพื่อค้นหาและนำกลับมาใช้ได้ง่าย</div></div>

          <button class="btn btn-primary" onclick="createFolder()">+ สร้างหมวด</button>

        </div>

        <div class="folder-grid" id="folderGrid"></div>

      </div>


      <div class="grid grid-2" style="margin-top:16px">

        <div class="card">

          <div class="card-title"><h3>กิจกรรมล่าสุด</h3><button class="btn btn-sm" onclick="toast('เปิด Activity Timeline แล้ว')">ดูทั้งหมด</button></div>

          <div id="storageActivity" class="list"></div>

        </div>

        <div class="card">

          <div class="card-title"><h3>รายการรอ Sync</h3><button class="btn btn-sm btn-primary" onclick="syncPendingData()">Sync ตอนนี้</button></div>

          <div id="pendingSyncList" class="list"></div>

        </div>

      </div>


      <div class="card" style="margin-top:16px">

        <div class="card-title">

          <div><h3>รายการล่าสุดในคลัง</h3><div class="muted small">รองรับ Version History, Favorite และ Restore ใน Backend จริง</div></div>

          <div class="row">

            <button class="btn btn-sm" onclick="toast('แสดงรายการโปรดแล้ว')">★ รายการโปรด</button>

            <button class="btn btn-sm" onclick="toast('แสดงรายการที่เปิดล่าสุดแล้ว')">ดูล่าสุด</button>

          </div>

        </div>

        <div id="storageTableWrap"></div>

      </div>

    </section>


    <!-- TEAM -->

    <section class="page" id="page-team">

      <div class="grid grid-4">

        <div class="card stat-card yellow"><div class="label">งานของฉัน</div><div class="value">8</div></div>

        <div class="card stat-card info"><div class="label">ลงพื้นที่วันนี้</div><div class="value">5</div></div>

        <div class="card stat-card warning"><div class="label">รอตรวจสอบ</div><div class="value">7</div></div>

        <div class="card stat-card success"><div class="label">เสร็จสิ้นสัปดาห์นี้</div><div class="value">19</div></div>

      </div>

      <div class="card" style="margin-top:16px">

        <div class="card-title">

          <div><h3>งานของทีม</h3><div class="muted small">เปลี่ยนสถานะ มอบหมายงาน และเปิดตำแหน่งได้</div></div>

          <button class="btn btn-primary" onclick="openAssignTaskModal()">+ มอบหมายงาน</button>

        </div>

        <div id="taskTable"></div>

      </div>

    </section>


    <!-- SAFETY -->

    <section class="page" id="page-safety">

      <div id="proximityAlert" class="alert danger hidden"></div>

      <div class="card">

        <div class="toolbar">

          <select id="safetySeverityFilter" class="select" style="max-width:210px" onchange="renderSafetyList()">

            <option value="">ทุกระดับ</option><option>ข้อมูลทั่วไป</option><option>ควรระวัง</option><option>เสี่ยงสูง</option>

          </select>

          <select id="safetyTypeFilter" class="select" style="max-width:210px" onchange="renderSafetyList()">

            <option value="">ทุกประเภท</option><option>สุนัขดุ</option><option>ทางเข้าแคบ</option><option>น้ำท่วม</option><option>ถนนชำรุด</option><option>พื้นที่เปลี่ยว</option>

          </select>

          <select id="safetyActiveFilter" class="select" style="max-width:210px" onchange="renderSafetyList()">

            <option value="">ทั้งหมด</option><option value="active">ยังมีอยู่</option><option value="resolved">แก้ไขแล้ว</option>

          </select>

          <button class="btn btn-primary" onclick="openSafetyModal()">+ เพิ่มจุดเตือน</button>

        </div>

        <div class="grid dashboard-grid">

          <div id="safetyMap" class="map"></div>

          <div>

            <div class="card-title"><div><h3>จุดเตือนใกล้คุณ</h3><div class="muted small">เรียงตามระยะจากตำแหน่งปัจจุบัน</div></div></div>

            <div id="safetyList" class="list" style="max-height:520px;overflow:auto"></div>

          </div>

        </div>

      </div>

    </section>


    <!-- NEARBY -->

    <section class="page" id="page-nearby">

      <div class="hero">

        <h2>พักไหนดีใกล้ฉัน ☕</h2>

        <p>ตัวช่วยหาร้านอาหาร คาเฟ่ ห้องน้ำ ปั๊มน้ำมัน ATM และจุดจอดรถสำหรับเจ้าหน้าที่ภาคสนาม</p>

        <button class="btn btn-primary" onclick="requestLocationWithExplanation()">ใช้ตำแหน่งปัจจุบัน</button>

      </div>

      <div class="card" style="margin-top:16px">

        <div class="toolbar" id="nearbyCategoryButtons"></div>

        <div class="alert info">ข้อมูลสถานที่ใน Prototype เป็นข้อมูลตัวอย่าง สามารถเปลี่ยนเป็น Places API หรือ OpenStreetMap Overpass API ได้ในระบบจริง</div>

        <div class="grid content-sidebar">

          <div id="nearbyMap" class="map"></div>

          <div id="nearbyList" class="list" style="max-height:540px;overflow:auto"></div>

        </div>

      </div>

    </section>


    <!-- REPORTS -->

    <section class="page" id="page-reports">

      <div class="grid grid-4">

        <div class="card stat-card success"><div class="label">ลดเวลาค้นหาข้อมูล</div><div class="value">80%</div></div>

        <div class="card stat-card success"><div class="label">ลดเวลาจัดทำรายงาน</div><div class="value">50%</div></div>

        <div class="card stat-card yellow"><div class="label">ข้อมูลถูกนำกลับมาใช้</div><div class="value">126</div></div>

        <div class="card stat-card info"><div class="label">ป้องกันลงพื้นที่ซ้ำ</div><div class="value">24</div></div>

      </div>

      <div class="grid grid-2" style="margin-top:16px">

        <div class="card">

          <div class="card-title"><h3>ตัวชี้วัดการปฏิบัติงาน</h3></div>

          <table>

            <tbody>

              <tr><td>จำนวนข้อมูลภาคสนาม</td><td><strong>248 รายการ</strong></td></tr>

              <tr><td>ผู้ใช้งานที่ Active</td><td><strong>38 คน</strong></td></tr>

              <tr><td>ข้อมูลที่นำกลับมาใช้</td><td><strong>126 ครั้ง</strong></td></tr>

              <tr><td>รายการซ้ำที่ตรวจพบ</td><td><strong>31 รายการ</strong></td></tr>

              <tr><td>GPS Capture Success Rate</td><td><strong>94%</strong></td></tr>

              <tr><td>Camera Capture Success Rate</td><td><strong>96%</strong></td></tr>

            </tbody>

          </table>

        </div>

        <div class="card">

          <div class="card-title"><h3>จุดเตือนตามประเภท</h3></div>

          <div class="stack">

            <div><div class="spread"><span>สุนัขดุ</span><strong>12</strong></div><div class="progress"><span style="width:75%"></span></div></div>

            <div><div class="spread"><span>ทางเข้าแคบ</span><strong>9</strong></div><div class="progress"><span style="width:58%"></span></div></div>

            <div><div class="spread"><span>ถนนชำรุด</span><strong>7</strong></div><div class="progress"><span style="width:44%"></span></div></div>

            <div><div class="spread"><span>น้ำท่วม</span><strong>5</strong></div><div class="progress"><span style="width:31%"></span></div></div>

            <div><div class="spread"><span>ไม่มีที่จอดรถ</span><strong>3</strong></div><div class="progress"><span style="width:19%"></span></div></div>

          </div>

        </div>

      </div>

      <div class="card" style="margin-top:16px">

        <div class="card-title"><h3>ผลงานของทีม</h3><button class="btn btn-sm" onclick="toast('ดาวน์โหลดรายงานแล้ว')">ดาวน์โหลดรายงาน</button></div>

        <div class="grid grid-4">

          <div class="folder"><strong>คุณปอ</strong><small>46 รายการ · ยืนยัน 38</small></div>

          <div class="folder"><strong>คุณเมย์</strong><small>41 รายการ · ยืนยัน 35</small></div>

          <div class="folder"><strong>คุณต้น</strong><small>37 รายการ · ยืนยัน 29</small></div>

          <div class="folder"><strong>คุณฝน</strong><small>34 รายการ · ยืนยัน 27</small></div>

        </div>

      </div>

    </section>

  </main>

</div>


<nav class="bottom-nav" id="mobileNav">

  <button class="active" data-page="dashboard"><span>⌂</span>ภาพรวม</button>

  <button data-page="map"><span>⌖</span>แผนที่</button>

  <button class="add-mobile" data-page="add">+</button>

  <button data-page="storage"><span>▣</span>คลังกลาง</button>

  <button data-page="team"><span>♙</span>งาน</button>

</nav>


<!-- CAMERA PERMISSION MODAL -->

<div class="modal" id="cameraPermissionModal">

  <div class="modal-card">

    <div class="modal-header"><h3>อนุญาตให้ใช้กล้อง</h3><button class="icon-btn" onclick="closeModal('cameraPermissionModal')">✕</button></div>

    <p>Fieldmate ใช้กล้องเพื่อบันทึกป้ายประกาศ สภาพทรัพย์ ทางเข้า และจุดที่ต้องระวัง</p>

    <div class="alert info">คุณสามารถหยุดกล้องได้ทุกเมื่อ และภาพจะไม่ถูกบันทึกจนกว่าจะกดยืนยัน</div>

    <div class="row" style="justify-content:flex-end">

      <button class="btn" onclick="closeModal('cameraPermissionModal')">ยังไม่อนุญาต</button>

      <button class="btn btn-primary" onclick="startCamera()">อนุญาตและดำเนินการต่อ</button>

    </div>

  </div>

</div>


<!-- CAMERA MODAL -->

<div class="modal" id="cameraModal">

  <div class="modal-card wide">

    <div class="modal-header"><h3>กล้องภาคสนาม</h3><button class="icon-btn" onclick="closeCamera()">✕</button></div>

    <div class="camera-box">

      <div class="camera-active">● กล้องกำลังทำงาน</div>

      <video id="cameraVideo" autoplay playsinline></video>

      <canvas id="cameraCanvas" class="hidden"></canvas>

      <div id="cameraError" class="hidden" style="padding:30px;text-align:center"></div>

    </div>

    <div class="toolbar" style="margin-top:14px;justify-content:center">

      <button class="btn" onclick="switchCamera()">↻ สลับกล้อง</button>

      <button class="btn btn-primary" onclick="capturePhoto()">● ถ่ายภาพ</button>

      <label class="btn">อัปโหลดแทน<input type="file" accept="image/*" capture="environment" hidden onchange="handleCameraFallback(event)"></label>

    </div>

  </div>

</div>


<!-- LOCATION PERMISSION MODAL -->

<div class="modal" id="locationPermissionModal">

  <div class="modal-card">

    <div class="modal-header"><h3>อนุญาตให้ใช้ตำแหน่ง</h3><button class="icon-btn" onclick="closeModal('locationPermissionModal')">✕</button></div>

    <p>Fieldmate ใช้ตำแหน่งของคุณเพื่อค้นหาข้อมูลเดิม ปักหมุดพื้นที่สำรวจ และแจ้งจุดที่ต้องระวังใกล้เคียง</p>

    <div class="alert info">คุณสามารถหยุดการติดตามตำแหน่งได้ทุกเมื่อ และระบบจะไม่ติดตามต่อหลังจากกดหยุด</div>

    <div class="row" style="justify-content:flex-end">

      <button class="btn" onclick="closeModal('locationPermissionModal')">ยังไม่อนุญาต</button>

      <button class="btn btn-primary" onclick="getCurrentLocation()">อนุญาตและดำเนินการต่อ</button>

    </div>

  </div>

</div>


<!-- RECORD DETAIL MODAL -->

<div class="modal" id="recordModal">

  <div class="modal-card wide">

    <div class="modal-header"><h3>รายละเอียดข้อมูลภาคสนาม</h3><button class="icon-btn" onclick="closeModal('recordModal')">✕</button></div>

    <div id="recordDetailContent"></div>

  </div>

</div>


<!-- ASSIGN TASK MODAL -->

<div class="modal" id="assignTaskModal">

  <div class="modal-card">

    <div class="modal-header"><h3>มอบหมายงานสำรวจ</h3><button class="icon-btn" onclick="closeModal('assignTaskModal')">✕</button></div>

    <div class="stack">

      <div class="field"><label>รายการหรือพื้นที่</label><input id="taskRecordInput" class="input" placeholder="เช่น FM-2026-001"></div>

      <div class="field"><label>ผู้รับผิดชอบ</label><select id="taskAssigneeInput" class="select"><option>คุณปอ</option><option>คุณเมย์</option><option>คุณต้น</option><option>คุณฝน</option></select></div>

      <div class="field"><label>วันครบกำหนด</label><input id="taskDueInput" class="input" type="date"></div>

      <div class="field"><label>รายละเอียด</label><textarea id="taskNoteInput" class="textarea"></textarea></div>

      <button class="btn btn-primary" onclick="createTask()">มอบหมายงาน</button>

    </div>

  </div>

</div>


<!-- SAFETY MODAL -->

<div class="modal" id="safetyModal">

  <div class="modal-card">

    <div class="modal-header"><h3>เพิ่มจุดเตือน</h3><button class="icon-btn" onclick="closeModal('safetyModal')">✕</button></div>

    <div class="field-grid">

      <div class="field"><label>ประเภท</label><select id="modalWarningType" class="select"><option>สุนัขดุ</option><option>ทางเข้าแคบ</option><option>น้ำท่วม</option><option>ถนนชำรุด</option><option>พื้นที่เปลี่ยว</option></select></div>

      <div class="field"><label>ระดับ</label><select id="modalWarningSeverity" class="select"><option>ข้อมูลทั่วไป</option><option>ควรระวัง</option><option>เสี่ยงสูง</option></select></div>

      <div class="field"><label>Latitude</label><input id="modalWarningLat" class="input" type="number" step="any"></div>

      <div class="field"><label>Longitude</label><input id="modalWarningLng" class="input" type="number" step="any"></div>

    </div>

    <div class="field" style="margin-top:14px"><label>รายละเอียด</label><textarea id="modalWarningDescription" class="textarea"></textarea></div>

    <button class="btn btn-primary full" style="margin-top:14px" onclick="saveSafetyWarning()">บันทึกจุดเตือน</button>

  </div>

</div>


<div class="toast" id="toast"></div>


<script>

/* =========================================================

   FIELD MATE PROTOTYPE

   - Mock data อยู่ใน JavaScript

   - Draft / Pending Sync ใช้ localStorage

   - จุดเชื่อม Backend จริงควรแทนที่ records, warnings, places, tasks

   ========================================================= */


// ---------- MOCK DATA ----------

const placeholderImages = [

  "https://images.unsplash.com/photo-1564013799919-ab600027ffc6?auto=format&fit=crop&w=600&q=70",

  "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?auto=format&fit=crop&w=600&q=70",

  "https://images.unsplash.com/photo-1600607687939-ce8a6c25118c?auto=format&fit=crop&w=600&q=70",

  "https://images.unsplash.com/photo-1600047509807-ba8f99d2cdde?auto=format&fit=crop&w=600&q=70"

];


let records = [

  {id:"FM-2026-001",type:"บ้านเดี่ยว",area:"บางนา",address:"ซอยบางนา-ตราด 23 เขตบางนา กรุงเทพมหานคร",lat:13.6678,lng:100.6351,price:"7,900,000 บาท",land:"58 ตร.ว.",usable:"210 ตร.ม.",phone:"0892345678",contact:"คุณเอ",surveyDate:"2026-07-12",updated:"2026-07-16",createdBy:"คุณปอ",editedBy:"คุณเมย์",status:"ยืนยันแล้ว",notes:"เข้าทางซอยหลักได้ สภาพทรัพย์ใช้งานได้",access:"รถยนต์เข้าได้",parking:"จอดในบ้าน 2 คัน",signal:"ดี",warnings:["สุนัขดุ"],project:"บ้านสวนบางนา",titleDeed:"12345",images:[placeholderImages[0]],history:["สำรวจครั้งแรก 12 ก.ค. 2569","ยืนยันตำแหน่ง 16 ก.ค. 2569"],comments:["ควรโทรแจ้งก่อนเข้าพื้นที่"]},

  {id:"FM-2026-002",type:"ทาวน์โฮม",area:"ศรีนครินทร์",address:"ถนนศรีนครินทร์ ซอย 42 เขตประเวศ กรุงเทพมหานคร",lat:13.6920,lng:100.6462,price:"",land:"22 ตร.ว.",usable:"120 ตร.ม.",phone:"0817788990",contact:"คุณบี",surveyDate:"2026-07-08",updated:"2026-07-15",createdBy:"คุณเมย์",editedBy:"คุณเมย์",status:"ข้อมูลใหม่",notes:"ทางเข้าโครงการชัดเจน",access:"รถยนต์เข้าได้",parking:"หน้าบ้าน 1 คัน",signal:"ดี",warnings:[],project:"เดอะคอนเนค ศรีนครินทร์",titleDeed:"22348",images:[placeholderImages[1]],history:["สำรวจครั้งแรก 8 ก.ค. 2569"],comments:[]},

  {id:"FM-2026-003",type:"ที่ดินเปล่า",area:"ลาดกระบัง",address:"ถนนหลวงแพ่ง เขตลาดกระบัง กรุงเทพมหานคร",lat:13.7180,lng:100.7802,price:"12,000,000 บาท",land:"2 ไร่ 1 งาน",usable:"-",phone:"0861112223",contact:"คุณซี",surveyDate:"2026-06-22",updated:"2026-06-22",createdBy:"คุณต้น",editedBy:"คุณต้น",status:"ควรสำรวจซ้ำ",notes:"หน้าฝนทางเข้ามีน้ำขัง",access:"ทางเข้าแคบ",parking:"จอดริมถนน",signal:"ปานกลาง",warnings:["น้ำท่วม","ถนนลูกรัง"],project:"",titleDeed:"33490",images:[placeholderImages[2]],history:["สำรวจ 22 มิ.ย. 2569"],comments:["ตรวจซ้ำหลังฤดูฝน"]},

  {id:"FM-2026-004",type:"คอนโดมิเนียม",area:"พระโขนง",address:"ถนนสุขุมวิท 71 เขตวัฒนา กรุงเทพมหานคร",lat:13.7134,lng:100.5958,price:"3,250,000 บาท",land:"-",usable:"31 ตร.ม.",phone:"0924455667",contact:"คุณดี",surveyDate:"2026-07-01",updated:"2026-07-14",createdBy:"คุณฝน",editedBy:"คุณปอ",status:"ยืนยันแล้ว",notes:"ติดต่อสำนักงานนิติบุคคลก่อนเข้า",access:"รถยนต์เข้าได้",parking:"ต้องแลกบัตร",signal:"ดี",warnings:[],project:"The Line Sukhumvit 71",titleDeed:"CN-4490",images:[placeholderImages[3]],history:["สำรวจ 1 ก.ค. 2569","Reviewer ยืนยัน 14 ก.ค. 2569"],comments:["ข้อมูลส่วนกลางครบ"]},

  {id:"FM-2026-005",type:"โกดัง",area:"บางพลี",address:"ถนนเทพารักษ์ อำเภอบางพลี สมุทรปราการ",lat:13.6052,lng:100.7015,price:"",land:"1 ไร่",usable:"1,200 ตร.ม.",phone:"0909876543",contact:"คุณอี",surveyDate:"2026-06-28",updated:"2026-07-10",createdBy:"คุณปอ",editedBy:"คุณต้น",status:"อาจซ้ำ",notes:"พบข้อมูลใกล้เคียงอีก 1 รายการ",access:"รถบรรทุกเข้าได้",parking:"พื้นที่กว้าง",signal:"ดี",warnings:["พื้นที่ก่อสร้าง"],project:"BP Warehouse",titleDeed:"55901",images:[placeholderImages[0]],history:["สำรวจ 28 มิ.ย. 2569"],comments:["ตรวจเลขที่โฉนดอีกครั้ง"]},

  {id:"FM-2026-006",type:"อาคารพาณิชย์",area:"สมุทรปราการ",address:"ถนนศรีสมุทร อำเภอเมือง สมุทรปราการ",lat:13.5996,lng:100.5968,price:"6,500,000 บาท",land:"18 ตร.ว.",usable:"160 ตร.ม.",phone:"0951119090",contact:"คุณเอฟ",surveyDate:"2026-06-30",updated:"2026-07-09",createdBy:"คุณเมย์",editedBy:"คุณฝน",status:"ยืนยันแล้ว",notes:"จอดรถยากช่วงกลางวัน",access:"รถยนต์เข้าได้",parking:"จำกัด",signal:"ดี",warnings:["ที่จอดรถจำกัด"],project:"",titleDeed:"66123",images:[placeholderImages[1]],history:["สำรวจ 30 มิ.ย. 2569"],comments:[]},

  {id:"FM-2026-007",type:"บ้านเดี่ยว",area:"บางพลี",address:"กิ่งแก้ว 19 อำเภอบางพลี สมุทรปราการ",lat:13.6464,lng:100.7284,price:"",land:"65 ตร.ว.",usable:"230 ตร.ม.",phone:"0892345678",contact:"คุณจี",surveyDate:"2026-07-02",updated:"2026-07-02",createdBy:"คุณต้น",editedBy:"คุณต้น",status:"อาจซ้ำ",notes:"เบอร์โทรซ้ำกับ FM-2026-001",access:"รถยนต์เข้าได้",parking:"ในบ้าน",signal:"ปานกลาง",warnings:["สุนัขดุ"],project:"บ้านกิ่งแก้ว",titleDeed:"77100",images:[placeholderImages[2]],history:["สำรวจ 2 ก.ค. 2569"],comments:["ตรวจสอบผู้ติดต่อ"]},

  {id:"FM-2026-008",type:"โรงงาน",area:"บางนา",address:"ถนนบางนา-ตราด กม. 18 สมุทรปราการ",lat:13.6252,lng:100.7821,price:"",land:"3 ไร่",usable:"2,800 ตร.ม.",phone:"0825556777",contact:"คุณเอช",surveyDate:"2026-05-16",updated:"2026-06-20",createdBy:"คุณฝน",editedBy:"คุณเมย์",status:"ควรสำรวจซ้ำ",notes:"ต้องนัดหมายล่วงหน้า 2 วัน",access:"รถบรรทุกเข้าได้",parking:"มีลานจอด",signal:"ดี",warnings:["พื้นที่ห้ามเข้า"],project:"Bangna Industrial",titleDeed:"88991",images:[placeholderImages[3]],history:["สำรวจ 16 พ.ค. 2569"],comments:["ใบอนุญาตเข้าพื้นที่หมดอายุ"]},

  {id:"FM-2026-009",type:"ทาวน์โฮม",area:"พระโขนง",address:"ซอยปุณณวิถี 20 เขตพระโขนง กรุงเทพมหานคร",lat:13.6861,lng:100.6119,price:"4,200,000 บาท",land:"19 ตร.ว.",usable:"135 ตร.ม.",phone:"0801122334",contact:"คุณไอ",surveyDate:"2026-07-11",updated:"2026-07-11",createdBy:"คุณปอ",editedBy:"คุณปอ",status:"ข้อมูลใหม่",notes:"ถนนในซอยค่อนข้างแคบ",access:"ทางเข้าแคบ",parking:"หน้าบ้าน",signal:"ดี",warnings:["ทางเข้าแคบ"],project:"Punnawithi Home",titleDeed:"99012",images:[placeholderImages[0]],history:["สำรวจ 11 ก.ค. 2569"],comments:[]},

  {id:"FM-2026-010",type:"คอนโดมิเนียม",area:"ศรีนครินทร์",address:"ถนนศรีนครินทร์ ใกล้ MRT สวนหลวง ร.9",lat:13.6987,lng:100.6428,price:"2,850,000 บาท",land:"-",usable:"28 ตร.ม.",phone:"0849988776",contact:"คุณเจ",surveyDate:"2026-07-13",updated:"2026-07-16",createdBy:"คุณเมย์",editedBy:"คุณปอ",status:"ยืนยันแล้ว",notes:"เข้าอาคารผ่านนิติบุคคล",access:"รถยนต์เข้าได้",parking:"Visitor 2 ชั่วโมง",signal:"ดี",warnings:[],project:"Rich Park Triple Station",titleDeed:"CN-10012",images:[placeholderImages[1]],history:["สำรวจ 13 ก.ค. 2569","อัปเดตภาพ 16 ก.ค. 2569"],comments:["ข้อมูลครบ"]},

  {id:"FM-2026-011",type:"ที่ดินเปล่า",area:"ลาดกระบัง",address:"ซอยฉลองกรุง 31 เขตลาดกระบัง กรุงเทพมหานคร",lat:13.7298,lng:100.7902,price:"",land:"3 งาน 40 ตร.ว.",usable:"-",phone:"0886677889",contact:"คุณเค",surveyDate:"2026-06-15",updated:"2026-06-15",createdBy:"คุณฝน",editedBy:"คุณฝน",status:"ฉบับร่าง",notes:"สัญญาณโทรศัพท์ไม่เสถียร",access:"รถยนต์เข้าได้",parking:"จอดข้างทาง",signal:"อ่อน",warnings:["ไม่มีสัญญาณโทรศัพท์"],project:"",titleDeed:"11145",images:[placeholderImages[2]],history:["บันทึกร่าง 15 มิ.ย. 2569"],comments:[]},

  {id:"FM-2026-012",type:"อาคารสำนักงาน",area:"บางนา",address:"ถนนเทพรัตน เขตบางนา กรุงเทพมหานคร",lat:13.6689,lng:100.6359,price:"",land:"45 ตร.ว.",usable:"520 ตร.ม.",phone:"0834455990",contact:"คุณแอล",surveyDate:"2026-07-16",updated:"2026-07-16",createdBy:"คุณต้น",editedBy:"คุณต้น",status:"ข้อมูลใหม่",notes:"อยู่ใกล้ FM-2026-001 ประมาณ 130 เมตร",access:"รถยนต์เข้าได้",parking:"4 คัน",signal:"ดี",warnings:[],project:"Bangna Office Place",titleDeed:"12190",images:[placeholderImages[3]],history:["สำรวจ 16 ก.ค. 2569"],comments:[]}

];


let warnings = [

  {id:"W-001",type:"สุนัขดุ",severity:"เสี่ยงสูง",lat:13.6684,lng:100.6356,distance:120,date:"2026-07-16",reporter:"คุณปอ",description:"สุนัข 2 ตัว ไม่ได้ล่าม อยู่หน้าประตูรั้ว",active:true,confirm:6,lastConfirm:"วันนี้ 09:18",image:placeholderImages[0]},

  {id:"W-002",type:"ทางเข้าแคบ",severity:"ควรระวัง",lat:13.6865,lng:100.6124,distance:450,date:"2026-07-15",reporter:"คุณเมย์",description:"รถใหญ่กลับรถยาก แนะนำจอดปากซอย",active:true,confirm:3,lastConfirm:"เมื่อวาน 16:30",image:placeholderImages[1]},

  {id:"W-003",type:"น้ำท่วม",severity:"เสี่ยงสูง",lat:13.7186,lng:100.7805,distance:820,date:"2026-07-12",reporter:"คุณต้น",description:"น้ำขังช่วงฝนตกหนัก รถเล็กไม่ควรเข้า",active:true,confirm:8,lastConfirm:"12 ก.ค. 14:10",image:placeholderImages[2]},

  {id:"W-004",type:"ถนนชำรุด",severity:"ควรระวัง",lat:13.6460,lng:100.7290,distance:1100,date:"2026-07-10",reporter:"คุณฝน",description:"มีหลุมลึกช่วงก่อนถึงโครงการ",active:true,confirm:4,lastConfirm:"10 ก.ค. 11:05",image:placeholderImages[3]},

  {id:"W-005",type:"พื้นที่เปลี่ยว",severity:"ควรระวัง",lat:13.7301,lng:100.7907,distance:2100,date:"2026-07-09",reporter:"คุณปอ",description:"แนะนำลงพื้นที่ก่อน 17:00",active:true,confirm:2,lastConfirm:"9 ก.ค. 15:40",image:placeholderImages[0]},

  {id:"W-006",type:"ที่จอดรถจำกัด",severity:"ข้อมูลทั่วไป",lat:13.5998,lng:100.5964,distance:3200,date:"2026-07-05",reporter:"คุณเมย์",description:"จอดได้เฉพาะช่วง 10:00–14:00",active:true,confirm:5,lastConfirm:"8 ก.ค. 10:00",image:placeholderImages[1]},

  {id:"W-007",type:"พื้นที่ก่อสร้าง",severity:"ควรระวัง",lat:13.6055,lng:100.7010,distance:4600,date:"2026-07-03",reporter:"คุณต้น",description:"มีรถบรรทุกเข้าออกตลอดวัน",active:true,confirm:3,lastConfirm:"7 ก.ค. 13:20",image:placeholderImages[2]},

  {id:"W-008",type:"ไม่มีสัญญาณโทรศัพท์",severity:"ข้อมูลทั่วไป",lat:13.7294,lng:100.7898,distance:5100,date:"2026-06-30",reporter:"คุณฝน",description:"บางเครือข่ายไม่มีสัญญาณ",active:true,confirm:2,lastConfirm:"2 ก.ค. 09:45",image:placeholderImages[3]},

  {id:"W-009",type:"รถยนต์เข้าไม่ได้",severity:"เสี่ยงสูง",lat:13.6248,lng:100.7815,distance:6500,date:"2026-06-28",reporter:"คุณปอ",description:"ถนนปิดชั่วคราว ต้องเดินประมาณ 300 เมตร",active:false,confirm:7,lastConfirm:"แก้ไขแล้ว 5 ก.ค.",image:placeholderImages[0]},

  {id:"W-010",type:"เสี่ยงอุบัติเหตุ",severity:"ควรระวัง",lat:13.6925,lng:100.6458,distance:900,date:"2026-07-14",reporter:"คุณเมย์",description:"ทางโค้งไม่มีไฟส่องสว่าง",active:true,confirm:4,lastConfirm:"14 ก.ค. 18:20",image:placeholderImages[1]}

];


let places = [

  {id:"P01",name:"ครัวบางนา",category:"ร้านอาหาร",lat:13.6687,lng:100.6346,distance:180,time:"3 นาที",open:true,rating:4.3,description:"อาหารตามสั่ง มีที่จอดรถ"},

  {id:"P02",name:"บ้านกาแฟสนาม",category:"ร้านกาแฟ",lat:13.6670,lng:100.6338,distance:240,time:"4 นาที",open:true,rating:4.5,description:"มีปลั๊กและห้องน้ำ"},

  {id:"P03",name:"7-Eleven บางนา 23",category:"ร้านสะดวกซื้อ",lat:13.6691,lng:100.6362,distance:260,time:"4 นาที",open:true,rating:4.0,description:"เปิด 24 ชั่วโมง"},

  {id:"P04",name:"ห้องน้ำสาธารณะ ศูนย์บริการ",category:"ห้องน้ำ",lat:13.6665,lng:100.6368,distance:340,time:"5 นาที",open:true,rating:null,description:"ข้อมูลตัวอย่าง"},

  {id:"P05",name:"PTT Station บางนา",category:"ปั๊มน้ำมัน",lat:13.6710,lng:100.6329,distance:520,time:"6 นาที",open:true,rating:4.2,description:"มีร้านอาหารและห้องน้ำ"},

  {id:"P06",name:"ATM Krungsri",category:"ATM",lat:13.6682,lng:100.6373,distance:300,time:"4 นาที",open:true,rating:null,description:"หน้าร้านสะดวกซื้อ"},

  {id:"P07",name:"โรงพยาบาลไทยนครินทร์",category:"โรงพยาบาล",lat:13.6698,lng:100.6340,distance:680,time:"8 นาที",open:true,rating:4.1,description:"เปิด 24 ชั่วโมง"},

  {id:"P08",name:"สน.บางนา",category:"สถานีตำรวจ",lat:13.6648,lng:100.6410,distance:1100,time:"12 นาที",open:true,rating:null,description:"สถานีตำรวจใกล้พื้นที่"},

  {id:"P09",name:"ลานจอดรถชุมชน",category:"จุดจอดรถ",lat:13.6674,lng:100.6328,distance:400,time:"5 นาที",open:true,rating:3.9,description:"คิดค่าบริการรายชั่วโมง"},

  {id:"P10",name:"ก๋วยเตี๋ยวเรือคุณนิด",category:"ร้านอาหาร",lat:13.6669,lng:100.6370,distance:360,time:"5 นาที",open:false,rating:4.4,description:"ปิดทุกวันจันทร์"},

  {id:"P11",name:"Yellow Cup Café",category:"ร้านกาแฟ",lat:13.6694,lng:100.6334,distance:410,time:"5 นาที",open:true,rating:4.6,description:"นั่งทำงานได้"},

  {id:"P12",name:"Mini Big C",category:"ร้านสะดวกซื้อ",lat:13.6658,lng:100.6345,distance:590,time:"7 นาที",open:true,rating:4.1,description:"มี ATM"},

  {id:"P13",name:"Shell ศรีนครินทร์",category:"ปั๊มน้ำมัน",lat:13.6915,lng:100.6480,distance:2100,time:"9 นาที",open:true,rating:4.0,description:"ข้อมูลตัวอย่าง"},

  {id:"P14",name:"ตลาดนัดบางนา",category:"ร้านอาหาร",lat:13.6702,lng:100.6385,distance:780,time:"10 นาที",open:true,rating:4.2,description:"ร้านอาหารหลายร้าน"},

  {id:"P15",name:"อาคารจอดรถ B1",category:"จุดจอดรถ",lat:13.6708,lng:100.6350,distance:620,time:"7 นาที",open:true,rating:null,description:"มี รปภ. ดูแล"}

];


let tasks = [

  {id:"T-101",record:"FM-2026-003",title:"สำรวจซ้ำที่ดินถนนหลวงแพ่ง",assignee:"คุณปอ",due:"วันนี้ 14:00",status:"รอดำเนินการ",area:"ลาดกระบัง"},

  {id:"T-102",record:"FM-2026-008",title:"ตรวจสอบใบอนุญาตเข้าพื้นที่",assignee:"คุณเมย์",due:"วันนี้ 15:30",status:"กำลังเดินทาง",area:"บางนา"},

  {id:"T-103",record:"FM-2026-005",title:"ตรวจเลขที่โฉนดรายการอาจซ้ำ",assignee:"คุณต้น",due:"วันนี้ 17:00",status:"รอตรวจสอบ",area:"บางพลี"},

  {id:"T-104",record:"FM-2026-011",title:"เก็บภาพทางเข้าเพิ่มเติม",assignee:"คุณฝน",due:"18 ก.ค. 2569",status:"กำลังลงพื้นที่",area:"ลาดกระบัง"},

  {id:"T-105",record:"FM-2026-006",title:"ยืนยันข้อจำกัดที่จอดรถ",assignee:"คุณปอ",due:"19 ก.ค. 2569",status:"รอดำเนินการ",area:"สมุทรปราการ"}

];


const folders = [

  {icon:"🏠",name:"Property Records",count:"248 รายการ"},

  {icon:"🖼️",name:"Images",count:"2,184 ไฟล์"},

  {icon:"📄",name:"Documents",count:"164 ไฟล์"},

  {icon:"📍",name:"GPS & Map",count:"248 จุด"},

  {icon:"🕘",name:"Survey History",count:"612 เหตุการณ์"},

  {icon:"⚠️",name:"Safety Reports",count:"36 จุด"},

  {icon:"💬",name:"Team Comments",count:"189 ความคิดเห็น"},

  {icon:"✅",name:"Tasks",count:"52 งาน"},

  {icon:"📎",name:"Attachments",count:"431 ไฟล์"},

  {icon:"↩️",name:"Version History",count:"1,024 เวอร์ชัน"}

];


// ---------- STATE ----------

let currentPage = 1;

let currentStep = 1;

let currentPosition = null;

let locationWatchId = null;

let cameraStream = null;

let cameraFacingMode = "environment";

let capturedPhotos = [];

let selectedNearbyCategory = "";

let maps = {};

let layers = {};

let manualPinMode = false;

let formPin = null;


// ---------- UTILITIES ----------

const $ = id => document.getElementById(id);

const formatDateThai = d => new Intl.DateTimeFormat("th-TH",{dateStyle:"long"}).format(new Date(d));

const todayISO = () => new Date().toISOString().slice(0,10);

const maskPhone = phone => phone ? phone.slice(0,3)+"-xxx-"+phone.slice(-4) : "—";

const safe = value => value ?? "—";


function toast(message){

  const t = $("toast");

  t.textContent = message;

  t.classList.add("show");

  clearTimeout(t._timer);

  t._timer = setTimeout(()=>t.classList.remove("show"),2800);

}

function openModal(id){$(id).classList.add("open")}

function closeModal(id){$(id).classList.remove("open")}


function distanceMeters(lat1,lng1,lat2,lng2){

  const R=6371000, p1=lat1*Math.PI/180, p2=lat2*Math.PI/180;

  const dp=(lat2-lat1)*Math.PI/180, dl=(lng2-lng1)*Math.PI/180;

  const a=Math.sin(dp/2)**2+Math.cos(p1)*Math.cos(p2)*Math.sin(dl/2)**2;

  return 2*R*Math.atan2(Math.sqrt(a),Math.sqrt(1-a));

}

function markerColor(status){

  return {"ข้อมูลใหม่":"#2D6CDF","ยืนยันแล้ว":"#20865A","ควรสำรวจซ้ำ":"#E67E22","อาจซ้ำ":"#C73B32","ฉบับร่าง":"#746D6A"}[status] || "#241918";

}

function divIcon(color,label=""){

  return L.divIcon({

    className:"",

    html:`<div style="width:28px;height:28px;border-radius:50% 50% 50% 0;background:${color};border:3px solid #fff;box-shadow:0 3px 10px rgba(0,0,0,.28);transform:rotate(-45deg);display:grid;place-items:center"><span style="transform:rotate(45deg);font-size:12px">${label}</span></div>`,

    iconSize:[30,30],iconAnchor:[15,28]

  });

}


// ---------- NAVIGATION ----------

const pageTitles = {

  dashboard:["ภาพรวม","ข้อมูลภาคสนามของทีมในที่เดียว"],

  map:["แผนที่ข้อมูล","Smart Map พร้อมตำแหน่งจริง ข้อมูลเดิม จุดเตือน และสถานที่ใกล้เคียง"],

  search:["ค้นหาข้อมูลกลาง","ค้นหาข้อมูลเดิมก่อนเดินทางหรือสร้างรายการใหม่"],

  add:["เพิ่มข้อมูลภาคสนาม","ขั้นตอนบันทึกข้อมูลที่ตรวจสอบรายการซ้ำก่อนบันทึก"],

  storage:["คลังข้อมูลกลาง","ถังเก็บข้อมูลและเอกสารแบบ Single Source of Truth"],

  team:["งานของทีม","มอบหมาย ติดตาม และตรวจสอบงานภาคสนาม"],

  safety:["แจ้งเตือนพื้นที่","แชร์ข้อมูลความเสี่ยงและข้อจำกัดการเข้าถึงให้ทีม"],

  nearby:["พักไหนดีใกล้ฉัน","สถานที่ที่เป็นประโยชน์ระหว่างลงพื้นที่"],

  reports:["รายงาน","ตัวชี้วัดด้านการปฏิบัติงานและการนำข้อมูลกลับมาใช้"]

};


function openPage(page){

  document.querySelectorAll(".page").forEach(p=>p.classList.remove("active"));

  $("page-"+page).classList.add("active");

  document.querySelectorAll("[data-page]").forEach(b=>b.classList.toggle("active",b.dataset.page===page));

  $("topPageTitle").textContent=pageTitles[page][0];

  $("topPageSubtitle").textContent=pageTitles[page][1];

  window.scrollTo({top:0,behavior:"smooth"});


  setTimeout(()=>{

    if(page==="map"){initMainMap();maps.main?.invalidateSize();renderMapMarkers()}

    if(page==="add"){initFormMap();maps.form?.invalidateSize()}

    if(page==="safety"){initSafetyMap();maps.safety?.invalidateSize();renderSafetyList()}

    if(page==="nearby"){initNearbyMap();maps.nearby?.invalidateSize();renderNearbyPlaces()}

    if(page==="search") renderSearchResults();

    if(page==="storage") renderStorage();

    if(page==="team") renderTasks();

  },100);

}

document.querySelectorAll("[data-page]").forEach(btn=>btn.addEventListener("click",()=>openPage(btn.dataset.page)));


// ---------- MAP INITIALIZATION & FALLBACK ----------

function createMap(id,center=[13.6678,100.6351],zoom=13){

  const el=$(id);

  if(!window.L){

    el.innerHTML=`<div class="map-fallback"><div><strong>ไม่สามารถโหลดแผนที่ได้</strong><p>ตรวจสอบอินเทอร์เน็ต หรือกรอก Latitude / Longitude ด้วยตนเอง</p></div></div>`;

    return null;

  }

  const map=L.map(id).setView(center,zoom);

  const tiles=L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{

    maxZoom:19,attribution:"&copy; OpenStreetMap contributors"

  });

  let tileErrorCount=0;

  tiles.on("tileerror",()=>{

    tileErrorCount++;

    if(tileErrorCount===3) toast("โหลดแผนที่บางส่วนไม่สำเร็จ แต่ยังกรอกพิกัดด้วยตนเองได้");

  });

  tiles.addTo(map);

  return map;

}


function initDashboardMap(){

  if(maps.dashboard)return;

  maps.dashboard=createMap("dashboardMap",[13.6678,100.6351],12);

  if(!maps.dashboard)return;

  records.slice(0,6).forEach(r=>L.marker([r.lat,r.lng],{icon:divIcon(markerColor(r.status))}).addTo(maps.dashboard).bindPopup(`<strong>${r.id}</strong><br>${r.type}<br>${r.address}`));

  warnings.slice(0,4).forEach(w=>L.marker([w.lat,w.lng],{icon:divIcon("#C73B32","⚠")}).addTo(maps.dashboard).bindPopup(`<strong>${w.type}</strong><br>${w.description}`));

}

function initMainMap(){

  if(maps.main)return;

  maps.main=createMap("mainMap",[13.6678,100.6351],12);

  if(!maps.main)return;

  maps.main.on("click",e=>{

    if(manualPinMode){

      updateFormPosition(e.latlng.lat,e.latlng.lng,null);

      toast("ย้ายหมุดไปยังตำแหน่งที่เลือกแล้ว");

    }

  });

}

function initFormMap(){

  if(maps.form)return;

  maps.form=createMap("formMap",[13.6678,100.6351],15);

  if(!maps.form)return;

  formPin=L.marker([13.6678,100.6351],{draggable:true,icon:divIcon("#FFD91E")}).addTo(maps.form);

  formPin.on("dragend",e=>{

    const p=e.target.getLatLng();

    updateFormPosition(p.lat,p.lng,null,false);

  });

  maps.form.on("click",e=>{

    if(manualPinMode) updateFormPosition(e.latlng.lat,e.latlng.lng,null);

  });

}

function initSafetyMap(){

  if(maps.safety)return;

  maps.safety=createMap("safetyMap",[13.6678,100.6351],12);

  renderSafetyMapMarkers();

}

function initNearbyMap(){

  if(maps.nearby)return;

  maps.nearby=createMap("nearbyMap",[13.6678,100.6351],14);

  renderNearbyMapMarkers();

}


function renderMapMarkers(filtered=records){

  if(!maps.main)return;

  if(layers.mainGroup) layers.mainGroup.clearLayers();

  layers.mainGroup=L.layerGroup().addTo(maps.main);


  filtered.forEach(r=>{

    const marker=L.marker([r.lat,r.lng],{icon:divIcon(markerColor(r.status))})

      .addTo(layers.mainGroup)

      .on("click",()=>showMapRecord(r));

    marker.bindTooltip(`${r.id} · ${r.type}`);

  });

  warnings.filter(w=>w.active).forEach(w=>{

    L.marker([w.lat,w.lng],{icon:divIcon(w.severity==="เสี่ยงสูง"?"#C73B32":"#E67E22","⚠")})

      .addTo(layers.mainGroup).on("click",()=>showMapWarning(w));

  });


  const placeFilter=$("mapPlaceFilter")?.value;

  if(placeFilter){

    places.filter(p=>p.category===placeFilter).forEach(p=>{

      L.marker([p.lat,p.lng],{icon:divIcon("#2D6CDF","●")}).addTo(layers.mainGroup).on("click",()=>showMapPlace(p));

    });

  }

  if(currentPosition){

    L.circleMarker([currentPosition.lat,currentPosition.lng],{radius:9,color:"#2D6CDF",fillColor:"#2D6CDF",fillOpacity:.7}).addTo(layers.mainGroup).bindTooltip("ตำแหน่งปัจจุบัน");

  }

}

function renderSafetyMapMarkers(){

  if(!maps.safety)return;

  if(layers.safetyGroup)layers.safetyGroup.clearLayers();

  layers.safetyGroup=L.layerGroup().addTo(maps.safety);

  warnings.forEach(w=>{

    L.marker([w.lat,w.lng],{icon:divIcon(w.active?(w.severity==="เสี่ยงสูง"?"#C73B32":"#E67E22"):"#746D6A","⚠")})

      .addTo(layers.safetyGroup).bindPopup(`<strong>${w.type}</strong><br>${w.description}<br>${w.active?"ยังมีอยู่":"แก้ไขแล้ว"}`);

  });

  if(currentPosition) L.circleMarker([currentPosition.lat,currentPosition.lng],{radius:9,color:"#2D6CDF"}).addTo(layers.safetyGroup);

}

function renderNearbyMapMarkers(){

  if(!maps.nearby)return;

  if(layers.nearbyGroup)layers.nearbyGroup.clearLayers();

  layers.nearbyGroup=L.layerGroup().addTo(maps.nearby);

  const list=selectedNearbyCategory?places.filter(p=>p.category===selectedNearbyCategory):places;

  list.forEach(p=>L.marker([p.lat,p.lng],{icon:divIcon("#2D6CDF","●")}).addTo(layers.nearbyGroup).bindPopup(`<strong>${p.name}</strong><br>${p.category}<br>${p.distance} เมตร`));

  if(currentPosition)L.circleMarker([currentPosition.lat,currentPosition.lng],{radius:9,color:"#2D6CDF"}).addTo(layers.nearbyGroup);

}

function filterMapRecords(){

  const q=$("mapSearchInput").value.trim().toLowerCase();

  const type=$("mapPropertyFilter").value;

  const status=$("mapStatusFilter").value;

  const warning=$("mapWarningFilter").value;

  const filtered=records.filter(r=>{

    const text=[r.id,r.address,r.phone,r.project,r.titleDeed,r.type,r.notes].join(" ").toLowerCase();

    return (!q||text.includes(q))&&(!type||r.type===type)&&(!status||r.status===status)&&(!warning||r.warnings.includes(warning));

  });

  renderMapMarkers(filtered);

  toast(`พบ ${filtered.length} รายการบนแผนที่`);

}

function recenterMap(){

  if(!currentPosition){requestLocationWithExplanation();return}

  maps.main?.setView([currentPosition.lat,currentPosition.lng],16);

}

function fitAllMarkers(){

  if(!maps.main||!layers.mainGroup)return;

  const bounds=layers.mainGroup.getBounds?.();

  if(bounds?.isValid()) maps.main.fitBounds(bounds.pad(.12));

}

function showMapRecord(r){

  const dist=currentPosition?Math.round(distanceMeters(currentPosition.lat,currentPosition.lng,r.lat,r.lng)):"—";

  $("mapSidePanel").innerHTML=`

    <img class="full" style="height:160px;object-fit:cover;border-radius:14px" src="${r.images[0]}" alt="">

    <div class="spread" style="margin-top:12px"><strong>${r.id}</strong><span class="chip">${r.status}</span></div>

    <h3 style="margin-top:10px">${r.type}</h3>

    <p class="muted small">${r.address}</p>

    <div class="stack small">

      <div class="spread"><span>พิกัด</span><strong>${r.lat.toFixed(5)}, ${r.lng.toFixed(5)}</strong></div>

      <div class="spread"><span>ระยะจากคุณ</span><strong>${dist} เมตร</strong></div>

      <div class="spread"><span>สำรวจล่าสุด</span><strong>${r.updated}</strong></div>

      <div class="spread"><span>ผู้บันทึก</span><strong>${r.createdBy}</strong></div>

      <div class="spread"><span>ราคาที่ประกาศ</span><strong>${r.price||"ไม่ได้บันทึก"}</strong></div>

      <div class="spread"><span>ที่จอดรถ</span><strong>${r.parking}</strong></div>

    </div>

    <div class="meta">${r.warnings.map(w=>`<span class="chip red">⚠ ${w}</span>`).join("")||'<span class="chip green">ไม่มีจุดเตือน</span>'}</div>

    <div class="grid grid-2" style="margin-top:14px">

      <button class="btn btn-primary" onclick="openRecord('${r.id}')">ดูรายละเอียด</button>

      <button class="btn" onclick="navigateTo(${r.lat},${r.lng})">นำทาง</button>

      <button class="btn" onclick="updateExisting('${r.id}')">อัปเดตข้อมูล</button>

      <button class="btn" onclick="assignResurvey('${r.id}')">มอบหมายสำรวจซ้ำ</button>

    </div>`;

}

function showMapWarning(w){

  $("mapSidePanel").innerHTML=`

    <img class="full" style="height:160px;object-fit:cover;border-radius:14px" src="${w.image}" alt="">

    <div class="spread" style="margin-top:12px"><strong>${w.type}</strong><span class="chip ${w.severity==="เสี่ยงสูง"?"red":"orange"}">${w.severity}</span></div>

    <p>${w.description}</p>

    <div class="stack small">

      <div class="spread"><span>วันที่รายงาน</span><strong>${w.date}</strong></div>

      <div class="spread"><span>ผู้รายงาน</span><strong>${w.reporter}</strong></div>

      <div class="spread"><span>สถานะ</span><strong>${w.active?"ยังมีอยู่":"แก้ไขแล้ว"}</strong></div>

      <div class="spread"><span>ยืนยัน</span><strong>${w.confirm} ครั้ง</strong></div>

    </div>

    <div class="grid grid-2" style="margin-top:14px">

      <button class="btn btn-primary" onclick="confirmWarning('${w.id}')">ยืนยันจุดเตือน</button>

      <button class="btn" onclick="resolveWarning('${w.id}')">แจ้งว่าแก้ไขแล้ว</button>

    </div>`;

}

function showMapPlace(p){

  $("mapSidePanel").innerHTML=`

    <div class="chip blue">ข้อมูลตัวอย่าง</div>

    <h3 style="margin-top:12px">${p.name}</h3>

    <p class="muted">${p.category} · ${p.distance} เมตร · ${p.time}</p>

    <p>${p.description}</p>

    <div class="grid grid-2">

      <button class="btn btn-primary" onclick="navigateTo(${p.lat},${p.lng})">นำทาง</button>

      <button class="btn" onclick="toast('บันทึกสถานที่แล้ว')">บันทึกไว้</button>

    </div>`;

}


// ---------- GEOLOCATION ----------

// Browser Geolocation จะถูกเรียกหลังผู้ใช้กดอนุญาตเท่านั้น

function requestLocationWithExplanation(){openModal("locationPermissionModal")}

function getCurrentLocation(){

  closeModal("locationPermissionModal");

  if(!window.isSecureContext && location.protocol!=="file:"){

    showLocationError("ต้องเปิดผ่าน HTTPS หรือ localhost จึงจะใช้ตำแหน่งได้");

    return;

  }

  if(!navigator.geolocation){

    showLocationError("Browser นี้ไม่รองรับการระบุตำแหน่ง กรุณากรอกพิกัดด้วยตนเอง");

    return;

  }

  navigator.geolocation.getCurrentPosition(

    pos=>handlePosition(pos),

    err=>handleLocationError(err),

    {enableHighAccuracy:true,timeout:12000,maximumAge:0}

  );

}

function handlePosition(pos){

  currentPosition={lat:pos.coords.latitude,lng:pos.coords.longitude,accuracy:pos.coords.accuracy,updated:new Date()};

  updateLocationUI();

  updateFormPosition(currentPosition.lat,currentPosition.lng,currentPosition.accuracy);

  renderMapMarkers();

  renderSafetyMapMarkers();

  renderNearbyMapMarkers();

  checkProximityWarnings();

  closeModal("locationPermissionModal");

  toast("ใช้ตำแหน่งปัจจุบันแล้ว");

}

function updateLocationUI(){

  if(!currentPosition)return;

  $("gpsChip").textContent=locationWatchId!==null?"GPS: ติดตามแบบเรียลไทม์":"GPS: เชื่อมต่อแล้ว";

  $("gpsChip").className="chip "+(locationWatchId!==null?"green":"blue");

  $("accuracyChip").textContent=`ความแม่นยำ: ±${Math.round(currentPosition.accuracy)} เมตร`;

  $("updateChip").textContent=`อัปเดตล่าสุด: ${currentPosition.updated.toLocaleTimeString("th-TH",{hour:"2-digit",minute:"2-digit",second:"2-digit"})}`;

  $("locationSummary").textContent=`พิกัด ${currentPosition.lat.toFixed(5)}, ${currentPosition.lng.toFixed(5)} · ±${Math.round(currentPosition.accuracy)} ม.`;

  if(currentPosition.accuracy>80) toast("ความแม่นยำ GPS ค่อนข้างต่ำ กรุณาตรวจสอบหมุดก่อนบันทึก");

}

function handleLocationError(err){

  const msgs={1:"ไม่ได้รับอนุญาตให้ใช้ตำแหน่ง กรุณากรอกที่อยู่หรือพิกัดด้วยตนเอง",2:"ไม่สามารถระบุตำแหน่งได้ กรุณาตรวจสอบ GPS",3:"ใช้เวลาระบุตำแหน่งนานเกินไป กรุณาลองใหม่"};

  showLocationError(msgs[err.code]||"เกิดข้อผิดพลาดในการระบุตำแหน่ง");

}

function showLocationError(message){

  toast(message);

  $("existingCheckInfo").className="alert warning";

  $("existingCheckInfo").innerHTML=`${message}<br><span class="small">คุณยังสามารถกรอกที่อยู่ Latitude และ Longitude หรือปักหมุดด้วยตนเองได้</span>`;

}

function toggleTracking(){

  if(locationWatchId!==null){stopTracking();return}

  if(!navigator.geolocation){showLocationError("Browser นี้ไม่รองรับการติดตามตำแหน่ง");return}

  locationWatchId=navigator.geolocation.watchPosition(

    handlePosition,

    handleLocationError,

    {enableHighAccuracy:true,timeout:15000,maximumAge:2000}

  );

  $("trackingBtn").textContent="■ หยุดติดตาม";

  $("trackingBtn").classList.add("btn-danger");

  toast("เริ่มติดตามตำแหน่งแบบเรียลไทม์แล้ว");

}

function stopTracking(){

  if(locationWatchId!==null) navigator.geolocation.clearWatch(locationWatchId);

  locationWatchId=null;

  if($("trackingBtn")){

    $("trackingBtn").textContent="▶ เริ่มติดตาม";

    $("trackingBtn").classList.remove("btn-danger");

  }

  updateLocationUI();

  toast("หยุดติดตามตำแหน่งแล้ว");

}

function updateFormPosition(lat,lng,accuracy=null,moveMap=true){

  $("formLat").value=lat.toFixed(7);

  $("formLng").value=lng.toFixed(7);

  $("formAccuracy").value=accuracy?`±${Math.round(accuracy)} เมตร`:"ปักหมุดด้วยตนเอง";

  if(formPin)formPin.setLatLng([lat,lng]);

  if(moveMap)maps.form?.setView([lat,lng],16);

}

function enableManualPin(){

  manualPinMode=true;

  toast("คลิกแผนที่หรือจับหมุดลากไปยังตำแหน่งที่ต้องการ");

}

function checkProximityWarnings(){

  if(!currentPosition)return;

  const near=warnings.filter(w=>w.active).map(w=>({...w,realDistance:distanceMeters(currentPosition.lat,currentPosition.lng,w.lat,w.lng)})).sort((a,b)=>a.realDistance-b.realDistance)[0];

  if(near&&near.realDistance<300){

    $("proximityAlert").classList.remove("hidden");

    $("proximityAlert").innerHTML=`⚠ คุณอยู่ห่างจากจุดที่มีรายงาน<strong>${near.type}</strong>ประมาณ ${Math.round(near.realDistance)} เมตร — ${near.description}`;

  }else $("proximityAlert").classList.add("hidden");

}

function searchNearMe(){

  if(!currentPosition){requestLocationWithExplanation();return}

  openPage("search");

  setTimeout(()=>{

    const near=records.filter(r=>distanceMeters(currentPosition.lat,currentPosition.lng,r.lat,r.lng)<=250);

    $("centralSearchInput").value="";

    renderSearchResults(near);

    toast(`พบข้อมูล ${near.length} รายการภายใน 250 เมตร`);

  },150);

}


// ---------- CAMERA ----------

// ใช้ getUserMedia สำหรับ preview จริง และหยุด track ทุกครั้งเมื่อปิด modal

function openCameraPermissionModal(){openModal("cameraPermissionModal")}

async function startCamera(){

  closeModal("cameraPermissionModal");

  openModal("cameraModal");

  $("cameraError").classList.add("hidden");

  $("cameraVideo").classList.remove("hidden");

  if(!window.isSecureContext && location.protocol!=="file:"){

    showCameraError("ต้องเปิดผ่าน HTTPS หรือ localhost เพื่อใช้กล้อง");

    return;

  }

  if(!navigator.mediaDevices?.getUserMedia){

    showCameraError("Browser นี้ไม่รองรับกล้อง กรุณาใช้อัปโหลดรูปแทน");

    return;

  }

  try{

    stopCameraTracks();

    cameraStream=await navigator.mediaDevices.getUserMedia({video:{facingMode:{ideal:cameraFacingMode}},audio:false});

    $("cameraVideo").srcObject=cameraStream;

  }catch(err){

    const name=err.name||"";

    let msg="ไม่สามารถเปิดกล้องได้";

    if(name==="NotAllowedError")msg="ไม่ได้รับอนุญาตให้ใช้กล้อง กรุณาอัปโหลดรูปแทน";

    if(name==="NotFoundError")msg="ไม่พบกล้องในอุปกรณ์นี้";

    if(name==="NotReadableError")msg="กล้องอาจถูกใช้งานโดยแอปอื่น";

    if(name==="OverconstrainedError")msg="ไม่พบกล้องตามรูปแบบที่เลือก";

    showCameraError(msg);

  }

}

function showCameraError(msg){

  $("cameraVideo").classList.add("hidden");

  $("cameraError").classList.remove("hidden");

  $("cameraError").innerHTML=`<strong>${msg}</strong><p class="muted" style="color:#ccc">คุณยังสามารถเลือก “อัปโหลดแทน” ได้</p>`;

}

function stopCameraTracks(){

  if(cameraStream)cameraStream.getTracks().forEach(t=>t.stop());

  cameraStream=null;

  $("cameraVideo").srcObject=null;

}

function closeCamera(){stopCameraTracks();closeModal("cameraModal")}

async function switchCamera(){

  cameraFacingMode=cameraFacingMode==="environment"?"user":"environment";

  await startCamera();

}

function capturePhoto(){

  const video=$("cameraVideo");

  if(!cameraStream||!video.videoWidth){toast("กล้องยังไม่พร้อม");return}

  const canvas=$("cameraCanvas");

  canvas.width=video.videoWidth;canvas.height=video.videoHeight;

  canvas.getContext("2d").drawImage(video,0,0);

  const data=canvas.toDataURL("image/jpeg",.88);

  capturedPhotos.push({src:data,category:$("photoCategory").value,cover:capturedPhotos.length===0});

  renderPhotos();

  closeCamera();

  toast("ถ่ายภาพแล้ว กรุณาตรวจสอบก่อนบันทึก");

}

function handleGalleryUpload(event){

  Array.from(event.target.files).forEach(file=>{

    const reader=new FileReader();

    reader.onload=e=>{capturedPhotos.push({src:e.target.result,category:$("photoCategory").value,cover:capturedPhotos.length===0});renderPhotos()};

    reader.readAsDataURL(file);

  });

  event.target.value="";

}

function handleCameraFallback(event){handleGalleryUpload(event);closeCamera()}

function renderPhotos(){

  $("photoGrid").innerHTML=capturedPhotos.length?capturedPhotos.map((p,i)=>`

    <div class="photo-item" draggable="true">

      <img src="${p.src}" alt="${p.category}">

      ${p.cover?'<span class="cover">ภาพปก</span>':""}

      <button onclick="removePhoto(${i})">✕</button>

      <div style="padding:8px;font-size:12px;background:#fff">${p.category}<br><button class="btn btn-sm" style="margin-top:5px" onclick="setCover(${i})">ตั้งเป็นภาพปก</button></div>

    </div>`).join(""):`<div class="alert info" style="grid-column:1/-1">ยังไม่มีรูปภาพ คุณสามารถเปิดกล้องหรืออัปโหลดจากอุปกรณ์ได้</div>`;

}

function removePhoto(i){

  if(!confirm("ต้องการลบรูปนี้หรือไม่?"))return;

  const wasCover=capturedPhotos[i]?.cover;

  capturedPhotos.splice(i,1);

  if(wasCover&&capturedPhotos[0])capturedPhotos[0].cover=true;

  renderPhotos();

}

function setCover(i){capturedPhotos.forEach((p,idx)=>p.cover=idx===i);renderPhotos();toast("ตั้งภาพปกแล้ว")}

function runMockOCR(){

  if(!capturedPhotos.length){toast("กรุณาเพิ่มรูปป้ายก่อนใช้ OCR");return}

  $("ocrFields").classList.remove("hidden");

  $("ocrPhone").value="0892345678";

  $("ocrPrice").value="7,900,000 บาท";

  $("ocrArea").value="58 ตร.ว.";

  $("ocrContact").value="คุณเอ";

  toast("อ่านข้อมูลตัวอย่างจากภาพแล้ว กรุณาตรวจสอบและแก้ไขก่อนยืนยัน");

}


// ---------- SEARCH ----------

function renderSearchResults(forced=null){

  $("searchLoading").classList.remove("hidden");

  setTimeout(()=>{

    const q=$("centralSearchInput")?.value.trim().toLowerCase()||"";

    const type=$("searchType")?.value||"";

    const area=$("searchArea")?.value||"";

    const status=$("searchStatus")?.value||"";

    const officer=$("searchOfficer")?.value||"";

    let list=forced||records.filter(r=>{

      const text=[r.id,r.type,r.address,r.titleDeed,r.phone,r.contact,r.project,r.createdBy,r.editedBy,r.notes,r.warnings.join(" ")].join(" ").toLowerCase();

      return (!q||text.includes(q))&&(!type||r.type===type)&&(!area||r.area===area)&&(!status||r.status===status)&&(!officer||r.createdBy===officer);

    });

    const sort=$("searchSort")?.value||"latest";

    if(sort==="latest")list.sort((a,b)=>b.updated.localeCompare(a.updated));

    if(sort==="oldest")list.sort((a,b)=>a.updated.localeCompare(b.updated));

    if(sort==="nearest"&&currentPosition)list.sort((a,b)=>distanceMeters(currentPosition.lat,currentPosition.lng,a.lat,a.lng)-distanceMeters(currentPosition.lat,currentPosition.lng,b.lat,b.lng));

    const per=6,totalPages=Math.max(1,Math.ceil(list.length/per));

    currentPage=Math.min(currentPage,totalPages);

    const pageList=list.slice((currentPage-1)*per,currentPage*per);

    $("searchResultCount").textContent=list.length;

    $("paginationLabel").textContent=`หน้า ${currentPage} / ${totalPages}`;

    $("searchResults").innerHTML=pageList.length?pageList.map(recordCard).join(""):`<div class="alert warning">ไม่พบข้อมูลที่ตรงกับการค้นหา ลองปรับคำค้นหรือเงื่อนไข</div>`;

    $("searchLoading").classList.add("hidden");

  },180);

}

function recordCard(r){

  const dist=currentPosition?`${Math.round(distanceMeters(currentPosition.lat,currentPosition.lng,r.lat,r.lng))} ม.`:"—";

  return `<div class="list-item record-card">

    <img class="thumb" src="${r.images[0]}" alt="">

    <div>

      <div class="row"><h4>${r.id}</h4><span class="chip">${r.status}</span></div>

      <p><strong>${r.type}</strong> · ${r.address}</p>

      <p>ระยะ ${dist} · สำรวจ ${r.surveyDate} · อัปเดต ${r.updated}</p>

      <div class="meta">

        <span class="chip blue">${r.createdBy}</span>

        <span class="chip">${maskPhone(r.phone)}</span>

        ${r.warnings.map(w=>`<span class="chip red">⚠ ${w}</span>`).join("")}

      </div>

    </div>

    <div class="record-actions stack">

      <button class="btn btn-sm btn-primary" onclick="openRecord('${r.id}')">ดู