{"id":2213,"date":"2026-07-07T18:24:21","date_gmt":"2026-07-07T11:24:21","guid":{"rendered":"https:\/\/pandaigadai.com\/blog\/?page_id=2213"},"modified":"2026-07-07T18:42:46","modified_gmt":"2026-07-07T11:42:46","slug":"gmaps-reviews","status":"publish","type":"page","link":"https:\/\/pandaigadai.com\/blog\/gmaps-reviews\/","title":{"rendered":"Google Maps Review Tracker &#8211; Pandai Gadai"},"content":{"rendered":"<!DOCTYPE html>\r\n<html lang=\"id\">\r\n<head>\r\n<meta charset=\"UTF-8\">\r\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\r\n<title>Dashboard Pertumbuhan Google Review \u2014 Pandai Gadai<\/title>\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\r\n<link rel=\"stylesheet\" href=\"https:\/\/fonts.googleapis.com\/css2?family=Rubik:wght@400;500;600;700;800;900&display=swap\">\r\n<style>\r\n\/* ---- Reset (scoped) ---- *\/\r\n#pg-page *, #pg-page *::before, #pg-page *::after{box-sizing:border-box;margin:0;padding:0}\r\nhtml,body{margin:0;padding:0;background:#f0f2f8}\r\n\r\n\/* ---- Design tokens ---- *\/\r\n#pg-page{\r\n  --radius:0.625rem;\r\n  --background:#ffffff;\r\n  --foreground:#021431;\r\n  --card:#ffffff;\r\n  --primary:#02439F;\r\n  --primary-deep:#011455;\r\n  --primary-bright:#0255CA;\r\n  --primary-foreground:#f8fafc;\r\n  --accent:#ffcd05;\r\n  --accent-foreground:#021431;\r\n  --secondary:#f3f5fb;\r\n  --muted:#f0f2f8;\r\n  --muted-foreground:#6b7280;\r\n  --destructive:#dc2626;\r\n  --success:#047857;\r\n  --border:#e2e6f0;\r\n  --footer-bg:#02439f;\r\n  --shadow-card:0 2px 8px -2px rgba(2,20,49,0.08);\r\n  --shadow-elegant:0 10px 30px -12px rgba(2,67,159,0.35);\r\n  --gradient-hero:linear-gradient(135deg,#011455,#0255CA);\r\n}\r\n\r\n\/* ---- Base ---- *\/\r\n#pg-page{font-family:\"Rubik\",system-ui,-apple-system,\"Segoe UI\",sans-serif;background:var(--muted);color:var(--foreground);line-height:1.6;-webkit-font-smoothing:antialiased}\r\n#pg-page h1,#pg-page h2,#pg-page h3,#pg-page h4{letter-spacing:-0.02em}\r\n#pg-page p{margin:0}\r\n#pg-page a{text-decoration:none;color:inherit}\r\n#pg-page img{display:block;max-width:100%}\r\n#pg-page ul{list-style:none}\r\n#pg-page .section-container{max-width:78rem;margin:0 auto;padding:0 1rem}\r\n\r\n\/* ---- Header (LOCKED) ---- *\/\r\n#pg-page .site-header{position:sticky;top:0;z-index:100;background:var(--background);border-bottom:1px solid var(--border)}\r\n#pg-page .header-inner{max-width:78rem;margin:0 auto;display:flex;height:5rem;align-items:center;justify-content:space-between;padding:0 1rem}\r\n#pg-page .header-nav{display:flex;align-items:center;gap:.75rem}\r\n#pg-page .btn-header{display:inline-flex;align-items:center;gap:.375rem;border-radius:calc(var(--radius) - 2px);background:var(--accent);padding:.5rem .875rem;font-size:.875rem;font-weight:700;color:var(--accent-foreground);box-shadow:0 1px 2px rgba(0,0,0,.05);transition:filter .15s}\r\n#pg-page .btn-header:hover{filter:brightness(.95)}\r\n\r\n\/* ---- Dashboard hero strip ---- *\/\r\n#pg-page .dash-hero{background:var(--gradient-hero);color:var(--primary-foreground);position:relative;overflow:hidden}\r\n#pg-page .dash-hero-overlay{position:absolute;inset:0;opacity:.3;background:radial-gradient(ellipse at top right,rgba(255,205,5,.35),transparent 60%);pointer-events:none}\r\n#pg-page .dash-hero-inner{position:relative;max-width:78rem;margin:0 auto;padding:2rem 1rem 2.25rem}\r\n#pg-page .dash-hero .eyebrow{display:inline-flex;align-items:center;gap:.4rem;font-size:.7rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em;background:rgba(255,255,255,.15);padding:.3rem .7rem;border-radius:999px}\r\n#pg-page .dash-hero h1{font-size:1.6rem;font-weight:800;margin:.7rem 0 .25rem}\r\n#pg-page .dash-hero p{font-size:.9rem;color:rgba(255,255,255,.85)}\r\n@media(min-width:768px){#pg-page .dash-hero h1{font-size:2rem}}\r\n\r\n\/* ---- Main body ---- *\/\r\n#pg-page .dash-body{max-width:78rem;margin:0 auto;padding:1.25rem 1rem 2.5rem}\r\n\r\n\/* ---- Controls bar ---- *\/\r\n#pg-page .controls{display:flex;flex-wrap:wrap;gap:.6rem;align-items:center;background:var(--card);border:1px solid var(--border);border-radius:calc(var(--radius)+4px);padding:.75rem .9rem;box-shadow:var(--shadow-card);margin-bottom:1rem}\r\n#pg-page .ctl-label{font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted-foreground)}\r\n#pg-page .seg{display:inline-flex;border:1px solid var(--border);border-radius:calc(var(--radius) - 2px);overflow:hidden}\r\n#pg-page .seg button{padding:.4rem .85rem;border:none;background:var(--card);color:var(--foreground);font-family:inherit;font-size:.8125rem;font-weight:600;cursor:pointer;border-right:1px solid var(--border)}\r\n#pg-page .seg button:last-child{border-right:none}\r\n#pg-page .seg button.active{background:var(--primary);color:#fff}\r\n#pg-page select,#pg-page input[type=text],#pg-page input[type=date],#pg-page input[type=number]{font-family:inherit;padding:.42rem .55rem;border:1px solid var(--border);border-radius:calc(var(--radius) - 2px);font-size:.8125rem;color:var(--foreground);background:var(--card);outline:none}\r\n#pg-page select{cursor:pointer}\r\n#pg-page input[type=text]{cursor:text}\r\n#pg-page input:focus,#pg-page select:focus{border-color:var(--primary)}\r\n#pg-page .btn-accent{display:inline-flex;align-items:center;gap:.4rem;border-radius:calc(var(--radius) - 2px);background:var(--accent);padding:.5rem 1.1rem;font-family:inherit;font-size:.8125rem;font-weight:700;color:var(--accent-foreground);border:none;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.05);transition:filter .15s}\r\n#pg-page .btn-accent:hover{filter:brightness(.95)}\r\n#pg-page .btn-ghost{background:var(--secondary);color:var(--primary);border:1px solid var(--border);border-radius:calc(var(--radius) - 2px);padding:.5rem .9rem;font-family:inherit;font-size:.8125rem;font-weight:700;cursor:pointer}\r\n\r\n\/* ---- Tabs ---- *\/\r\n#pg-page .tabs{display:flex;gap:.2rem;border-bottom:2px solid var(--border);margin:.25rem 0 1.15rem;overflow-x:auto}\r\n#pg-page .tabs button{border:none;background:none;font-family:inherit;font-size:.9rem;font-weight:700;color:var(--muted-foreground);padding:.6rem .95rem;cursor:pointer;border-bottom:3px solid transparent;margin-bottom:-2px;display:inline-flex;align-items:center;gap:.4rem;white-space:nowrap}\r\n#pg-page .tabs button:hover{color:var(--foreground)}\r\n#pg-page .tabs button.active{color:var(--primary);border-bottom-color:var(--primary)}\r\n#pg-page .tabs button .cnt{font-size:.68rem;font-weight:800;background:var(--secondary);color:var(--primary);padding:.05rem .45rem;border-radius:999px}\r\n#pg-page .tabs button.warn .cnt{background:#fef2f2;color:var(--destructive)}\r\n\r\n\/* ---- Status ---- *\/\r\n#pg-page .status{font-size:.82rem;padding:.6rem .8rem;border-radius:calc(var(--radius) - 2px);margin-bottom:1rem;line-height:1.5}\r\n#pg-page .status.info{background:var(--secondary);color:var(--primary-deep);border:1px solid var(--border)}\r\n#pg-page .status.ok{background:#ecfdf5;color:var(--success);border:1px solid #a7f3d0}\r\n#pg-page .status.err{background:#fef2f2;color:var(--destructive);border:1px solid #fca5a5}\r\n\r\n\/* ---- Scorecards (Looker style) ---- *\/\r\n#pg-page .scorecards{display:grid;grid-template-columns:repeat(5,1fr);gap:.75rem;margin-bottom:1.25rem}\r\n#pg-page .sc{background:var(--card);border:1px solid var(--border);border-radius:calc(var(--radius)+4px);padding:.9rem 1rem;box-shadow:var(--shadow-card);border-top:3px solid var(--primary)}\r\n#pg-page .sc.accent{border-top-color:var(--accent)}\r\n#pg-page .sc.green{border-top-color:var(--success)}\r\n#pg-page .sc.amber{border-top-color:#f59e0b}\r\n#pg-page .sc.red{border-top-color:var(--destructive)}\r\n#pg-page .sc .lbl{font-size:.66rem;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--muted-foreground)}\r\n#pg-page .sc .val{font-size:1.55rem;font-weight:800;color:var(--primary);line-height:1.1;margin-top:.3rem}\r\n#pg-page .sc.accent .val{color:var(--primary-deep)}\r\n#pg-page .sc.green .val{color:var(--success)}\r\n#pg-page .sc.amber .val{color:#b45309}\r\n#pg-page .sc.red .val{color:var(--destructive)}\r\n#pg-page .sc .sub{font-size:.7rem;color:var(--muted-foreground);margin-top:.2rem}\r\n@media(max-width:1000px){#pg-page .scorecards{grid-template-columns:repeat(2,1fr)}}\r\n@media(max-width:560px){#pg-page .scorecards{grid-template-columns:1fr 1fr}#pg-page .sc .val{font-size:1.35rem}}\r\n\r\n\/* ---- Card \/ panel ---- *\/\r\n#pg-page .panel{background:var(--card);border:1px solid var(--border);border-radius:calc(var(--radius)+4px);padding:1rem 1.15rem;box-shadow:var(--shadow-card);margin-bottom:1.25rem}\r\n#pg-page .panel-head{display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-bottom:.9rem;flex-wrap:wrap}\r\n#pg-page .panel-title{font-size:1rem;font-weight:800;color:var(--foreground)}\r\n#pg-page .panel-sub{font-size:.72rem;color:var(--muted-foreground);font-weight:600}\r\n\r\n\/* ---- Table ---- *\/\r\n#pg-page .tbl-wrap{overflow:auto;max-height:min(66vh,620px);border-radius:calc(var(--radius) - 2px);border:1px solid var(--border)}\r\n#pg-page table{width:100%;border-collapse:collapse;font-size:.82rem}\r\n#pg-page thead th{position:sticky;top:0;z-index:4;background:var(--secondary);color:var(--primary-deep);font-size:.68rem;text-transform:uppercase;letter-spacing:.04em;font-weight:800;padding:.6rem .65rem;text-align:right;cursor:pointer;user-select:none;white-space:nowrap;border-bottom:2px solid var(--border)}\r\n#pg-page thead th.l,#pg-page tbody td.l{text-align:left}\r\n#pg-page thead th.sorted{color:var(--primary);background:#e8eefb}\r\n#pg-page tbody td{padding:.5rem .65rem;text-align:right;border-bottom:1px solid var(--border);white-space:nowrap;font-variant-numeric:tabular-nums}\r\n#pg-page tbody tr:hover{background:var(--secondary)}\r\n#pg-page td.branch{font-weight:700;color:var(--foreground)}\r\n#pg-page td.branch a{color:var(--foreground)} #pg-page td.branch a:hover{color:var(--primary)}\r\n#pg-page .rank{color:var(--muted-foreground);font-weight:700}\r\n#pg-page .medal{font-weight:800}\r\n#pg-page .bar-cell{position:relative}\r\n#pg-page .bar-fill{position:absolute;left:0;top:3px;bottom:3px;background:#e8eefb;border-radius:4px;z-index:0}\r\n#pg-page .bar-val{position:relative;z-index:1;font-weight:800}\r\n#pg-page .delta.up{color:var(--success);font-weight:800}\r\n#pg-page .delta.down{color:var(--destructive);font-weight:800}\r\n#pg-page .delta.flat{color:var(--muted-foreground)}\r\n#pg-page .muted{color:var(--muted-foreground)}\r\n\r\n\/* status badges *\/\r\n#pg-page .badge{display:inline-block;font-size:.66rem;font-weight:800;padding:.15rem .5rem;border-radius:999px;letter-spacing:.02em;text-transform:uppercase}\r\n#pg-page .badge.aktif{background:#ecfdf5;color:var(--success);border:1px solid #a7f3d0}\r\n#pg-page .badge.kurang{background:#fffbeb;color:#b45309;border:1px solid #fde68a}\r\n#pg-page .badge.pasif{background:#fef2f2;color:var(--destructive);border:1px solid #fca5a5}\r\n\r\n\/* days-ago color *\/\r\n#pg-page .ago{font-weight:700}\r\n#pg-page .ago.fresh{color:var(--success)}\r\n#pg-page .ago.warn{color:#b45309}\r\n#pg-page .ago.stale{color:var(--destructive)}\r\n\r\n\/* pivot sticky left column + heat *\/\r\n#pg-page table.pivot th.stick,#pg-page table.pivot td.stick{position:sticky;left:0;z-index:3;background:var(--card);text-align:left;box-shadow:1px 0 0 var(--border)}\r\n#pg-page table.pivot thead th.stick{z-index:6;background:var(--secondary)}\r\n#pg-page table.pivot td.heat{font-weight:700}\r\n#pg-page table.pivot td.zero{color:#c3c9d6}\r\n\r\n\/* banner *\/\r\n#pg-page .banner{display:flex;align-items:center;gap:1rem;background:linear-gradient(135deg,#fff,#fef2f2);border:1px solid #fca5a5;border-left:4px solid var(--destructive);border-radius:calc(var(--radius)+4px);padding:1rem 1.15rem;margin-bottom:1.15rem}\r\n#pg-page .banner .big{font-size:2.1rem;font-weight:800;color:var(--destructive);line-height:1;font-variant-numeric:tabular-nums}\r\n#pg-page .banner .txt{font-size:.86rem;color:var(--foreground)}\r\n#pg-page .banner.ok{background:linear-gradient(135deg,#fff,#ecfdf5);border-color:#a7f3d0;border-left-color:var(--success)}\r\n#pg-page .banner.ok .big{color:var(--success)}\r\n\r\n\/* apresiasi top list *\/\r\n#pg-page .toplist{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:repeat(5,auto);grid-auto-flow:column;gap:.1rem .9rem}\r\n@media(max-width:640px){#pg-page .toplist{grid-template-columns:1fr;grid-template-rows:none;grid-auto-flow:row}}\r\n#pg-page .toprow{display:flex;align-items:center;gap:.6rem;padding:.4rem .2rem;border-bottom:1px solid var(--border);font-size:.85rem}\r\n#pg-page .toprow .medal2{font-size:1rem;width:1.4rem;text-align:center;flex-shrink:0}\r\n#pg-page .toprow .nm{font-weight:700;flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\r\n#pg-page .toprow .n{font-weight:800;color:var(--success);flex-shrink:0}\r\n\r\n\/* ---- Charts ---- *\/\r\n#pg-page .chart-wrap{overflow-x:auto;position:relative}\r\n#pg-page svg{display:block;max-width:100%}\r\n#pg-page .line-tip{position:absolute;pointer-events:none;z-index:20;background:var(--foreground);color:#fff;font-size:.72rem;line-height:1.5;padding:.5rem .65rem;border-radius:8px;box-shadow:0 6px 18px -6px rgba(2,20,49,.5);white-space:nowrap;display:none;max-width:240px}\r\n#pg-page .line-tip .tt-h{font-weight:800;margin-bottom:.25rem;font-size:.72rem;color:var(--accent)}\r\n#pg-page .line-tip .tt-r{display:flex;align-items:center;gap:.4rem}\r\n#pg-page .line-tip .tt-sw{width:9px;height:9px;border-radius:2px;flex-shrink:0}\r\n#pg-page .line-tip .tt-v{margin-left:auto;font-weight:800;font-variant-numeric:tabular-nums}\r\n#pg-page .legend{display:flex;flex-wrap:wrap;gap:.45rem .9rem;margin-top:.6rem}\r\n#pg-page .lg{display:flex;align-items:center;gap:.35rem;font-size:.74rem;color:var(--foreground);cursor:pointer;user-select:none;font-weight:600}\r\n#pg-page .lg .sw{width:12px;height:12px;border-radius:3px;flex-shrink:0}\r\n#pg-page .lg.off{opacity:.35;text-decoration:line-through}\r\n#pg-page details{margin-bottom:1rem}\r\n#pg-page summary{cursor:pointer;font-size:.8rem;font-weight:700;color:var(--muted-foreground);padding:.3rem 0}\r\n#pg-page .hint{font-size:.72rem;color:var(--muted-foreground);margin-top:.5rem;line-height:1.55}\r\n#pg-page .settings-grid{display:flex;flex-wrap:wrap;gap:.75rem;margin-top:.6rem}\r\n#pg-page .fld{display:flex;flex-direction:column;gap:.25rem}\r\n#pg-page .fld label{font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--muted-foreground)}\r\n\r\n\/* ---- Footer (LOCKED) ---- *\/\r\n#pg-page .site-footer{background:var(--footer-bg);color:#fff}\r\n#pg-page .footer-grid{display:grid;grid-template-columns:1fr;gap:2.5rem;max-width:78rem;margin:0 auto;padding:3rem 1rem}\r\n#pg-page .footer-bottom{border-top:1px solid rgba(255,255,255,.15)}\r\n#pg-page .footer-bottom-inner{display:flex;flex-direction:column-reverse;align-items:center;justify-content:space-between;gap:.75rem;max-width:78rem;margin:0 auto;padding:1.25rem 1rem;font-size:.75rem;color:rgba(255,255,255,.8)}\r\n#pg-page .social-link{display:inline-flex;height:2rem;width:2rem;align-items:center;justify-content:center;border-radius:9999px;background:rgba(255,255,255,.1);transition:background .15s,color .15s;color:#fff}\r\n#pg-page .social-link:hover{background:var(--accent);color:var(--accent-foreground)}\r\n#pg-page .footer-nav-link{color:rgba(255,255,255,.85);transition:color .15s}\r\n#pg-page .footer-nav-link:hover{color:var(--accent)}\r\n@media(min-width:640px){#pg-page .footer-bottom-inner{flex-direction:row}}\r\n@media(min-width:768px){#pg-page .footer-grid{grid-template-columns:5fr 3fr 4fr}}\r\n\r\n\/* ---- WordPress theme overrides (dark sections) ---- *\/\r\n#pg-page .dash-hero h1,#pg-page .dash-hero p,#pg-page .dash-hero .eyebrow{color:#fff!important}\r\n#pg-page .dash-hero p{color:rgba(255,255,255,.85)!important}\r\n#pg-page .site-footer h1,#pg-page .site-footer h2,#pg-page .site-footer h3,#pg-page .site-footer h4{color:#fff!important}\r\n#pg-page .site-footer p,#pg-page .site-footer a,#pg-page .site-footer li{color:rgba(255,255,255,.85)!important}\r\n#pg-page .footer-bottom-inner,#pg-page .footer-bottom-inner span{color:rgba(255,255,255,.8)!important}\r\n<\/style>\r\n<\/head>\r\n<body>\r\n<div id=\"pg-page\">\r\n\r\n<!-- ===================== HEADER (LOCKED) ===================== -->\r\n<div class=\"site-header\">\r\n  <div class=\"header-inner\">\r\n    <a href=\"https:\/\/pandaigadai.com\" style=\"display:flex;align-items:center\">\r\n      <img decoding=\"async\" src=\"https:\/\/pandaigadai.com\/blog\/wp-content\/uploads\/2026\/01\/cropped-panda-1.webp\" alt=\"Pandai Gadai\" style=\"height:3rem;width:auto\">\r\n    <\/a>\r\n    <nav class=\"header-nav\">\r\n      <a href=\"https:\/\/pandaigadai.com\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"btn-header\">pandaigadai.com<\/a>\r\n    <\/nav>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- ===================== HERO ===================== -->\r\n<div class=\"dash-hero\">\r\n  <div class=\"dash-hero-overlay\"><\/div>\r\n  <div class=\"dash-hero-inner\">\r\n    <span class=\"eyebrow\">\ud83d\udccd Google Review Activity Tracker<\/span>\r\n    <h1>Keaktifan cabang minta Google review<\/h1>\r\n    <p>Pantau tiap cabang: siapa yang rajin minta review ke nasabah untuk diapresiasi, dan siapa yang pasif untuk ditegur.<\/p>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- ===================== CONTENT ===================== -->\r\n<div class=\"dash-body\">\r\n\r\n  <div id=\"status\" class=\"status info\">Siap. Klik <b>Muat \/ Refresh<\/b> untuk menarik data langsung dari Google Sheet.<\/div>\r\n\r\n  <!-- Controls (global) -->\r\n  <div class=\"controls\">\r\n    <button class=\"btn-accent\" onclick=\"RG.load()\">\u27f3 Muat \/ Refresh<\/button>\r\n    <span class=\"ctl-label\">Rentang tanggal:<\/span>\r\n    <select id=\"sel-range\" onchange=\"RG.setRange()\">\r\n      <option value=\"all\" selected>Semua waktu<\/option>\r\n      <option value=\"7\">7 hari terakhir<\/option>\r\n      <option value=\"30\">30 hari terakhir<\/option>\r\n      <option value=\"90\">90 hari terakhir<\/option>\r\n      <option value=\"month\">Bulan ini<\/option>\r\n      <option value=\"ytd\">Tahun ini<\/option>\r\n      <option value=\"custom\">Kustom\u2026<\/option>\r\n    <\/select>\r\n    <span id=\"custom-range\" style=\"display:none;align-items:center;gap:.4rem\">\r\n      <input type=\"date\" id=\"cfg-from\"> <span class=\"muted\">\u2014<\/span> <input type=\"date\" id=\"cfg-to\">\r\n      <button class=\"btn-ghost\" onclick=\"RG.applyCustom()\">Terapkan<\/button>\r\n    <\/span>\r\n    <span style=\"width:1px;height:1.4rem;background:var(--border)\"><\/span>\r\n    <span class=\"ctl-label\">Target review \/ cabang \/ bulan:<\/span>\r\n    <input type=\"number\" id=\"cfg-target\" value=\"8\" min=\"0\" step=\"1\" style=\"width:72px\" onchange=\"RG.render()\">\r\n  <\/div>\r\n\r\n  <details style=\"display:none\">\r\n    <summary>\u2699\ufe0f Pengaturan sumber data<\/summary>\r\n    <div class=\"settings-grid\">\r\n      <div class=\"fld\" style=\"flex:1;min-width:280px\"><label>Sheet ID (Dataset review)<\/label><input type=\"text\" id=\"cfg-id\" value=\"1tW7HybWuvBWjZVbQs-T1jDPgfSbbSdzkpGRUyXFqmU8\"><\/div>\r\n      <div class=\"fld\"><label>Tab Dataset (GID)<\/label><input type=\"text\" id=\"cfg-gid\" value=\"1992217644\" style=\"width:120px\"><\/div>\r\n      <div class=\"fld\"><label>Kolom huruf (title,date,reviews,city,url)<\/label><input type=\"text\" id=\"cfg-cols\" value=\"I,D,F,A,K\" style=\"width:170px\"><\/div>\r\n      <div class=\"fld\"><label>Tab Master (nama)<\/label><input type=\"text\" id=\"cfg-master\" value=\"Master\" style=\"width:120px\"><\/div>\r\n      <div class=\"fld\" style=\"flex:1;min-width:280px\"><label>Sheet ID (Belum Live)<\/label><input type=\"text\" id=\"cfg-belum-id\" value=\"1Yc1keL_w-6RfaFwdARo6HvmrrtFQnc2A6a-b8-1ljK0\"><\/div>\r\n      <div class=\"fld\"><label>Tab Belum Live (GID)<\/label><input type=\"text\" id=\"cfg-belum-gid\" value=\"0\" style=\"width:120px\"><\/div>\r\n    <\/div>\r\n    <div class=\"hint\">Dashboard membaca sheet lewat endpoint gviz Google (query kolom). Sheet harus dibagikan <b>\u201cSiapa saja yang memiliki link \u2192 Pelihat\u201d<\/b>. Kolom wajib: <b>title<\/b> (nama cabang) &amp; <b>publishedAtDate<\/b> (tanggal review). Buka file ini lewat <b>http:\/\/<\/b> (server lokal), bukan double-click file, supaya tidak diblokir CORS.<\/div>\r\n  <\/details>\r\n\r\n  <!-- ===================== TABS ===================== -->\r\n  <div class=\"tabs\" id=\"tabs\" style=\"display:none\">\r\n    <button data-tab=\"ringkasan\" class=\"active\" onclick=\"RG.setTab('ringkasan')\">\ud83d\udcca Ringkasan<\/button>\r\n    <button data-tab=\"tabel\" onclick=\"RG.setTab('tabel')\">\ud83d\udccb Tabel Cabang<\/button>\r\n    <button data-tab=\"pasif\" onclick=\"RG.setTab('pasif')\">\ud83d\udea8 Cabang Pasif <span class=\"cnt\" id=\"tab-pasif-cnt\">0<\/span><\/button>\r\n    <button data-tab=\"am\" onclick=\"RG.setTab('am')\">\ud83d\udc64 Ringkasan AM<\/button>\r\n    <button data-tab=\"belum\" onclick=\"RG.setTab('belum')\">\ud83d\udccd Belum Live <span class=\"cnt\" id=\"tab-belum-cnt\">0<\/span><\/button>\r\n  <\/div>\r\n\r\n  <!-- ===================== TAB: RINGKASAN ===================== -->\r\n  <section class=\"tabpane\" id=\"pane-ringkasan\" style=\"display:none\">\r\n    <div class=\"scorecards\" id=\"scorecards\">\r\n      <div class=\"sc\"><div class=\"lbl\">Cabang dilacak<\/div><div class=\"val\" id=\"k-branches\">\u2014<\/div><div class=\"sub\">total cabang<\/div><\/div>\r\n      <div class=\"sc accent\"><div class=\"lbl\">Review terkumpul<\/div><div class=\"val\" id=\"k-total\">\u2014<\/div><div class=\"sub\" id=\"k-total-sub\">rentang terpilih<\/div><\/div>\r\n      <div class=\"sc green\"><div class=\"lbl\">Cabang aktif<\/div><div class=\"val\" id=\"k-aktif\">\u2014<\/div><div class=\"sub\" id=\"k-aktif-sub\">\u2265 target (30 hari)<\/div><\/div>\r\n      <div class=\"sc amber\"><div class=\"lbl\">Kurang aktif<\/div><div class=\"val\" id=\"k-kurang\">\u2014<\/div><div class=\"sub\">di bawah target (30 hari)<\/div><\/div>\r\n      <div class=\"sc red\"><div class=\"lbl\">Pasif \u2014 perlu ditegur<\/div><div class=\"val\" id=\"k-pasif\">\u2014<\/div><div class=\"sub\">0 review (30 hari)<\/div><\/div>\r\n    <\/div>\r\n\r\n    <div class=\"panel\">\r\n      <div class=\"panel-head\">\r\n        <div class=\"panel-title\">\ud83c\udf89 Cabang paling aktif \u2014 30 hari terakhir<\/div>\r\n        <div class=\"panel-sub\" id=\"apresiasi-sub\"><\/div>\r\n      <\/div>\r\n      <div class=\"toplist\" id=\"toplist\"><\/div>\r\n    <\/div>\r\n\r\n    <div class=\"panel\">\r\n      <div class=\"panel-head\">\r\n        <div class=\"panel-title\">\ud83d\udcc8 Pertumbuhan review dari waktu ke waktu<\/div>\r\n        <div class=\"seg\" id=\"seg-metric\">\r\n          <button data-m=\"net\" class=\"active\" onclick=\"RG.setMetric('net')\">Per periode<\/button>\r\n          <button data-m=\"cum\" onclick=\"RG.setMetric('cum')\">Kumulatif<\/button>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"chart-wrap\" id=\"line-chart\"><\/div>\r\n      <div class=\"legend\" id=\"legend\"><\/div>\r\n      <div class=\"hint\">Dihitung dari tanggal review (publishedAtDate), granularitas ikut pilihan di tab \u201cTabel Cabang\u201d. Arahkan kursor ke grafik untuk melihat angkanya. Klik nama cabang di legenda untuk sembunyikan\/tampilkan. Default 10 cabang dengan review terbanyak.<\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- ===================== TAB: TABEL CABANG ===================== -->\r\n  <section class=\"tabpane\" id=\"pane-tabel\" style=\"display:none\">\r\n    <div class=\"panel\">\r\n      <div class=\"panel-head\">\r\n        <div class=\"panel-title\" id=\"tabel-title\">\ud83d\udccb Review per cabang<\/div>\r\n        <div style=\"display:flex;gap:.6rem;align-items:center;flex-wrap:wrap\">\r\n          <span class=\"ctl-label\" id=\"gran-label\" style=\"display:none\">Pecah per:<\/span>\r\n          <div class=\"seg\" id=\"seg-gran\" style=\"display:none\">\r\n            <button data-g=\"day\" onclick=\"RG.setGran('day')\">Harian<\/button>\r\n            <button data-g=\"week\" onclick=\"RG.setGran('week')\">Mingguan<\/button>\r\n            <button data-g=\"month\" class=\"active\" onclick=\"RG.setGran('month')\">Bulanan<\/button>\r\n          <\/div>\r\n          <div class=\"seg\" id=\"seg-mode\">\r\n            <button data-mode=\"ringkasan\" class=\"active\" onclick=\"RG.setMode('ringkasan')\">Ringkasan<\/button>\r\n            <button data-mode=\"timeline\" onclick=\"RG.setMode('timeline')\">Timeline<\/button>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"tbl-wrap\">\r\n        <table id=\"tbl\"><thead><tr id=\"thead-row\"><\/tr><\/thead><tbody id=\"tbody\"><\/tbody><\/table>\r\n      <\/div>\r\n      <div class=\"hint\" id=\"tabel-hint\"><\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- ===================== TAB: CABANG PASIF ===================== -->\r\n  <section class=\"tabpane\" id=\"pane-pasif\" style=\"display:none\">\r\n    <div class=\"banner\" id=\"pasif-banner\">\r\n      <div class=\"big\" id=\"pasif-big\">\u2014<\/div>\r\n      <div class=\"txt\" id=\"pasif-txt\"><\/div>\r\n    <\/div>\r\n\r\n    <div class=\"panel\">\r\n      <div class=\"panel-head\">\r\n        <div>\r\n          <div class=\"panel-title\">\ud83d\udea8 Pasif \u2014 0 review baru dalam 30 hari<\/div>\r\n          <div class=\"panel-sub\">urut dari yang paling lama tidak dapat review<\/div>\r\n        <\/div>\r\n        <div style=\"display:flex;gap:.4rem\">\r\n          <button class=\"btn-ghost\" onclick=\"RG.exportPasif('csv')\">\u2b07 CSV<\/button>\r\n          <button class=\"btn-ghost\" onclick=\"RG.exportPasif('xls')\">\u2b07 Excel<\/button>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"tbl-wrap\">\r\n        <table id=\"tbl-pasif\"><thead><tr>\r\n          <th class=\"l\">#<\/th><th class=\"l\">Cabang<\/th><th class=\"l\">Kota<\/th><th class=\"l\">AM<\/th>\r\n          <th>Review terakhir<\/th><th>Total review<\/th><th class=\"l\">Buka<\/th>\r\n        <\/tr><\/thead><tbody id=\"tbody-pasif\"><\/tbody><\/table>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"panel\">\r\n      <div class=\"panel-head\">\r\n        <div class=\"panel-title\">\ud83d\udfe1 Kurang aktif \u2014 ada review tapi di bawah target<\/div>\r\n        <div class=\"panel-sub\" id=\"kurang-sub\"><\/div>\r\n      <\/div>\r\n      <div class=\"tbl-wrap\">\r\n        <table id=\"tbl-kurang\"><thead><tr>\r\n          <th class=\"l\">#<\/th><th class=\"l\">Cabang<\/th><th class=\"l\">Kota<\/th><th class=\"l\">AM<\/th>\r\n          <th>30 hari<\/th><th>Target<\/th><th>Review terakhir<\/th><th class=\"l\">Buka<\/th>\r\n        <\/tr><\/thead><tbody id=\"tbody-kurang\"><\/tbody><\/table>\r\n      <\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- ===================== TAB: RINGKASAN AM ===================== -->\r\n  <section class=\"tabpane\" id=\"pane-am\" style=\"display:none\">\r\n    <div class=\"scorecards\" id=\"am-scorecards\" style=\"grid-template-columns:repeat(4,1fr)\">\r\n      <div class=\"sc\"><div class=\"lbl\">Jumlah AM<\/div><div class=\"val\" id=\"am-k-count\">\u2014<\/div><div class=\"sub\">area manager<\/div><\/div>\r\n      <div class=\"sc green\"><div class=\"lbl\">Cabang ter-cover<\/div><div class=\"val\" id=\"am-k-covered\">\u2014<\/div><div class=\"sub\">punya AM<\/div><\/div>\r\n      <div class=\"sc amber\"><div class=\"lbl\">Cabang tanpa AM<\/div><div class=\"val\" id=\"am-k-noam\">\u2014<\/div><div class=\"sub\">belum ada di Master<\/div><\/div>\r\n      <div class=\"sc red\"><div class=\"lbl\">AM dengan cabang pasif<\/div><div class=\"val\" id=\"am-k-warn\">\u2014<\/div><div class=\"sub\">perlu ditindak<\/div><\/div>\r\n    <\/div>\r\n    <div class=\"panel\">\r\n      <div class=\"panel-head\">\r\n        <div class=\"panel-title\">\ud83d\udc64 Status cabang per Area Manager<\/div>\r\n        <div class=\"panel-sub\">status 30 hari terakhir \u2022 klik judul kolom untuk mengurutkan<\/div>\r\n      <\/div>\r\n      <div class=\"tbl-wrap\">\r\n        <table id=\"tbl-am\"><thead><tr id=\"am-thead\"><\/tr><\/thead><tbody id=\"am-tbody\"><\/tbody><\/table>\r\n      <\/div>\r\n      <div class=\"hint\" id=\"am-hint\"><\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- ===================== TAB: BELUM LIVE ===================== -->\r\n  <section class=\"tabpane\" id=\"pane-belum\" style=\"display:none\">\r\n    <div class=\"banner\" id=\"belum-banner\">\r\n      <div class=\"big\" id=\"belum-big\">\u2014<\/div>\r\n      <div class=\"txt\" id=\"belum-txt\">Memuat data belum-live\u2026<\/div>\r\n    <\/div>\r\n    <div class=\"panel\">\r\n      <div class=\"panel-head\">\r\n        <div class=\"panel-title\">\ud83d\udccd Cabang belum live di Google Maps<\/div>\r\n        <div class=\"panel-sub\">sudah lewat Launch Date tapi kolom Q (Shortener Link) kosong \u2022 urut dari paling telat<\/div>\r\n      <\/div>\r\n      <div class=\"tbl-wrap\">\r\n        <table id=\"tbl-belum\"><thead><tr>\r\n          <th class=\"l\">#<\/th><th class=\"l\">Cabang<\/th><th class=\"l\">Area<\/th><th class=\"l\">AM<\/th>\r\n          <th>Launch Date<\/th><th>Telat<\/th>\r\n        <\/tr><\/thead><tbody id=\"belum-tbody\"><\/tbody><\/table>\r\n      <\/div>\r\n      <div class=\"hint\" id=\"belum-hint\"><\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <div class=\"hint\" id=\"footer-note\" style=\"display:none\"><\/div>\r\n<\/div>\r\n\r\n<!-- ===================== FOOTER (LOCKED) ===================== -->\r\n<div class=\"site-footer\">\r\n  <div class=\"footer-grid\">\r\n    <div>\r\n      <img decoding=\"async\" src=\"https:\/\/pandaigadai.com\/blog\/wp-content\/uploads\/2026\/01\/cropped-panda-1.webp\" alt=\"Pandai Gadai\" style=\"height:3.5rem;width:auto\">\r\n      <p style=\"margin-top:1.25rem;font-size:.875rem;color:rgba(255,255,255,0.85)\">Berizin dan Diawasi Otoritas Jasa Keuangan<\/p>\r\n      <p style=\"margin-top:.5rem;font-size:.875rem;font-weight:600\">Nomor Izin: KEP-180\/PL.02\/2023<\/p>\r\n    <\/div>\r\n    <div>\r\n      <h3 style=\"font-size:1rem;font-weight:700\">Navigasi<\/h3>\r\n      <ul style=\"margin-top:1rem;display:flex;flex-direction:column;gap:.625rem;font-size:.875rem;color:rgba(255,255,255,0.85)\">\r\n        <li><a href=\"https:\/\/pandaigadai.com\/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"footer-nav-link\">pandaigadai.com<\/a><\/li>\r\n      <\/ul>\r\n    <\/div>\r\n    <div>\r\n      <h3 style=\"font-size:1rem;font-weight:700\">Layanan Pengaduan Kantor Pusat<\/h3>\r\n      <p style=\"margin-top:1rem;font-size:.875rem;color:rgba(255,255,255,0.85)\">\r\n        Telepon: <a href=\"tel:085715322146\" class=\"footer-nav-link\">0857-1532-2146<\/a><br>\r\n        Email: <a href=\"mailto:hello@pandaigadai.com\" class=\"footer-nav-link\">hello@pandaigadai.com<\/a>\r\n      <\/p>\r\n    <\/div>\r\n  <\/div>\r\n  <div class=\"footer-bottom\">\r\n    <div class=\"footer-bottom-inner\">\r\n      <span>&copy; Copyright PT Solusi Gadai Pintar 2026 All Rights Reserved<\/span>\r\n      <div style=\"display:flex;align-items:center;gap:.75rem\">\r\n        <a href=\"https:\/\/www.instagram.com\/pandaigadai\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"Instagram\" class=\"social-link\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"height:1rem;width:1rem\"><rect x=\"2\" y=\"2\" width=\"20\" height=\"20\" rx=\"5\" ry=\"5\"\/><path d=\"M16 11.37A4 4 0 1112.63 8 4 4 0 0116 11.37z\"\/><line x1=\"17.5\" y1=\"6.5\" x2=\"17.51\" y2=\"6.5\"\/><\/svg><\/a>\r\n        <a href=\"https:\/\/www.tiktok.com\/@pandaigadai.id\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"TikTok\" class=\"social-link\"><svg viewBox=\"0 0 24 24\" fill=\"currentColor\" style=\"height:1rem;width:1rem\"><path d=\"M19.59 6.69a4.83 4.83 0 01-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 01-5.2 1.74 2.89 2.89 0 012.31-4.64 2.93 2.93 0 01.88.13V9.4a6.84 6.84 0 00-1-.05A6.33 6.33 0 005.8 20.1a6.34 6.34 0 0010.86-4.43V8.92a8.16 8.16 0 004.77 1.52V7A4.86 4.86 0 0119.59 6.69z\"\/><\/svg><\/a>\r\n        <a href=\"https:\/\/www.facebook.com\/pandaigadai\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"Facebook\" class=\"social-link\"><svg viewBox=\"0 0 24 24\" fill=\"currentColor\" style=\"height:1rem;width:1rem\"><path d=\"M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z\"\/><\/svg><\/a>\r\n        <a href=\"https:\/\/www.youtube.com\/@PandaiGadai\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"YouTube\" class=\"social-link\"><svg viewBox=\"0 0 24 24\" fill=\"currentColor\" style=\"height:1rem;width:1rem\"><path d=\"M23.498 6.186a3.016 3.016 0 00-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 00.502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 002.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 002.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814z\"\/><\/svg><\/a>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<\/div><!-- \/pg-page -->\r\n\r\n<script>\r\n(function(){\r\n'use strict';\r\nvar $=function(id){return document.getElementById(id);};\r\nvar PALETTE=['#02439F','#0255CA','#011455','#e8a800','#16a34a','#0891b2','#7c3aed','#db2777','#d97706','#0d9488','#4f46e5','#65a30d'];\r\nvar LS='rg_dash_pg_v3';\r\nvar DAY=86400000, MAXCOLS=40;\r\nvar state={gran:'month',metric:'net',mode:'ringkasan',tab:'ringkasan',range:'all',\r\n  sortKey:'l30',sortDir:-1,pivotKey:'first',pivotDir:1,amSort:{key:'pasif',dir:-1},\r\n  branches:[],timeline:[],hidden:{},raw:null,anchor:null,minDate:null,metrics:[],\r\n  amByBranch:{},amLoaded:false,belum:null,belumErr:false};\r\n\r\n\/* ---- prefs ---- *\/\r\n\/\/ Catatan: id\/gid\/cols sengaja TIDAK disimpan di localStorage \u2014 biar nilai di source HTML selalu jadi acuan (hindari config basi).\r\nfunction savePrefs(){try{localStorage.setItem(LS,JSON.stringify({gran:state.gran,metric:state.metric,mode:state.mode,tab:state.tab,range:state.range,\r\n  target:$('cfg-target').value}));}catch(e){}}\r\nfunction loadPrefs(){try{var p=JSON.parse(localStorage.getItem(LS)||'{}');\r\n  if(p.gran)state.gran=p.gran;if(p.metric)state.metric=p.metric;if(p.mode)state.mode=p.mode;if(p.tab)state.tab=p.tab;\r\n  if(p.range){state.range=p.range;$('sel-range').value=p.range;}\r\n  if(p.target)$('cfg-target').value=p.target;}catch(e){}}\r\n\r\nfunction setStatus(m,c){var s=$('status');s.style.display='block';s.className='status '+(c||'info');s.innerHTML=m;}\r\nfunction nf(n){return isFinite(n)?Math.round(n).toLocaleString('id-ID'):'\u2014';}\r\nfunction esc(s){return String(s==null?'':s).replace(\/[&<>\"']\/g,function(c){return{'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#39;'}[c];});}\r\nfunction clip(s,n){s=String(s||'');return s.length>n?s.slice(0,n-1)+'\u2026':s;}\r\nfunction shortName(s){s=String(s||'').trim();\r\n s=s.replace(\/^Pandai Gadai\\s*\/i,'');   \/\/ buang prefix brand\r\n s=s.replace(\/^[-\u2013\u2014]\\s*\/,'');            \/\/ buang tanda hubung di depan\r\n s=s.replace(\/^Cabang\\s+\/i,'');          \/\/ buang kata \"Cabang \" di depan\r\n s=s.replace(\/\\s*\\([^)]*\\)\\s*$\/,'');     \/\/ buang embel-embel \"(...)\" di belakang\r\n return s.trim();}\r\nfunction normName(s){s=String(s||'').trim();return \/^pandai gadai\/i.test(s)?s.replace(\/^pandai gadai\\s*\/i,'Pandai Gadai '):('Pandai Gadai '+s);}\r\n\/\/ key untuk join nama cabang antar-sheet (Dataset title <-> Master BRANCH <-> Belum Live Branch)\r\nfunction matchKey(s){s=String(s||'').replace(\/^pandai gadai\\s*\/i,'').toLowerCase();\r\n s=s.replace(\/\\(.*?\\)\/g,'').replace(\/^-\\s*cabang\\s*\/,'').replace(\/\\bcabang\\b\/g,'');\r\n return s.replace(\/[^a-z0-9]+\/g,' ').trim();}\r\nfunction normCity(s){s=String(s||'').trim();if(!s)return '';\r\n s=s.replace(\/\\bJkt\\b\/gi,'Jakarta').replace(\/\\bBks\\b\/gi,'Bekasi');\r\n if(\/^kabupaten\\s+\/i.test(s))return 'Kab. '+s.replace(\/^kabupaten\\s+\/i,'');\r\n if(\/^kota\\s+\/i.test(s))return s.replace(\/^kota\\s+\/i,'');\r\n return s;}\r\nfunction num(v){if(v==null)return null;var n=parseFloat(String(v).replace(\/[^0-9.\\-]\/g,''));return isFinite(n)?n:null;}\r\nfunction target(){var t=parseInt($('cfg-target').value,10);return isFinite(t)&&t>=0?t:8;}\r\n\r\n\/* ---- CSV parser ---- *\/\r\nfunction parseCSV(text){var rows=[],row=[],cur='',i=0,q=false;while(i<text.length){var c=text[i];\r\n if(q){if(c==='\"'){if(text[i+1]==='\"'){cur+='\"';i++;}else q=false;}else cur+=c;}\r\n else{if(c==='\"')q=true;else if(c===','){row.push(cur);cur='';}else if(c==='\\n'){row.push(cur);rows.push(row);row=[];cur='';}else if(c==='\\r'){}else cur+=c;}\r\n i++;}\r\n if(cur.length||row.length){row.push(cur);rows.push(row);}return rows;}\r\n\r\nfunction pickCols(header){var norm=header.map(function(h){return String(h).trim().toLowerCase();});\r\n function find(){for(var a=0;a<arguments.length;a++){var i=norm.indexOf(arguments[a]);if(i>=0)return i;}return -1;}\r\n return{title:find('title','branch','cabang'),date:find('publishedatdate','publishedat','date','reviewdate'),\r\n  stars:find('stars','rating','star'),city:find('city','kota'),count:find('reviewscount','totalreviews','reviews'),\r\n  score:find('totalscore','averagerating','avgrating'),url:find('url','placeurl','link'),\r\n  id:find('reviewid','review_id','reviewurl','reviewurlid','id')};}\r\n\r\n\/* ---- dates ---- *\/\r\nfunction parseDate(v){if(v==null||v==='')return null;var s=String(v).trim();var d=new Date(s);\r\n if(isNaN(d)){var m=s.match(\/^(\\d{4})-(\\d{1,2})-(\\d{1,2})\/);if(m)d=new Date(Date.UTC(+m[1],+m[2]-1,+m[3]));}\r\n return isNaN(d)?null:d;}\r\nfunction bucketKey(t,g){var d=new Date(t),y=d.getUTCFullYear();\r\n if(g==='month')return y+'-'+String(d.getUTCMonth()+1).padStart(2,'0');\r\n if(g==='week'){var dt=new Date(Date.UTC(y,d.getUTCMonth(),d.getUTCDate()));var day=(dt.getUTCDay()+6)%7;dt.setUTCDate(dt.getUTCDate()-day);return dt.toISOString().slice(0,10);}\r\n return d.toISOString().slice(0,10);}\r\nfunction bucketLabel(k,g){if(g==='month'){var p=k.split('-');return new Date(p[0],p[1]-1,1).toLocaleDateString('id-ID',{month:'short',year:'numeric'});}\r\n if(g==='week')return 'mgg '+k.slice(5);return k.slice(5);}\r\nfunction dmy(t){return new Date(t).toLocaleDateString('id-ID',{day:'numeric',month:'short',year:'numeric'});}\r\nfunction agoText(days){if(days==null)return{t:'belum ada',c:'stale'};if(days<=0)return{t:'hari ini',c:'fresh'};if(days===1)return{t:'kemarin',c:'fresh'};\r\n var c=days<=7?'fresh':(days<=30?'warn':'stale');return{t:days+' hr lalu',c:c};}\r\n\r\n\/* ---- load with fallback cascade ---- *\/\r\nfunction cbucket(){return Math.floor(Date.now()\/300000);} \/\/ bucket 5 menit: refresh sering = nempel cache Google (cepat), data tetap segar tiap ~5 menit\r\nfunction buildUrl(kind,cols){var id=$('cfg-id').value.trim(),gid=encodeURIComponent($('cfg-gid').value.trim());\r\n var base='https:\/\/docs.google.com\/spreadsheets\/d\/'+id,cb='&_cb='+cbucket();\r\n if(kind==='sel')return base+'\/gviz\/tq?tqx=out:csv&tq='+encodeURIComponent('select '+cols)+'&gid='+gid+cb;\r\n if(kind==='all')return base+'\/gviz\/tq?tqx=out:csv&tq='+encodeURIComponent('select *')+'&gid='+gid+cb;\r\n return base+'\/export?format=csv&gid='+gid+cb;}\r\n\r\nfunction tryFetch(url){return fetch(url,{credentials:'omit'}).then(function(r){\r\n if(!r.ok)throw new Error('HTTP '+r.status);var ct=r.headers.get('content-type')||'';return r.text().then(function(t){\r\n  if(\/text\\\/html\/i.test(ct)||new RegExp('<'+'html','i').test(t.slice(0,200)))throw new Error('html');\r\n  var rows=parseCSV(t).filter(function(x){return x.length>1||(x.length===1&&x[0]!=='');});\r\n  if(rows.length<2)throw new Error('empty');var cols=pickCols(rows[0]);\r\n  if(cols.title<0||cols.date<0)throw new Error('cols');return{rows:rows,cols:cols};});});}\r\n\r\nfunction load(){\r\n if(!$('cfg-id').value.trim()){setStatus('Isi Sheet ID di pengaturan sumber data.','err');return;}\r\n setStatus('Memuat data langsung dari sheet\u2026','info');savePrefs();\r\n var attempts=[buildUrl('sel',$('cfg-cols').value.trim()||'I,D,F,A,K'),buildUrl('all'),buildUrl('exp')];\r\n var idx=0;\r\n function next(){\r\n  if(idx>=attempts.length){\r\n   setStatus('Gagal memuat sheet. <b>Pastikan sheet dibagikan \u201cSiapa saja yang memiliki link \u2192 Pelihat\u201d.<\/b> Kalau browser memblokir karena CORS, buka file ini lewat server lokal (http:\/\/), bukan double-click.','err');return;}\r\n  tryFetch(attempts[idx]).then(function(res){ingest(res.rows,res.cols);}).catch(function(){idx++;next();});\r\n }\r\n next();\r\n}\r\n\r\n\/* ---- aux sources: Master (AM) + Belum Live sheet ---- *\/\r\nfunction fetchCsvRaw(url){return fetch(url,{credentials:'omit'}).then(function(r){\r\n if(!r.ok)throw new Error('HTTP '+r.status);return r.text().then(function(t){\r\n  if(new RegExp('<'+'html','i').test(t.slice(0,200)))throw new Error('html');\r\n  return parseCSV(t).filter(function(x){return x.length>1||(x.length===1&&x[0]!=='');});});});}\r\nfunction normHdr(h){return String(h).trim().toLowerCase().replace(\/\\s+\/g,' ');}\r\nfunction findHdr(hdr){var norm=hdr.map(normHdr);return function(){for(var a=0;a<arguments.length;a++){var i=norm.indexOf(arguments[a]);if(i>=0)return i;}return -1;};}\r\n\r\nfunction loadAux(){\r\n var id=$('cfg-id').value.trim(),master=encodeURIComponent(($('cfg-master')?$('cfg-master').value.trim():'Master')||'Master');\r\n var mUrl='https:\/\/docs.google.com\/spreadsheets\/d\/'+id+'\/gviz\/tq?tqx=out:csv&sheet='+master+'&_cb='+cbucket();\r\n fetchCsvRaw(mUrl).then(function(rows){buildAM(rows);render();}).catch(function(){state.amLoaded=false;});\r\n var bid=($('cfg-belum-id')?$('cfg-belum-id').value.trim():''),bgid=encodeURIComponent($('cfg-belum-gid')?$('cfg-belum-gid').value.trim():'0');\r\n if(bid){var bUrl='https:\/\/docs.google.com\/spreadsheets\/d\/'+bid+'\/gviz\/tq?tqx=out:csv&gid='+bgid+'&_cb='+cbucket();\r\n  fetchCsvRaw(bUrl).then(function(rows){state.belum=parseBelum(rows);state.belumErr=false;renderBelum();syncTabCounts();}).catch(function(){state.belumErr=true;renderBelum();});}\r\n}\r\n\r\nfunction buildAM(rows){if(!rows||rows.length<2)return;\r\n var f=findHdr(rows[0]);var bi=f('branch','cabang','branch name','nama cabang'),mi=f('area manager name','area manager','am','manager'),ai=f('area','wilayah');\r\n if(bi<0)return;var map={};\r\n for(var r=1;r<rows.length;r++){var row=rows[r];if(!row)continue;var b=(row[bi]||'').trim();if(!b)continue;\r\n  var k=matchKey(b);if(!map[k])map[k]={am:mi>=0?(row[mi]||'').trim():'',area:ai>=0?(row[ai]||'').trim():''};}\r\n state.amByBranch=map;state.amLoaded=true;}\r\n\r\nfunction parseLaunch(s){s=String(s||'').trim();if(!s)return null;var d=new Date(s);\r\n if(isNaN(d)){var m=s.match(\/^(\\d{4})-(\\d{1,2})-(\\d{1,2})\/);if(m)d=new Date(Date.UTC(+m[1],+m[2]-1,+m[3]));}\r\n return isNaN(d)?null:d;}\r\nfunction parseBelum(rows){if(!rows||rows.length<2)return{items:[],totalBranch:0,pastCount:0};\r\n var f=findHdr(rows[0]);\r\n var bi=f('branch','cabang','nama cabang'),ai=f('area','wilayah'),di=f('launch date','launchdate','tanggal launch'),\r\n     qi=f('google maps shortener link','shortener link','google maps shortener'),pi=f('link google maps','google maps link','link maps');\r\n var now=Date.now(),items=[],totalBranch=0,pastCount=0;\r\n for(var r=1;r<rows.length;r++){var row=rows[r];if(!row)continue;var b=(bi>=0?(row[bi]||''):'').trim();if(!b)continue;totalBranch++;\r\n  var ld=di>=0?parseLaunch(row[di]):null;if(!ld)continue;var ldm=ld.getTime();if(ldm>now)continue;pastCount++;\r\n  var q=(qi>=0?(row[qi]||''):'').trim();if(q)continue; \/\/ ada shortener = sudah live\r\n  var days=Math.floor((now-ldm)\/DAY);\r\n  var amInfo=state.amByBranch[matchKey(b)]||null;\r\n  items.push({branch:b,area:(ai>=0?(row[ai]||''):'').trim(),am:amInfo?amInfo.am:'',launch:ldm,days:days,maps:(pi>=0?(row[pi]||''):'').trim()});\r\n }\r\n items.sort(function(a,b){return b.days-a.days;});\r\n return{items:items,totalBranch:totalBranch,pastCount:pastCount};}\r\n\r\nfunction ingest(rows,cols){\r\n var byB={},total=0,undated=0,dup=0,seen={};\r\n for(var r=1;r<rows.length;r++){var row=rows[r];if(!row)continue;\r\n  var name=(row[cols.title]||'').trim();if(!name)continue;\r\n  \/\/ dedup baris review yang sama \u2014 cegah double-count saat append hasil scrape baru.\r\n  \/\/ Pakai reviewId\/reviewUrl kalau ada; kalau tidak, pakai kombinasi nama cabang + publishedAtDate (presisi milidetik = unik).\r\n  var dkey;\r\n  if(cols.id>=0){dkey=(row[cols.id]||'').trim();}\r\n  else{var ds=(row[cols.date]||'').trim();dkey=ds?(name+'|'+ds):'';}\r\n  if(dkey){if(seen[dkey]){dup++;continue;}seen[dkey]=1;}\r\n  total++;\r\n  var d=parseDate(row[cols.date]);if(!d){undated++;}\r\n  if(!byB[name])byB[name]={name:name,city:cols.city>=0?normCity(row[cols.city]||''):'',url:cols.url>=0?(row[cols.url]||'').trim():'',gReviews:null,gScore:null,dts:[],stars:[]};\r\n  var b=byB[name];if(d)b.dts.push(d.getTime());\r\n  if(cols.stars>=0){var s=num(row[cols.stars]);if(s)b.stars.push(s);}\r\n  \/\/ reviewsCount = snapshot total Google per scrape; ambil MAX supaya selalu nilai terbaru walau baris lama & baru bercampur\r\n  if(cols.count>=0){var c=num(row[cols.count]);if(c!=null&&(b.gReviews==null||c>b.gReviews))b.gReviews=c;}\r\n  if(cols.score>=0){var sc=num(row[cols.score]);if(sc!=null&&(b.gScore==null||sc>b.gScore))b.gScore=sc;}\r\n }\r\n state.raw_dup=dup;\r\n state.branches=Object.keys(byB).map(function(k){return byB[k];});\r\n var minD=Infinity,maxD=-Infinity;\r\n state.branches.forEach(function(b){b.dts.sort(function(x,y){return x-y;});\r\n  if(b.dts.length){if(b.dts[0]<minD)minD=b.dts[0];if(b.dts[b.dts.length-1]>maxD)maxD=b.dts[b.dts.length-1];}\r\n  b.avgStars=b.stars.length?b.stars.reduce(function(a,c){return a+c;},0)\/b.stars.length:(b.gScore||null);\r\n  if(b.gReviews==null)b.gReviews=b.dts.length; });\r\n state.anchor=isFinite(maxD)?maxD:Date.now();\r\n state.minDate=isFinite(minD)?minD:state.anchor;\r\n state.raw={total:total,undated:undated,rows:rows.length-1};\r\n state.hidden={};\r\n $('tabs').style.display='flex';\r\n assignColors();\r\n buildTimeline();\r\n render();\r\n loadAux();\r\n setStatus('\u2713 Termuat '+nf(state.raw.total)+' review dari '+state.branches.length+' cabang. Data terbaru: <b>'+dmy(state.anchor)+'<\/b>.'+(state.raw_dup?(' <b>'+nf(state.raw_dup)+' baris duplikat dibuang.<\/b>'):'')+(undated?(' '+nf(undated)+' baris tanpa tanggal dilewati.'):''),'ok');\r\n}\r\n\r\n\/* ---- color assignment (top branches by all-time review count) ---- *\/\r\nfunction assignColors(){\r\n var top=state.branches.slice().sort(function(a,b){return b.dts.length-a.dts.length;});\r\n state.branches.forEach(function(b){b.color=null;});\r\n top.forEach(function(b,i){b._rank=i;if(i<12)b.color=PALETTE[i%PALETTE.length];if(i>=10)state.hidden[b.name]=true;});\r\n}\r\n\r\n\/* ---- all-time timeline (for growth line chart) ---- *\/\r\nfunction buildTimeline(){\r\n var g=state.gran,keys={};\r\n state.branches.forEach(function(b){b.net={};b.dts.forEach(function(t){var k=bucketKey(t,g);b.net[k]=(b.net[k]||0)+1;keys[k]=1;});});\r\n state.timeline=Object.keys(keys).sort();\r\n state.branches.forEach(function(b){b.cum={};var run=0;state.timeline.forEach(function(k){run+=b.net[k]||0;b.cum[k]=run;});});\r\n}\r\n\r\n\/* ---- window from date filter ---- *\/\r\nfunction computeWindow(){\r\n var a=state.anchor,r=state.range,s,e=a,label;\r\n var ad=new Date(a);\r\n if(r==='all'){s=-Infinity;e=Infinity;label='Semua waktu';}\r\n else if(r==='7'||r==='30'||r==='90'){s=a-(+r)*DAY;label=r+' hari terakhir';}\r\n else if(r==='month'){s=Date.UTC(ad.getUTCFullYear(),ad.getUTCMonth(),1);label='Bulan '+ad.toLocaleDateString('id-ID',{month:'long',year:'numeric'});}\r\n else if(r==='ytd'){s=Date.UTC(ad.getUTCFullYear(),0,1);label='Tahun '+ad.getUTCFullYear();}\r\n else if(r==='custom'){\r\n  var fs=$('cfg-from').value,ts=$('cfg-to').value;\r\n  s=fs?Date.parse(fs+'T00:00:00Z'):-Infinity;\r\n  e=ts?Date.parse(ts+'T23:59:59Z'):Infinity;\r\n  label='Kustom'+((fs||ts)?(' ('+(fs||'awal')+' \u2192 '+(ts||'akhir')+')'):'');\r\n } else {s=-Infinity;e=Infinity;label='Semua waktu';}\r\n return{s:s,e:e,label:label};\r\n}\r\n\r\n\/* ---- compute per-branch metrics for current window + recency ---- *\/\r\nfunction computeMetrics(){\r\n var win=state.win=computeWindow();\r\n var a=state.anchor,s30=a-30*DAY,s60=a-60*DAY,g=state.gran,t=target();\r\n var keySet={};\r\n state.metrics=state.branches.map(function(b){\r\n  var winCnt=0,l30=0,p30=0,winNet={},dts=b.dts;\r\n  for(var i=0;i<dts.length;i++){var tt=dts[i];\r\n   if(tt>=win.s&&tt<=win.e){winCnt++;var k=bucketKey(tt,g);winNet[k]=(winNet[k]||0)+1;keySet[k]=1;}\r\n   if(tt>s30)l30++;else if(tt>s60)p30++;\r\n  }\r\n  var last=dts.length?dts[dts.length-1]:null;\r\n  var first=dts.length?dts[0]:null;\r\n  var days=last!=null?Math.floor((a-last)\/DAY):null;\r\n  var isNew=first!=null&&first>s30;\r\n  var delta=l30-p30, growth=p30>0?(delta\/p30*100):(l30>0?null:0);\r\n  var status=l30===0?'pasif':(l30<t?'kurang':'aktif');\r\n  var amInfo=state.amByBranch[matchKey(b.name)]||null;\r\n  return{name:b.name,city:b.city,url:b.url,gReviews:b.gReviews,avg:b.avgStars,\r\n   am:amInfo?amInfo.am:'',area:amInfo?amInfo.area:'',\r\n   win:winCnt,l30:l30,p30:p30,delta:delta,growth:growth,last:last,first:first,isNew:isNew,days:days,status:status,winNet:winNet,color:b.color,rank:b._rank};\r\n });\r\n \/\/ pivot columns: sorted keys within window, cap to most recent MAXCOLS\r\n var keys=Object.keys(keySet).sort();\r\n state.pivotCapped=keys.length>MAXCOLS;\r\n state.pivotKeys=keys.slice(-MAXCOLS);\r\n}\r\n\r\n\/* ================= RENDER ================= *\/\r\nfunction render(){\r\n if(!state.branches.length)return;\r\n syncControls();\r\n computeMetrics();\r\n var m=state.metrics,t=target(),win=state.win;\r\n var aktif=0,kurang=0,pasif=0,winTotal=0;\r\n m.forEach(function(x){winTotal+=x.win;if(x.status==='aktif')aktif++;else if(x.status==='kurang')kurang++;else pasif++;});\r\n\r\n \/\/ scorecards\r\n $('k-branches').textContent=state.branches.length;\r\n $('k-total').textContent=nf(winTotal);\r\n $('k-total-sub').textContent=win.label;\r\n $('k-aktif').textContent=aktif;\r\n $('k-aktif-sub').textContent='\u2265 '+t+' review (30 hari)';\r\n $('k-kurang').textContent=kurang;\r\n $('k-pasif').textContent=pasif;\r\n syncTabCounts();\r\n\r\n renderTopList(m);\r\n renderLine();\r\n renderTableTab(m);\r\n renderPasif(m,t);\r\n renderAM(m);\r\n\r\n $('footer-note').style.display='block';\r\n $('footer-note').innerHTML='Sumber: '+nf(state.raw.rows)+' baris \u2022 '+state.branches.length+' cabang \u2022 rentang: '+esc(win.label)+' \u2022 target '+t+'\/bln \u2022 anchor '+dmy(state.anchor)+' \u2022 diperbarui '+new Date().toLocaleString('id-ID');\r\n}\r\n\r\n\/* ---- apresiasi top list (last 30 days) ---- *\/\r\nfunction renderTopList(m){\r\n \/\/ exclude cabang baru (review pertama dalam 30 hari terakhir) \u2014 bulan pertama SOP-nya agresif, ini soal disiplin maintain\r\n var arr=m.filter(function(x){return x.l30>0&&!x.isNew;}).sort(function(a,b){return b.l30-a.l30;}).slice(0,10);\r\n var excluded=m.filter(function(x){return x.l30>0&&x.isNew;}).length;\r\n var wrap=$('toplist');\r\n if(!arr.length){wrap.innerHTML='<div class=\"hint\">Belum ada cabang lama dengan review baru dalam 30 hari terakhir.<\/div>';$('apresiasi-sub').textContent='';return;}\r\n $('apresiasi-sub').textContent='s\/d '+dmy(state.anchor)+(excluded?(' \u2022 '+excluded+' cabang baru dikecualikan'):'');\r\n var medals=['\ud83e\udd47','\ud83e\udd48','\ud83e\udd49'];\r\n wrap.innerHTML=arr.map(function(x,i){\r\n  return '<div class=\"toprow\"><span class=\"medal2\">'+(i<3?medals[i]:(i+1))+'<\/span>'+\r\n   '<span class=\"nm\">'+(x.url?'<a href=\"'+esc(x.url)+'\" target=\"_blank\" rel=\"noopener\">'+esc(shortName(x.name))+'<\/a>':esc(shortName(x.name)))+'<\/span>'+\r\n   '<span class=\"n\">+'+nf(x.l30)+'<\/span><\/div>';\r\n }).join('');\r\n}\r\n\r\n\/* ---- table tab (two modes) ---- *\/\r\nvar SUMCOLS=[{k:'rank',t:'#',s:false,l:true},{k:'name',t:'Cabang',s:true,l:true},{k:'city',t:'Kota',s:true,l:true},{k:'am',t:'AM',s:true,l:true},\r\n {k:'win',t:'Terekam',s:true},{k:'gReviews',t:'Google',s:true},{k:'l30',t:'30 hari',s:true},{k:'delta',t:'vs 30hr lalu',s:true},\r\n {k:'days',t:'Review terakhir',s:true},{k:'status',t:'Status',s:true}];\r\nvar STORD={pasif:0,kurang:1,aktif:2};\r\n\r\nfunction renderTableTab(m){\r\n if(state.mode==='timeline'){renderPivot(m);} else {renderSummary(m);}\r\n}\r\n\r\nfunction renderSummary(m){\r\n $('tabel-title').textContent='\ud83d\udccb Review per cabang \u2014 ringkasan';\r\n $('seg-gran').style.display='none';$('gran-label').style.display='none';\r\n $('tbl').className='';\r\n var th=$('thead-row');th.innerHTML='';\r\n SUMCOLS.forEach(function(c){var el=document.createElement('th');\r\n  var lbl=c.k==='win'?('Terekam ('+shortRange()+')'):c.t;\r\n  el.textContent=lbl+(state.sortKey===c.k?(state.sortDir<0?' \u25bc':' \u25b2'):'');\r\n  if(c.k==='gReviews')el.title='Total review di Google saat ini (reviewsCount)';\r\n  if(c.k==='win')el.title='Jumlah review bertanggal yang terekam di sheet pada rentang terpilih';\r\n  el.className=(c.l?'l':'')+(state.sortKey===c.k?' sorted':'');\r\n  if(c.s)el.onclick=function(){if(state.sortKey===c.k)state.sortDir*=-1;else{state.sortKey=c.k;state.sortDir=(c.k==='name'||c.k==='city'||c.k==='am')?1:-1;}render();};\r\n  th.appendChild(el);});\r\n var sorted=m.slice().sort(function(a,b){var k=state.sortKey,x=a[k],y=b[k];\r\n  if(k==='status'){x=STORD[a.status];y=STORD[b.status];}\r\n  if(k==='days'){x=a.days==null?Infinity:a.days;y=b.days==null?Infinity:b.days;}\r\n  if(typeof x==='string')return state.sortDir*x.localeCompare(y);return state.sortDir*((x||0)-(y||0));});\r\n var maxWin=Math.max.apply(null,m.map(function(r){return r.win||0;}))||1;\r\n var body=$('tbody');body.innerHTML='';\r\n sorted.forEach(function(r,i){var tr=document.createElement('tr');\r\n  var nameCell=r.url?('<a href=\"'+esc(r.url)+'\" target=\"_blank\" rel=\"noopener\">'+esc(shortName(r.name))+'<\/a>'):esc(shortName(r.name));\r\n  var dcls='flat',dtxt='0';if(r.delta>0){dcls='up';dtxt='\u25b2 '+nf(r.delta);}else if(r.delta<0){dcls='down';dtxt='\u25bc '+nf(-r.delta);}\r\n  var ago=agoText(r.days);\r\n  var barW=Math.round((r.win||0)\/maxWin*100);\r\n  tr.innerHTML='<td class=\"l rank\">'+(i+1)+'<\/td>'+\r\n   '<td class=\"l branch\">'+nameCell+'<\/td>'+\r\n   '<td class=\"l muted\">'+esc(r.city||'\u2014')+'<\/td>'+\r\n   '<td class=\"l\">'+(r.am?esc(r.am):'<span class=\"muted\">\u2014<\/span>')+'<\/td>'+\r\n   '<td class=\"bar-cell\"><span class=\"bar-fill\" style=\"width:'+barW+'%\"><\/span><span class=\"bar-val\">'+nf(r.win)+'<\/span><\/td>'+\r\n   '<td class=\"muted\">'+nf(r.gReviews)+'<\/td>'+\r\n   '<td style=\"font-weight:700\">'+nf(r.l30)+'<\/td>'+\r\n   '<td class=\"delta '+dcls+'\">'+dtxt+'<\/td>'+\r\n   '<td class=\"ago '+ago.c+'\">'+ago.t+'<\/td>'+\r\n   '<td><span class=\"badge '+r.status+'\">'+r.status+'<\/span><\/td>';\r\n  body.appendChild(tr);});\r\n $('tabel-hint').innerHTML='<b>Terekam<\/b> = jumlah review bertanggal di sheet pada rentang terpilih ('+esc(state.win.label)+'). <b>Google<\/b> = total review di Google saat ini (termasuk rating tanpa teks, jadi biasanya lebih besar dari Terekam). <b>30 hari<\/b> &amp; <b>Status<\/b> selalu memakai 30 hari terakhir s\/d '+dmy(state.anchor)+' (Aktif \u2265 target, Kurang aktif &lt; target, Pasif = 0). Klik judul kolom untuk mengurutkan.';\r\n}\r\n\r\nfunction shortRange(){var r=state.range;return r==='all'?'semua':(r==='month'?'bln ini':(r==='ytd'?'thn ini':(r==='custom'?'kustom':r+'hr')));}\r\n\r\nvar PIVCOLS=[{k:'name',t:'Cabang'},{k:'first',t:'Pertama'},{k:'gReviews',t:'Google'},{k:'win',t:'Terekam'}];\r\nfunction renderPivot(m){\r\n $('tabel-title').textContent='\ud83d\udccb Review per cabang \u2014 timeline';\r\n $('seg-gran').style.display='inline-flex';$('gran-label').style.display='inline';\r\n $('tbl').className='pivot';\r\n var keys=state.pivotKeys,g=state.gran;\r\n var pk=state.pivotKey,pd=state.pivotDir;\r\n var sorted=m.slice().sort(function(a,b){var x,y;\r\n  if(pk==='name'){return pd*shortName(a.name).localeCompare(shortName(b.name));}\r\n  if(pk==='first'){x=a.first==null?Infinity:a.first;y=b.first==null?Infinity:b.first;}\r\n  else{x=a[pk]||0;y=b[pk]||0;}\r\n  return pd*(x-y);});\r\n var maxCell=1;sorted.forEach(function(r){keys.forEach(function(k){var v=r.winNet[k]||0;if(v>maxCell)maxCell=v;});});\r\n var th=$('thead-row');th.innerHTML='';\r\n var h='';\r\n PIVCOLS.forEach(function(c){var arrow=pk===c.k?(pd<0?' \u25bc':' \u25b2'):'';\r\n  var cls=(c.k==='name'?'l stick':'')+(pk===c.k?' sorted':'');\r\n  h+='<th class=\"'+cls+'\" data-pk=\"'+c.k+'\">'+c.t+arrow+'<\/th>';});\r\n keys.forEach(function(k){h+='<th>'+esc(bucketLabel(k,g))+'<\/th>';});\r\n th.innerHTML=h;\r\n th.querySelectorAll('th[data-pk]').forEach(function(el){el.onclick=function(){var k=el.getAttribute('data-pk');\r\n  if(state.pivotKey===k)state.pivotDir*=-1;else{state.pivotKey=k;state.pivotDir=(k==='name'||k==='first')?1:-1;}render();};});\r\n var body=$('tbody');body.innerHTML='';\r\n sorted.forEach(function(r){var tr=document.createElement('tr');\r\n  var nm=shortName(r.name);\r\n  var nameCell=r.url?('<a href=\"'+esc(r.url)+'\" target=\"_blank\" rel=\"noopener\">'+esc(nm)+'<\/a>'):esc(nm);\r\n  var firstTxt=r.first!=null?dmy(r.first):'\u2014';\r\n  var row='<td class=\"l stick branch\">'+nameCell+'<\/td>'+\r\n   '<td class=\"muted\" style=\"white-space:nowrap\">'+firstTxt+'<\/td>'+\r\n   '<td class=\"muted\">'+nf(r.gReviews)+'<\/td>'+\r\n   '<td style=\"font-weight:800;color:var(--primary)\">'+nf(r.win)+'<\/td>';\r\n  keys.forEach(function(k){var v=r.winNet[k]||0;\r\n   if(!v){row+='<td class=\"zero\">\u00b7<\/td>';}\r\n   else{var ratio=v\/maxCell,al=(0.10+0.72*ratio).toFixed(2),col=ratio>0.55?'#fff':'#02439F';\r\n    row+='<td class=\"heat\" style=\"background:rgba(2,67,159,'+al+');color:'+col+'\">'+nf(v)+'<\/td>';}\r\n  });\r\n  tr.innerHTML=row;body.appendChild(tr);});\r\n var note='Sel = jumlah review baru per '+({day:'hari',week:'minggu',month:'bulan'}[g])+' (warna makin pekat = makin banyak). <b>Pertama<\/b> = tanggal review pertama cabang (default urut dari yang paling awal \u2014 cabang tertua di atas). <b>Terekam<\/b> = total review bertanggal di rentang ini; <b>Google<\/b> = total review live di Google (termasuk rating tanpa teks, biasanya lebih besar). Klik <b>Total<\/b>\/<b>Google<\/b>\/<b>Pertama<\/b> untuk ubah urutan.';\r\n if(state.pivotCapped)note+=' Menampilkan '+MAXCOLS+' periode terakhir \u2014 persempit lewat rentang tanggal untuk lihat lainnya.';\r\n $('tabel-hint').innerHTML=note;\r\n}\r\n\r\n\/* ---- pasif tab ---- *\/\r\nfunction pasifList(){return state.metrics.filter(function(x){return x.status==='pasif';})\r\n .sort(function(a,b){var x=a.days==null?Infinity:a.days,y=b.days==null?Infinity:b.days;return y-x;});}\r\n\r\nfunction csvCell(v){v=String(v==null?'':v);return \/[\",\\n]\/.test(v)?('\"'+v.replace(\/\"\/g,'\"\"')+'\"'):v;}\r\nfunction triggerDownload(blob,fname){var a=document.createElement('a'),url=URL.createObjectURL(blob);\r\n a.href=url;a.download=fname;document.body.appendChild(a);a.click();\r\n setTimeout(function(){document.body.removeChild(a);URL.revokeObjectURL(url);},0);}\r\nfunction exportPasif(fmt){\r\n if(!state.metrics||!state.metrics.length){return;}\r\n var list=pasifList();\r\n var cols=['No','Cabang','Kota','AM','Review Terakhir','Hari Sejak Review','Total Review (Google)'];\r\n var rows=list.map(function(x,i){return [i+1,shortName(x.name),x.city||'',x.am||'',x.last!=null?dmy(x.last):'',x.days==null?'':x.days,x.gReviews||0];});\r\n var fname='cabang-pasif-'+dmy(state.anchor).replace(\/\\s\/g,'-');\r\n if(fmt==='xls'){\r\n  \/\/ tabel HTML polos tanpa wrapper dokumen \\u2014 tag penutup dokumen bikin WordPress balanceTags menutup script lebih awal\r\n  var h='<table border=\"1\"><thead><tr>'+cols.map(function(c){return '<th>'+esc(c)+'<\/th>';}).join('')+'<\/tr><\/thead><tbody>';\r\n  rows.forEach(function(r){h+='<tr>'+r.map(function(v){return '<td>'+esc(v)+'<\/td>';}).join('')+'<\/tr>';});\r\n  h+='<\/tbody><\/table>';\r\n  triggerDownload(new Blob(['\\ufeff'+h],{type:'application\/vnd.ms-excel'}),fname+'.xls');\r\n } else {\r\n  var lines=[cols.map(csvCell).join(',')];\r\n  rows.forEach(function(r){lines.push(r.map(csvCell).join(','));});\r\n  triggerDownload(new Blob(['\\ufeff'+lines.join('\\r\\n')],{type:'text\/csv;charset=utf-8;'}),fname+'.csv');\r\n }\r\n}\r\n\r\nfunction renderPasif(m,t){\r\n var pasif=pasifList();\r\n var kurang=m.filter(function(x){return x.status==='kurang';}).sort(function(a,b){return a.l30-b.l30;});\r\n var total=state.branches.length,pct=total?Math.round(pasif.length\/total*100):0;\r\n var ban=$('pasif-banner');\r\n if(pasif.length===0){ban.className='banner ok';$('pasif-big').textContent='0';$('pasif-txt').innerHTML='<b>Semua cabang aktif \ud83c\udf89<\/b> Tidak ada cabang yang nol review dalam 30 hari terakhir (s\/d '+dmy(state.anchor)+').';}\r\n else{ban.className='banner';$('pasif-big').textContent=pasif.length;$('pasif-txt').innerHTML='dari <b>'+total+'<\/b> cabang ('+pct+'%) <b>tidak ada review baru<\/b> dalam 30 hari terakhir s\/d '+dmy(state.anchor)+'. Cabang-cabang ini perlu ditegur untuk mulai minta review lagi.';}\r\n\r\n var pb=$('tbody-pasif');pb.innerHTML='';\r\n if(!pasif.length)pb.innerHTML='<tr><td colspan=\"7\" class=\"muted\" style=\"padding:1rem;text-align:center\">Tidak ada cabang pasif. \ud83c\udf89<\/td><\/tr>';\r\n pasif.forEach(function(r,i){var ago=agoText(r.days);\r\n  pb.insertAdjacentHTML('beforeend','<tr><td class=\"l rank\">'+(i+1)+'<\/td>'+\r\n   '<td class=\"l branch\">'+esc(shortName(r.name))+'<\/td>'+\r\n   '<td class=\"l muted\">'+esc(r.city||'\u2014')+'<\/td>'+\r\n   '<td class=\"l\">'+(r.am?esc(r.am):'<span class=\"muted\">\u2014<\/span>')+'<\/td>'+\r\n   '<td class=\"ago '+ago.c+'\">'+(r.last!=null?dmy(r.last)+' <span class=\"muted\">('+ago.t+')<\/span>':'belum ada')+'<\/td>'+\r\n   '<td style=\"font-weight:700\">'+nf(r.gReviews)+'<\/td>'+\r\n   '<td class=\"l\">'+(r.url?'<a href=\"'+esc(r.url)+'\" target=\"_blank\" rel=\"noopener\" style=\"color:var(--primary);font-weight:700\">Maps \u2197<\/a>':'\u2014')+'<\/td><\/tr>');\r\n });\r\n\r\n $('kurang-sub').textContent='1 s\/d '+(t-1)+' review dalam 30 hari (target '+t+')';\r\n var kb=$('tbody-kurang');kb.innerHTML='';\r\n if(!kurang.length)kb.innerHTML='<tr><td colspan=\"8\" class=\"muted\" style=\"padding:1rem;text-align:center\">Tidak ada cabang di kategori ini.<\/td><\/tr>';\r\n kurang.forEach(function(r,i){var ago=agoText(r.days);\r\n  kb.insertAdjacentHTML('beforeend','<tr><td class=\"l rank\">'+(i+1)+'<\/td>'+\r\n   '<td class=\"l branch\">'+esc(shortName(r.name))+'<\/td>'+\r\n   '<td class=\"l muted\">'+esc(r.city||'\u2014')+'<\/td>'+\r\n   '<td class=\"l\">'+(r.am?esc(r.am):'<span class=\"muted\">\u2014<\/span>')+'<\/td>'+\r\n   '<td style=\"font-weight:800;color:#b45309\">'+nf(r.l30)+'<\/td>'+\r\n   '<td class=\"muted\">'+t+'<\/td>'+\r\n   '<td class=\"ago '+ago.c+'\">'+ago.t+'<\/td>'+\r\n   '<td class=\"l\">'+(r.url?'<a href=\"'+esc(r.url)+'\" target=\"_blank\" rel=\"noopener\" style=\"color:var(--primary);font-weight:700\">Maps \u2197<\/a>':'\u2014')+'<\/td><\/tr>');\r\n });\r\n}\r\n\r\n\/* ---- tab counts ---- *\/\r\nfunction syncTabCounts(){\r\n var pasif=state.metrics.filter(function(x){return x.status==='pasif';}).length;\r\n $('tab-pasif-cnt').textContent=pasif;\r\n var pb=document.querySelector('#tabs button[data-tab=pasif]');if(pb)pb.classList.toggle('warn',pasif>0);\r\n var bc=state.belum&&state.belum.items?state.belum.items.length:0;\r\n var be=$('tab-belum-cnt');if(be)be.textContent=state.belumErr?'!':bc;\r\n var bb=document.querySelector('#tabs button[data-tab=belum]');if(bb)bb.classList.toggle('warn',bc>0||state.belumErr);\r\n}\r\n\r\n\/* ---- Ringkasan AM ---- *\/\r\nvar AMCOLS=[{k:'am',t:'Area Manager',l:true},{k:'areaList',t:'Area',l:true},{k:'n',t:'Cabang'},\r\n {k:'aktif',t:'Aktif'},{k:'kurang',t:'Kurang'},{k:'pasif',t:'Pasif'},{k:'pctPasif',t:'% Pasif'},{k:'l30',t:'Review 30hr'}];\r\nfunction renderAM(m){\r\n var agg={},noAM=0;\r\n m.forEach(function(x){var am=(x.am&&x.am.trim())?x.am.trim():'\u2014';if(am==='\u2014')noAM++;\r\n  if(!agg[am])agg[am]={am:am,areas:{},n:0,aktif:0,kurang:0,pasif:0,l30:0};\r\n  var a=agg[am];a.n++;a[x.status]++;a.l30+=x.l30;if(x.area)a.areas[x.area]=1;});\r\n var arr=Object.keys(agg).map(function(k){var a=agg[k];a.areaList=Object.keys(a.areas).join(', ');a.pctPasif=a.n?Math.round(a.pasif\/a.n*100):0;return a;});\r\n var real=arr.filter(function(a){return a.am!=='\u2014';});\r\n var warnAM=real.filter(function(a){return a.pasif>0;}).length;\r\n $('am-k-count').textContent=real.length;\r\n $('am-k-covered').textContent=m.length-noAM;\r\n $('am-k-noam').textContent=noAM;\r\n $('am-k-warn').textContent=warnAM;\r\n var sk=state.amSort.key,sd=state.amSort.dir;\r\n arr.sort(function(a,b){var x=a[sk],y=b[sk];if(typeof x==='string')return sd*x.localeCompare(y);return sd*((x||0)-(y||0));});\r\n var th=$('am-thead');th.innerHTML='';\r\n AMCOLS.forEach(function(c){var el=document.createElement('th');el.textContent=c.t+(state.amSort.key===c.k?(sd<0?' \u25bc':' \u25b2'):'');\r\n  el.className=(c.l?'l':'')+(state.amSort.key===c.k?' sorted':'');\r\n  el.onclick=function(){if(state.amSort.key===c.k)state.amSort.dir*=-1;else{state.amSort.key=c.k;state.amSort.dir=(c.k==='am'||c.k==='areaList')?1:-1;}renderAM(state.metrics);};\r\n  th.appendChild(el);});\r\n var tb=$('am-tbody');tb.innerHTML='';\r\n arr.forEach(function(a){var tr=document.createElement('tr');\r\n  var pc=a.pctPasif>=30?'style=\"color:var(--destructive);font-weight:800\"':(a.pctPasif>0?'style=\"color:#b45309;font-weight:700\"':'class=\"muted\"');\r\n  tr.innerHTML='<td class=\"l branch\">'+(a.am==='\u2014'?'<span class=\"muted\">\u2014 (belum ada AM)<\/span>':esc(a.am))+'<\/td>'+\r\n   '<td class=\"l muted\">'+esc(a.areaList||'\u2014')+'<\/td>'+\r\n   '<td style=\"font-weight:700\">'+nf(a.n)+'<\/td>'+\r\n   '<td style=\"color:var(--success);font-weight:700\">'+nf(a.aktif)+'<\/td>'+\r\n   '<td style=\"color:#b45309;font-weight:700\">'+nf(a.kurang)+'<\/td>'+\r\n   '<td style=\"color:var(--destructive);font-weight:800\">'+nf(a.pasif)+'<\/td>'+\r\n   '<td '+pc+'>'+a.pctPasif+'%<\/td>'+\r\n   '<td style=\"font-weight:700\">'+nf(a.l30)+'<\/td>';\r\n  tb.appendChild(tr);});\r\n $('am-hint').innerHTML='Aktif\/Kurang\/Pasif dihitung dari 30 hari terakhir (target '+target()+'\/bln). '+(state.amLoaded?('AM diambil dari tab Master.'+(noAM?(' <b>'+noAM+' cabang belum ketemu AM-nya<\/b> \u2014 cek penulisan nama di Master.'):'')):'<i>Memuat data AM dari tab Master\u2026<\/i>');\r\n}\r\n\r\n\/* ---- Belum Live ---- *\/\r\nfunction renderBelum(){\r\n var ban=$('belum-banner'),big=$('belum-big'),txt=$('belum-txt'),tb=$('belum-tbody'),hint=$('belum-hint');\r\n if(state.belumErr){ban.className='banner';big.textContent='!';txt.innerHTML='Gagal memuat sheet Belum Live. Pastikan sheet-nya dibagikan <b>\u201cSiapa saja yang memiliki link \u2192 Pelihat\u201d<\/b>.';tb.innerHTML='<tr><td colspan=\"6\" class=\"muted\" style=\"padding:1rem;text-align:center\">\u2014<\/td><\/tr>';hint.textContent='';return;}\r\n if(!state.belum){big.textContent='\u2026';txt.textContent='Memuat data belum-live\u2026';return;}\r\n var it=state.belum.items;\r\n if(it.length===0){ban.className='banner ok';big.textContent='0';txt.innerHTML='<b>Semua cabang yang sudah lewat launch date sudah live \ud83c\udf89<\/b> Tidak ada yang kolom Q-nya kosong.';}\r\n else{ban.className='banner';big.textContent=it.length;txt.innerHTML='cabang <b>sudah lewat Launch Date<\/b> tapi <b>belum punya Google Maps Shortener Link (kolom Q)<\/b> \u2014 indikasi Google Maps-nya belum live. Perlu ditindaklanjuti.';}\r\n tb.innerHTML='';\r\n if(!it.length){tb.innerHTML='<tr><td colspan=\"6\" class=\"muted\" style=\"padding:1rem;text-align:center\">Tidak ada. \ud83c\udf89<\/td><\/tr>';}\r\n it.forEach(function(x,i){var c=x.days>=30?'stale':(x.days>=14?'warn':'fresh');\r\n  tb.insertAdjacentHTML('beforeend','<tr><td class=\"l rank\">'+(i+1)+'<\/td>'+\r\n   '<td class=\"l branch\">'+esc(x.branch)+'<\/td>'+\r\n   '<td class=\"l muted\">'+esc(x.area||'\u2014')+'<\/td>'+\r\n   '<td class=\"l\">'+(x.am?esc(x.am):'<span class=\"muted\">\u2014<\/span>')+'<\/td>'+\r\n   '<td>'+dmy(x.launch)+'<\/td>'+\r\n   '<td class=\"ago '+c+'\">'+x.days+' hari<\/td><\/tr>');\r\n });\r\n hint.innerHTML='Dari '+nf(state.belum.totalBranch)+' cabang di sheet, '+nf(state.belum.pastCount)+' sudah lewat Launch Date; <b>'+it.length+'<\/b> di antaranya belum ada Shortener Link (kolom Q). Telat dihitung dari Launch Date s\/d hari ini.';\r\n}\r\n\r\n\/* ---- growth line chart (all-time) with hover tooltip ---- *\/\r\nfunction renderLine(){\r\n var wrap=$('line-chart'),tl=state.timeline;if(tl.length<1){wrap.innerHTML='';return;}\r\n var W=Math.max(640,tl.length*Math.max(38,Math.min(90,760\/Math.max(1,tl.length)))+150),H=340;\r\n var mL=54,mR=18,mT=14,mB=48,pw=W-mL-mR,ph=H-mT-mB;\r\n var shown=state.branches.filter(function(b){return !state.hidden[b.name]&&b.color;});\r\n var metric=state.metric,maxV=0;\r\n shown.forEach(function(b){tl.forEach(function(k){var val=metric==='cum'?(b.cum[k]||0):(b.net[k]||0);if(val>maxV)maxV=val;});});\r\n maxV=Math.max(1,maxV);\r\n var x=function(i){return mL+(tl.length===1?pw\/2:i\/(tl.length-1)*pw);};\r\n var y=function(val){return mT+ph-(val\/maxV)*ph;};\r\n var svg='<svg viewBox=\"0 0 '+W+' '+H+'\" width=\"'+W+'\">';\r\n for(var tk=0;tk<=4;tk++){var val=maxV*tk\/4,yy=y(val);svg+='<line x1=\"'+mL+'\" y1=\"'+yy+'\" x2=\"'+(W-mR)+'\" y2=\"'+yy+'\" stroke=\"#e2e6f0\"\/>';\r\n  svg+='<text x=\"'+(mL-8)+'\" y=\"'+(yy+4)+'\" text-anchor=\"end\" font-size=\"10\" fill=\"#9aa3b2\">'+nf(val)+'<\/text>';}\r\n var step=Math.ceil(tl.length\/12);\r\n tl.forEach(function(k,i){if(i%step!==0&&i!==tl.length-1)return;svg+='<text x=\"'+x(i)+'\" y=\"'+(H-mB+18)+'\" text-anchor=\"middle\" font-size=\"10\" fill=\"#9aa3b2\">'+esc(bucketLabel(k,state.gran))+'<\/text>';});\r\n svg+='<line id=\"rg-hoverline\" x1=\"0\" y1=\"'+mT+'\" x2=\"0\" y2=\"'+(mT+ph)+'\" stroke=\"#8895ab\" stroke-width=\"1\" stroke-dasharray=\"3 3\" style=\"visibility:hidden\"\/>';\r\n shown.forEach(function(b){var d='';tl.forEach(function(k,i){var val=metric==='cum'?(b.cum[k]||0):(b.net[k]||0);d+=(i===0?'M':'L')+x(i).toFixed(1)+' '+y(val).toFixed(1)+' ';});\r\n  svg+='<path d=\"'+d+'\" fill=\"none\" stroke=\"'+b.color+'\" stroke-width=\"2.2\"\/>';\r\n  var li=tl.length-1,lv=metric==='cum'?(b.cum[tl[li]]||0):(b.net[tl[li]]||0);svg+='<circle cx=\"'+x(li)+'\" cy=\"'+y(lv)+'\" r=\"3.2\" fill=\"'+b.color+'\"\/>';});\r\n \/\/ hover dots (revealed per-period)\r\n shown.forEach(function(b){tl.forEach(function(k,i){var val=metric==='cum'?(b.cum[k]||0):(b.net[k]||0);\r\n  svg+='<circle class=\"rg-dot rg-dot-'+i+'\" cx=\"'+x(i).toFixed(1)+'\" cy=\"'+y(val).toFixed(1)+'\" r=\"3.4\" fill=\"'+b.color+'\" stroke=\"#fff\" stroke-width=\"1.2\" style=\"visibility:hidden\"\/>';});});\r\n svg+='<\/svg><div class=\"line-tip\" id=\"rg-tip\"><\/div>';\r\n wrap.innerHTML=svg;\r\n\r\n \/\/ ---- interactivity ----\r\n var svgEl=wrap.querySelector('svg'),tip=$('rg-tip'),hline=svgEl.querySelector('#rg-hoverline');\r\n var curDot=-1;\r\n function showAt(idx,clientX){\r\n  if(idx<0||idx>=tl.length){hide();return;}\r\n  var k=tl[idx];\r\n  hline.setAttribute('x1',x(idx));hline.setAttribute('x2',x(idx));hline.style.visibility='visible';\r\n  if(curDot!==idx){var old=svgEl.querySelectorAll('.rg-dot-'+curDot);for(var o=0;o<old.length;o++)old[o].style.visibility='hidden';\r\n   var now=svgEl.querySelectorAll('.rg-dot-'+idx);for(var n=0;n<now.length;n++)now[n].style.visibility='visible';curDot=idx;}\r\n  var rows=shown.map(function(b){var val=metric==='cum'?(b.cum[k]||0):(b.net[k]||0);return{c:b.color,n:shortName(b.name),v:val};})\r\n    .sort(function(a,b){return b.v-a.v;});\r\n  var html='<div class=\"tt-h\">'+esc(bucketLabel(k,state.gran))+' \u00b7 '+(metric==='cum'?'kumulatif':'per periode')+'<\/div>';\r\n  rows.forEach(function(r){html+='<div class=\"tt-r\"><span class=\"tt-sw\" style=\"background:'+r.c+'\"><\/span>'+esc(clip(r.n,22))+'<span class=\"tt-v\">'+nf(r.v)+'<\/span><\/div>';});\r\n  tip.innerHTML=html;tip.style.display='block';\r\n  var wr=wrap.getBoundingClientRect(),tw=tip.offsetWidth;\r\n  var left=clientX-wr.left+14;if(left+tw>wrap.clientWidth)left=clientX-wr.left-tw-14;if(left<0)left=4;\r\n  tip.style.left=left+'px';tip.style.top='8px';\r\n }\r\n function hide(){tip.style.display='none';hline.style.visibility='hidden';\r\n  if(curDot>=0){var old=svgEl.querySelectorAll('.rg-dot-'+curDot);for(var o=0;o<old.length;o++)old[o].style.visibility='hidden';curDot=-1;}}\r\n function onMove(e){var rect=svgEl.getBoundingClientRect();var sc=rect.width\/W;var mx=(e.clientX-rect.left)\/sc;\r\n  var idx=tl.length===1?0:Math.round((mx-mL)\/pw*(tl.length-1));if(idx<0)idx=0;if(idx>=tl.length)idx=tl.length-1;showAt(idx,e.clientX);}\r\n svgEl.addEventListener('mousemove',onMove);\r\n svgEl.addEventListener('mouseleave',hide);\r\n\r\n var lg=$('legend');lg.innerHTML='';\r\n state.branches.filter(function(b){return b.color;}).sort(function(a,b){return a._rank-b._rank;}).forEach(function(b){\r\n  var el=document.createElement('span');el.className='lg'+(state.hidden[b.name]?' off':'');\r\n  el.innerHTML='<span class=\"sw\" style=\"background:'+b.color+'\"><\/span>'+esc(clip(shortName(b.name),28));\r\n  el.onclick=function(){state.hidden[b.name]=!state.hidden[b.name];renderLine();};lg.appendChild(el);});\r\n}\r\n\r\n\/* ---- controls sync ---- *\/\r\nfunction syncControls(){\r\n var i;\r\n var gb=document.querySelectorAll('#seg-gran button');for(i=0;i<gb.length;i++)gb[i].classList.toggle('active',gb[i].getAttribute('data-g')===state.gran);\r\n var mb=document.querySelectorAll('#seg-metric button');for(i=0;i<mb.length;i++)mb[i].classList.toggle('active',mb[i].getAttribute('data-m')===state.metric);\r\n var mo=document.querySelectorAll('#seg-mode button');for(i=0;i<mo.length;i++)mo[i].classList.toggle('active',mo[i].getAttribute('data-mode')===state.mode);\r\n var tabs=document.querySelectorAll('#tabs button');for(i=0;i<tabs.length;i++)tabs[i].classList.toggle('active',tabs[i].getAttribute('data-tab')===state.tab);\r\n ['ringkasan','tabel','pasif','am','belum'].forEach(function(p){var el=$('pane-'+p);if(el)el.style.display=(state.tab===p)?'block':'none';});\r\n $('custom-range').style.display=(state.range==='custom')?'inline-flex':'none';\r\n}\r\n\r\n\/* ---- public API ---- *\/\r\nwindow.RG={\r\n load:load,\r\n render:function(){savePrefs();render();},\r\n setTab:function(t){state.tab=t;savePrefs();syncControls();},\r\n setMode:function(m){state.mode=m;savePrefs();if(state.branches.length)render();else syncControls();},\r\n setGran:function(g){state.gran=g;savePrefs();if(state.branches.length){buildTimeline();render();}else syncControls();},\r\n setMetric:function(m){state.metric=m;savePrefs();syncControls();renderLine();},\r\n setRange:function(){state.range=$('sel-range').value;savePrefs();if(state.range==='custom'){syncControls();if(!$('cfg-from').value&&!$('cfg-to').value)return;}if(state.branches.length)render();else syncControls();},\r\n applyCustom:function(){state.range='custom';savePrefs();if(state.branches.length)render();},\r\n exportPasif:exportPasif\r\n};\r\n\r\nloadPrefs();syncControls();\r\n})();\r\n<\/script>\r\n<\/body>\r\n<\/html>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":3,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_uag_custom_page_level_css":"","site-sidebar-layout":"no-sidebar","site-content-layout":"","ast-site-content-layout":"full-width-container","site-content-style":"unboxed","site-sidebar-style":"unboxed","ast-global-header-display":"disabled","ast-banner-title-visibility":"disabled","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"disabled","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"disabled","ast-disable-related-posts":"disabled","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-2213","page","type-page","status-publish","hentry"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Janu Prasetya","author_link":"https:\/\/pandaigadai.com\/blog\/author\/janu\/"},"uagb_comment_info":0,"uagb_excerpt":null,"_links":{"self":[{"href":"https:\/\/pandaigadai.com\/blog\/wp-json\/wp\/v2\/pages\/2213","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pandaigadai.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/pandaigadai.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/pandaigadai.com\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/pandaigadai.com\/blog\/wp-json\/wp\/v2\/comments?post=2213"}],"version-history":[{"count":3,"href":"https:\/\/pandaigadai.com\/blog\/wp-json\/wp\/v2\/pages\/2213\/revisions"}],"predecessor-version":[{"id":2224,"href":"https:\/\/pandaigadai.com\/blog\/wp-json\/wp\/v2\/pages\/2213\/revisions\/2224"}],"wp:attachment":[{"href":"https:\/\/pandaigadai.com\/blog\/wp-json\/wp\/v2\/media?parent=2213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}