{"id":11048,"date":"2026-07-11T00:58:42","date_gmt":"2026-07-10T16:58:42","guid":{"rendered":"https:\/\/lesgo.my\/?page_id=11048"},"modified":"2026-07-11T00:58:43","modified_gmt":"2026-07-10T16:58:43","slug":"training-plan-2","status":"publish","type":"page","link":"https:\/\/lesgo.my\/index.php\/training-plan-2\/","title":{"rendered":"Training Plan Lengkap Lesgo!"},"content":{"rendered":"<style>\n.jl-app {\n    --accent: #ff6b2c;\n    --accent-2: #ffa53d;\n    --ok: #34d399;\n    --warn: #fbbf24;\n    --info: #60a5fa;\n    --radius: 14px;\n    --max: 1080px;\n    --font: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n  }\n.jl-app[data-theme=\"dark\"] {\n    --bg: #0c0d12; --bg-2: #12131b; --card: #161824; --card-2: #1d2030;\n    --border: #262a3c; --text: #f3f4f8; --dim: #9aa0b4; --shadow: rgba(0,0,0,0.5);\n  }\n.jl-app[data-theme=\"light\"] {\n    --bg: #f6f7fb; --bg-2: #eef0f6; --card: #ffffff; --card-2: #f1f3f9; --border: #e2e5ee; --text: #14161f; --dim: #5b6173; --shadow: rgba(20,30,60,0.08);\n  }\n.jl-app * { margin: 0; padding: 0; box-sizing: border-box; }\n.jl-app { font-family: var(--font); background: var(--bg); color: var(--text); line-height: 1.55; -webkit-font-smoothing: antialiased; }\n.jl-app a { color: inherit; }\n.jl-app .wrap { width: 100%; max-width: var(--max); margin: 0 auto; padding: 0 20px; }\n.jl-app .accent { background: linear-gradient(90deg, var(--accent), var(--accent-2)); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }\n\/* Header *\/\n.jl-app header { position: sticky; top: 0; z-index: 50; backdrop-filter: blur(12px); background: color-mix(in srgb, var(--bg) 78%, transparent); border-bottom: 1px solid var(--border); }\n.jl-app .nav { display: flex; align-items: center; justify-content: space-between; height: 62px; }\n.jl-app .logo { display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 1.08rem; letter-spacing: -0.02em; }\n.jl-app .logo .mark { width: 30px; height: 30px; border-radius: 9px; background: linear-gradient(135deg, var(--accent), var(--accent-2)); display: grid; place-items: center; font-size: 1rem; box-shadow: 0 6px 16px color-mix(in srgb, var(--accent) 45%, transparent); }\n.jl-app .theme-btn { background: var(--card); border: 1px solid var(--border); color: var(--text); width: 40px; height: 40px; border-radius: 10px; cursor: pointer; font-size: 1.1rem; transition: .15s; }\n.jl-app .theme-btn:hover { background: var(--card-2); }\n\/* Hero *\/\n.jl-app .hero { padding: 46px 0 22px; text-align: center; position: relative; overflow: hidden; }\n.jl-app .hero::before { content:\"\"; position:absolute; top:-180px; left:50%; transform:translateX(-50%); width:560px; height:560px; background: radial-gradient(circle, color-mix(in srgb, var(--accent) 22%, transparent) 0%, transparent 70%); z-index:-1; }\n.jl-app .eyebrow { display:inline-block; font-size:.74rem; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:var(--accent); border:1px solid var(--border); background:var(--card); border-radius:999px; padding:5px 14px; margin-bottom:16px; }\n.jl-app .hero h1 { font-size: clamp(1.9rem, 5vw, 3rem); line-height:1.08; font-weight:800; letter-spacing:-0.03em; }\n.jl-app .hero p { margin: 14px auto 0; max-width: 560px; color: var(--dim); font-size: 1.02rem; }\n\/* Card \/ form *\/\n.jl-app .card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: 0 10px 30px var(--shadow); }\n.jl-app .form-card { padding: 26px; margin-top: 8px; }\n.jl-app .form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }\n.jl-app .field { display: flex; flex-direction: column; gap: 7px; }\n.jl-app .field.full { grid-column: 1 \/ -1; }\n.jl-app label { font-size: .82rem; font-weight: 600; color: var(--dim); }\n.jl-app input, .jl-app select { width: 100%; padding: 12px 13px; border-radius: 10px; border: 1px solid var(--border); background: var(--bg-2); color: var(--text); font-size: .95rem; font-family: var(--font); transition: .15s; }\n.jl-app input:focus, .jl-app select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }\n.jl-app .vdot-row { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }\n.jl-app .vdot-row input#vdot { max-width: 110px; }\n.jl-app .vdot-row #rdCalc { max-width: 130px; }\n.jl-app .vdot-row .time-fields { display:inline-flex; align-items:center; gap:5px; }\n.jl-app .vdot-row .time-fields input { width:64px; text-align:center; }\n.jl-app .vdot-row .time-fields span { color:var(--dim); }\n.jl-app .vdot-row .btn { padding:11px 16px; }\n.jl-app .vdot-sep { font-size:.84rem; color:var(--dim); }\n.jl-app input[type=range] { width:130px; padding:0; border:none; background:transparent; accent-color:var(--accent); }\n.jl-app input[type=range]:focus { box-shadow:none; }\n.jl-app .btn.on { background:linear-gradient(90deg,var(--accent),var(--accent-2)); color:#fff; border-color:transparent; }\n.jl-app #vdotOut { font-weight:800; color:var(--accent); }\n.jl-app .hint { font-size:.78rem; color:var(--dim); }\n.jl-app .seg { display: inline-flex; background: var(--bg-2); border: 1px solid var(--border); border-radius: 10px; padding: 3px; gap: 3px; }\n.jl-app .seg button { flex:1; border: none; background: transparent; color: var(--dim); padding: 8px 14px; border-radius: 7px; cursor: pointer; font-weight: 600; font-size: .88rem; transition: .15s; font-family: var(--font); }\n.jl-app .seg button.on { background: var(--card); color: var(--text); box-shadow: 0 2px 6px var(--shadow); }\n.jl-app .btn { display:inline-flex; align-items:center; justify-content:center; gap:8px; padding:13px 22px; border-radius:11px; font-size:.95rem; font-weight:700; cursor:pointer; border:1px solid var(--border); background:var(--card); color:var(--text); transition:.15s; font-family:var(--font); }\n.jl-app .btn:hover { background: var(--card-2); transform: translateY(-1px); }\n.jl-app .btn-primary { background: linear-gradient(90deg, var(--accent), var(--accent-2)); color:#fff; border:none; box-shadow: 0 8px 22px color-mix(in srgb, var(--accent) 40%, transparent); width:100%; padding:15px; font-size:1rem; margin-top:4px; }\n.jl-app .btn-primary:hover { box-shadow: 0 12px 28px color-mix(in srgb, var(--accent) 55%, transparent); }\n\/* Results *\/\n.jl-app #results { margin-top: 34px; display: none; }\n.jl-app .summary { display:grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap:1px; background:var(--border); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden; }\n.jl-app .summary .cell { background:var(--card); padding:18px 20px; }\n.jl-app .summary .cell .k { font-size:.74rem; text-transform:uppercase; letter-spacing:.05em; color:var(--dim); font-weight:600; }\n.jl-app .summary .cell .v { font-size:1.35rem; font-weight:800; margin-top:3px; letter-spacing:-0.02em; }\n.jl-app .summary .cell .v small { font-size:.8rem; font-weight:600; color:var(--dim); }\n.jl-app .advisories { display:grid; grid-template-columns: repeat(auto-fit, minmax(240px,1fr)); gap:14px; margin-top:18px; }\n.jl-app .adv { border:1px solid var(--border); border-radius:12px; padding:16px 17px; background:var(--card); display:flex; gap:12px; }\n.jl-app .adv .ic { font-size:1.4rem; flex-shrink:0; }\n.jl-app .adv h4 { font-size:.92rem; font-weight:700; margin-bottom:3px; }\n.jl-app .adv p { font-size:.84rem; color:var(--dim); }\n.jl-app .adv.warn { border-color: color-mix(in srgb, var(--warn) 50%, var(--border)); background: color-mix(in srgb, var(--warn) 8%, var(--card)); }\n.jl-app .toolbar { display:flex; align-items:center; justify-content:space-between; gap:12px; margin:26px 0 14px; flex-wrap:wrap; }\n.jl-app .toolbar h2 { font-size:1.3rem; font-weight:800; letter-spacing:-0.02em; }\n.jl-app .actions { display:flex; gap:8px; flex-wrap:wrap; }\n.jl-app .actions .btn { padding:10px 15px; font-size:.86rem; }\n\/* Week list *\/\n.jl-app .week { border:1px solid var(--border); border-radius:12px; margin-bottom:12px; overflow:hidden; background:var(--card); }\n.jl-app .week-head { display:flex; align-items:center; justify-content:space-between; padding:13px 18px; background:var(--card-2); border-bottom:1px solid var(--border); flex-wrap:wrap; gap:8px; }\n.jl-app .week-head .wk { font-weight:800; font-size:.98rem; }\n.jl-app .week-head .wk span { color:var(--dim); font-weight:600; font-size:.84rem; margin-left:8px; }\n.jl-app .week-head .meta { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }\n.jl-app .pill { font-size:.72rem; font-weight:700; padding:4px 10px; border-radius:999px; background:var(--bg-2); border:1px solid var(--border); color:var(--dim); }\n.jl-app .pill.vol { color:var(--text); }\n.jl-app .pill.ramadan { background: color-mix(in srgb, var(--warn) 18%, transparent); border-color: color-mix(in srgb, var(--warn) 40%, var(--border)); color: var(--warn); }\n.jl-app .pill.cut { background: color-mix(in srgb, var(--info) 16%, transparent); border-color: color-mix(in srgb, var(--info) 40%, var(--border)); color: var(--info); }\n.jl-app .days { display:grid; grid-template-columns: repeat(7, 1fr); }\n.jl-app .day { padding:12px 12px 14px; border-right:1px solid var(--border); min-height:118px; position:relative; }\n.jl-app .day:last-child { border-right:none; }\n.jl-app .day .dname { font-size:.72rem; font-weight:700; color:var(--dim); text-transform:uppercase; letter-spacing:.04em; }\n.jl-app .day .date { font-size:.72rem; color:var(--dim); margin-bottom:7px; }\n.jl-app .day .wtype { font-size:.82rem; font-weight:700; line-height:1.25; }\n.jl-app .day .wkm { font-size:.78rem; color:var(--dim); margin-top:2px; }\n.jl-app .day .wnote { font-size:.71rem; color:var(--dim); margin-top:6px; line-height:1.35; }\n.jl-app .day.t-rest { opacity:.62; }\n.jl-app .day .dot { width:8px; height:8px; border-radius:50%; display:inline-block; margin-right:5px; vertical-align:middle; }\n.jl-app .day.today { box-shadow: inset 0 0 0 2px var(--accent); }\n.jl-app .day.race { background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 16%, var(--card)), color-mix(in srgb, var(--accent-2) 12%, var(--card))); }\n.jl-app .day.race .wtype { color: var(--accent); }\n.jl-app .day.ramadan::after { content:\"\ud83c\udf19\"; position:absolute; top:10px; right:10px; font-size:.8rem; opacity:.8; }\n\/* compact list view *\/\n.jl-app .lview .days { grid-template-columns: 1fr; }\n.jl-app .lview .day { display:grid; grid-template-columns: 110px 150px 1fr; gap:10px; border-right:none; border-bottom:1px solid var(--border); min-height:auto; align-items:center; padding:11px 16px; }\n.jl-app .lview .day:last-child { border-bottom:none; }\n.jl-app .lview .day .date { margin:0; }\n.jl-app .lview .day .wnote { margin-top:2px; }\n.jl-app .legend { display:flex; gap:16px; flex-wrap:wrap; margin:18px 0 4px; font-size:.8rem; color:var(--dim); }\n.jl-app .legend span { display:inline-flex; align-items:center; }\n.jl-app footer { border-top:1px solid var(--border); margin-top:60px; padding:28px 0 40px; color:var(--dim); font-size:.86rem; }\n.jl-app footer a { color: var(--accent); text-decoration:none; }\n.jl-app .disclaimer { font-size:.78rem; color:var(--dim); margin-top:10px; }\n.jl-app .hide { display:none !important; }\n@media (max-width: 760px) {\n.jl-app .form-grid { grid-template-columns: 1fr; }\n.jl-app .summary { grid-template-columns: 1fr 1fr; }\n.jl-app .days { grid-template-columns: 1fr; }\n.jl-app .day { border-right:none; border-bottom:1px solid var(--border); min-height:auto; display:grid; grid-template-columns:96px 1fr; gap:8px; }\n.jl-app .day .wnote { grid-column:1\/-1; }\n}\n\/* Brand bar (screen + print) *\/\n.jl-app .brandbar { display:flex; align-items:center; justify-content:space-between; gap:10px; padding:12px 16px; border:1px solid var(--border); border-radius:12px; margin-bottom:14px; background:var(--card); }\n.jl-app .brandbar .bl { display:flex; align-items:center; gap:9px; font-weight:800; font-size:1.05rem; letter-spacing:-0.02em; }\n.jl-app .brandbar .bl .bmark { width:26px; height:26px; border-radius:7px; background:linear-gradient(135deg,var(--accent),var(--accent-2)); display:grid; place-items:center; font-size:.9rem; }\n.jl-app .brandbar .bl b { color:var(--accent); }\n.jl-app .brandbar .bt { font-size:.82rem; color:var(--dim); font-weight:600; }\n\/* Print \u2014 force white background to save ink, keep branding *\/\n@media print {\n.jl-app, .jl-app[data-theme=\"dark\"], .jl-app[data-theme=\"light\"] {\n      --bg:#fff; --bg-2:#fff; --card:#fff; --card-2:#fff; --border:#bbb;\n      --text:#000; --dim:#333; --shadow:transparent; --accent:#111; --accent-2:#111;\n    }\n.jl-app header, .jl-app .hero, .jl-app .form-card, .jl-app .actions, .jl-app .theme-btn, .jl-app footer .links, .jl-app #viewSeg, .jl-app .legend { display:none !important; }\n.jl-app * { background:#fff !important; background-image:none !important; box-shadow:none !important; color:#000 !important; }\n.jl-app .accent, .jl-app .brandbar .bl b { -webkit-text-fill-color:#000 !important; color:#000 !important; }\n.jl-app .brandbar .bl .bmark { border:1px solid #000; }\n.jl-app #results { display:block !important; margin:0; }\n.jl-app .week { break-inside: avoid; border-color:#bbb !important; }\n.jl-app .day { border-color:#ddd !important; min-height:auto; }\n.jl-app .days { grid-template-columns: repeat(7,1fr) !important; }\n.jl-app .pill, .jl-app .adv, .jl-app .summary .cell { border-color:#bbb !important; }\n.jl-app .day .dot { outline:1px solid #000; }\n.jl-app a[href]:after { content:\"\"; }\n}\n\n@media print {\n  body * { visibility: hidden !important; }\n  .jl-app, .jl-app * { visibility: visible !important; }\n  .jl-app { position: absolute !important; left: 0; top: 0; width: 100% !important; }\n}\n\n<\/style>\n<div id=\"jl-app\" class=\"jl-app\" data-theme=\"dark\">\n<header>\n  <div class=\"wrap nav\">\n    <div class=\"logo\"><span class=\"mark\">\ud83c\udfc3<\/span> Jadual<span class=\"accent\">Lari<\/span> <span style=\"font-size:.72rem;font-weight:600;color:var(--dim)\">by lesgo.my<\/span><\/div>\n    <button class=\"theme-btn\" id=\"themeBtn\" title=\"Tukar tema\">\ud83c\udf19<\/button>\n  <\/div>\n<\/header>\n\n<div class=\"hero\">\n  <div class=\"wrap\">\n    <span class=\"eyebrow\">Penjana Jadual Latihan \u00b7 Malaysia<\/span>\n    <h1>Dari tarikh perlumbaan ke<br><span class=\"accent\">jadual latihan mingguan<\/span><\/h1>\n    <p>Pilih perlumbaan, kami susun pelan latihan progresif untuk kau \u2014 siap ambil kira cuaca panas & bulan Ramadan. Export PDF, kalendar, atau share ke WhatsApp.<\/p>\n  <\/div>\n<\/div>\n\n<div class=\"wrap\">\n  <div class=\"card form-card\">\n    <div class=\"form-grid\">\n      <div class=\"field full\">\n        <label for=\"preset\">Perlumbaan (pilihan \u2014 auto-isi tarikh)<\/label>\n        <select id=\"preset\"><\/select>\n      <\/div>\n      <div class=\"field\">\n        <label for=\"raceName\">Nama perlumbaan<\/label>\n        <input type=\"text\" id=\"raceName\" placeholder=\"cth: SCKLM 2026\" \/>\n      <\/div>\n      <div class=\"field\">\n        <label for=\"raceDate\">Tarikh perlumbaan<\/label>\n        <input type=\"date\" id=\"raceDate\" \/>\n      <\/div>\n      <div class=\"field full\">\n        <label for=\"plan\">Jenis pelan<\/label>\n        <select id=\"plan\"><\/select>\n        <small class=\"hint\">Nama pelan diambil dari expl.space (kaedah Pfitzinger, Hansons, Hal Higdon, Davis). Jadual di sini <em>dijana<\/em> mengikut struktur setiap kaedah (minggu + jumlah km puncak), bukan salinan buku \u2014 untuk \"kenapa & bagaimana\" setiap sesi, dapatkan buku asal.<\/small>\n      <\/div>\n      <div class=\"field full\">\n        <label for=\"vdot\">VDOT \/ pace sasaran (pilihan)<\/label>\n        <div class=\"vdot-row\">\n          <input type=\"number\" id=\"vdot\" min=\"25\" max=\"85\" step=\"1\" placeholder=\"cth: 45\" \/>\n          <span class=\"vdot-sep\">tak tahu VDOT?<\/span>\n          <select id=\"rdCalc\">\n            <option value=\"5000\">5 KM<\/option>\n            <option value=\"10000\">10 KM<\/option>\n            <option value=\"21097\" selected>Half (21.1K)<\/option>\n            <option value=\"42195\">Full (42.2K)<\/option>\n          <\/select>\n          <span class=\"time-fields\">\n            <input type=\"number\" id=\"rtH\" min=\"0\" max=\"9\" placeholder=\"jam\" \/>\n            <span>:<\/span>\n            <input type=\"number\" id=\"rtM\" min=\"0\" max=\"59\" placeholder=\"min\" \/>\n            <span>:<\/span>\n            <input type=\"number\" id=\"rtS\" min=\"0\" max=\"59\" placeholder=\"saat\" \/>\n          <\/span>\n          <button class=\"btn\" id=\"calcVdot\" type=\"button\">Kira VDOT<\/button>\n          <span id=\"vdotOut\"><\/span>\n        <\/div>\n        <small class=\"hint\">VDOT = ukuran kecergasan lari (kaedah Jack Daniels). Kalau diisi, setiap larian akan papar pace sasaran (min:saat\/km).<\/small>\n      <\/div>\n      <div class=\"field full\">\n        <label>Pelarasan cuaca panas (pilihan)<\/label>\n        <div class=\"vdot-row\">\n          <button type=\"button\" class=\"btn\" id=\"wxToggle\">\u2600\ufe0f Aktifkan pelarasan cuaca<\/button>\n          <span id=\"wxControls\" class=\"hide\" style=\"display:flex;gap:12px;align-items:center;flex-wrap:wrap\">\n            <span style=\"font-size:.84rem;color:var(--dim)\">Suhu <b id=\"tVal\" style=\"color:var(--text)\">30\u00b0C<\/b><\/span>\n            <input type=\"range\" id=\"temp\" min=\"15\" max=\"38\" value=\"30\" step=\"1\" \/>\n            <span style=\"font-size:.84rem;color:var(--dim)\">Lembap <b id=\"hVal\" style=\"color:var(--text)\">80%<\/b><\/span>\n            <input type=\"range\" id=\"humid\" min=\"30\" max=\"100\" value=\"80\" step=\"5\" \/>\n            <span id=\"wxOut\"><\/span>\n          <\/span>\n        <\/div>\n        <small class=\"hint\">Cuaca panas & lembap melambatkan pace pada usaha yang sama. Aktifkan untuk laras pace sasaran ikut iklim tempat kau lari (default 30\u00b0C, 80% \u2014 tipikal Malaysia tengah hari).<\/small>\n      <\/div>\n    <\/div>\n    <button class=\"btn-primary\" id=\"genBtn\">Jana Jadual Latihan \u2192<\/button>\n  <\/div>\n\n  <div id=\"results\"><\/div>\n<\/div>\n\n<footer>\n  <div class=\"wrap\">\n    <strong>JadualLari<\/strong> by <a href=\"https:\/\/lesgo.my\" target=\"_blank\" rel=\"noopener\">lesgo.my<\/a> \u2014 penjana jadual latihan lari percuma untuk pelari Malaysia.\n    <div class=\"disclaimer\">\u26a0\ufe0f Jadual ini panduan umum berdasarkan prinsip latihan biasa (binaan beransur + taper), bukan nasihat perubatan atau jurulatih peribadi. Tarikh perlumbaan yang dipratetap adalah <em>anggaran<\/em> \u2014 sila sahkan dengan penganjur rasmi. Rujuk doktor sebelum mula program latihan baru.<\/div>\n  <\/div>\n<\/footer>\n<\/div>\n<script>\n\n\/* ---------- Reference data ---------- *\/\nconst BRAND = 'lesgo.my';\nconst BRAND_URL = 'https:\/\/lesgo.my';\nconst DAY_NAMES = ['Isnin','Selasa','Rabu','Khamis','Jumaat','Sabtu','Ahad'];\n\n\/\/ Malaysian race presets \u2014 ESTIMATED dates, user must confirm.\nconst PRESETS = [\n  { id:'', name:'\u2014 Tetapkan sendiri \u2014', date:'', plan:'' },\n  { id:'scklm',   name:'Standard Chartered KL Marathon (SCKLM)', date:'2026-09-27', plan:'higdon_novice_1' },\n  { id:'penang',  name:'Penang Bridge International Marathon',    date:'2026-11-22', plan:'higdon_novice_1' },\n  { id:'putrajaya', name:'Putrajaya Night Marathon',             date:'2026-11-14', plan:'hansons_half_beginner' },\n  { id:'twincity', name:'Twincity Marathon (Shah Alam)',         date:'2026-11-29', plan:'hansons_half_beginner' },\n  { id:'borneo',  name:'Borneo International Marathon (KK)',      date:'2027-05-02', plan:'higdon_novice_1' },\n  { id:'kuching', name:'Kuching Marathon',                       date:'2026-08-16', plan:'higdon_novice_1' },\n  { id:'ms63',    name:'MILO\u00ae Malaysia Breakfast Run (10K)',     date:'2026-07-19', plan:'pfitz_10k_42' },\n];\n\n\/\/ Ramadan ESTIMATED Gregorian ranges (sila sahkan ikut takwim rasmi).\nconst RAMADAN = [\n  ['2026-02-18','2026-03-19'],\n  ['2027-02-08','2027-03-09'],\n  ['2028-01-28','2028-02-26'],\n  ['2029-01-16','2029-02-14'],\n];\n\nconst DIST = {\n  '5k':  { label:'5 KM',  km:5.0  },\n  '10k': { label:'10 KM', km:10.0 },\n  '21k': { label:'Half Marathon', km:21.1 },\n  '42k': { label:'Full Marathon', km:42.2 },\n};\nconst LEVELS = { beginner:'Pemula', intermediate:'Pertengahan', advanced:'Mahir' };\n\n\/\/ pattern index 0=Isnin ... 6=Ahad\nconst PATTERN = {\n  beginner:     ['rest','easy','rest','easy','rest','easy','long'],\n  intermediate: ['rest','easy','tempo','easy','rest','easy','long'],\n  advanced:     ['easy','interval','easy','tempo','rest','easy','long'],\n};\n\n\/\/ Named plans \u2014 nama diambil dari expl.space (plans.json) & diterjemah ke BM.\n\/\/ Jarak batu\/minggu ditukar ke km\/minggu. Setiap pelan dipetakan ke penjana:\n\/\/ { distance, level(\u2192corak+hari), weeks, peakWeek(km\/mgu puncak), taper, author }\nconst PLAN_GROUPS = [\n  ['mee', 'Marathon Excellence (John Davis)'],\n  ['pfitzM', 'Marathon: Pfitzinger\/Douglas'],\n  ['hansonsM', 'Marathon: Hansons'],\n  ['higdon', 'Marathon: Hal Higdon'],\n  ['halfH', 'Half Marathon: Hansons'],\n  ['p10k', '10 KM: Pfitzinger'],\n  ['p5k', '5 KM: Pfitzinger'],\n];\nconst PLANS = [\n  \/\/ Marathon Excellence (Davis) \u2014 Breeze<Wind<Gale<Tornado<Hurricane (makin berat)\n  { id:'mee_breeze_12', g:'mee', author:'John Davis', d:'42k', lv:'beginner',     w:12, pw:64,  t:3, name:'Marathon Excellence: Breeze \u2014 jadual 12 minggu' },\n  { id:'mee_breeze_18', g:'mee', author:'John Davis', d:'42k', lv:'beginner',     w:18, pw:64,  t:3, name:'Marathon Excellence: Breeze \u2014 jadual 18 minggu' },\n  { id:'mee_wind_12',   g:'mee', author:'John Davis', d:'42k', lv:'intermediate', w:12, pw:80,  t:3, name:'Marathon Excellence: Wind \u2014 jadual 12 minggu' },\n  { id:'mee_wind_18',   g:'mee', author:'John Davis', d:'42k', lv:'intermediate', w:18, pw:80,  t:3, name:'Marathon Excellence: Wind \u2014 jadual 18 minggu' },\n  { id:'mee_gale_12',   g:'mee', author:'John Davis', d:'42k', lv:'advanced',     w:12, pw:97,  t:3, name:'Marathon Excellence: Gale \u2014 jadual 12 minggu' },\n  { id:'mee_gale_18',   g:'mee', author:'John Davis', d:'42k', lv:'advanced',     w:18, pw:97,  t:3, name:'Marathon Excellence: Gale \u2014 jadual 18 minggu' },\n  { id:'mee_tornado_12',g:'mee', author:'John Davis', d:'42k', lv:'advanced',     w:12, pw:113, t:3, name:'Marathon Excellence: Tornado \u2014 jadual 12 minggu' },\n  { id:'mee_tornado_18',g:'mee', author:'John Davis', d:'42k', lv:'advanced',     w:18, pw:113, t:3, name:'Marathon Excellence: Tornado \u2014 jadual 18 minggu' },\n  { id:'mee_hurricane_12',g:'mee',author:'John Davis',d:'42k', lv:'advanced',     w:12, pw:130, t:3, name:'Marathon Excellence: Hurricane \u2014 jadual 12 minggu' },\n  { id:'mee_hurricane_18',g:'mee',author:'John Davis',d:'42k', lv:'advanced',     w:18, pw:130, t:3, name:'Marathon Excellence: Hurricane \u2014 jadual 18 minggu' },\n  \/\/ Pfitzinger\/Douglas Marathon (Advanced Marathoning)\n  { id:'pfitz_18_55',  g:'pfitzM', author:'Pfitzinger\/Douglas', d:'42k', lv:'intermediate', w:18, pw:88,  t:3, name:'Pfitzinger\/Douglas \u2014 sehingga 88 km\/mgu, 18 minggu' },\n  { id:'pfitz_18_70',  g:'pfitzM', author:'Pfitzinger\/Douglas', d:'42k', lv:'advanced',     w:18, pw:113, t:3, name:'Pfitzinger\/Douglas \u2014 88\u2013113 km\/mgu, 18 minggu' },\n  { id:'pfitz_18_85',  g:'pfitzM', author:'Pfitzinger\/Douglas', d:'42k', lv:'advanced',     w:18, pw:137, t:3, name:'Pfitzinger\/Douglas \u2014 113\u2013137 km\/mgu, 18 minggu' },\n  { id:'pfitz_18_high',g:'pfitzM', author:'Pfitzinger\/Douglas', d:'42k', lv:'advanced',     w:18, pw:153, t:3, name:'Pfitzinger\/Douglas \u2014 lebih 137 km\/mgu, 18 minggu' },\n  { id:'pfitz_12_55',  g:'pfitzM', author:'Pfitzinger\/Douglas', d:'42k', lv:'intermediate', w:12, pw:88,  t:2, name:'Pfitzinger\/Douglas \u2014 sehingga 88 km\/mgu, 12 minggu' },\n  { id:'pfitz_12_70',  g:'pfitzM', author:'Pfitzinger\/Douglas', d:'42k', lv:'advanced',     w:12, pw:113, t:2, name:'Pfitzinger\/Douglas \u2014 88\u2013113 km\/mgu, 12 minggu' },\n  { id:'pfitz_12_85',  g:'pfitzM', author:'Pfitzinger\/Douglas', d:'42k', lv:'advanced',     w:12, pw:137, t:2, name:'Pfitzinger\/Douglas \u2014 113\u2013137 km\/mgu, 12 minggu' },\n  { id:'pfitz_12_high',g:'pfitzM', author:'Pfitzinger\/Douglas', d:'42k', lv:'advanced',     w:12, pw:153, t:2, name:'Pfitzinger\/Douglas \u2014 lebih 137 km\/mgu, 12 minggu' },\n  \/\/ Hansons Marathon Method\n  { id:'hansons_from_scratch', g:'hansonsM', author:'Hansons', d:'42k', lv:'beginner',     w:18, pw:60,  t:2, name:'Hansons \u2014 Marathon Pertama Dari Mula' },\n  { id:'hansons_beginner',     g:'hansonsM', author:'Hansons', d:'42k', lv:'intermediate', w:18, pw:80,  t:2, name:'Hansons \u2014 Marathon Pemula' },\n  { id:'hansons_advanced',     g:'hansonsM', author:'Hansons', d:'42k', lv:'advanced',     w:18, pw:100, t:2, name:'Hansons \u2014 Marathon Lanjutan' },\n  \/\/ Hal Higdon Marathon\n  { id:'higdon_novice_1',       g:'higdon', author:'Hal Higdon', d:'42k', lv:'beginner',     w:18, pw:58,  t:3, name:'Hal Higdon \u2014 Novis 1' },\n  { id:'higdon_novice_2',       g:'higdon', author:'Hal Higdon', d:'42k', lv:'beginner',     w:18, pw:68,  t:3, name:'Hal Higdon \u2014 Novis 2' },\n  { id:'higdon_intermediate_1', g:'higdon', author:'Hal Higdon', d:'42k', lv:'intermediate', w:18, pw:85,  t:3, name:'Hal Higdon \u2014 Pertengahan 1' },\n  { id:'higdon_intermediate_2', g:'higdon', author:'Hal Higdon', d:'42k', lv:'intermediate', w:18, pw:93,  t:3, name:'Hal Higdon \u2014 Pertengahan 2' },\n  { id:'higdon_advanced_1',     g:'higdon', author:'Hal Higdon', d:'42k', lv:'advanced',     w:18, pw:100, t:3, name:'Hal Higdon \u2014 Lanjutan 1' },\n  { id:'higdon_advanced_2',     g:'higdon', author:'Hal Higdon', d:'42k', lv:'advanced',     w:18, pw:110, t:3, name:'Hal Higdon \u2014 Lanjutan 2' },\n  \/\/ Half Marathon: Hansons\n  { id:'hansons_half_beginner', g:'halfH', author:'Hansons', d:'21k', lv:'intermediate', w:12, pw:55, t:2, name:'Hansons \u2014 Half Marathon Pemula' },\n  { id:'hansons_half_advanced', g:'halfH', author:'Hansons', d:'21k', lv:'advanced',     w:14, pw:80, t:3, name:'Hansons \u2014 Half Marathon Lanjutan' },\n  \/\/ 10K: Pfitzinger (Faster Road Racing)\n  { id:'pfitz_10k_42', g:'p10k', author:'Pfitzinger', d:'10k', lv:'advanced', w:12, pw:68, t:2, name:'Pfitzinger \u2014 48\u201368 km\/mgu, 12 minggu' },\n  \/\/ 5K: Pfitzinger\n  { id:'pfitz_5k_40', g:'p5k', author:'Pfitzinger', d:'5k', lv:'intermediate', w:12, pw:64,  t:1, name:'Pfitzinger \u2014 48\u201364 km\/mgu, 12 minggu' },\n  { id:'pfitz_5k_55', g:'p5k', author:'Pfitzinger', d:'5k', lv:'advanced',     w:12, pw:88,  t:1, name:'Pfitzinger \u2014 72\u201388 km\/mgu, 12 minggu' },\n  { id:'pfitz_5k_70', g:'p5k', author:'Pfitzinger', d:'5k', lv:'advanced',     w:12, pw:113, t:1, name:'Pfitzinger \u2014 96\u2013113 km\/mgu, 12 minggu' },\n];\nconst PLAN_BY_ID = {};\nPLANS.forEach(p=>PLAN_BY_ID[p.id]=p);\n\n\/\/ derive generator config from a named plan (weekly-volume driven)\nconst LONG_CAP = { '5k':11, '10k':17, '21k':27, '42k':37 };  \/\/ max long run km by race\nconst LEVEL_M  = { beginner:2.3, intermediate:2.9, advanced:3.45 }; \/\/ weekly-volume multiplier of long run\nfunction deriveCfg(plan){\n  const peakLong = Math.min(LONG_CAP[plan.d], Math.round(plan.pw \/ LEVEL_M[plan.lv]));\n  return { weeks:plan.w, taper:plan.t, peak:peakLong, start:Math.max(4, Math.round(peakLong*0.45)) };\n}\n\nconst WTYPE = {\n  rest:     { label:'Rehat',           color:'#6b7280' },\n  easy:     { label:'Larian Mudah',    color:'#34d399' },\n  long:     { label:'Larian Jauh',     color:'#60a5fa' },\n  tempo:    { label:'Tempo',           color:'#fbbf24' },\n  interval: { label:'Interval \/ Laju', color:'#f472b6' },\n  race:     { label:'HARI PERLUMBAAN', color:'#ff6b2c' },\n};\n\n\/* ---------- Helpers ---------- *\/\nconst APP = document.getElementById('jl-app');\nconst $ = s => APP.querySelector(s);\nconst pad = n => String(n).padStart(2,'0');\nfunction ymd(d){ return d.getFullYear()+'-'+pad(d.getMonth()+1)+'-'+pad(d.getDate()); }\nfunction parseYMD(s){ const [y,m,d]=s.split('-').map(Number); return new Date(y, m-1, d); }\nfunction addDays(d,n){ const x=new Date(d); x.setDate(x.getDate()+n); return x; }\nfunction mondayOf(d){ const x=new Date(d); const wd=(x.getDay()+6)%7; return addDays(x,-wd); } \/\/ Mon=0\nfunction fmtDate(d){ return d.getDate()+' '+['Jan','Feb','Mac','Apr','Mei','Jun','Jul','Ogo','Sep','Okt','Nov','Dis'][d.getMonth()]; }\nfunction inRamadan(d){ const s=ymd(d); return RAMADAN.some(([a,b])=> s>=a && s<=b ); }\n\nfunction showDist(km){\n  if(km<=0) return '\u2014';\n  return (km<10 && km%1!==0 ? km.toFixed(1) : Math.round(km))+' km';\n}\n\n\/* ---------- VDOT \/ pace (Jack Daniels model) ---------- *\/\nfunction paceFromVDOT(vdot, frac){\n  \/\/ solve 0.000104 v^2 + 0.182258 v - (4.60 + frac*vdot) = 0  \u2192 v in m\/min\n  const a=0.000104, b=0.182258, c=-(4.60 + frac*vdot);\n  const v=(-b + Math.sqrt(b*b - 4*a*c))\/(2*a);\n  return 1000\/v; \/\/ minutes per km\n}\nfunction vdotFromRace(meters, seconds){\n  const t=seconds\/60, v=meters\/t;\n  const vo2=-4.60 + 0.182258*v + 0.000104*v*v;\n  const pmax=0.8 + 0.1894393*Math.exp(-0.012778*t) + 0.2989558*Math.exp(-0.1932605*t);\n  return vo2\/pmax;\n}\nfunction fmtPace(minPerKm){ const s=Math.round(minPerKm*60); return Math.floor(s\/60)+':'+pad(s%60); }\nfunction heatFactor(T, H){\n  \/\/ fraction slower at same effort; combines temperature + humidity (sweat-evaporation penalty)\n  const ex = Math.max(0, T - 15);            \/\/ \u00b0C above ~15\u00b0C neutral\n  const base = ex * 0.003;                    \/\/ ~0.3%\/\u00b0C dry\n  const humF = Math.max(0, (H - 50)) \/ 50;    \/\/ humidity weight above 50%\n  const humPen = humF * ex * 0.004;           \/\/ humidity amplifies with heat\n  return Math.min(0.18, base + humPen);       \/\/ cap 18%\n}\nfunction computePaces(vdot, distKey, heat){\n  if(!vdot) return null;\n  heat = heat || 0;\n  const m = p => p * (1 + heat);\n  const raceFrac = {'5k':0.97,'10k':0.92,'21k':0.88,'42k':0.84}[distKey];\n  return {\n    easyFast: m(paceFromVDOT(vdot,0.72)), easySlow: m(paceFromVDOT(vdot,0.66)),\n    M: m(paceFromVDOT(vdot,0.84)), T: m(paceFromVDOT(vdot,0.88)),\n    I: m(paceFromVDOT(vdot,0.975)), R: m(paceFromVDOT(vdot,1.05)),\n    race: m(paceFromVDOT(vdot,raceFrac)), heat,\n  };\n}\nfunction easyRange(P){ return fmtPace(P.easyFast)+'\u2013'+fmtPace(P.easySlow)+'\/km'; }\nfunction clock(secs){ secs=Math.round(secs); const h=Math.floor(secs\/3600), m=Math.floor((secs%3600)\/60), s=secs%60; return h? h+':'+pad(m)+':'+pad(s) : m+':'+pad(s); }\nfunction predictTime(vdot, meters){\n  \/\/ bisection: find time t (min) where predicted VDOT for running `meters` equals vdot\n  let lo=1, hi=600;\n  for(let i=0;i<60;i++){\n    const t=(lo+hi)\/2, v=meters\/t;\n    const vo2=-4.60 + 0.182258*v + 0.000104*v*v;\n    const pmax=0.8 + 0.1894393*Math.exp(-0.012778*t) + 0.2989558*Math.exp(-0.1932605*t);\n    if(vo2\/pmax > vdot) lo=t; else hi=t; \/\/ est decreases as t grows\n  }\n  return (lo+hi)\/2*60; \/\/ seconds\n}\n\n\/* ---------- Plan generator ---------- *\/\nfunction longRunForWeek(w, cfg){\n  const lastWeek = cfg.weeks-1;            \/\/ race week index\n  const tw = lastWeek - w;                 \/\/ weeks until race (0=race week)\n  if(tw===0) return 0;                     \/\/ race week handled separately\n  if(tw<=cfg.taper){                       \/\/ taper zone\n    const factors = { 1:0.55, 2:0.75, 3:0.85 };\n    return Math.round(cfg.peak * (factors[tw] || 0.6));\n  }\n  const buildEnd = lastWeek - cfg.taper - 1; \/\/ last build week reaches peak\n  const t = buildEnd<=0 ? 1 : w \/ buildEnd;\n  let km = cfg.start + (cfg.peak - cfg.start) * t;\n  \/\/ cutback every 4th build week (but never the peak week)\n  if(w>0 && w % 4 === 3 && w !== buildEnd) km *= 0.75;\n  return Math.max(cfg.start, Math.round(km));\n}\n\nfunction intervalNote(distKey, w){\n  const sets = distKey==='5k' ? '6 \u00d7 400m' : distKey==='10k' ? '5 \u00d7 800m' : distKey==='21k' ? '5 \u00d7 1km' : '6 \u00d7 1km';\n  return sets+' pace laju, pulih 90s antara set. Termasuk pemanasan & pendinginan.';\n}\n\nfunction buildPlan(opts){\n  const cfg = deriveCfg(PLAN_BY_ID[opts.planId]);\n  const pattern = PATTERN[opts.level];\n  const raceDate = parseYMD(opts.raceDate);\n  const raceMon = mondayOf(raceDate);\n  const startMon = addDays(raceMon, -(cfg.weeks-1)*7);\n  const today = new Date(); today.setHours(0,0,0,0);\n  const distKm = DIST[opts.distance].km;\n  const P = computePaces(opts.vdot, opts.distance, opts.heat);\n\n  const weeks = [];\n  for(let w=0; w<cfg.weeks; w++){\n    const isRaceWeek = (w === cfg.weeks-1);\n    const baseLong = longRunForWeek(w, cfg);\n    const isCutback = (w>0 && w%4===3 && w!==(cfg.weeks-cfg.taper-2));\n    const days = [];\n    let vol = 0, hasRamadan=false;\n\n    for(let i=0; i<7; i++){\n      const date = addDays(startMon, w*7 + i);\n      let type = pattern[i];\n      let km = 0, note = '';\n\n      \/\/ ease in: no hard sessions in first 2 weeks\n      if(w<2 && (type==='tempo'||type==='interval')) type='easy';\n\n      if(isRaceWeek){\n        const isRace = ymd(date)===ymd(raceDate);\n        if(isRace){ type='race'; km=distKm; }\n        else if(date < raceDate){ type = (i===1||i===3) ? 'easy' : 'rest'; }\n        else { type='rest'; }\n      }\n\n      if(type==='long'){ km = baseLong; note='Pace perlahan & stabil \u2014 boleh berbual. Bawa air, lari awal pagi\/lewat petang elak panas.'; }\n      else if(type==='easy'){ km = Math.max(3, Math.round(baseLong*0.45)); if(isRaceWeek) km=Math.max(3,Math.round(distKm*0.25)); note='Pace selesa, nafas terkawal.'; }\n      else if(type==='tempo'){ const t=Math.max(4,Math.round(baseLong*0.6)); km=t; note='Pemanasan + '+showDist(Math.round(t*0.6))+' pace \"sukar tapi terkawal\" + pendinginan.'; }\n      else if(type==='interval'){ km=Math.max(4,Math.round(baseLong*0.55)); note=intervalNote(opts.distance,w); }\n      else if(type==='race'){ note='Hari kau! Selamat berlari \ud83c\udf89 Jangan over-pace 5km pertama.'; }\n      else { type='rest'; note='Rehat \/ regangan ringan.'; }\n\n      let pace = '';\n      if(P && km>0){\n        if(type==='easy'||type==='long') pace=easyRange(P);\n        else if(type==='tempo') pace=fmtPace(P.T)+'\/km';\n        else if(type==='interval') pace=fmtPace(P.I)+'\/km';\n        else if(type==='race') pace=fmtPace(P.race)+'\/km';\n      }\n      vol += km;\n      const ram = inRamadan(date);\n      if(ram) hasRamadan=true;\n      days.push({ date, name:DAY_NAMES[i], type, km, note, pace, ramadan:ram, isToday: ymd(date)===ymd(today) });\n    }\n    weeks.push({ n:w+1, days, vol:Math.round(vol), isRaceWeek, isCutback, hasRamadan });\n  }\n\n  const peakVol = Math.max(...weeks.map(w=>w.vol));\n  return { weeks, cfg, raceDate, distKm, peakVol, today, paces:P };\n}\n\n\/* ---------- Render ---------- *\/\nlet CURRENT = null;\nlet VIEW = 'grid';\n\nfunction render(plan, opts){\n  CURRENT = { plan, opts };\n  const res = $('#results');\n  const daysLeft = Math.max(0, Math.round((plan.raceDate - plan.today)\/86400000));\n  const anyRamadan = plan.weeks.some(w=>w.hasRamadan);\n\n  let html = `\n  <div class=\"brandbar\">\n    <span class=\"bl\"><span class=\"bmark\">\ud83c\udfc3<\/span> Jadual<b>Lari<\/b><\/span>\n    <span class=\"bt\">${esc(opts.raceName||'')}${opts.raceName?' \u00b7 ':''}${BRAND}<\/span>\n  <\/div>\n  <div class=\"summary\">\n    <div class=\"cell\"><div class=\"k\">Perlumbaan<\/div><div class=\"v\">${esc(opts.raceName||'Perlumbaan kau')}<\/div><\/div>\n    <div class=\"cell\"><div class=\"k\">Tarikh<\/div><div class=\"v\">${fmtDate(plan.raceDate)} <small>'${String(plan.raceDate.getFullYear()).slice(2)}<\/small><\/div><\/div>\n    <div class=\"cell\"><div class=\"k\">Kira detik<\/div><div class=\"v\">${daysLeft} <small>hari lagi<\/small><\/div><\/div>\n    <div class=\"cell\"><div class=\"k\">Pelan<\/div><div class=\"v\">${DIST[opts.distance].label} <small>\u00b7 ${plan.cfg.weeks} mgu \u00b7 ${LEVELS[opts.level]}<\/small><\/div><\/div>\n  <\/div>\n  <div class=\"adv\" style=\"margin-top:14px\"><div class=\"ic\">\ud83d\udccb<\/div><div><h4>${esc(opts.planName||'Pelan tersuai')}<\/h4><p>Distruktur ikut kaedah <b>${esc(opts.author||'\u2014')}<\/b>. Jadual dijana (minggu + jumlah km puncak) mengikut kaedah ini \u2014 bukan salinan buku. Dapatkan buku asal untuk butiran setiap sesi.<\/p><\/div><\/div>`;\n\n  \/\/ pace reference\n  if(plan.paces){\n    const P = plan.paces;\n    const cell = (lbl,val)=>`<div style=\"background:var(--bg-2);border:1px solid var(--border);border-radius:10px;padding:11px 13px\"><div style=\"font-size:.72rem;color:var(--dim);font-weight:600;text-transform:uppercase;letter-spacing:.04em\">${lbl}<\/div><div style=\"font-weight:800;font-size:1.02rem;margin-top:2px\">${val}<\/div><\/div>`;\n    html += `<div class=\"card\" style=\"padding:17px 18px;margin-top:18px\">\n      <div style=\"font-weight:800;margin-bottom:11px\">\ud83c\udfaf Pace sasaran <span style=\"color:var(--dim);font-weight:600\">\u00b7 VDOT ${opts.vdot}<\/span>${P.heat>0? ` <span class=\"pill\" style=\"background:color-mix(in srgb,var(--warn) 18%,transparent);border-color:color-mix(in srgb,var(--warn) 40%,var(--border));color:var(--warn)\">\u2600\ufe0f +${Math.round(P.heat*100)}% panas \u00b7 ${opts.weather.temp}\u00b0C, ${opts.weather.humid}%<\/span>`:''}<\/div>\n      <div style=\"display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:10px\">\n        ${cell('Mudah \/ Jauh (E)', easyRange(P))}\n        ${cell('Marathon (M)', fmtPace(P.M)+'\/km')}\n        ${cell('Tempo (T)', fmtPace(P.T)+'\/km')}\n        ${cell('Interval (I)', fmtPace(P.I)+'\/km')}\n        ${cell('Repetition (R)', fmtPace(P.R)+'\/km')}\n        ${cell('Pace lumba sasaran', fmtPace(P.race)+'\/km')}\n      <\/div>\n      <div style=\"font-weight:800;margin:14px 0 8px\">\ud83d\udcca Anggaran masa setara <span style=\"color:var(--dim);font-weight:600\">\u00b7 keadaan neutral (~15\u00b0C), penanda aras kecergasan<\/span><\/div>\n      <div style=\"display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:10px\">\n        ${cell('5 KM', clock(predictTime(opts.vdot,5000)))}\n        ${cell('10 KM', clock(predictTime(opts.vdot,10000)))}\n        ${cell('Half (21.1K)', clock(predictTime(opts.vdot,21097)))}\n        ${cell('Full (42.2K)', clock(predictTime(opts.vdot,42195)))}\n      <\/div><\/div>`;\n  }\n\n  \/\/ advisories\n  html += `<div class=\"advisories\">`;\n  html += adv('\ud83c\udf21\ufe0f','Cuaca panas & lembap','Malaysia panas sepanjang tahun. Lari sebelum 7:30 pagi atau selepas 6:30 petang, minum 400\u2013600ml\/jam, dan jangan kejar pace masa tengah hari.', false);\n  if(anyRamadan){\n    html += adv('\ud83c\udf19','Latihan waktu Ramadan','Sebahagian minggu jatuh dalam Ramadan. Lari ringan selepas Terawih atau sebelum Sahur, kurangkan intensiti, dan utamakan hidrasi masa berbuka & sahur.', true);\n  }\n  html += adv('\ud83d\udca7','Hidrasi & elektrolit','Tambah sedikit garam\/elektrolit untuk larian >75 minit. Berat badan turun >2% selepas lari = kau kurang minum.', false);\n  html += `<\/div>`;\n\n  \/\/ toolbar\n  html += `\n  <div class=\"toolbar\">\n    <h2>Jadual Latihan<\/h2>\n    <div class=\"actions\">\n      <div class=\"seg\" id=\"viewSeg\">\n        <button data-view=\"grid\" class=\"${VIEW==='grid'?'on':''}\">Grid<\/button>\n        <button data-view=\"list\" class=\"${VIEW==='list'?'on':''}\">Senarai<\/button>\n      <\/div>\n      <button class=\"btn\" id=\"printBtn\">\ud83d\udda8\ufe0f Cetak \/ PDF<\/button>\n      <button class=\"btn\" id=\"icsBtn\">\ud83d\udcc5 Kalendar (.ics)<\/button>\n      <button class=\"btn\" id=\"waBtn\">\ud83d\udcac WhatsApp<\/button>\n    <\/div>\n  <\/div>`;\n\n  \/\/ legend\n  html += `<div class=\"legend\">`;\n  ['easy','long','tempo','interval','rest','race'].forEach(t=>{\n    html += `<span><i class=\"dot\" style=\"background:${WTYPE[t].color};width:9px;height:9px;border-radius:50%;display:inline-block;margin-right:6px\"><\/i>${WTYPE[t].label}<\/span>`;\n  });\n  html += `<\/div>`;\n\n  \/\/ weeks\n  html += `<div class=\"${VIEW==='list'?'lview':''}\" id=\"weeksWrap\">`;\n  plan.weeks.forEach(w=>{\n    html += `<div class=\"week\">\n      <div class=\"week-head\">\n        <div class=\"wk\">Minggu ${w.n}<span>${fmtDate(w.days[0].date)} \u2013 ${fmtDate(w.days[6].date)}<\/span><\/div>\n        <div class=\"meta\">\n          ${w.isRaceWeek? `<span class=\"pill\" style=\"background:color-mix(in srgb,var(--accent) 18%,transparent);border-color:var(--accent);color:var(--accent)\">Minggu Perlumbaan<\/span>`:''}\n          ${w.isCutback && !w.isRaceWeek? `<span class=\"pill cut\">Minggu pemulihan \u2193<\/span>`:''}\n          ${w.hasRamadan? `<span class=\"pill ramadan\">\ud83c\udf19 Ramadan<\/span>`:''}\n          <span class=\"pill vol\">${showDist(w.vol)} jumlah<\/span>\n        <\/div>\n      <\/div>\n      <div class=\"days\">`;\n    w.days.forEach(d=>{\n      const wt = WTYPE[d.type];\n      const cls = ['day','t-'+d.type, d.type==='race'?'race':'', d.isToday?'today':'', d.ramadan?'ramadan':''].join(' ');\n      html += `<div class=\"${cls}\">\n        <div class=\"dname\">${d.name}<\/div>\n        <div class=\"date\">${fmtDate(d.date)}<\/div>\n        <div>\n          <div class=\"wtype\"><span class=\"dot\" style=\"background:${wt.color}\"><\/span>${wt.label}<\/div>\n          ${d.km>0? `<div class=\"wkm\">${showDist(d.km)}${d.pace? ' \u00b7 <b style=\"color:var(--text)\">'+d.pace+'<\/b>':''}<\/div>`:''}\n        <\/div>\n        ${d.note? `<div class=\"wnote\">${d.note}<\/div>`:''}\n      <\/div>`;\n    });\n    html += `<\/div><\/div>`;\n  });\n  html += `<\/div>`;\n\n  res.innerHTML = html;\n  res.style.display = 'block';\n\n  \/\/ wire buttons\n  $('#printBtn').onclick = ()=> window.print();\n  $('#icsBtn').onclick = exportICS;\n  $('#waBtn').onclick = shareWA;\n  APP.querySelectorAll('#viewSeg button').forEach(b=> b.onclick=()=>{ VIEW=b.dataset.view; render(plan,opts); res.scrollIntoView({behavior:'smooth',block:'start'}); });\n  res.scrollIntoView({behavior:'smooth', block:'start'});\n}\n\nfunction adv(ic,title,body,warn){\n  return `<div class=\"adv ${warn?'warn':''}\"><div class=\"ic\">${ic}<\/div><div><h4>${title}<\/h4><p>${body}<\/p><\/div><\/div>`;\n}\nfunction esc(s){ return String(s).replace(\/[&<>\"]\/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c])); }\n\n\/* ---------- Export: ICS ---------- *\/\nfunction exportICS(){\n  const { plan, opts } = CURRENT;\n  let lines = ['BEGIN:VCALENDAR','VERSION:2.0','PRODID:-\/\/'+BRAND+'\/\/JadualLari\/\/EN','CALSCALE:GREGORIAN',\n    'X-WR-CALNAME:'+icsEsc('JadualLari \u00b7 '+(opts.raceName||'Latihan Lari')+' \u00b7 '+BRAND)];\n  plan.weeks.forEach(w=>{\n    w.days.forEach(d=>{\n      if(d.type==='rest') return;\n      const wt = WTYPE[d.type];\n      const dt = d.date.getFullYear()+pad(d.date.getMonth()+1)+pad(d.date.getDate());\n      const dtEnd = (()=>{ const e=addDays(d.date,1); return e.getFullYear()+pad(e.getMonth()+1)+pad(e.getDate()); })();\n      const title = (d.type==='race'? '\ud83c\udfc1 '+(opts.raceName||'Perlumbaan') : wt.label) + (d.km>0? ' \u2014 '+showDist(d.km):'') + (d.pace? ' @ '+d.pace:'');\n      const desc = (d.note||'') + '\\n\u2014 JadualLari \u00b7 '+BRAND;\n      lines.push('BEGIN:VEVENT');\n      lines.push('UID:'+dt+'-'+d.type+'-'+Math.random().toString(36).slice(2,8)+'@lesgo.my');\n      lines.push('DTSTART;VALUE=DATE:'+dt);\n      lines.push('DTEND;VALUE=DATE:'+dtEnd);\n      lines.push('SUMMARY:'+icsEsc(title));\n      lines.push('DESCRIPTION:'+icsEsc(desc));\n      lines.push('URL:'+BRAND_URL);\n      lines.push('END:VEVENT');\n    });\n  });\n  lines.push('END:VCALENDAR');\n  const blob = new Blob([lines.join('\\r\\n')], {type:'text\/calendar'});\n  const a = document.createElement('a');\n  a.href = URL.createObjectURL(blob);\n  a.download = 'jaduallari-'+opts.distance+'-lesgo.my.ics';\n  a.click();\n}\nfunction icsEsc(s){ return String(s).replace(\/[\\\\;,]\/g,m=>'\\\\'+m).replace(\/\\n\/g,'\\\\n'); }\n\n\/* ---------- Export: WhatsApp ---------- *\/\nfunction shareWA(){\n  const { plan, opts } = CURRENT;\n  const daysLeft = Math.max(0, Math.round((plan.raceDate - plan.today)\/86400000));\n  let t = `\ud83c\udfc3 *JadualLari by ${BRAND}*\\n`;\n  t += `*Jadual Latihan ${DIST[opts.distance].label}* \u2014 ${opts.raceName||'perlumbaan'}\\n`;\n  t += `\ud83d\udccb ${opts.planName||''}\\n`;\n  t += `\ud83d\udcc5 ${fmtDate(plan.raceDate)} ${plan.raceDate.getFullYear()} (${daysLeft} hari lagi)\\n`;\n  t += `\ud83d\udcc8 ${plan.cfg.weeks} minggu \u00b7 tahap ${LEVELS[opts.level]} \u00b7 puncak ${showDist(plan.peakVol)}\/minggu\\n\\n`;\n  plan.weeks.slice(0,4).forEach(w=>{\n    const lr = w.days.find(d=>d.type==='long'||d.type==='race');\n    t += `M${w.n}: ${showDist(w.vol)}${lr&&lr.km?` (jauh ${showDist(lr.km)})`:''}\\n`;\n  });\n  t += `\u2026dan ${Math.max(0,plan.weeks.length-4)} minggu lagi.\\n\\n\ud83c\uddf2\ud83c\uddfe Jana jadual kau sendiri di ${BRAND_URL}`;\n  window.open('https:\/\/wa.me\/?text='+encodeURIComponent(t), '_blank');\n}\n\n\/* ---------- Wiring ---------- *\/\nfunction initPlans(){\n  const sel = $('#plan');\n  PLAN_GROUPS.forEach(([gid,glabel])=>{\n    const og = document.createElement('optgroup'); og.label = glabel;\n    PLANS.filter(p=>p.g===gid).forEach(p=>{\n      const o = document.createElement('option'); o.value = p.id; o.textContent = p.name + ' \u00b7 ' + p.w + ' mgu';\n      og.appendChild(o);\n    });\n    sel.appendChild(og);\n  });\n  sel.value = 'hansons_half_beginner';\n}\nfunction initPresets(){\n  const sel = $('#preset');\n  PRESETS.forEach(p=>{ const o=document.createElement('option'); o.value=p.id; o.textContent=p.name + (p.date?` (${p.date} \u00b7 anggaran)`:''); sel.appendChild(o); });\n  sel.onchange = ()=>{\n    const p = PRESETS.find(x=>x.id===sel.value);\n    if(p && p.id){ $('#raceName').value=p.name; if(p.date) $('#raceDate').value=p.date; if(p.plan) $('#plan').value=p.plan; }\n  };\n}\n\nfunction defaultDate(){ \/\/ 14 weeks from today, on a Sunday\n  let d = addDays(new Date(), 98);\n  while(d.getDay()!==0) d=addDays(d,1);\n  return ymd(d);\n}\n\nfunction generate(){\n  const planId = $('#plan').value;\n  const p = PLAN_BY_ID[planId];\n  const opts = {\n    raceName: $('#raceName').value.trim(),\n    raceDate: $('#raceDate').value,\n    planId, planName: p.name, author: p.author,\n    distance: p.d, level: p.lv,\n    vdot: parseFloat($('#vdot').value) || null,\n  };\n  const wxOn = $('#wxToggle').classList.contains('on');\n  const temp = parseInt($('#temp').value,10), humid = parseInt($('#humid').value,10);\n  opts.weather = { on:wxOn, temp, humid };\n  opts.heat = wxOn ? heatFactor(temp, humid) : 0;\n  if(!opts.raceDate){ alert('Sila pilih tarikh perlumbaan dulu.'); return; }\n  if(parseYMD(opts.raceDate) <= new Date()){ if(!confirm('Tarikh perlumbaan dah lepas atau hari ni. Tetap jana?')) return; }\n  localStorage.setItem('jl_opts', JSON.stringify(opts));\n  const plan = buildPlan(opts);\n  render(plan, opts);\n}\n\nfunction calcVdot(){\n  const meters = parseFloat($('#rdCalc').value);\n  const h = parseInt($('#rtH').value,10) || 0;\n  const m = parseInt($('#rtM').value,10) || 0;\n  const s = parseInt($('#rtS').value,10) || 0;\n  const secs = h*3600 + m*60 + s;\n  if(secs<=0){ alert('Masukkan masa larian (jam \/ minit \/ saat).'); return; }\n  const v = Math.round(vdotFromRace(meters, secs));\n  $('#vdot').value = v;\n  $('#vdotOut').textContent = 'VDOT \u2248 '+v;\n}\n\nfunction initTheme(){\n  const saved = localStorage.getItem('jl_theme') || 'dark';\n  APP.setAttribute('data-theme', saved);\n  $('#themeBtn').textContent = saved==='dark'?'\u2600\ufe0f':'\ud83c\udf19';\n  $('#themeBtn').onclick = ()=>{\n    const cur = APP.getAttribute('data-theme');\n    const next = cur==='dark'?'light':'dark';\n    APP.setAttribute('data-theme', next);\n    $('#themeBtn').textContent = next==='dark'?'\u2600\ufe0f':'\ud83c\udf19';\n    localStorage.setItem('jl_theme', next);\n  };\n}\n\nfunction setWeatherOn(on){\n  $('#wxToggle').classList.toggle('on', on);\n  $('#wxControls').classList.toggle('hide', !on);\n  $('#wxToggle').textContent = on ? '\u2600\ufe0f Pelarasan cuaca: AKTIF' : '\u2600\ufe0f Aktifkan pelarasan cuaca';\n}\nfunction initWeather(){\n  const upd = ()=>{\n    $('#tVal').textContent = $('#temp').value+'\u00b0C';\n    $('#hVal').textContent = $('#humid').value+'%';\n    const f = heatFactor(+$('#temp').value, +$('#humid').value);\n    $('#wxOut').textContent = '\u2248 +'+Math.round(f*100)+'% lebih perlahan';\n    $('#wxOut').style.cssText = 'font-weight:800;color:var(--accent)';\n  };\n  $('#temp').oninput = upd; $('#humid').oninput = upd; upd();\n  $('#wxToggle').onclick = ()=> setWeatherOn(!$('#wxToggle').classList.contains('on'));\n}\n\n\/\/ init\ninitTheme();\ninitPlans();\ninitPresets();\ninitWeather();\n$('#raceDate').value = defaultDate();\n$('#genBtn').onclick = generate;\n$('#calcVdot').onclick = calcVdot;\n\/\/ restore last\ntry {\n  const o = JSON.parse(localStorage.getItem('jl_opts')||'null');\n  if(o){\n    $('#raceName').value=o.raceName||'';\n    if(o.raceDate)$('#raceDate').value=o.raceDate;\n    if(o.planId && PLAN_BY_ID[o.planId]) $('#plan').value=o.planId;\n    if(o.vdot) $('#vdot').value=o.vdot;\n    if(o.weather){\n      if(o.weather.temp){ $('#temp').value=o.weather.temp; }\n      if(o.weather.humid){ $('#humid').value=o.weather.humid; }\n      $('#temp').dispatchEvent(new Event('input'));\n      if(o.weather.on) setWeatherOn(true);\n    }\n  }\n} catch(e){}\n\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"\ud83c\udfc3 JadualLari by lesgo.my \ud83c\udf19 Penjana Jadual Latihan \u00b7 Malaysia Dari tarikh perlumbaan kejadual latihan mingguan Pilih perlumbaan, kami susun pelan latihan progresif untuk kau \u2014 siap ambil kira cuaca panas & bulan Ramadan. Export PDF, kalendar, atau share ke...","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-11048","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Training Plan Lengkap Lesgo! - Lesgo.My!<\/title>\n<meta name=\"description\" content=\"Training Plan Lengkap Lesgo! Training plan untuk 5km 10km Half Marathon dan Marathon. Bookmark page ni. Boleh print direct.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/lesgo.my\/index.php\/training-plan-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Training Plan Lengkap Lesgo! - Lesgo.My!\" \/>\n<meta property=\"og:description\" content=\"Training Plan Lengkap Lesgo! Training plan untuk 5km 10km Half Marathon dan Marathon. Bookmark page ni. Boleh print direct.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/lesgo.my\/index.php\/training-plan-2\/\" \/>\n<meta property=\"og:site_name\" content=\"Lesgo.My!\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-10T16:58:43+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/lesgo.my\\\/index.php\\\/training-plan-2\\\/\",\"url\":\"https:\\\/\\\/lesgo.my\\\/index.php\\\/training-plan-2\\\/\",\"name\":\"Training Plan Lengkap Lesgo! - Lesgo.My!\",\"isPartOf\":{\"@id\":\"http:\\\/\\\/165.22.102.237\\\/#website\"},\"datePublished\":\"2026-07-10T16:58:42+00:00\",\"dateModified\":\"2026-07-10T16:58:43+00:00\",\"description\":\"Training Plan Lengkap Lesgo! Training plan untuk 5km 10km Half Marathon dan Marathon. Bookmark page ni. Boleh print direct.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/lesgo.my\\\/index.php\\\/training-plan-2\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/lesgo.my\\\/index.php\\\/training-plan-2\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/lesgo.my\\\/index.php\\\/training-plan-2\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"http:\\\/\\\/165.22.102.237\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Training Plan Lengkap Lesgo!\"}]},{\"@type\":\"WebSite\",\"@id\":\"http:\\\/\\\/165.22.102.237\\\/#website\",\"url\":\"http:\\\/\\\/165.22.102.237\\\/\",\"name\":\"Lesgo.My!\",\"description\":\"by runners\",\"publisher\":{\"@id\":\"http:\\\/\\\/165.22.102.237\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"http:\\\/\\\/165.22.102.237\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"http:\\\/\\\/165.22.102.237\\\/#organization\",\"name\":\"Lesgo.My!\",\"url\":\"http:\\\/\\\/165.22.102.237\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"http:\\\/\\\/165.22.102.237\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"http:\\\/\\\/165.22.102.237\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/lesgo.my-media-lesgo-logo.png\",\"contentUrl\":\"http:\\\/\\\/165.22.102.237\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/lesgo.my-media-lesgo-logo.png\",\"width\":1024,\"height\":682,\"caption\":\"Lesgo.My!\"},\"image\":{\"@id\":\"http:\\\/\\\/165.22.102.237\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Training Plan Lengkap Lesgo! - Lesgo.My!","description":"Training Plan Lengkap Lesgo! Training plan untuk 5km 10km Half Marathon dan Marathon. Bookmark page ni. Boleh print direct.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/lesgo.my\/index.php\/training-plan-2\/","og_locale":"en_US","og_type":"article","og_title":"Training Plan Lengkap Lesgo! - Lesgo.My!","og_description":"Training Plan Lengkap Lesgo! Training plan untuk 5km 10km Half Marathon dan Marathon. Bookmark page ni. Boleh print direct.","og_url":"https:\/\/lesgo.my\/index.php\/training-plan-2\/","og_site_name":"Lesgo.My!","article_modified_time":"2026-07-10T16:58:43+00:00","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/lesgo.my\/index.php\/training-plan-2\/","url":"https:\/\/lesgo.my\/index.php\/training-plan-2\/","name":"Training Plan Lengkap Lesgo! - Lesgo.My!","isPartOf":{"@id":"http:\/\/165.22.102.237\/#website"},"datePublished":"2026-07-10T16:58:42+00:00","dateModified":"2026-07-10T16:58:43+00:00","description":"Training Plan Lengkap Lesgo! Training plan untuk 5km 10km Half Marathon dan Marathon. Bookmark page ni. Boleh print direct.","breadcrumb":{"@id":"https:\/\/lesgo.my\/index.php\/training-plan-2\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/lesgo.my\/index.php\/training-plan-2\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/lesgo.my\/index.php\/training-plan-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"http:\/\/165.22.102.237\/"},{"@type":"ListItem","position":2,"name":"Training Plan Lengkap Lesgo!"}]},{"@type":"WebSite","@id":"http:\/\/165.22.102.237\/#website","url":"http:\/\/165.22.102.237\/","name":"Lesgo.My!","description":"by runners","publisher":{"@id":"http:\/\/165.22.102.237\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/165.22.102.237\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"http:\/\/165.22.102.237\/#organization","name":"Lesgo.My!","url":"http:\/\/165.22.102.237\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/165.22.102.237\/#\/schema\/logo\/image\/","url":"http:\/\/165.22.102.237\/wp-content\/uploads\/2025\/05\/lesgo.my-media-lesgo-logo.png","contentUrl":"http:\/\/165.22.102.237\/wp-content\/uploads\/2025\/05\/lesgo.my-media-lesgo-logo.png","width":1024,"height":682,"caption":"Lesgo.My!"},"image":{"@id":"http:\/\/165.22.102.237\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/lesgo.my\/index.php\/wp-json\/wp\/v2\/pages\/11048","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lesgo.my\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/lesgo.my\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/lesgo.my\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lesgo.my\/index.php\/wp-json\/wp\/v2\/comments?post=11048"}],"version-history":[{"count":3,"href":"https:\/\/lesgo.my\/index.php\/wp-json\/wp\/v2\/pages\/11048\/revisions"}],"predecessor-version":[{"id":11051,"href":"https:\/\/lesgo.my\/index.php\/wp-json\/wp\/v2\/pages\/11048\/revisions\/11051"}],"wp:attachment":[{"href":"https:\/\/lesgo.my\/index.php\/wp-json\/wp\/v2\/media?parent=11048"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}